Completed
Branch master (76375f)
by
unknown
10:42 queued 05:22
created
core/db_classes/EE_Transaction.class.php 2 patches
Indentation   +1749 added lines, -1749 removed lines patch added patch discarded remove patch
@@ -13,1753 +13,1753 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Transaction extends EE_Base_Class implements EEI_Transaction
15 15
 {
16
-    /**
17
-     * The length of time in seconds that a lock is applied before being considered expired.
18
-     * It is not long because a transaction should only be locked for the duration of the request that locked it
19
-     */
20
-    const LOCK_EXPIRATION = 2;
21
-
22
-    /**
23
-     * txn status upon initial construction.
24
-     *
25
-     * @var string
26
-     */
27
-    protected $_old_txn_status;
28
-
29
-    private ?EE_Registration $_primary_registrant = null;
30
-
31
-    /**
32
-     * @param array  $props_n_values          incoming values
33
-     * @param string $timezone                incoming timezone
34
-     *                                        (if not set the timezone set for the website will be used.)
35
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
36
-     *                                        date_format and the second value is the time format
37
-     * @return EE_Transaction
38
-     * @throws EE_Error
39
-     * @throws InvalidArgumentException
40
-     * @throws InvalidDataTypeException
41
-     * @throws InvalidInterfaceException
42
-     * @throws ReflectionException
43
-     */
44
-    public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
45
-    {
46
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
47
-        $txn        = $has_object
48
-            ? $has_object
49
-            : new self($props_n_values, false, $timezone, $date_formats);
50
-        if (! $has_object) {
51
-            $txn->set_old_txn_status($txn->status_ID());
52
-        }
53
-        return $txn;
54
-    }
55
-
56
-
57
-    /**
58
-     * @param array  $props_n_values  incoming values from the database
59
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
60
-     *                                the website will be used.
61
-     * @return EE_Transaction
62
-     * @throws EE_Error
63
-     * @throws InvalidArgumentException
64
-     * @throws InvalidDataTypeException
65
-     * @throws InvalidInterfaceException
66
-     * @throws ReflectionException
67
-     */
68
-    public static function new_instance_from_db($props_n_values = [], $timezone = '')
69
-    {
70
-        $txn = new self($props_n_values, true, $timezone);
71
-        $txn->set_old_txn_status($txn->status_ID());
72
-        return $txn;
73
-    }
74
-
75
-
76
-    /**
77
-     * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
78
-     * If a lock has already been set, then we will attempt to remove it in case it has expired.
79
-     * If that also fails, then an exception is thrown.
80
-     *
81
-     * @throws EE_Error
82
-     * @throws InvalidArgumentException
83
-     * @throws InvalidDataTypeException
84
-     * @throws InvalidInterfaceException
85
-     * @throws ReflectionException
86
-     */
87
-    public function lock()
88
-    {
89
-        // attempt to set lock, but if that fails...
90
-        if (! $this->add_extra_meta('lock', time(), true)) {
91
-            // then attempt to remove the lock in case it is expired
92
-            if ($this->_remove_expired_lock()) {
93
-                // if removal was successful, then try setting lock again
94
-                $this->lock();
95
-            } else {
96
-                // but if the lock can not be removed, then throw an exception
97
-                throw new EE_Error(
98
-                    sprintf(
99
-                        esc_html__(
100
-                            'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
101
-                            'event_espresso'
102
-                        ),
103
-                        $this->ID()
104
-                    )
105
-                );
106
-            }
107
-        }
108
-    }
109
-
110
-
111
-    /**
112
-     * removes transaction lock applied in EE_Transaction::lock()
113
-     *
114
-     * @return int
115
-     * @throws EE_Error
116
-     * @throws InvalidArgumentException
117
-     * @throws InvalidDataTypeException
118
-     * @throws InvalidInterfaceException
119
-     * @throws ReflectionException
120
-     */
121
-    public function unlock()
122
-    {
123
-        return $this->delete_extra_meta('lock');
124
-    }
125
-
126
-
127
-    /**
128
-     * Decides whether or not now is the right time to update the transaction.
129
-     * This is useful because we don't always know if it is safe to update the transaction
130
-     * and its related data. why?
131
-     * because it's possible that the transaction is being used in another
132
-     * request and could overwrite anything we save.
133
-     * So we want to only update the txn once we know that won't happen.
134
-     * We also check that the lock isn't expired, and remove it if it is
135
-     *
136
-     * @return boolean
137
-     * @throws EE_Error
138
-     * @throws InvalidArgumentException
139
-     * @throws InvalidDataTypeException
140
-     * @throws InvalidInterfaceException
141
-     * @throws ReflectionException
142
-     */
143
-    public function is_locked()
144
-    {
145
-        // if TXN is not locked, then return false immediately
146
-        if (! $this->_get_lock()) {
147
-            return false;
148
-        }
149
-        // if not, then let's try and remove the lock in case it's expired...
150
-        // _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
151
-        // and a positive number if the lock was removed (ie: number of locks deleted),
152
-        // so we need to return the opposite
153
-        return ! $this->_remove_expired_lock();
154
-    }
155
-
156
-
157
-    /**
158
-     * Gets the meta field indicating that this TXN is locked
159
-     *
160
-     * @return int
161
-     * @throws EE_Error
162
-     * @throws InvalidArgumentException
163
-     * @throws InvalidDataTypeException
164
-     * @throws InvalidInterfaceException
165
-     * @throws ReflectionException
166
-     */
167
-    protected function _get_lock()
168
-    {
169
-        return (int) $this->get_extra_meta('lock', true, 0);
170
-    }
171
-
172
-
173
-    /**
174
-     * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
175
-     *
176
-     * @return int
177
-     * @throws EE_Error
178
-     * @throws InvalidArgumentException
179
-     * @throws InvalidDataTypeException
180
-     * @throws InvalidInterfaceException
181
-     * @throws ReflectionException
182
-     */
183
-    protected function _remove_expired_lock()
184
-    {
185
-        $locked = $this->_get_lock();
186
-        if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
187
-            return $this->unlock();
188
-        }
189
-        return 0;
190
-    }
191
-
192
-
193
-    /**
194
-     * Set transaction total
195
-     *
196
-     * @param float $total total value of transaction
197
-     * @throws EE_Error
198
-     * @throws InvalidArgumentException
199
-     * @throws InvalidDataTypeException
200
-     * @throws InvalidInterfaceException
201
-     * @throws ReflectionException
202
-     */
203
-    public function set_total($total = 0.00)
204
-    {
205
-        $this->set('TXN_total', (float) $total);
206
-    }
207
-
208
-
209
-    /**
210
-     * Set Total Amount Paid to Date
211
-     *
212
-     * @param float $total_paid total amount paid to date (sum of all payments)
213
-     * @throws EE_Error
214
-     * @throws InvalidArgumentException
215
-     * @throws InvalidDataTypeException
216
-     * @throws InvalidInterfaceException
217
-     * @throws ReflectionException
218
-     */
219
-    public function set_paid($total_paid = 0.00)
220
-    {
221
-        $this->set('TXN_paid', (float) $total_paid);
222
-    }
223
-
224
-
225
-    /**
226
-     * Set transaction status
227
-     *
228
-     * @param string $status        whether the transaction is open, declined, accepted,
229
-     *                              or any number of custom values that can be set
230
-     * @throws EE_Error
231
-     * @throws InvalidArgumentException
232
-     * @throws InvalidDataTypeException
233
-     * @throws InvalidInterfaceException
234
-     * @throws ReflectionException
235
-     */
236
-    public function set_status($status = '')
237
-    {
238
-        $this->set('STS_ID', $status);
239
-    }
240
-
241
-
242
-    /**
243
-     * Set hash salt
244
-     *
245
-     * @param string $hash_salt required for some payment gateways
246
-     * @throws EE_Error
247
-     * @throws InvalidArgumentException
248
-     * @throws InvalidDataTypeException
249
-     * @throws InvalidInterfaceException
250
-     * @throws ReflectionException
251
-     */
252
-    public function set_hash_salt($hash_salt = '')
253
-    {
254
-        $this->set('TXN_hash_salt', $hash_salt);
255
-    }
256
-
257
-
258
-    /**
259
-     * Sets TXN_reg_steps array
260
-     *
261
-     * @param array $txn_reg_steps
262
-     * @throws EE_Error
263
-     * @throws InvalidArgumentException
264
-     * @throws InvalidDataTypeException
265
-     * @throws InvalidInterfaceException
266
-     * @throws ReflectionException
267
-     */
268
-    public function set_reg_steps(array $txn_reg_steps)
269
-    {
270
-        $this->set('TXN_reg_steps', $txn_reg_steps);
271
-    }
272
-
273
-
274
-    /**
275
-     * Gets TXN_reg_steps
276
-     *
277
-     * @return array
278
-     * @throws EE_Error
279
-     * @throws InvalidArgumentException
280
-     * @throws InvalidDataTypeException
281
-     * @throws InvalidInterfaceException
282
-     * @throws ReflectionException
283
-     */
284
-    public function reg_steps()
285
-    {
286
-        $TXN_reg_steps = $this->get('TXN_reg_steps');
287
-        return is_array($TXN_reg_steps)
288
-            ? $TXN_reg_steps
289
-            : [];
290
-    }
291
-
292
-
293
-    /**
294
-     * @param string|null $schema
295
-     *     Schemas:
296
-     *     'localized_float': "3,023.00"
297
-     *     'no_currency_code': "$3,023.00"
298
-     *     null: "$3,023.00<span>USD</span>"
299
-     * @return string of transaction's total cost, with currency symbol and decimal
300
-     * @throws EE_Error
301
-     * @throws InvalidArgumentException
302
-     * @throws InvalidDataTypeException
303
-     * @throws InvalidInterfaceException
304
-     * @throws ReflectionException
305
-     */
306
-    public function pretty_total(?string $schema = null)
307
-    {
308
-        return $this->get_pretty('TXN_total', $schema);
309
-    }
310
-
311
-
312
-    /**
313
-     * Gets the amount paid in a pretty string (formatted and with currency symbol)
314
-     *
315
-     * @param string|null $schema
316
-     *     Schemas:
317
-     *     'localized_float': "3,023.00"
318
-     *     'no_currency_code': "$3,023.00"
319
-     *     null: "$3,023.00<span>USD</span>"
320
-     * @return string
321
-     * @throws EE_Error
322
-     * @throws InvalidArgumentException
323
-     * @throws InvalidDataTypeException
324
-     * @throws InvalidInterfaceException
325
-     * @throws ReflectionException
326
-     */
327
-    public function pretty_paid(?string $schema = null)
328
-    {
329
-        return $this->get_pretty('TXN_paid', $schema);
330
-    }
331
-
332
-
333
-    /**
334
-     * calculate the amount remaining for this transaction and return;
335
-     *
336
-     * @return float amount remaining
337
-     * @throws EE_Error
338
-     * @throws InvalidArgumentException
339
-     * @throws InvalidDataTypeException
340
-     * @throws InvalidInterfaceException
341
-     * @throws ReflectionException
342
-     */
343
-    public function remaining()
344
-    {
345
-        return $this->total() - $this->paid();
346
-    }
347
-
348
-
349
-    /**
350
-     * get Transaction Total
351
-     *
352
-     * @return float
353
-     * @throws EE_Error
354
-     * @throws InvalidArgumentException
355
-     * @throws InvalidDataTypeException
356
-     * @throws InvalidInterfaceException
357
-     * @throws ReflectionException
358
-     */
359
-    public function total()
360
-    {
361
-        return (float) $this->get('TXN_total');
362
-    }
363
-
364
-
365
-    /**
366
-     * get Total Amount Paid to Date
367
-     *
368
-     * @return float
369
-     * @throws EE_Error
370
-     * @throws InvalidArgumentException
371
-     * @throws InvalidDataTypeException
372
-     * @throws InvalidInterfaceException
373
-     * @throws ReflectionException
374
-     */
375
-    public function paid()
376
-    {
377
-        return (float) $this->get('TXN_paid');
378
-    }
379
-
380
-
381
-    /**
382
-     * @return mixed|null
383
-     * @throws EE_Error
384
-     * @throws InvalidArgumentException
385
-     * @throws InvalidDataTypeException
386
-     * @throws InvalidInterfaceException
387
-     * @throws ReflectionException
388
-     */
389
-    public function get_cart_session()
390
-    {
391
-        $session_data = (array) $this->get('TXN_session_data');
392
-        return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
393
-            ? $session_data['cart']
394
-            : null;
395
-    }
396
-
397
-
398
-    /**
399
-     * get Transaction session data
400
-     *
401
-     * @return array|mixed
402
-     * @throws EE_Error
403
-     * @throws InvalidArgumentException
404
-     * @throws InvalidDataTypeException
405
-     * @throws InvalidInterfaceException
406
-     * @throws ReflectionException
407
-     */
408
-    public function session_data()
409
-    {
410
-        $session_data = $this->get('TXN_session_data');
411
-        if (empty($session_data)) {
412
-            $session_data = [
413
-                'id'            => null,
414
-                'user_id'       => null,
415
-                'ip_address'    => null,
416
-                'user_agent'    => null,
417
-                'init_access'   => null,
418
-                'last_access'   => null,
419
-                'pages_visited' => [],
420
-            ];
421
-        }
422
-        return $session_data;
423
-    }
424
-
425
-
426
-    /**
427
-     * Set session data within the TXN object
428
-     *
429
-     * @param EE_Session|array|null $session_data
430
-     * @throws EE_Error
431
-     * @throws InvalidArgumentException
432
-     * @throws InvalidDataTypeException
433
-     * @throws InvalidInterfaceException
434
-     * @throws ReflectionException
435
-     */
436
-    public function set_txn_session_data($session_data)
437
-    {
438
-        if ($session_data instanceof EE_Session) {
439
-            $this->set('TXN_session_data', $session_data->get_session_data(null, true));
440
-        } else {
441
-            $this->set('TXN_session_data', $session_data);
442
-        }
443
-    }
444
-
445
-
446
-    /**
447
-     * get Transaction hash salt
448
-     *
449
-     * @return mixed
450
-     * @throws EE_Error
451
-     * @throws InvalidArgumentException
452
-     * @throws InvalidDataTypeException
453
-     * @throws InvalidInterfaceException
454
-     * @throws ReflectionException
455
-     */
456
-    public function hash_salt_()
457
-    {
458
-        return $this->get('TXN_hash_salt');
459
-    }
460
-
461
-
462
-    /**
463
-     * Returns the transaction datetime as either:
464
-     *            - unix timestamp format ($format = false, $gmt = true)
465
-     *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
466
-     *              has no affect with this option)), this also may include a timezone abbreviation if the
467
-     *              set timezone in this class differs from what the timezone is on the blog.
468
-     *            - formatted date string including the UTC (timezone) offset (default).
469
-     *
470
-     * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
471
-     * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
472
-     *                          or no UTC offset applied
473
-     * @return string | int
474
-     * @throws EE_Error
475
-     * @throws InvalidArgumentException
476
-     * @throws InvalidDataTypeException
477
-     * @throws InvalidInterfaceException
478
-     * @throws ReflectionException
479
-     */
480
-    public function datetime($format = false, $gmt = false)
481
-    {
482
-        if ($format) {
483
-            return $this->get_pretty('TXN_timestamp');
484
-        }
485
-        if ($gmt) {
486
-            return $this->get_raw('TXN_timestamp');
487
-        }
488
-        return $this->get('TXN_timestamp');
489
-    }
490
-
491
-
492
-    /**
493
-     * Gets registrations on this transaction
494
-     *
495
-     * @param array   $query_params array of query parameters
496
-     * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
497
-     * @return EE_Base_Class[]|EE_Registration[]
498
-     * @throws EE_Error
499
-     * @throws InvalidArgumentException
500
-     * @throws InvalidDataTypeException
501
-     * @throws InvalidInterfaceException
502
-     * @throws ReflectionException
503
-     */
504
-    public function registrations($query_params = [], $get_cached = false)
505
-    {
506
-        $query_params = (empty($query_params) || ! is_array($query_params))
507
-            ? [
508
-                'order_by' => [
509
-                    'Event.EVT_name'     => 'ASC',
510
-                    'Attendee.ATT_lname' => 'ASC',
511
-                    'Attendee.ATT_fname' => 'ASC',
512
-                    'REG_ID'             => 'ASC',
513
-                ],
514
-            ]
515
-            : $query_params;
516
-        $query_params = $get_cached
517
-            ? []
518
-            : $query_params;
519
-        return $this->get_many_related('Registration', $query_params);
520
-    }
521
-
522
-
523
-    /**
524
-     * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
525
-     * function for getting attendees and how many registrations they each have for an event)
526
-     *
527
-     * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
528
-     * @throws EE_Error
529
-     * @throws InvalidArgumentException
530
-     * @throws InvalidDataTypeException
531
-     * @throws InvalidInterfaceException
532
-     * @throws ReflectionException
533
-     */
534
-    public function attendees()
535
-    {
536
-        return $this->get_many_related('Attendee', [['Registration.Transaction.TXN_ID' => $this->ID()]]);
537
-    }
538
-
539
-
540
-    /**
541
-     * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
542
-     *
543
-     * @param array $query_params @see
544
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
545
-     * @return EE_Base_Class[]|EE_Payment[]
546
-     * @throws EE_Error
547
-     * @throws InvalidArgumentException
548
-     * @throws InvalidDataTypeException
549
-     * @throws InvalidInterfaceException
550
-     * @throws ReflectionException
551
-     */
552
-    public function payments($query_params = [])
553
-    {
554
-        return $this->get_many_related('Payment', $query_params);
555
-    }
556
-
557
-
558
-    /**
559
-     * gets only approved payments for this transaction
560
-     *
561
-     * @return EE_Base_Class[]|EE_Payment[]
562
-     * @throws EE_Error
563
-     * @throws InvalidArgumentException
564
-     * @throws ReflectionException
565
-     * @throws InvalidDataTypeException
566
-     * @throws InvalidInterfaceException
567
-     */
568
-    public function approved_payments()
569
-    {
570
-        EE_Registry::instance()->load_model('Payment');
571
-        return $this->get_many_related(
572
-            'Payment',
573
-            [
574
-                ['STS_ID' => EEM_Payment::status_id_approved],
575
-                'order_by' => ['PAY_timestamp' => 'DESC'],
576
-            ]
577
-        );
578
-    }
579
-
580
-
581
-    /**
582
-     * Gets all payments which have not been approved
583
-     *
584
-     * @return EE_Base_Class[]|EEI_Payment[]
585
-     * @throws EE_Error if a model is misconfigured somehow
586
-     * @throws InvalidArgumentException
587
-     * @throws InvalidDataTypeException
588
-     * @throws InvalidInterfaceException
589
-     * @throws ReflectionException
590
-     */
591
-    public function pending_payments()
592
-    {
593
-        return $this->get_many_related(
594
-            'Payment',
595
-            [
596
-                [
597
-                    'STS_ID' => EEM_Payment::status_id_pending,
598
-                ],
599
-                'order_by' => [
600
-                    'PAY_timestamp' => 'DESC',
601
-                ],
602
-            ]
603
-        );
604
-    }
605
-
606
-
607
-    /**
608
-     * echoes $this->pretty_status()
609
-     *
610
-     * @param bool $show_icons
611
-     * @throws EE_Error
612
-     * @throws InvalidArgumentException
613
-     * @throws InvalidDataTypeException
614
-     * @throws InvalidInterfaceException
615
-     * @throws ReflectionException
616
-     */
617
-    public function e_pretty_status($show_icons = false)
618
-    {
619
-        echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
620
-    }
621
-
622
-
623
-    /**
624
-     * returns a pretty version of the status, good for displaying to users
625
-     *
626
-     * @param bool $show_icons
627
-     * @return string
628
-     * @throws EE_Error
629
-     * @throws InvalidArgumentException
630
-     * @throws InvalidDataTypeException
631
-     * @throws InvalidInterfaceException
632
-     * @throws ReflectionException
633
-     */
634
-    public function pretty_status($show_icons = false)
635
-    {
636
-        $status = EEM_Status::instance()->localized_status(
637
-            [$this->status_ID() => esc_html__('unknown', 'event_espresso')],
638
-            false,
639
-            'sentence'
640
-        );
641
-        $icon   = '';
642
-        switch ($this->status_ID()) {
643
-            case EEM_Transaction::complete_status_code:
644
-                $icon = $show_icons
645
-                    ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>'
646
-                    : '';
647
-                break;
648
-            case EEM_Transaction::incomplete_status_code:
649
-                $icon = $show_icons
650
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
651
-                    : '';
652
-                break;
653
-            case EEM_Transaction::abandoned_status_code:
654
-                $icon = $show_icons
655
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>'
656
-                    : '';
657
-                break;
658
-            case EEM_Transaction::failed_status_code:
659
-                $icon = $show_icons
660
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
661
-                    : '';
662
-                break;
663
-            case EEM_Transaction::overpaid_status_code:
664
-                $icon = $show_icons
665
-                    ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>'
666
-                    : '';
667
-                break;
668
-        }
669
-        return $icon . $status[ $this->status_ID() ];
670
-    }
671
-
672
-
673
-    /**
674
-     * get Transaction Status
675
-     *
676
-     * @return mixed
677
-     * @throws EE_Error
678
-     * @throws InvalidArgumentException
679
-     * @throws InvalidDataTypeException
680
-     * @throws InvalidInterfaceException
681
-     * @throws ReflectionException
682
-     */
683
-    public function status_ID()
684
-    {
685
-        return $this->get('STS_ID');
686
-    }
687
-
688
-
689
-    /**
690
-     * Returns TRUE or FALSE for whether or not this transaction cost any money
691
-     *
692
-     * @return boolean
693
-     * @throws EE_Error
694
-     * @throws InvalidArgumentException
695
-     * @throws InvalidDataTypeException
696
-     * @throws InvalidInterfaceException
697
-     * @throws ReflectionException
698
-     */
699
-    public function is_free()
700
-    {
701
-        return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
702
-    }
703
-
704
-
705
-    /**
706
-     * Returns whether this transaction is complete
707
-     * Useful in templates and other logic for deciding if we should ask for another payment...
708
-     *
709
-     * @return boolean
710
-     * @throws EE_Error
711
-     * @throws InvalidArgumentException
712
-     * @throws InvalidDataTypeException
713
-     * @throws InvalidInterfaceException
714
-     * @throws ReflectionException
715
-     */
716
-    public function is_completed()
717
-    {
718
-        return $this->status_ID() === EEM_Transaction::complete_status_code;
719
-    }
720
-
721
-
722
-    /**
723
-     * Returns whether this transaction is incomplete
724
-     * Useful in templates and other logic for deciding if we should ask for another payment...
725
-     *
726
-     * @return boolean
727
-     * @throws EE_Error
728
-     * @throws InvalidArgumentException
729
-     * @throws InvalidDataTypeException
730
-     * @throws InvalidInterfaceException
731
-     * @throws ReflectionException
732
-     */
733
-    public function is_incomplete()
734
-    {
735
-        return $this->status_ID() === EEM_Transaction::incomplete_status_code;
736
-    }
737
-
738
-
739
-    /**
740
-     * Returns whether this transaction is overpaid
741
-     * Useful in templates and other logic for deciding if monies need to be refunded
742
-     *
743
-     * @return boolean
744
-     * @throws EE_Error
745
-     * @throws InvalidArgumentException
746
-     * @throws InvalidDataTypeException
747
-     * @throws InvalidInterfaceException
748
-     * @throws ReflectionException
749
-     */
750
-    public function is_overpaid()
751
-    {
752
-        return $this->status_ID() === EEM_Transaction::overpaid_status_code;
753
-    }
754
-
755
-
756
-    /**
757
-     * Returns whether this transaction was abandoned
758
-     * meaning that the transaction/registration process was somehow interrupted and never completed
759
-     * but that contact information exists for at least one registrant
760
-     *
761
-     * @return boolean
762
-     * @throws EE_Error
763
-     * @throws InvalidArgumentException
764
-     * @throws InvalidDataTypeException
765
-     * @throws InvalidInterfaceException
766
-     * @throws ReflectionException
767
-     */
768
-    public function is_abandoned()
769
-    {
770
-        return $this->status_ID() === EEM_Transaction::abandoned_status_code;
771
-    }
772
-
773
-
774
-    /**
775
-     * Returns whether this transaction failed
776
-     * meaning that the transaction/registration process was somehow interrupted and never completed
777
-     * and that NO contact information exists for any registrants
778
-     *
779
-     * @return boolean
780
-     * @throws EE_Error
781
-     * @throws InvalidArgumentException
782
-     * @throws InvalidDataTypeException
783
-     * @throws InvalidInterfaceException
784
-     * @throws ReflectionException
785
-     */
786
-    public function failed()
787
-    {
788
-        return $this->status_ID() === EEM_Transaction::failed_status_code;
789
-    }
790
-
791
-
792
-    /**
793
-     * This returns the url for the invoice of this transaction
794
-     *
795
-     * @param string $type 'html' or 'pdf' (default is pdf)
796
-     * @return string
797
-     * @throws DomainException
798
-     * @throws EE_Error
799
-     * @throws InvalidArgumentException
800
-     * @throws InvalidDataTypeException
801
-     * @throws InvalidInterfaceException
802
-     * @throws ReflectionException
803
-     */
804
-    public function invoice_url($type = 'html')
805
-    {
806
-        $REG = $this->primary_registration();
807
-        if (! $REG instanceof EE_Registration) {
808
-            return '';
809
-        }
810
-        return $REG->invoice_url($type);
811
-    }
812
-
813
-
814
-    /**
815
-     * Gets the primary registration only
816
-     *
817
-     * @return EE_Base_Class|EE_Registration
818
-     * @throws EE_Error
819
-     * @throws InvalidArgumentException
820
-     * @throws InvalidDataTypeException
821
-     * @throws InvalidInterfaceException
822
-     * @throws ReflectionException
823
-     */
824
-    public function primary_registration()
825
-    {
826
-        if ($this->_primary_registrant instanceof EE_Registration) {
827
-            return $this->_primary_registrant;
828
-        }
829
-
830
-        $registrations = (array) $this->get_many_related(
831
-            'Registration',
832
-            [['REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT]]
833
-        );
834
-        foreach ($registrations as $registration) {
835
-            // valid registration that is NOT cancelled or declined ?
836
-            if (
837
-                $registration instanceof EE_Registration
838
-                && ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
839
-            ) {
840
-                $this->_primary_registrant = $registration;
841
-                return $registration;
842
-            }
843
-        }
844
-        // nothing valid found, so just return first thing from array of results
845
-        $primary_registrant = reset($registrations);
846
-        $this->_primary_registrant = $primary_registrant instanceof EE_Registration ? $primary_registrant : null;
847
-        return $this->_primary_registrant;
848
-    }
849
-
850
-
851
-    /**
852
-     * Gets the URL for viewing the receipt
853
-     *
854
-     * @param string $type 'pdf' or 'html' (default is 'html')
855
-     * @return string
856
-     * @throws DomainException
857
-     * @throws EE_Error
858
-     * @throws InvalidArgumentException
859
-     * @throws InvalidDataTypeException
860
-     * @throws InvalidInterfaceException
861
-     * @throws ReflectionException
862
-     */
863
-    public function receipt_url($type = 'html')
864
-    {
865
-        $REG = $this->primary_registration();
866
-        if (! $REG instanceof EE_Registration) {
867
-            return '';
868
-        }
869
-        return $REG->receipt_url($type);
870
-    }
871
-
872
-
873
-    /**
874
-     * Gets the URL of the thank you page with this registration REG_url_link added as
875
-     * a query parameter
876
-     *
877
-     * @return string
878
-     * @throws EE_Error
879
-     * @throws InvalidArgumentException
880
-     * @throws InvalidDataTypeException
881
-     * @throws InvalidInterfaceException
882
-     * @throws ReflectionException
883
-     */
884
-    public function payment_overview_url()
885
-    {
886
-        $primary_registration = $this->primary_registration();
887
-        return $primary_registration instanceof EE_Registration
888
-            ? $primary_registration->payment_overview_url()
889
-            : false;
890
-    }
891
-
892
-
893
-    /**
894
-     * @return string
895
-     * @throws EE_Error
896
-     * @throws InvalidArgumentException
897
-     * @throws InvalidDataTypeException
898
-     * @throws InvalidInterfaceException
899
-     * @throws ReflectionException
900
-     */
901
-    public function gateway_response_on_transaction()
902
-    {
903
-        $payment = $this->get_first_related('Payment');
904
-        return $payment instanceof EE_Payment
905
-            ? $payment->gateway_response()
906
-            : '';
907
-    }
908
-
909
-
910
-    /**
911
-     * Get the status object of this object
912
-     *
913
-     * @return EE_Base_Class|EE_Status
914
-     * @throws EE_Error
915
-     * @throws InvalidArgumentException
916
-     * @throws InvalidDataTypeException
917
-     * @throws InvalidInterfaceException
918
-     * @throws ReflectionException
919
-     */
920
-    public function status_obj()
921
-    {
922
-        return $this->get_first_related('Status');
923
-    }
924
-
925
-
926
-    /**
927
-     * Gets all the extra meta info on this payment
928
-     *
929
-     * @param array $query_params
930
-     * @return EE_Base_Class[]|EE_Extra_Meta
931
-     * @throws EE_Error
932
-     * @throws InvalidArgumentException
933
-     * @throws InvalidDataTypeException
934
-     * @throws InvalidInterfaceException
935
-     * @throws ReflectionException
936
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
937
-     */
938
-    public function extra_meta($query_params = [])
939
-    {
940
-        return $this->get_many_related('Extra_Meta', $query_params);
941
-    }
942
-
943
-
944
-    /**
945
-     * Wrapper for _add_relation_to
946
-     *
947
-     * @param EE_Registration $registration
948
-     * @return EE_Base_Class the relation was added to
949
-     * @throws EE_Error
950
-     * @throws InvalidArgumentException
951
-     * @throws InvalidDataTypeException
952
-     * @throws InvalidInterfaceException
953
-     * @throws ReflectionException
954
-     */
955
-    public function add_registration(EE_Registration $registration)
956
-    {
957
-        return $this->_add_relation_to($registration, 'Registration');
958
-    }
959
-
960
-
961
-    /**
962
-     * Removes the given registration from being related (even before saving this transaction).
963
-     * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
964
-     *
965
-     * @param int $registration_or_id
966
-     * @return EE_Base_Class that was removed from being related
967
-     * @throws EE_Error
968
-     * @throws InvalidArgumentException
969
-     * @throws InvalidDataTypeException
970
-     * @throws InvalidInterfaceException
971
-     * @throws ReflectionException
972
-     */
973
-    public function remove_registration_with_id($registration_or_id)
974
-    {
975
-        return $this->_remove_relation_to($registration_or_id, 'Registration');
976
-    }
977
-
978
-
979
-    /**
980
-     * Gets all the line items which are for ACTUAL items
981
-     *
982
-     * @return EE_Line_Item[]
983
-     * @throws EE_Error
984
-     * @throws InvalidArgumentException
985
-     * @throws InvalidDataTypeException
986
-     * @throws InvalidInterfaceException
987
-     * @throws ReflectionException
988
-     */
989
-    public function items_purchased()
990
-    {
991
-        return $this->line_items([['LIN_type' => EEM_Line_Item::type_line_item]]);
992
-    }
993
-
994
-
995
-    /**
996
-     * Wrapper for _add_relation_to
997
-     *
998
-     * @param EE_Line_Item $line_item
999
-     * @return EE_Base_Class the relation was added to
1000
-     * @throws EE_Error
1001
-     * @throws InvalidArgumentException
1002
-     * @throws InvalidDataTypeException
1003
-     * @throws InvalidInterfaceException
1004
-     * @throws ReflectionException
1005
-     */
1006
-    public function add_line_item(EE_Line_Item $line_item)
1007
-    {
1008
-        return $this->_add_relation_to($line_item, 'Line_Item');
1009
-    }
1010
-
1011
-
1012
-    /**
1013
-     * Gets ALL the line items related to this transaction (unstructured)
1014
-     *
1015
-     * @param array $query_params
1016
-     * @return EE_Base_Class[]|EE_Line_Item[]
1017
-     * @throws EE_Error
1018
-     * @throws InvalidArgumentException
1019
-     * @throws InvalidDataTypeException
1020
-     * @throws InvalidInterfaceException
1021
-     * @throws ReflectionException
1022
-     */
1023
-    public function line_items($query_params = [])
1024
-    {
1025
-        return $this->get_many_related('Line_Item', $query_params);
1026
-    }
1027
-
1028
-
1029
-    /**
1030
-     * Gets all the line items which are taxes on the total
1031
-     *
1032
-     * @return EE_Line_Item[]
1033
-     * @throws EE_Error
1034
-     * @throws InvalidArgumentException
1035
-     * @throws InvalidDataTypeException
1036
-     * @throws InvalidInterfaceException
1037
-     * @throws ReflectionException
1038
-     */
1039
-    public function tax_items()
1040
-    {
1041
-        return $this->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1042
-    }
1043
-
1044
-
1045
-    /**
1046
-     * Gets the total line item (which is a parent of all other related line items,
1047
-     * meaning it takes them all into account on its total)
1048
-     *
1049
-     * @param bool $create_if_not_found
1050
-     * @return EE_Line_Item|null
1051
-     * @throws EE_Error
1052
-     * @throws InvalidArgumentException
1053
-     * @throws InvalidDataTypeException
1054
-     * @throws InvalidInterfaceException
1055
-     * @throws ReflectionException
1056
-     */
1057
-    public function total_line_item(bool $create_if_not_found = true): ?EE_Line_Item
1058
-    {
1059
-        $item = $this->get_first_related('Line_Item', [['LIN_type' => EEM_Line_Item::type_total]]);
1060
-        if ($item instanceof EE_Line_Item) {
1061
-            return $item;
1062
-        }
1063
-        return $create_if_not_found
1064
-            ? EEH_Line_Item::create_total_line_item($this)
1065
-            : null;
1066
-    }
1067
-
1068
-
1069
-    /**
1070
-     * Returns the total amount of tax on this transaction
1071
-     * (assumes there's only one tax subtotal line item)
1072
-     *
1073
-     * @return float
1074
-     * @throws EE_Error
1075
-     * @throws InvalidArgumentException
1076
-     * @throws InvalidDataTypeException
1077
-     * @throws InvalidInterfaceException
1078
-     * @throws ReflectionException
1079
-     */
1080
-    public function tax_total()
1081
-    {
1082
-        $tax_line_item = $this->tax_total_line_item();
1083
-        if ($tax_line_item) {
1084
-            return (float) $tax_line_item->total();
1085
-        }
1086
-        return (float) 0;
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * Gets the tax subtotal line item (assumes there's only one)
1092
-     *
1093
-     * @return EE_Line_Item
1094
-     * @throws EE_Error
1095
-     * @throws InvalidArgumentException
1096
-     * @throws InvalidDataTypeException
1097
-     * @throws InvalidInterfaceException
1098
-     * @throws ReflectionException
1099
-     */
1100
-    public function tax_total_line_item()
1101
-    {
1102
-        return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1103
-    }
1104
-
1105
-
1106
-    /**
1107
-     * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1108
-     *
1109
-     * @return EE_Form_Section_Proper|null
1110
-     * @throws EE_Error
1111
-     * @throws InvalidArgumentException
1112
-     * @throws InvalidDataTypeException
1113
-     * @throws InvalidInterfaceException
1114
-     * @throws ReflectionException
1115
-     */
1116
-    public function billing_info(): ?EE_Form_Section_Proper
1117
-    {
1118
-        $payment_method = $this->payment_method();
1119
-        if (! $payment_method) {
1120
-            EE_Error::add_error(
1121
-                esc_html__(
1122
-                    'Could not find billing info for transaction because no gateway has been used for it yet',
1123
-                    'event_espresso'
1124
-                ),
1125
-                __FILE__,
1126
-                __FUNCTION__,
1127
-                __LINE__
1128
-            );
1129
-            return null;
1130
-        }
1131
-        $primary_reg = $this->primary_registration();
1132
-        if (! $primary_reg) {
1133
-            EE_Error::add_error(
1134
-                esc_html__(
1135
-                    'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1136
-                    'event_espresso'
1137
-                ),
1138
-                __FILE__,
1139
-                __FUNCTION__,
1140
-                __LINE__
1141
-            );
1142
-            return null;
1143
-        }
1144
-        $attendee = $primary_reg->attendee();
1145
-        if (! $attendee) {
1146
-            EE_Error::add_error(
1147
-                esc_html__(
1148
-                    'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1149
-                    'event_espresso'
1150
-                ),
1151
-                __FILE__,
1152
-                __FUNCTION__,
1153
-                __LINE__
1154
-            );
1155
-            return null;
1156
-        }
1157
-        return $attendee->billing_info_for_payment_method($payment_method);
1158
-    }
1159
-
1160
-
1161
-    /**
1162
-     * Gets PMD_ID
1163
-     *
1164
-     * @return int
1165
-     * @throws EE_Error
1166
-     * @throws InvalidArgumentException
1167
-     * @throws InvalidDataTypeException
1168
-     * @throws InvalidInterfaceException
1169
-     * @throws ReflectionException
1170
-     */
1171
-    public function payment_method_ID()
1172
-    {
1173
-        return $this->get('PMD_ID');
1174
-    }
1175
-
1176
-
1177
-    /**
1178
-     * Sets PMD_ID
1179
-     *
1180
-     * @param int $PMD_ID
1181
-     * @throws EE_Error
1182
-     * @throws InvalidArgumentException
1183
-     * @throws InvalidDataTypeException
1184
-     * @throws InvalidInterfaceException
1185
-     * @throws ReflectionException
1186
-     */
1187
-    public function set_payment_method_ID($PMD_ID)
1188
-    {
1189
-        $this->set('PMD_ID', $PMD_ID);
1190
-    }
1191
-
1192
-
1193
-    /**
1194
-     * Gets the last-used payment method on this transaction
1195
-     * (we COULD just use the last-made payment, but some payment methods, namely
1196
-     * offline ones, dont' create payments)
1197
-     *
1198
-     * @return EE_Payment_Method
1199
-     * @throws EE_Error
1200
-     * @throws InvalidArgumentException
1201
-     * @throws InvalidDataTypeException
1202
-     * @throws InvalidInterfaceException
1203
-     * @throws ReflectionException
1204
-     */
1205
-    public function payment_method()
1206
-    {
1207
-        $PMD_ID = $this->payment_method_ID();
1208
-        if($PMD_ID) {
1209
-            $pm = EEM_Payment_Method::instance()->get_one_by_ID($this->payment_method_ID());
1210
-            if ($pm instanceof EE_Payment_Method) {
1211
-                return $pm;
1212
-            }
1213
-        }
1214
-        $last_payment = $this->last_payment();
1215
-        if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1216
-            return $last_payment->payment_method();
1217
-        }
1218
-        return null;
1219
-    }
1220
-
1221
-
1222
-    /**
1223
-     * Gets the last payment made
1224
-     *
1225
-     * @return EE_Base_Class|EE_Payment|null
1226
-     * @throws EE_Error
1227
-     * @throws InvalidArgumentException
1228
-     * @throws InvalidDataTypeException
1229
-     * @throws InvalidInterfaceException
1230
-     * @throws ReflectionException
1231
-     */
1232
-    public function last_payment(): ?EE_Payment
1233
-    {
1234
-        return $this->get_first_related('Payment', ['order_by' => ['PAY_ID' => 'desc']]);
1235
-    }
1236
-
1237
-
1238
-    /**
1239
-     * Gets all the line items which are unrelated to tickets on this transaction
1240
-     *
1241
-     * @return EE_Line_Item[]
1242
-     * @throws EE_Error
1243
-     * @throws InvalidArgumentException
1244
-     * @throws InvalidDataTypeException
1245
-     * @throws InvalidInterfaceException
1246
-     * @throws ReflectionException
1247
-     */
1248
-    public function non_ticket_line_items()
1249
-    {
1250
-        return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1251
-    }
1252
-
1253
-
1254
-    /**
1255
-     * possibly toggles TXN status
1256
-     *
1257
-     * @param boolean $update whether to save the TXN
1258
-     * @return bool whether the TXN was saved
1259
-     * @throws EE_Error
1260
-     * @throws InvalidArgumentException
1261
-     * @throws InvalidDataTypeException
1262
-     * @throws InvalidInterfaceException
1263
-     * @throws ReflectionException
1264
-     * @throws RuntimeException
1265
-     */
1266
-    public function update_status_based_on_total_paid($update = true)
1267
-    {
1268
-        // set transaction status based on comparison of TXN_paid vs TXN_total
1269
-        if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1270
-            $new_txn_status = EEM_Transaction::overpaid_status_code;
1271
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1272
-            $new_txn_status = EEM_Transaction::complete_status_code;
1273
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1274
-            $new_txn_status = EEM_Transaction::incomplete_status_code;
1275
-        } else {
1276
-            throw new RuntimeException(
1277
-                esc_html__('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1278
-            );
1279
-        }
1280
-        if ($new_txn_status !== $this->status_ID()) {
1281
-            $this->set_status($new_txn_status);
1282
-            if ($update) {
1283
-                return (bool) $this->save();
1284
-            }
1285
-        }
1286
-        return false;
1287
-    }
1288
-
1289
-
1290
-    /**
1291
-     * Updates the transaction's status and total_paid based on all the payments
1292
-     * that apply to it
1293
-     *
1294
-     * @return array|bool
1295
-     * @throws EE_Error
1296
-     * @throws InvalidArgumentException
1297
-     * @throws ReflectionException
1298
-     * @throws InvalidDataTypeException
1299
-     * @throws InvalidInterfaceException
1300
-     * @deprecated
1301
-     */
1302
-    public function update_based_on_payments()
1303
-    {
1304
-        EE_Error::doing_it_wrong(
1305
-            __CLASS__ . '::' . __FUNCTION__,
1306
-            sprintf(
1307
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1308
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1309
-            ),
1310
-            '4.6.0'
1311
-        );
1312
-        /** @type EE_Transaction_Processor $transaction_processor */
1313
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1314
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1315
-    }
1316
-
1317
-
1318
-    /**
1319
-     * @return string
1320
-     */
1321
-    public function old_txn_status()
1322
-    {
1323
-        return $this->_old_txn_status;
1324
-    }
1325
-
1326
-
1327
-    /**
1328
-     * @param string $old_txn_status
1329
-     */
1330
-    public function set_old_txn_status($old_txn_status)
1331
-    {
1332
-        // only set the first time
1333
-        if ($this->_old_txn_status === null) {
1334
-            $this->_old_txn_status = $old_txn_status;
1335
-        }
1336
-    }
1337
-
1338
-
1339
-    /**
1340
-     * reg_status_updated
1341
-     *
1342
-     * @return bool
1343
-     * @throws EE_Error
1344
-     * @throws InvalidArgumentException
1345
-     * @throws InvalidDataTypeException
1346
-     * @throws InvalidInterfaceException
1347
-     * @throws ReflectionException
1348
-     */
1349
-    public function txn_status_updated()
1350
-    {
1351
-        return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1352
-    }
1353
-
1354
-
1355
-    /**
1356
-     * _reg_steps_completed
1357
-     * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1358
-     * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1359
-     * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1360
-     *
1361
-     * @param string $reg_step_slug
1362
-     * @param bool   $check_all
1363
-     * @return bool|int
1364
-     * @throws EE_Error
1365
-     * @throws InvalidArgumentException
1366
-     * @throws InvalidDataTypeException
1367
-     * @throws InvalidInterfaceException
1368
-     * @throws ReflectionException
1369
-     */
1370
-    private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1371
-    {
1372
-        $reg_steps = $this->reg_steps();
1373
-        if (! is_array($reg_steps) || empty($reg_steps)) {
1374
-            return false;
1375
-        }
1376
-        // loop thru reg steps array)
1377
-        foreach ($reg_steps as $slug => $reg_step_completed) {
1378
-            // if NOT checking ALL steps (only checking one step)
1379
-            if (! $check_all) {
1380
-                // and this is the one
1381
-                if ($slug === $reg_step_slug) {
1382
-                    return $reg_step_completed;
1383
-                }
1384
-                // skip to next reg step in loop
1385
-                continue;
1386
-            }
1387
-            // $check_all must be true, else we would never have gotten to this point
1388
-            if ($slug === $reg_step_slug) {
1389
-                // if we reach this point, then we are testing either:
1390
-                // all_reg_steps_completed_except() or
1391
-                // all_reg_steps_completed_except_final_step(),
1392
-                // and since this is the reg step EXCEPTION being tested
1393
-                // we want to return true (yes true) if this reg step is NOT completed
1394
-                // ie: "is everything completed except the final step?"
1395
-                // "that is correct... the final step is not completed, but all others are."
1396
-                return $reg_step_completed !== true;
1397
-            }
1398
-            if ($reg_step_completed !== true) {
1399
-                // if any reg step is NOT completed, then ALL steps are not completed
1400
-                return false;
1401
-            }
1402
-        }
1403
-        return true;
1404
-    }
1405
-
1406
-
1407
-    /**
1408
-     * all_reg_steps_completed
1409
-     * returns:
1410
-     *    true if ALL reg steps have been marked as completed
1411
-     *        or false if any step is not completed
1412
-     *
1413
-     * @return bool
1414
-     * @throws EE_Error
1415
-     * @throws InvalidArgumentException
1416
-     * @throws InvalidDataTypeException
1417
-     * @throws InvalidInterfaceException
1418
-     * @throws ReflectionException
1419
-     */
1420
-    public function all_reg_steps_completed()
1421
-    {
1422
-        return $this->_reg_steps_completed();
1423
-    }
1424
-
1425
-
1426
-    /**
1427
-     * all_reg_steps_completed_except
1428
-     * returns:
1429
-     *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1430
-     *        or false if any other step is not completed
1431
-     *        or false if ALL steps are completed including the exception you are testing !!!
1432
-     *
1433
-     * @param string $exception
1434
-     * @return bool
1435
-     * @throws EE_Error
1436
-     * @throws InvalidArgumentException
1437
-     * @throws InvalidDataTypeException
1438
-     * @throws InvalidInterfaceException
1439
-     * @throws ReflectionException
1440
-     */
1441
-    public function all_reg_steps_completed_except($exception = '')
1442
-    {
1443
-        return $this->_reg_steps_completed($exception);
1444
-    }
1445
-
1446
-
1447
-    /**
1448
-     * all_reg_steps_completed_except
1449
-     * returns:
1450
-     *        true if ALL reg steps, except the final step, have been marked as completed
1451
-     *        or false if any step is not completed
1452
-     *    or false if ALL steps are completed including the final step !!!
1453
-     *
1454
-     * @return bool
1455
-     * @throws EE_Error
1456
-     * @throws InvalidArgumentException
1457
-     * @throws InvalidDataTypeException
1458
-     * @throws InvalidInterfaceException
1459
-     * @throws ReflectionException
1460
-     */
1461
-    public function all_reg_steps_completed_except_final_step()
1462
-    {
1463
-        return $this->_reg_steps_completed('finalize_registration');
1464
-    }
1465
-
1466
-
1467
-    /**
1468
-     * reg_step_completed
1469
-     * returns:
1470
-     *    true if a specific reg step has been marked as completed
1471
-     *    a Unix timestamp if it has been initialized but not yet completed,
1472
-     *    or false if it has not yet been initialized
1473
-     *
1474
-     * @param string $reg_step_slug
1475
-     * @return bool|int
1476
-     * @throws EE_Error
1477
-     * @throws InvalidArgumentException
1478
-     * @throws InvalidDataTypeException
1479
-     * @throws InvalidInterfaceException
1480
-     * @throws ReflectionException
1481
-     */
1482
-    public function reg_step_completed($reg_step_slug)
1483
-    {
1484
-        return $this->_reg_steps_completed($reg_step_slug, false);
1485
-    }
1486
-
1487
-
1488
-    /**
1489
-     * completed_final_reg_step
1490
-     * returns:
1491
-     *    true if the finalize_registration reg step has been marked as completed
1492
-     *    a Unix timestamp if it has been initialized but not yet completed,
1493
-     *    or false if it has not yet been initialized
1494
-     *
1495
-     * @return bool|int
1496
-     * @throws EE_Error
1497
-     * @throws InvalidArgumentException
1498
-     * @throws InvalidDataTypeException
1499
-     * @throws InvalidInterfaceException
1500
-     * @throws ReflectionException
1501
-     */
1502
-    public function final_reg_step_completed()
1503
-    {
1504
-        return $this->_reg_steps_completed('finalize_registration', false);
1505
-    }
1506
-
1507
-
1508
-    /**
1509
-     * set_reg_step_initiated
1510
-     * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1511
-     *
1512
-     * @param string $reg_step_slug
1513
-     * @return boolean
1514
-     * @throws EE_Error
1515
-     * @throws InvalidArgumentException
1516
-     * @throws InvalidDataTypeException
1517
-     * @throws InvalidInterfaceException
1518
-     * @throws ReflectionException
1519
-     */
1520
-    public function set_reg_step_initiated($reg_step_slug)
1521
-    {
1522
-        return $this->_set_reg_step_completed_status($reg_step_slug, time());
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * set_reg_step_completed
1528
-     * given a valid TXN_reg_step, this sets the step as completed
1529
-     *
1530
-     * @param string $reg_step_slug
1531
-     * @return boolean
1532
-     * @throws EE_Error
1533
-     * @throws InvalidArgumentException
1534
-     * @throws InvalidDataTypeException
1535
-     * @throws InvalidInterfaceException
1536
-     * @throws ReflectionException
1537
-     */
1538
-    public function set_reg_step_completed($reg_step_slug)
1539
-    {
1540
-        return $this->_set_reg_step_completed_status($reg_step_slug, true);
1541
-    }
1542
-
1543
-
1544
-    /**
1545
-     * set_reg_step_completed
1546
-     * given a valid TXN_reg_step slug, this sets the step as NOT completed
1547
-     *
1548
-     * @param string $reg_step_slug
1549
-     * @return boolean
1550
-     * @throws EE_Error
1551
-     * @throws InvalidArgumentException
1552
-     * @throws InvalidDataTypeException
1553
-     * @throws InvalidInterfaceException
1554
-     * @throws ReflectionException
1555
-     */
1556
-    public function set_reg_step_not_completed($reg_step_slug)
1557
-    {
1558
-        return $this->_set_reg_step_completed_status($reg_step_slug, false);
1559
-    }
1560
-
1561
-
1562
-    /**
1563
-     * set_reg_step_completed
1564
-     * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1565
-     *
1566
-     * @param string      $reg_step_slug
1567
-     * @param boolean|int $status
1568
-     * @return boolean
1569
-     * @throws EE_Error
1570
-     * @throws InvalidArgumentException
1571
-     * @throws InvalidDataTypeException
1572
-     * @throws InvalidInterfaceException
1573
-     * @throws ReflectionException
1574
-     */
1575
-    private function _set_reg_step_completed_status($reg_step_slug, $status)
1576
-    {
1577
-        // validate status
1578
-        $status = is_bool($status) || is_int($status)
1579
-            ? $status
1580
-            : false;
1581
-        // get reg steps array
1582
-        $txn_reg_steps = $this->reg_steps();
1583
-        // if reg step does NOT exist
1584
-        if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1585
-            return false;
1586
-        }
1587
-        // if  we're trying to complete a step that is already completed
1588
-        if ($txn_reg_steps[ $reg_step_slug ] === true) {
1589
-            return true;
1590
-        }
1591
-        // if  we're trying to complete a step that hasn't even started
1592
-        if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1593
-            return false;
1594
-        }
1595
-        // if current status value matches the incoming value (no change)
1596
-        // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1597
-        if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1598
-            // this will happen in cases where multiple AJAX requests occur during the same step
1599
-            return true;
1600
-        }
1601
-        // if we're trying to set a start time, but it has already been set...
1602
-        if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1603
-            // skip the update below, but don't return FALSE so that errors won't be displayed
1604
-            return true;
1605
-        }
1606
-        // update completed status
1607
-        $txn_reg_steps[ $reg_step_slug ] = $status;
1608
-        $this->set_reg_steps($txn_reg_steps);
1609
-        $this->save();
1610
-        return true;
1611
-    }
1612
-
1613
-
1614
-    /**
1615
-     * remove_reg_step
1616
-     * given a valid TXN_reg_step slug, this will remove (unset)
1617
-     * the reg step from the TXN reg step array
1618
-     *
1619
-     * @param string $reg_step_slug
1620
-     * @return void
1621
-     * @throws EE_Error
1622
-     * @throws InvalidArgumentException
1623
-     * @throws InvalidDataTypeException
1624
-     * @throws InvalidInterfaceException
1625
-     * @throws ReflectionException
1626
-     */
1627
-    public function remove_reg_step($reg_step_slug)
1628
-    {
1629
-        // get reg steps array
1630
-        $txn_reg_steps = $this->reg_steps();
1631
-        unset($txn_reg_steps[ $reg_step_slug ]);
1632
-        $this->set_reg_steps($txn_reg_steps);
1633
-    }
1634
-
1635
-
1636
-    /**
1637
-     * toggle_failed_transaction_status
1638
-     * upgrades a TXNs status from failed to abandoned,
1639
-     * meaning that contact information has been captured for at least one registrant
1640
-     *
1641
-     * @param bool $save
1642
-     * @return bool
1643
-     * @throws EE_Error
1644
-     * @throws InvalidArgumentException
1645
-     * @throws InvalidDataTypeException
1646
-     * @throws InvalidInterfaceException
1647
-     * @throws ReflectionException
1648
-     */
1649
-    public function toggle_failed_transaction_status($save = true)
1650
-    {
1651
-        // if TXN status is still set as "failed"...
1652
-        if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1653
-            $this->set_status(EEM_Transaction::abandoned_status_code);
1654
-            if ($save) {
1655
-                $this->save();
1656
-            }
1657
-            return true;
1658
-        }
1659
-        return false;
1660
-    }
1661
-
1662
-
1663
-    /**
1664
-     * toggle_abandoned_transaction_status
1665
-     * upgrades a TXNs status from failed or abandoned to incomplete
1666
-     *
1667
-     * @return bool
1668
-     * @throws EE_Error
1669
-     * @throws InvalidArgumentException
1670
-     * @throws InvalidDataTypeException
1671
-     * @throws InvalidInterfaceException
1672
-     * @throws ReflectionException
1673
-     */
1674
-    public function toggle_abandoned_transaction_status()
1675
-    {
1676
-        // if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1677
-        $txn_status = $this->status_ID();
1678
-        if (
1679
-            $txn_status === EEM_Transaction::failed_status_code
1680
-            || $txn_status === EEM_Transaction::abandoned_status_code
1681
-        ) {
1682
-            // if a contact record for the primary registrant has been created
1683
-            if (
1684
-                $this->primary_registration() instanceof EE_Registration
1685
-                && $this->primary_registration()->attendee() instanceof EE_Attendee
1686
-            ) {
1687
-                $this->set_status(EEM_Transaction::incomplete_status_code);
1688
-            } else {
1689
-                // no contact record? yer abandoned!
1690
-                $this->set_status(EEM_Transaction::abandoned_status_code);
1691
-            }
1692
-            return true;
1693
-        }
1694
-        return false;
1695
-    }
1696
-
1697
-
1698
-    /**
1699
-     * checks if an Abandoned TXN has any related payments, and if so,
1700
-     * updates the TXN status based on the amount paid
1701
-     *
1702
-     * @throws EE_Error
1703
-     * @throws InvalidArgumentException
1704
-     * @throws InvalidDataTypeException
1705
-     * @throws InvalidInterfaceException
1706
-     * @throws ReflectionException
1707
-     * @throws RuntimeException
1708
-     * @throws ReflectionException
1709
-     */
1710
-    public function verify_abandoned_transaction_status()
1711
-    {
1712
-        if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1713
-            return;
1714
-        }
1715
-        $payments = $this->get_many_related('Payment');
1716
-        if (! empty($payments)) {
1717
-            foreach ($payments as $payment) {
1718
-                if ($payment instanceof EE_Payment) {
1719
-                    // kk this TXN should NOT be abandoned
1720
-                    $this->update_status_based_on_total_paid();
1721
-                    if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1722
-                        EE_Error::add_attention(
1723
-                            sprintf(
1724
-                                esc_html__(
1725
-                                    'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1726
-                                    'event_espresso'
1727
-                                ),
1728
-                                $this->ID(),
1729
-                                $this->pretty_status()
1730
-                            )
1731
-                        );
1732
-                    }
1733
-                    // get final reg step status
1734
-                    $finalized = $this->final_reg_step_completed();
1735
-                    // if the 'finalize_registration' step has been initiated (has a timestamp)
1736
-                    // but has not yet been fully completed (TRUE)
1737
-                    if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1738
-                        $this->set_reg_step_completed('finalize_registration');
1739
-                        $this->save();
1740
-                    }
1741
-                }
1742
-            }
1743
-        }
1744
-    }
1745
-
1746
-
1747
-    /**
1748
-     * @throws EE_Error
1749
-     * @throws InvalidArgumentException
1750
-     * @throws InvalidDataTypeException
1751
-     * @throws InvalidInterfaceException
1752
-     * @throws ReflectionException
1753
-     * @throws RuntimeException
1754
-     * @since 4.10.4.p
1755
-     */
1756
-    public function recalculateLineItems()
1757
-    {
1758
-        $total_line_item = $this->total_line_item(false);
1759
-        if ($total_line_item instanceof EE_Line_Item) {
1760
-            EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1761
-            return EEH_Line_Item::apply_taxes($total_line_item, true);
1762
-        }
1763
-        return false;
1764
-    }
16
+	/**
17
+	 * The length of time in seconds that a lock is applied before being considered expired.
18
+	 * It is not long because a transaction should only be locked for the duration of the request that locked it
19
+	 */
20
+	const LOCK_EXPIRATION = 2;
21
+
22
+	/**
23
+	 * txn status upon initial construction.
24
+	 *
25
+	 * @var string
26
+	 */
27
+	protected $_old_txn_status;
28
+
29
+	private ?EE_Registration $_primary_registrant = null;
30
+
31
+	/**
32
+	 * @param array  $props_n_values          incoming values
33
+	 * @param string $timezone                incoming timezone
34
+	 *                                        (if not set the timezone set for the website will be used.)
35
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
36
+	 *                                        date_format and the second value is the time format
37
+	 * @return EE_Transaction
38
+	 * @throws EE_Error
39
+	 * @throws InvalidArgumentException
40
+	 * @throws InvalidDataTypeException
41
+	 * @throws InvalidInterfaceException
42
+	 * @throws ReflectionException
43
+	 */
44
+	public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
45
+	{
46
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
47
+		$txn        = $has_object
48
+			? $has_object
49
+			: new self($props_n_values, false, $timezone, $date_formats);
50
+		if (! $has_object) {
51
+			$txn->set_old_txn_status($txn->status_ID());
52
+		}
53
+		return $txn;
54
+	}
55
+
56
+
57
+	/**
58
+	 * @param array  $props_n_values  incoming values from the database
59
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
60
+	 *                                the website will be used.
61
+	 * @return EE_Transaction
62
+	 * @throws EE_Error
63
+	 * @throws InvalidArgumentException
64
+	 * @throws InvalidDataTypeException
65
+	 * @throws InvalidInterfaceException
66
+	 * @throws ReflectionException
67
+	 */
68
+	public static function new_instance_from_db($props_n_values = [], $timezone = '')
69
+	{
70
+		$txn = new self($props_n_values, true, $timezone);
71
+		$txn->set_old_txn_status($txn->status_ID());
72
+		return $txn;
73
+	}
74
+
75
+
76
+	/**
77
+	 * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
78
+	 * If a lock has already been set, then we will attempt to remove it in case it has expired.
79
+	 * If that also fails, then an exception is thrown.
80
+	 *
81
+	 * @throws EE_Error
82
+	 * @throws InvalidArgumentException
83
+	 * @throws InvalidDataTypeException
84
+	 * @throws InvalidInterfaceException
85
+	 * @throws ReflectionException
86
+	 */
87
+	public function lock()
88
+	{
89
+		// attempt to set lock, but if that fails...
90
+		if (! $this->add_extra_meta('lock', time(), true)) {
91
+			// then attempt to remove the lock in case it is expired
92
+			if ($this->_remove_expired_lock()) {
93
+				// if removal was successful, then try setting lock again
94
+				$this->lock();
95
+			} else {
96
+				// but if the lock can not be removed, then throw an exception
97
+				throw new EE_Error(
98
+					sprintf(
99
+						esc_html__(
100
+							'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
101
+							'event_espresso'
102
+						),
103
+						$this->ID()
104
+					)
105
+				);
106
+			}
107
+		}
108
+	}
109
+
110
+
111
+	/**
112
+	 * removes transaction lock applied in EE_Transaction::lock()
113
+	 *
114
+	 * @return int
115
+	 * @throws EE_Error
116
+	 * @throws InvalidArgumentException
117
+	 * @throws InvalidDataTypeException
118
+	 * @throws InvalidInterfaceException
119
+	 * @throws ReflectionException
120
+	 */
121
+	public function unlock()
122
+	{
123
+		return $this->delete_extra_meta('lock');
124
+	}
125
+
126
+
127
+	/**
128
+	 * Decides whether or not now is the right time to update the transaction.
129
+	 * This is useful because we don't always know if it is safe to update the transaction
130
+	 * and its related data. why?
131
+	 * because it's possible that the transaction is being used in another
132
+	 * request and could overwrite anything we save.
133
+	 * So we want to only update the txn once we know that won't happen.
134
+	 * We also check that the lock isn't expired, and remove it if it is
135
+	 *
136
+	 * @return boolean
137
+	 * @throws EE_Error
138
+	 * @throws InvalidArgumentException
139
+	 * @throws InvalidDataTypeException
140
+	 * @throws InvalidInterfaceException
141
+	 * @throws ReflectionException
142
+	 */
143
+	public function is_locked()
144
+	{
145
+		// if TXN is not locked, then return false immediately
146
+		if (! $this->_get_lock()) {
147
+			return false;
148
+		}
149
+		// if not, then let's try and remove the lock in case it's expired...
150
+		// _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
151
+		// and a positive number if the lock was removed (ie: number of locks deleted),
152
+		// so we need to return the opposite
153
+		return ! $this->_remove_expired_lock();
154
+	}
155
+
156
+
157
+	/**
158
+	 * Gets the meta field indicating that this TXN is locked
159
+	 *
160
+	 * @return int
161
+	 * @throws EE_Error
162
+	 * @throws InvalidArgumentException
163
+	 * @throws InvalidDataTypeException
164
+	 * @throws InvalidInterfaceException
165
+	 * @throws ReflectionException
166
+	 */
167
+	protected function _get_lock()
168
+	{
169
+		return (int) $this->get_extra_meta('lock', true, 0);
170
+	}
171
+
172
+
173
+	/**
174
+	 * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
175
+	 *
176
+	 * @return int
177
+	 * @throws EE_Error
178
+	 * @throws InvalidArgumentException
179
+	 * @throws InvalidDataTypeException
180
+	 * @throws InvalidInterfaceException
181
+	 * @throws ReflectionException
182
+	 */
183
+	protected function _remove_expired_lock()
184
+	{
185
+		$locked = $this->_get_lock();
186
+		if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
187
+			return $this->unlock();
188
+		}
189
+		return 0;
190
+	}
191
+
192
+
193
+	/**
194
+	 * Set transaction total
195
+	 *
196
+	 * @param float $total total value of transaction
197
+	 * @throws EE_Error
198
+	 * @throws InvalidArgumentException
199
+	 * @throws InvalidDataTypeException
200
+	 * @throws InvalidInterfaceException
201
+	 * @throws ReflectionException
202
+	 */
203
+	public function set_total($total = 0.00)
204
+	{
205
+		$this->set('TXN_total', (float) $total);
206
+	}
207
+
208
+
209
+	/**
210
+	 * Set Total Amount Paid to Date
211
+	 *
212
+	 * @param float $total_paid total amount paid to date (sum of all payments)
213
+	 * @throws EE_Error
214
+	 * @throws InvalidArgumentException
215
+	 * @throws InvalidDataTypeException
216
+	 * @throws InvalidInterfaceException
217
+	 * @throws ReflectionException
218
+	 */
219
+	public function set_paid($total_paid = 0.00)
220
+	{
221
+		$this->set('TXN_paid', (float) $total_paid);
222
+	}
223
+
224
+
225
+	/**
226
+	 * Set transaction status
227
+	 *
228
+	 * @param string $status        whether the transaction is open, declined, accepted,
229
+	 *                              or any number of custom values that can be set
230
+	 * @throws EE_Error
231
+	 * @throws InvalidArgumentException
232
+	 * @throws InvalidDataTypeException
233
+	 * @throws InvalidInterfaceException
234
+	 * @throws ReflectionException
235
+	 */
236
+	public function set_status($status = '')
237
+	{
238
+		$this->set('STS_ID', $status);
239
+	}
240
+
241
+
242
+	/**
243
+	 * Set hash salt
244
+	 *
245
+	 * @param string $hash_salt required for some payment gateways
246
+	 * @throws EE_Error
247
+	 * @throws InvalidArgumentException
248
+	 * @throws InvalidDataTypeException
249
+	 * @throws InvalidInterfaceException
250
+	 * @throws ReflectionException
251
+	 */
252
+	public function set_hash_salt($hash_salt = '')
253
+	{
254
+		$this->set('TXN_hash_salt', $hash_salt);
255
+	}
256
+
257
+
258
+	/**
259
+	 * Sets TXN_reg_steps array
260
+	 *
261
+	 * @param array $txn_reg_steps
262
+	 * @throws EE_Error
263
+	 * @throws InvalidArgumentException
264
+	 * @throws InvalidDataTypeException
265
+	 * @throws InvalidInterfaceException
266
+	 * @throws ReflectionException
267
+	 */
268
+	public function set_reg_steps(array $txn_reg_steps)
269
+	{
270
+		$this->set('TXN_reg_steps', $txn_reg_steps);
271
+	}
272
+
273
+
274
+	/**
275
+	 * Gets TXN_reg_steps
276
+	 *
277
+	 * @return array
278
+	 * @throws EE_Error
279
+	 * @throws InvalidArgumentException
280
+	 * @throws InvalidDataTypeException
281
+	 * @throws InvalidInterfaceException
282
+	 * @throws ReflectionException
283
+	 */
284
+	public function reg_steps()
285
+	{
286
+		$TXN_reg_steps = $this->get('TXN_reg_steps');
287
+		return is_array($TXN_reg_steps)
288
+			? $TXN_reg_steps
289
+			: [];
290
+	}
291
+
292
+
293
+	/**
294
+	 * @param string|null $schema
295
+	 *     Schemas:
296
+	 *     'localized_float': "3,023.00"
297
+	 *     'no_currency_code': "$3,023.00"
298
+	 *     null: "$3,023.00<span>USD</span>"
299
+	 * @return string of transaction's total cost, with currency symbol and decimal
300
+	 * @throws EE_Error
301
+	 * @throws InvalidArgumentException
302
+	 * @throws InvalidDataTypeException
303
+	 * @throws InvalidInterfaceException
304
+	 * @throws ReflectionException
305
+	 */
306
+	public function pretty_total(?string $schema = null)
307
+	{
308
+		return $this->get_pretty('TXN_total', $schema);
309
+	}
310
+
311
+
312
+	/**
313
+	 * Gets the amount paid in a pretty string (formatted and with currency symbol)
314
+	 *
315
+	 * @param string|null $schema
316
+	 *     Schemas:
317
+	 *     'localized_float': "3,023.00"
318
+	 *     'no_currency_code': "$3,023.00"
319
+	 *     null: "$3,023.00<span>USD</span>"
320
+	 * @return string
321
+	 * @throws EE_Error
322
+	 * @throws InvalidArgumentException
323
+	 * @throws InvalidDataTypeException
324
+	 * @throws InvalidInterfaceException
325
+	 * @throws ReflectionException
326
+	 */
327
+	public function pretty_paid(?string $schema = null)
328
+	{
329
+		return $this->get_pretty('TXN_paid', $schema);
330
+	}
331
+
332
+
333
+	/**
334
+	 * calculate the amount remaining for this transaction and return;
335
+	 *
336
+	 * @return float amount remaining
337
+	 * @throws EE_Error
338
+	 * @throws InvalidArgumentException
339
+	 * @throws InvalidDataTypeException
340
+	 * @throws InvalidInterfaceException
341
+	 * @throws ReflectionException
342
+	 */
343
+	public function remaining()
344
+	{
345
+		return $this->total() - $this->paid();
346
+	}
347
+
348
+
349
+	/**
350
+	 * get Transaction Total
351
+	 *
352
+	 * @return float
353
+	 * @throws EE_Error
354
+	 * @throws InvalidArgumentException
355
+	 * @throws InvalidDataTypeException
356
+	 * @throws InvalidInterfaceException
357
+	 * @throws ReflectionException
358
+	 */
359
+	public function total()
360
+	{
361
+		return (float) $this->get('TXN_total');
362
+	}
363
+
364
+
365
+	/**
366
+	 * get Total Amount Paid to Date
367
+	 *
368
+	 * @return float
369
+	 * @throws EE_Error
370
+	 * @throws InvalidArgumentException
371
+	 * @throws InvalidDataTypeException
372
+	 * @throws InvalidInterfaceException
373
+	 * @throws ReflectionException
374
+	 */
375
+	public function paid()
376
+	{
377
+		return (float) $this->get('TXN_paid');
378
+	}
379
+
380
+
381
+	/**
382
+	 * @return mixed|null
383
+	 * @throws EE_Error
384
+	 * @throws InvalidArgumentException
385
+	 * @throws InvalidDataTypeException
386
+	 * @throws InvalidInterfaceException
387
+	 * @throws ReflectionException
388
+	 */
389
+	public function get_cart_session()
390
+	{
391
+		$session_data = (array) $this->get('TXN_session_data');
392
+		return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
393
+			? $session_data['cart']
394
+			: null;
395
+	}
396
+
397
+
398
+	/**
399
+	 * get Transaction session data
400
+	 *
401
+	 * @return array|mixed
402
+	 * @throws EE_Error
403
+	 * @throws InvalidArgumentException
404
+	 * @throws InvalidDataTypeException
405
+	 * @throws InvalidInterfaceException
406
+	 * @throws ReflectionException
407
+	 */
408
+	public function session_data()
409
+	{
410
+		$session_data = $this->get('TXN_session_data');
411
+		if (empty($session_data)) {
412
+			$session_data = [
413
+				'id'            => null,
414
+				'user_id'       => null,
415
+				'ip_address'    => null,
416
+				'user_agent'    => null,
417
+				'init_access'   => null,
418
+				'last_access'   => null,
419
+				'pages_visited' => [],
420
+			];
421
+		}
422
+		return $session_data;
423
+	}
424
+
425
+
426
+	/**
427
+	 * Set session data within the TXN object
428
+	 *
429
+	 * @param EE_Session|array|null $session_data
430
+	 * @throws EE_Error
431
+	 * @throws InvalidArgumentException
432
+	 * @throws InvalidDataTypeException
433
+	 * @throws InvalidInterfaceException
434
+	 * @throws ReflectionException
435
+	 */
436
+	public function set_txn_session_data($session_data)
437
+	{
438
+		if ($session_data instanceof EE_Session) {
439
+			$this->set('TXN_session_data', $session_data->get_session_data(null, true));
440
+		} else {
441
+			$this->set('TXN_session_data', $session_data);
442
+		}
443
+	}
444
+
445
+
446
+	/**
447
+	 * get Transaction hash salt
448
+	 *
449
+	 * @return mixed
450
+	 * @throws EE_Error
451
+	 * @throws InvalidArgumentException
452
+	 * @throws InvalidDataTypeException
453
+	 * @throws InvalidInterfaceException
454
+	 * @throws ReflectionException
455
+	 */
456
+	public function hash_salt_()
457
+	{
458
+		return $this->get('TXN_hash_salt');
459
+	}
460
+
461
+
462
+	/**
463
+	 * Returns the transaction datetime as either:
464
+	 *            - unix timestamp format ($format = false, $gmt = true)
465
+	 *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
466
+	 *              has no affect with this option)), this also may include a timezone abbreviation if the
467
+	 *              set timezone in this class differs from what the timezone is on the blog.
468
+	 *            - formatted date string including the UTC (timezone) offset (default).
469
+	 *
470
+	 * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
471
+	 * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
472
+	 *                          or no UTC offset applied
473
+	 * @return string | int
474
+	 * @throws EE_Error
475
+	 * @throws InvalidArgumentException
476
+	 * @throws InvalidDataTypeException
477
+	 * @throws InvalidInterfaceException
478
+	 * @throws ReflectionException
479
+	 */
480
+	public function datetime($format = false, $gmt = false)
481
+	{
482
+		if ($format) {
483
+			return $this->get_pretty('TXN_timestamp');
484
+		}
485
+		if ($gmt) {
486
+			return $this->get_raw('TXN_timestamp');
487
+		}
488
+		return $this->get('TXN_timestamp');
489
+	}
490
+
491
+
492
+	/**
493
+	 * Gets registrations on this transaction
494
+	 *
495
+	 * @param array   $query_params array of query parameters
496
+	 * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
497
+	 * @return EE_Base_Class[]|EE_Registration[]
498
+	 * @throws EE_Error
499
+	 * @throws InvalidArgumentException
500
+	 * @throws InvalidDataTypeException
501
+	 * @throws InvalidInterfaceException
502
+	 * @throws ReflectionException
503
+	 */
504
+	public function registrations($query_params = [], $get_cached = false)
505
+	{
506
+		$query_params = (empty($query_params) || ! is_array($query_params))
507
+			? [
508
+				'order_by' => [
509
+					'Event.EVT_name'     => 'ASC',
510
+					'Attendee.ATT_lname' => 'ASC',
511
+					'Attendee.ATT_fname' => 'ASC',
512
+					'REG_ID'             => 'ASC',
513
+				],
514
+			]
515
+			: $query_params;
516
+		$query_params = $get_cached
517
+			? []
518
+			: $query_params;
519
+		return $this->get_many_related('Registration', $query_params);
520
+	}
521
+
522
+
523
+	/**
524
+	 * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
525
+	 * function for getting attendees and how many registrations they each have for an event)
526
+	 *
527
+	 * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
528
+	 * @throws EE_Error
529
+	 * @throws InvalidArgumentException
530
+	 * @throws InvalidDataTypeException
531
+	 * @throws InvalidInterfaceException
532
+	 * @throws ReflectionException
533
+	 */
534
+	public function attendees()
535
+	{
536
+		return $this->get_many_related('Attendee', [['Registration.Transaction.TXN_ID' => $this->ID()]]);
537
+	}
538
+
539
+
540
+	/**
541
+	 * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
542
+	 *
543
+	 * @param array $query_params @see
544
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
545
+	 * @return EE_Base_Class[]|EE_Payment[]
546
+	 * @throws EE_Error
547
+	 * @throws InvalidArgumentException
548
+	 * @throws InvalidDataTypeException
549
+	 * @throws InvalidInterfaceException
550
+	 * @throws ReflectionException
551
+	 */
552
+	public function payments($query_params = [])
553
+	{
554
+		return $this->get_many_related('Payment', $query_params);
555
+	}
556
+
557
+
558
+	/**
559
+	 * gets only approved payments for this transaction
560
+	 *
561
+	 * @return EE_Base_Class[]|EE_Payment[]
562
+	 * @throws EE_Error
563
+	 * @throws InvalidArgumentException
564
+	 * @throws ReflectionException
565
+	 * @throws InvalidDataTypeException
566
+	 * @throws InvalidInterfaceException
567
+	 */
568
+	public function approved_payments()
569
+	{
570
+		EE_Registry::instance()->load_model('Payment');
571
+		return $this->get_many_related(
572
+			'Payment',
573
+			[
574
+				['STS_ID' => EEM_Payment::status_id_approved],
575
+				'order_by' => ['PAY_timestamp' => 'DESC'],
576
+			]
577
+		);
578
+	}
579
+
580
+
581
+	/**
582
+	 * Gets all payments which have not been approved
583
+	 *
584
+	 * @return EE_Base_Class[]|EEI_Payment[]
585
+	 * @throws EE_Error if a model is misconfigured somehow
586
+	 * @throws InvalidArgumentException
587
+	 * @throws InvalidDataTypeException
588
+	 * @throws InvalidInterfaceException
589
+	 * @throws ReflectionException
590
+	 */
591
+	public function pending_payments()
592
+	{
593
+		return $this->get_many_related(
594
+			'Payment',
595
+			[
596
+				[
597
+					'STS_ID' => EEM_Payment::status_id_pending,
598
+				],
599
+				'order_by' => [
600
+					'PAY_timestamp' => 'DESC',
601
+				],
602
+			]
603
+		);
604
+	}
605
+
606
+
607
+	/**
608
+	 * echoes $this->pretty_status()
609
+	 *
610
+	 * @param bool $show_icons
611
+	 * @throws EE_Error
612
+	 * @throws InvalidArgumentException
613
+	 * @throws InvalidDataTypeException
614
+	 * @throws InvalidInterfaceException
615
+	 * @throws ReflectionException
616
+	 */
617
+	public function e_pretty_status($show_icons = false)
618
+	{
619
+		echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
620
+	}
621
+
622
+
623
+	/**
624
+	 * returns a pretty version of the status, good for displaying to users
625
+	 *
626
+	 * @param bool $show_icons
627
+	 * @return string
628
+	 * @throws EE_Error
629
+	 * @throws InvalidArgumentException
630
+	 * @throws InvalidDataTypeException
631
+	 * @throws InvalidInterfaceException
632
+	 * @throws ReflectionException
633
+	 */
634
+	public function pretty_status($show_icons = false)
635
+	{
636
+		$status = EEM_Status::instance()->localized_status(
637
+			[$this->status_ID() => esc_html__('unknown', 'event_espresso')],
638
+			false,
639
+			'sentence'
640
+		);
641
+		$icon   = '';
642
+		switch ($this->status_ID()) {
643
+			case EEM_Transaction::complete_status_code:
644
+				$icon = $show_icons
645
+					? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>'
646
+					: '';
647
+				break;
648
+			case EEM_Transaction::incomplete_status_code:
649
+				$icon = $show_icons
650
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
651
+					: '';
652
+				break;
653
+			case EEM_Transaction::abandoned_status_code:
654
+				$icon = $show_icons
655
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>'
656
+					: '';
657
+				break;
658
+			case EEM_Transaction::failed_status_code:
659
+				$icon = $show_icons
660
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
661
+					: '';
662
+				break;
663
+			case EEM_Transaction::overpaid_status_code:
664
+				$icon = $show_icons
665
+					? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>'
666
+					: '';
667
+				break;
668
+		}
669
+		return $icon . $status[ $this->status_ID() ];
670
+	}
671
+
672
+
673
+	/**
674
+	 * get Transaction Status
675
+	 *
676
+	 * @return mixed
677
+	 * @throws EE_Error
678
+	 * @throws InvalidArgumentException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws InvalidInterfaceException
681
+	 * @throws ReflectionException
682
+	 */
683
+	public function status_ID()
684
+	{
685
+		return $this->get('STS_ID');
686
+	}
687
+
688
+
689
+	/**
690
+	 * Returns TRUE or FALSE for whether or not this transaction cost any money
691
+	 *
692
+	 * @return boolean
693
+	 * @throws EE_Error
694
+	 * @throws InvalidArgumentException
695
+	 * @throws InvalidDataTypeException
696
+	 * @throws InvalidInterfaceException
697
+	 * @throws ReflectionException
698
+	 */
699
+	public function is_free()
700
+	{
701
+		return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
702
+	}
703
+
704
+
705
+	/**
706
+	 * Returns whether this transaction is complete
707
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
708
+	 *
709
+	 * @return boolean
710
+	 * @throws EE_Error
711
+	 * @throws InvalidArgumentException
712
+	 * @throws InvalidDataTypeException
713
+	 * @throws InvalidInterfaceException
714
+	 * @throws ReflectionException
715
+	 */
716
+	public function is_completed()
717
+	{
718
+		return $this->status_ID() === EEM_Transaction::complete_status_code;
719
+	}
720
+
721
+
722
+	/**
723
+	 * Returns whether this transaction is incomplete
724
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
725
+	 *
726
+	 * @return boolean
727
+	 * @throws EE_Error
728
+	 * @throws InvalidArgumentException
729
+	 * @throws InvalidDataTypeException
730
+	 * @throws InvalidInterfaceException
731
+	 * @throws ReflectionException
732
+	 */
733
+	public function is_incomplete()
734
+	{
735
+		return $this->status_ID() === EEM_Transaction::incomplete_status_code;
736
+	}
737
+
738
+
739
+	/**
740
+	 * Returns whether this transaction is overpaid
741
+	 * Useful in templates and other logic for deciding if monies need to be refunded
742
+	 *
743
+	 * @return boolean
744
+	 * @throws EE_Error
745
+	 * @throws InvalidArgumentException
746
+	 * @throws InvalidDataTypeException
747
+	 * @throws InvalidInterfaceException
748
+	 * @throws ReflectionException
749
+	 */
750
+	public function is_overpaid()
751
+	{
752
+		return $this->status_ID() === EEM_Transaction::overpaid_status_code;
753
+	}
754
+
755
+
756
+	/**
757
+	 * Returns whether this transaction was abandoned
758
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
759
+	 * but that contact information exists for at least one registrant
760
+	 *
761
+	 * @return boolean
762
+	 * @throws EE_Error
763
+	 * @throws InvalidArgumentException
764
+	 * @throws InvalidDataTypeException
765
+	 * @throws InvalidInterfaceException
766
+	 * @throws ReflectionException
767
+	 */
768
+	public function is_abandoned()
769
+	{
770
+		return $this->status_ID() === EEM_Transaction::abandoned_status_code;
771
+	}
772
+
773
+
774
+	/**
775
+	 * Returns whether this transaction failed
776
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
777
+	 * and that NO contact information exists for any registrants
778
+	 *
779
+	 * @return boolean
780
+	 * @throws EE_Error
781
+	 * @throws InvalidArgumentException
782
+	 * @throws InvalidDataTypeException
783
+	 * @throws InvalidInterfaceException
784
+	 * @throws ReflectionException
785
+	 */
786
+	public function failed()
787
+	{
788
+		return $this->status_ID() === EEM_Transaction::failed_status_code;
789
+	}
790
+
791
+
792
+	/**
793
+	 * This returns the url for the invoice of this transaction
794
+	 *
795
+	 * @param string $type 'html' or 'pdf' (default is pdf)
796
+	 * @return string
797
+	 * @throws DomainException
798
+	 * @throws EE_Error
799
+	 * @throws InvalidArgumentException
800
+	 * @throws InvalidDataTypeException
801
+	 * @throws InvalidInterfaceException
802
+	 * @throws ReflectionException
803
+	 */
804
+	public function invoice_url($type = 'html')
805
+	{
806
+		$REG = $this->primary_registration();
807
+		if (! $REG instanceof EE_Registration) {
808
+			return '';
809
+		}
810
+		return $REG->invoice_url($type);
811
+	}
812
+
813
+
814
+	/**
815
+	 * Gets the primary registration only
816
+	 *
817
+	 * @return EE_Base_Class|EE_Registration
818
+	 * @throws EE_Error
819
+	 * @throws InvalidArgumentException
820
+	 * @throws InvalidDataTypeException
821
+	 * @throws InvalidInterfaceException
822
+	 * @throws ReflectionException
823
+	 */
824
+	public function primary_registration()
825
+	{
826
+		if ($this->_primary_registrant instanceof EE_Registration) {
827
+			return $this->_primary_registrant;
828
+		}
829
+
830
+		$registrations = (array) $this->get_many_related(
831
+			'Registration',
832
+			[['REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT]]
833
+		);
834
+		foreach ($registrations as $registration) {
835
+			// valid registration that is NOT cancelled or declined ?
836
+			if (
837
+				$registration instanceof EE_Registration
838
+				&& ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
839
+			) {
840
+				$this->_primary_registrant = $registration;
841
+				return $registration;
842
+			}
843
+		}
844
+		// nothing valid found, so just return first thing from array of results
845
+		$primary_registrant = reset($registrations);
846
+		$this->_primary_registrant = $primary_registrant instanceof EE_Registration ? $primary_registrant : null;
847
+		return $this->_primary_registrant;
848
+	}
849
+
850
+
851
+	/**
852
+	 * Gets the URL for viewing the receipt
853
+	 *
854
+	 * @param string $type 'pdf' or 'html' (default is 'html')
855
+	 * @return string
856
+	 * @throws DomainException
857
+	 * @throws EE_Error
858
+	 * @throws InvalidArgumentException
859
+	 * @throws InvalidDataTypeException
860
+	 * @throws InvalidInterfaceException
861
+	 * @throws ReflectionException
862
+	 */
863
+	public function receipt_url($type = 'html')
864
+	{
865
+		$REG = $this->primary_registration();
866
+		if (! $REG instanceof EE_Registration) {
867
+			return '';
868
+		}
869
+		return $REG->receipt_url($type);
870
+	}
871
+
872
+
873
+	/**
874
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
875
+	 * a query parameter
876
+	 *
877
+	 * @return string
878
+	 * @throws EE_Error
879
+	 * @throws InvalidArgumentException
880
+	 * @throws InvalidDataTypeException
881
+	 * @throws InvalidInterfaceException
882
+	 * @throws ReflectionException
883
+	 */
884
+	public function payment_overview_url()
885
+	{
886
+		$primary_registration = $this->primary_registration();
887
+		return $primary_registration instanceof EE_Registration
888
+			? $primary_registration->payment_overview_url()
889
+			: false;
890
+	}
891
+
892
+
893
+	/**
894
+	 * @return string
895
+	 * @throws EE_Error
896
+	 * @throws InvalidArgumentException
897
+	 * @throws InvalidDataTypeException
898
+	 * @throws InvalidInterfaceException
899
+	 * @throws ReflectionException
900
+	 */
901
+	public function gateway_response_on_transaction()
902
+	{
903
+		$payment = $this->get_first_related('Payment');
904
+		return $payment instanceof EE_Payment
905
+			? $payment->gateway_response()
906
+			: '';
907
+	}
908
+
909
+
910
+	/**
911
+	 * Get the status object of this object
912
+	 *
913
+	 * @return EE_Base_Class|EE_Status
914
+	 * @throws EE_Error
915
+	 * @throws InvalidArgumentException
916
+	 * @throws InvalidDataTypeException
917
+	 * @throws InvalidInterfaceException
918
+	 * @throws ReflectionException
919
+	 */
920
+	public function status_obj()
921
+	{
922
+		return $this->get_first_related('Status');
923
+	}
924
+
925
+
926
+	/**
927
+	 * Gets all the extra meta info on this payment
928
+	 *
929
+	 * @param array $query_params
930
+	 * @return EE_Base_Class[]|EE_Extra_Meta
931
+	 * @throws EE_Error
932
+	 * @throws InvalidArgumentException
933
+	 * @throws InvalidDataTypeException
934
+	 * @throws InvalidInterfaceException
935
+	 * @throws ReflectionException
936
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
937
+	 */
938
+	public function extra_meta($query_params = [])
939
+	{
940
+		return $this->get_many_related('Extra_Meta', $query_params);
941
+	}
942
+
943
+
944
+	/**
945
+	 * Wrapper for _add_relation_to
946
+	 *
947
+	 * @param EE_Registration $registration
948
+	 * @return EE_Base_Class the relation was added to
949
+	 * @throws EE_Error
950
+	 * @throws InvalidArgumentException
951
+	 * @throws InvalidDataTypeException
952
+	 * @throws InvalidInterfaceException
953
+	 * @throws ReflectionException
954
+	 */
955
+	public function add_registration(EE_Registration $registration)
956
+	{
957
+		return $this->_add_relation_to($registration, 'Registration');
958
+	}
959
+
960
+
961
+	/**
962
+	 * Removes the given registration from being related (even before saving this transaction).
963
+	 * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
964
+	 *
965
+	 * @param int $registration_or_id
966
+	 * @return EE_Base_Class that was removed from being related
967
+	 * @throws EE_Error
968
+	 * @throws InvalidArgumentException
969
+	 * @throws InvalidDataTypeException
970
+	 * @throws InvalidInterfaceException
971
+	 * @throws ReflectionException
972
+	 */
973
+	public function remove_registration_with_id($registration_or_id)
974
+	{
975
+		return $this->_remove_relation_to($registration_or_id, 'Registration');
976
+	}
977
+
978
+
979
+	/**
980
+	 * Gets all the line items which are for ACTUAL items
981
+	 *
982
+	 * @return EE_Line_Item[]
983
+	 * @throws EE_Error
984
+	 * @throws InvalidArgumentException
985
+	 * @throws InvalidDataTypeException
986
+	 * @throws InvalidInterfaceException
987
+	 * @throws ReflectionException
988
+	 */
989
+	public function items_purchased()
990
+	{
991
+		return $this->line_items([['LIN_type' => EEM_Line_Item::type_line_item]]);
992
+	}
993
+
994
+
995
+	/**
996
+	 * Wrapper for _add_relation_to
997
+	 *
998
+	 * @param EE_Line_Item $line_item
999
+	 * @return EE_Base_Class the relation was added to
1000
+	 * @throws EE_Error
1001
+	 * @throws InvalidArgumentException
1002
+	 * @throws InvalidDataTypeException
1003
+	 * @throws InvalidInterfaceException
1004
+	 * @throws ReflectionException
1005
+	 */
1006
+	public function add_line_item(EE_Line_Item $line_item)
1007
+	{
1008
+		return $this->_add_relation_to($line_item, 'Line_Item');
1009
+	}
1010
+
1011
+
1012
+	/**
1013
+	 * Gets ALL the line items related to this transaction (unstructured)
1014
+	 *
1015
+	 * @param array $query_params
1016
+	 * @return EE_Base_Class[]|EE_Line_Item[]
1017
+	 * @throws EE_Error
1018
+	 * @throws InvalidArgumentException
1019
+	 * @throws InvalidDataTypeException
1020
+	 * @throws InvalidInterfaceException
1021
+	 * @throws ReflectionException
1022
+	 */
1023
+	public function line_items($query_params = [])
1024
+	{
1025
+		return $this->get_many_related('Line_Item', $query_params);
1026
+	}
1027
+
1028
+
1029
+	/**
1030
+	 * Gets all the line items which are taxes on the total
1031
+	 *
1032
+	 * @return EE_Line_Item[]
1033
+	 * @throws EE_Error
1034
+	 * @throws InvalidArgumentException
1035
+	 * @throws InvalidDataTypeException
1036
+	 * @throws InvalidInterfaceException
1037
+	 * @throws ReflectionException
1038
+	 */
1039
+	public function tax_items()
1040
+	{
1041
+		return $this->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1042
+	}
1043
+
1044
+
1045
+	/**
1046
+	 * Gets the total line item (which is a parent of all other related line items,
1047
+	 * meaning it takes them all into account on its total)
1048
+	 *
1049
+	 * @param bool $create_if_not_found
1050
+	 * @return EE_Line_Item|null
1051
+	 * @throws EE_Error
1052
+	 * @throws InvalidArgumentException
1053
+	 * @throws InvalidDataTypeException
1054
+	 * @throws InvalidInterfaceException
1055
+	 * @throws ReflectionException
1056
+	 */
1057
+	public function total_line_item(bool $create_if_not_found = true): ?EE_Line_Item
1058
+	{
1059
+		$item = $this->get_first_related('Line_Item', [['LIN_type' => EEM_Line_Item::type_total]]);
1060
+		if ($item instanceof EE_Line_Item) {
1061
+			return $item;
1062
+		}
1063
+		return $create_if_not_found
1064
+			? EEH_Line_Item::create_total_line_item($this)
1065
+			: null;
1066
+	}
1067
+
1068
+
1069
+	/**
1070
+	 * Returns the total amount of tax on this transaction
1071
+	 * (assumes there's only one tax subtotal line item)
1072
+	 *
1073
+	 * @return float
1074
+	 * @throws EE_Error
1075
+	 * @throws InvalidArgumentException
1076
+	 * @throws InvalidDataTypeException
1077
+	 * @throws InvalidInterfaceException
1078
+	 * @throws ReflectionException
1079
+	 */
1080
+	public function tax_total()
1081
+	{
1082
+		$tax_line_item = $this->tax_total_line_item();
1083
+		if ($tax_line_item) {
1084
+			return (float) $tax_line_item->total();
1085
+		}
1086
+		return (float) 0;
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * Gets the tax subtotal line item (assumes there's only one)
1092
+	 *
1093
+	 * @return EE_Line_Item
1094
+	 * @throws EE_Error
1095
+	 * @throws InvalidArgumentException
1096
+	 * @throws InvalidDataTypeException
1097
+	 * @throws InvalidInterfaceException
1098
+	 * @throws ReflectionException
1099
+	 */
1100
+	public function tax_total_line_item()
1101
+	{
1102
+		return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1103
+	}
1104
+
1105
+
1106
+	/**
1107
+	 * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1108
+	 *
1109
+	 * @return EE_Form_Section_Proper|null
1110
+	 * @throws EE_Error
1111
+	 * @throws InvalidArgumentException
1112
+	 * @throws InvalidDataTypeException
1113
+	 * @throws InvalidInterfaceException
1114
+	 * @throws ReflectionException
1115
+	 */
1116
+	public function billing_info(): ?EE_Form_Section_Proper
1117
+	{
1118
+		$payment_method = $this->payment_method();
1119
+		if (! $payment_method) {
1120
+			EE_Error::add_error(
1121
+				esc_html__(
1122
+					'Could not find billing info for transaction because no gateway has been used for it yet',
1123
+					'event_espresso'
1124
+				),
1125
+				__FILE__,
1126
+				__FUNCTION__,
1127
+				__LINE__
1128
+			);
1129
+			return null;
1130
+		}
1131
+		$primary_reg = $this->primary_registration();
1132
+		if (! $primary_reg) {
1133
+			EE_Error::add_error(
1134
+				esc_html__(
1135
+					'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1136
+					'event_espresso'
1137
+				),
1138
+				__FILE__,
1139
+				__FUNCTION__,
1140
+				__LINE__
1141
+			);
1142
+			return null;
1143
+		}
1144
+		$attendee = $primary_reg->attendee();
1145
+		if (! $attendee) {
1146
+			EE_Error::add_error(
1147
+				esc_html__(
1148
+					'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1149
+					'event_espresso'
1150
+				),
1151
+				__FILE__,
1152
+				__FUNCTION__,
1153
+				__LINE__
1154
+			);
1155
+			return null;
1156
+		}
1157
+		return $attendee->billing_info_for_payment_method($payment_method);
1158
+	}
1159
+
1160
+
1161
+	/**
1162
+	 * Gets PMD_ID
1163
+	 *
1164
+	 * @return int
1165
+	 * @throws EE_Error
1166
+	 * @throws InvalidArgumentException
1167
+	 * @throws InvalidDataTypeException
1168
+	 * @throws InvalidInterfaceException
1169
+	 * @throws ReflectionException
1170
+	 */
1171
+	public function payment_method_ID()
1172
+	{
1173
+		return $this->get('PMD_ID');
1174
+	}
1175
+
1176
+
1177
+	/**
1178
+	 * Sets PMD_ID
1179
+	 *
1180
+	 * @param int $PMD_ID
1181
+	 * @throws EE_Error
1182
+	 * @throws InvalidArgumentException
1183
+	 * @throws InvalidDataTypeException
1184
+	 * @throws InvalidInterfaceException
1185
+	 * @throws ReflectionException
1186
+	 */
1187
+	public function set_payment_method_ID($PMD_ID)
1188
+	{
1189
+		$this->set('PMD_ID', $PMD_ID);
1190
+	}
1191
+
1192
+
1193
+	/**
1194
+	 * Gets the last-used payment method on this transaction
1195
+	 * (we COULD just use the last-made payment, but some payment methods, namely
1196
+	 * offline ones, dont' create payments)
1197
+	 *
1198
+	 * @return EE_Payment_Method
1199
+	 * @throws EE_Error
1200
+	 * @throws InvalidArgumentException
1201
+	 * @throws InvalidDataTypeException
1202
+	 * @throws InvalidInterfaceException
1203
+	 * @throws ReflectionException
1204
+	 */
1205
+	public function payment_method()
1206
+	{
1207
+		$PMD_ID = $this->payment_method_ID();
1208
+		if($PMD_ID) {
1209
+			$pm = EEM_Payment_Method::instance()->get_one_by_ID($this->payment_method_ID());
1210
+			if ($pm instanceof EE_Payment_Method) {
1211
+				return $pm;
1212
+			}
1213
+		}
1214
+		$last_payment = $this->last_payment();
1215
+		if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1216
+			return $last_payment->payment_method();
1217
+		}
1218
+		return null;
1219
+	}
1220
+
1221
+
1222
+	/**
1223
+	 * Gets the last payment made
1224
+	 *
1225
+	 * @return EE_Base_Class|EE_Payment|null
1226
+	 * @throws EE_Error
1227
+	 * @throws InvalidArgumentException
1228
+	 * @throws InvalidDataTypeException
1229
+	 * @throws InvalidInterfaceException
1230
+	 * @throws ReflectionException
1231
+	 */
1232
+	public function last_payment(): ?EE_Payment
1233
+	{
1234
+		return $this->get_first_related('Payment', ['order_by' => ['PAY_ID' => 'desc']]);
1235
+	}
1236
+
1237
+
1238
+	/**
1239
+	 * Gets all the line items which are unrelated to tickets on this transaction
1240
+	 *
1241
+	 * @return EE_Line_Item[]
1242
+	 * @throws EE_Error
1243
+	 * @throws InvalidArgumentException
1244
+	 * @throws InvalidDataTypeException
1245
+	 * @throws InvalidInterfaceException
1246
+	 * @throws ReflectionException
1247
+	 */
1248
+	public function non_ticket_line_items()
1249
+	{
1250
+		return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1251
+	}
1252
+
1253
+
1254
+	/**
1255
+	 * possibly toggles TXN status
1256
+	 *
1257
+	 * @param boolean $update whether to save the TXN
1258
+	 * @return bool whether the TXN was saved
1259
+	 * @throws EE_Error
1260
+	 * @throws InvalidArgumentException
1261
+	 * @throws InvalidDataTypeException
1262
+	 * @throws InvalidInterfaceException
1263
+	 * @throws ReflectionException
1264
+	 * @throws RuntimeException
1265
+	 */
1266
+	public function update_status_based_on_total_paid($update = true)
1267
+	{
1268
+		// set transaction status based on comparison of TXN_paid vs TXN_total
1269
+		if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1270
+			$new_txn_status = EEM_Transaction::overpaid_status_code;
1271
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1272
+			$new_txn_status = EEM_Transaction::complete_status_code;
1273
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1274
+			$new_txn_status = EEM_Transaction::incomplete_status_code;
1275
+		} else {
1276
+			throw new RuntimeException(
1277
+				esc_html__('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1278
+			);
1279
+		}
1280
+		if ($new_txn_status !== $this->status_ID()) {
1281
+			$this->set_status($new_txn_status);
1282
+			if ($update) {
1283
+				return (bool) $this->save();
1284
+			}
1285
+		}
1286
+		return false;
1287
+	}
1288
+
1289
+
1290
+	/**
1291
+	 * Updates the transaction's status and total_paid based on all the payments
1292
+	 * that apply to it
1293
+	 *
1294
+	 * @return array|bool
1295
+	 * @throws EE_Error
1296
+	 * @throws InvalidArgumentException
1297
+	 * @throws ReflectionException
1298
+	 * @throws InvalidDataTypeException
1299
+	 * @throws InvalidInterfaceException
1300
+	 * @deprecated
1301
+	 */
1302
+	public function update_based_on_payments()
1303
+	{
1304
+		EE_Error::doing_it_wrong(
1305
+			__CLASS__ . '::' . __FUNCTION__,
1306
+			sprintf(
1307
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1308
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1309
+			),
1310
+			'4.6.0'
1311
+		);
1312
+		/** @type EE_Transaction_Processor $transaction_processor */
1313
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1314
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1315
+	}
1316
+
1317
+
1318
+	/**
1319
+	 * @return string
1320
+	 */
1321
+	public function old_txn_status()
1322
+	{
1323
+		return $this->_old_txn_status;
1324
+	}
1325
+
1326
+
1327
+	/**
1328
+	 * @param string $old_txn_status
1329
+	 */
1330
+	public function set_old_txn_status($old_txn_status)
1331
+	{
1332
+		// only set the first time
1333
+		if ($this->_old_txn_status === null) {
1334
+			$this->_old_txn_status = $old_txn_status;
1335
+		}
1336
+	}
1337
+
1338
+
1339
+	/**
1340
+	 * reg_status_updated
1341
+	 *
1342
+	 * @return bool
1343
+	 * @throws EE_Error
1344
+	 * @throws InvalidArgumentException
1345
+	 * @throws InvalidDataTypeException
1346
+	 * @throws InvalidInterfaceException
1347
+	 * @throws ReflectionException
1348
+	 */
1349
+	public function txn_status_updated()
1350
+	{
1351
+		return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1352
+	}
1353
+
1354
+
1355
+	/**
1356
+	 * _reg_steps_completed
1357
+	 * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1358
+	 * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1359
+	 * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1360
+	 *
1361
+	 * @param string $reg_step_slug
1362
+	 * @param bool   $check_all
1363
+	 * @return bool|int
1364
+	 * @throws EE_Error
1365
+	 * @throws InvalidArgumentException
1366
+	 * @throws InvalidDataTypeException
1367
+	 * @throws InvalidInterfaceException
1368
+	 * @throws ReflectionException
1369
+	 */
1370
+	private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1371
+	{
1372
+		$reg_steps = $this->reg_steps();
1373
+		if (! is_array($reg_steps) || empty($reg_steps)) {
1374
+			return false;
1375
+		}
1376
+		// loop thru reg steps array)
1377
+		foreach ($reg_steps as $slug => $reg_step_completed) {
1378
+			// if NOT checking ALL steps (only checking one step)
1379
+			if (! $check_all) {
1380
+				// and this is the one
1381
+				if ($slug === $reg_step_slug) {
1382
+					return $reg_step_completed;
1383
+				}
1384
+				// skip to next reg step in loop
1385
+				continue;
1386
+			}
1387
+			// $check_all must be true, else we would never have gotten to this point
1388
+			if ($slug === $reg_step_slug) {
1389
+				// if we reach this point, then we are testing either:
1390
+				// all_reg_steps_completed_except() or
1391
+				// all_reg_steps_completed_except_final_step(),
1392
+				// and since this is the reg step EXCEPTION being tested
1393
+				// we want to return true (yes true) if this reg step is NOT completed
1394
+				// ie: "is everything completed except the final step?"
1395
+				// "that is correct... the final step is not completed, but all others are."
1396
+				return $reg_step_completed !== true;
1397
+			}
1398
+			if ($reg_step_completed !== true) {
1399
+				// if any reg step is NOT completed, then ALL steps are not completed
1400
+				return false;
1401
+			}
1402
+		}
1403
+		return true;
1404
+	}
1405
+
1406
+
1407
+	/**
1408
+	 * all_reg_steps_completed
1409
+	 * returns:
1410
+	 *    true if ALL reg steps have been marked as completed
1411
+	 *        or false if any step is not completed
1412
+	 *
1413
+	 * @return bool
1414
+	 * @throws EE_Error
1415
+	 * @throws InvalidArgumentException
1416
+	 * @throws InvalidDataTypeException
1417
+	 * @throws InvalidInterfaceException
1418
+	 * @throws ReflectionException
1419
+	 */
1420
+	public function all_reg_steps_completed()
1421
+	{
1422
+		return $this->_reg_steps_completed();
1423
+	}
1424
+
1425
+
1426
+	/**
1427
+	 * all_reg_steps_completed_except
1428
+	 * returns:
1429
+	 *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1430
+	 *        or false if any other step is not completed
1431
+	 *        or false if ALL steps are completed including the exception you are testing !!!
1432
+	 *
1433
+	 * @param string $exception
1434
+	 * @return bool
1435
+	 * @throws EE_Error
1436
+	 * @throws InvalidArgumentException
1437
+	 * @throws InvalidDataTypeException
1438
+	 * @throws InvalidInterfaceException
1439
+	 * @throws ReflectionException
1440
+	 */
1441
+	public function all_reg_steps_completed_except($exception = '')
1442
+	{
1443
+		return $this->_reg_steps_completed($exception);
1444
+	}
1445
+
1446
+
1447
+	/**
1448
+	 * all_reg_steps_completed_except
1449
+	 * returns:
1450
+	 *        true if ALL reg steps, except the final step, have been marked as completed
1451
+	 *        or false if any step is not completed
1452
+	 *    or false if ALL steps are completed including the final step !!!
1453
+	 *
1454
+	 * @return bool
1455
+	 * @throws EE_Error
1456
+	 * @throws InvalidArgumentException
1457
+	 * @throws InvalidDataTypeException
1458
+	 * @throws InvalidInterfaceException
1459
+	 * @throws ReflectionException
1460
+	 */
1461
+	public function all_reg_steps_completed_except_final_step()
1462
+	{
1463
+		return $this->_reg_steps_completed('finalize_registration');
1464
+	}
1465
+
1466
+
1467
+	/**
1468
+	 * reg_step_completed
1469
+	 * returns:
1470
+	 *    true if a specific reg step has been marked as completed
1471
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1472
+	 *    or false if it has not yet been initialized
1473
+	 *
1474
+	 * @param string $reg_step_slug
1475
+	 * @return bool|int
1476
+	 * @throws EE_Error
1477
+	 * @throws InvalidArgumentException
1478
+	 * @throws InvalidDataTypeException
1479
+	 * @throws InvalidInterfaceException
1480
+	 * @throws ReflectionException
1481
+	 */
1482
+	public function reg_step_completed($reg_step_slug)
1483
+	{
1484
+		return $this->_reg_steps_completed($reg_step_slug, false);
1485
+	}
1486
+
1487
+
1488
+	/**
1489
+	 * completed_final_reg_step
1490
+	 * returns:
1491
+	 *    true if the finalize_registration reg step has been marked as completed
1492
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1493
+	 *    or false if it has not yet been initialized
1494
+	 *
1495
+	 * @return bool|int
1496
+	 * @throws EE_Error
1497
+	 * @throws InvalidArgumentException
1498
+	 * @throws InvalidDataTypeException
1499
+	 * @throws InvalidInterfaceException
1500
+	 * @throws ReflectionException
1501
+	 */
1502
+	public function final_reg_step_completed()
1503
+	{
1504
+		return $this->_reg_steps_completed('finalize_registration', false);
1505
+	}
1506
+
1507
+
1508
+	/**
1509
+	 * set_reg_step_initiated
1510
+	 * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1511
+	 *
1512
+	 * @param string $reg_step_slug
1513
+	 * @return boolean
1514
+	 * @throws EE_Error
1515
+	 * @throws InvalidArgumentException
1516
+	 * @throws InvalidDataTypeException
1517
+	 * @throws InvalidInterfaceException
1518
+	 * @throws ReflectionException
1519
+	 */
1520
+	public function set_reg_step_initiated($reg_step_slug)
1521
+	{
1522
+		return $this->_set_reg_step_completed_status($reg_step_slug, time());
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * set_reg_step_completed
1528
+	 * given a valid TXN_reg_step, this sets the step as completed
1529
+	 *
1530
+	 * @param string $reg_step_slug
1531
+	 * @return boolean
1532
+	 * @throws EE_Error
1533
+	 * @throws InvalidArgumentException
1534
+	 * @throws InvalidDataTypeException
1535
+	 * @throws InvalidInterfaceException
1536
+	 * @throws ReflectionException
1537
+	 */
1538
+	public function set_reg_step_completed($reg_step_slug)
1539
+	{
1540
+		return $this->_set_reg_step_completed_status($reg_step_slug, true);
1541
+	}
1542
+
1543
+
1544
+	/**
1545
+	 * set_reg_step_completed
1546
+	 * given a valid TXN_reg_step slug, this sets the step as NOT completed
1547
+	 *
1548
+	 * @param string $reg_step_slug
1549
+	 * @return boolean
1550
+	 * @throws EE_Error
1551
+	 * @throws InvalidArgumentException
1552
+	 * @throws InvalidDataTypeException
1553
+	 * @throws InvalidInterfaceException
1554
+	 * @throws ReflectionException
1555
+	 */
1556
+	public function set_reg_step_not_completed($reg_step_slug)
1557
+	{
1558
+		return $this->_set_reg_step_completed_status($reg_step_slug, false);
1559
+	}
1560
+
1561
+
1562
+	/**
1563
+	 * set_reg_step_completed
1564
+	 * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1565
+	 *
1566
+	 * @param string      $reg_step_slug
1567
+	 * @param boolean|int $status
1568
+	 * @return boolean
1569
+	 * @throws EE_Error
1570
+	 * @throws InvalidArgumentException
1571
+	 * @throws InvalidDataTypeException
1572
+	 * @throws InvalidInterfaceException
1573
+	 * @throws ReflectionException
1574
+	 */
1575
+	private function _set_reg_step_completed_status($reg_step_slug, $status)
1576
+	{
1577
+		// validate status
1578
+		$status = is_bool($status) || is_int($status)
1579
+			? $status
1580
+			: false;
1581
+		// get reg steps array
1582
+		$txn_reg_steps = $this->reg_steps();
1583
+		// if reg step does NOT exist
1584
+		if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1585
+			return false;
1586
+		}
1587
+		// if  we're trying to complete a step that is already completed
1588
+		if ($txn_reg_steps[ $reg_step_slug ] === true) {
1589
+			return true;
1590
+		}
1591
+		// if  we're trying to complete a step that hasn't even started
1592
+		if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1593
+			return false;
1594
+		}
1595
+		// if current status value matches the incoming value (no change)
1596
+		// type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1597
+		if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1598
+			// this will happen in cases where multiple AJAX requests occur during the same step
1599
+			return true;
1600
+		}
1601
+		// if we're trying to set a start time, but it has already been set...
1602
+		if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1603
+			// skip the update below, but don't return FALSE so that errors won't be displayed
1604
+			return true;
1605
+		}
1606
+		// update completed status
1607
+		$txn_reg_steps[ $reg_step_slug ] = $status;
1608
+		$this->set_reg_steps($txn_reg_steps);
1609
+		$this->save();
1610
+		return true;
1611
+	}
1612
+
1613
+
1614
+	/**
1615
+	 * remove_reg_step
1616
+	 * given a valid TXN_reg_step slug, this will remove (unset)
1617
+	 * the reg step from the TXN reg step array
1618
+	 *
1619
+	 * @param string $reg_step_slug
1620
+	 * @return void
1621
+	 * @throws EE_Error
1622
+	 * @throws InvalidArgumentException
1623
+	 * @throws InvalidDataTypeException
1624
+	 * @throws InvalidInterfaceException
1625
+	 * @throws ReflectionException
1626
+	 */
1627
+	public function remove_reg_step($reg_step_slug)
1628
+	{
1629
+		// get reg steps array
1630
+		$txn_reg_steps = $this->reg_steps();
1631
+		unset($txn_reg_steps[ $reg_step_slug ]);
1632
+		$this->set_reg_steps($txn_reg_steps);
1633
+	}
1634
+
1635
+
1636
+	/**
1637
+	 * toggle_failed_transaction_status
1638
+	 * upgrades a TXNs status from failed to abandoned,
1639
+	 * meaning that contact information has been captured for at least one registrant
1640
+	 *
1641
+	 * @param bool $save
1642
+	 * @return bool
1643
+	 * @throws EE_Error
1644
+	 * @throws InvalidArgumentException
1645
+	 * @throws InvalidDataTypeException
1646
+	 * @throws InvalidInterfaceException
1647
+	 * @throws ReflectionException
1648
+	 */
1649
+	public function toggle_failed_transaction_status($save = true)
1650
+	{
1651
+		// if TXN status is still set as "failed"...
1652
+		if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1653
+			$this->set_status(EEM_Transaction::abandoned_status_code);
1654
+			if ($save) {
1655
+				$this->save();
1656
+			}
1657
+			return true;
1658
+		}
1659
+		return false;
1660
+	}
1661
+
1662
+
1663
+	/**
1664
+	 * toggle_abandoned_transaction_status
1665
+	 * upgrades a TXNs status from failed or abandoned to incomplete
1666
+	 *
1667
+	 * @return bool
1668
+	 * @throws EE_Error
1669
+	 * @throws InvalidArgumentException
1670
+	 * @throws InvalidDataTypeException
1671
+	 * @throws InvalidInterfaceException
1672
+	 * @throws ReflectionException
1673
+	 */
1674
+	public function toggle_abandoned_transaction_status()
1675
+	{
1676
+		// if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1677
+		$txn_status = $this->status_ID();
1678
+		if (
1679
+			$txn_status === EEM_Transaction::failed_status_code
1680
+			|| $txn_status === EEM_Transaction::abandoned_status_code
1681
+		) {
1682
+			// if a contact record for the primary registrant has been created
1683
+			if (
1684
+				$this->primary_registration() instanceof EE_Registration
1685
+				&& $this->primary_registration()->attendee() instanceof EE_Attendee
1686
+			) {
1687
+				$this->set_status(EEM_Transaction::incomplete_status_code);
1688
+			} else {
1689
+				// no contact record? yer abandoned!
1690
+				$this->set_status(EEM_Transaction::abandoned_status_code);
1691
+			}
1692
+			return true;
1693
+		}
1694
+		return false;
1695
+	}
1696
+
1697
+
1698
+	/**
1699
+	 * checks if an Abandoned TXN has any related payments, and if so,
1700
+	 * updates the TXN status based on the amount paid
1701
+	 *
1702
+	 * @throws EE_Error
1703
+	 * @throws InvalidArgumentException
1704
+	 * @throws InvalidDataTypeException
1705
+	 * @throws InvalidInterfaceException
1706
+	 * @throws ReflectionException
1707
+	 * @throws RuntimeException
1708
+	 * @throws ReflectionException
1709
+	 */
1710
+	public function verify_abandoned_transaction_status()
1711
+	{
1712
+		if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1713
+			return;
1714
+		}
1715
+		$payments = $this->get_many_related('Payment');
1716
+		if (! empty($payments)) {
1717
+			foreach ($payments as $payment) {
1718
+				if ($payment instanceof EE_Payment) {
1719
+					// kk this TXN should NOT be abandoned
1720
+					$this->update_status_based_on_total_paid();
1721
+					if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1722
+						EE_Error::add_attention(
1723
+							sprintf(
1724
+								esc_html__(
1725
+									'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1726
+									'event_espresso'
1727
+								),
1728
+								$this->ID(),
1729
+								$this->pretty_status()
1730
+							)
1731
+						);
1732
+					}
1733
+					// get final reg step status
1734
+					$finalized = $this->final_reg_step_completed();
1735
+					// if the 'finalize_registration' step has been initiated (has a timestamp)
1736
+					// but has not yet been fully completed (TRUE)
1737
+					if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1738
+						$this->set_reg_step_completed('finalize_registration');
1739
+						$this->save();
1740
+					}
1741
+				}
1742
+			}
1743
+		}
1744
+	}
1745
+
1746
+
1747
+	/**
1748
+	 * @throws EE_Error
1749
+	 * @throws InvalidArgumentException
1750
+	 * @throws InvalidDataTypeException
1751
+	 * @throws InvalidInterfaceException
1752
+	 * @throws ReflectionException
1753
+	 * @throws RuntimeException
1754
+	 * @since 4.10.4.p
1755
+	 */
1756
+	public function recalculateLineItems()
1757
+	{
1758
+		$total_line_item = $this->total_line_item(false);
1759
+		if ($total_line_item instanceof EE_Line_Item) {
1760
+			EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1761
+			return EEH_Line_Item::apply_taxes($total_line_item, true);
1762
+		}
1763
+		return false;
1764
+	}
1765 1765
 }
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -47,7 +47,7 @@  discard block
 block discarded – undo
47 47
         $txn        = $has_object
48 48
             ? $has_object
49 49
             : new self($props_n_values, false, $timezone, $date_formats);
50
-        if (! $has_object) {
50
+        if ( ! $has_object) {
51 51
             $txn->set_old_txn_status($txn->status_ID());
52 52
         }
53 53
         return $txn;
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
     public function lock()
88 88
     {
89 89
         // attempt to set lock, but if that fails...
90
-        if (! $this->add_extra_meta('lock', time(), true)) {
90
+        if ( ! $this->add_extra_meta('lock', time(), true)) {
91 91
             // then attempt to remove the lock in case it is expired
92 92
             if ($this->_remove_expired_lock()) {
93 93
                 // if removal was successful, then try setting lock again
@@ -143,7 +143,7 @@  discard block
 block discarded – undo
143 143
     public function is_locked()
144 144
     {
145 145
         // if TXN is not locked, then return false immediately
146
-        if (! $this->_get_lock()) {
146
+        if ( ! $this->_get_lock()) {
147 147
             return false;
148 148
         }
149 149
         // if not, then let's try and remove the lock in case it's expired...
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
             false,
639 639
             'sentence'
640 640
         );
641
-        $icon   = '';
641
+        $icon = '';
642 642
         switch ($this->status_ID()) {
643 643
             case EEM_Transaction::complete_status_code:
644 644
                 $icon = $show_icons
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
                     : '';
667 667
                 break;
668 668
         }
669
-        return $icon . $status[ $this->status_ID() ];
669
+        return $icon.$status[$this->status_ID()];
670 670
     }
671 671
 
672 672
 
@@ -804,7 +804,7 @@  discard block
 block discarded – undo
804 804
     public function invoice_url($type = 'html')
805 805
     {
806 806
         $REG = $this->primary_registration();
807
-        if (! $REG instanceof EE_Registration) {
807
+        if ( ! $REG instanceof EE_Registration) {
808 808
             return '';
809 809
         }
810 810
         return $REG->invoice_url($type);
@@ -863,7 +863,7 @@  discard block
 block discarded – undo
863 863
     public function receipt_url($type = 'html')
864 864
     {
865 865
         $REG = $this->primary_registration();
866
-        if (! $REG instanceof EE_Registration) {
866
+        if ( ! $REG instanceof EE_Registration) {
867 867
             return '';
868 868
         }
869 869
         return $REG->receipt_url($type);
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
     public function billing_info(): ?EE_Form_Section_Proper
1117 1117
     {
1118 1118
         $payment_method = $this->payment_method();
1119
-        if (! $payment_method) {
1119
+        if ( ! $payment_method) {
1120 1120
             EE_Error::add_error(
1121 1121
                 esc_html__(
1122 1122
                     'Could not find billing info for transaction because no gateway has been used for it yet',
@@ -1129,7 +1129,7 @@  discard block
 block discarded – undo
1129 1129
             return null;
1130 1130
         }
1131 1131
         $primary_reg = $this->primary_registration();
1132
-        if (! $primary_reg) {
1132
+        if ( ! $primary_reg) {
1133 1133
             EE_Error::add_error(
1134 1134
                 esc_html__(
1135 1135
                     'Cannot get billing info for gateway %s on transaction because no primary registration exists',
@@ -1142,7 +1142,7 @@  discard block
 block discarded – undo
1142 1142
             return null;
1143 1143
         }
1144 1144
         $attendee = $primary_reg->attendee();
1145
-        if (! $attendee) {
1145
+        if ( ! $attendee) {
1146 1146
             EE_Error::add_error(
1147 1147
                 esc_html__(
1148 1148
                     'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
@@ -1205,7 +1205,7 @@  discard block
 block discarded – undo
1205 1205
     public function payment_method()
1206 1206
     {
1207 1207
         $PMD_ID = $this->payment_method_ID();
1208
-        if($PMD_ID) {
1208
+        if ($PMD_ID) {
1209 1209
             $pm = EEM_Payment_Method::instance()->get_one_by_ID($this->payment_method_ID());
1210 1210
             if ($pm instanceof EE_Payment_Method) {
1211 1211
                 return $pm;
@@ -1302,7 +1302,7 @@  discard block
 block discarded – undo
1302 1302
     public function update_based_on_payments()
1303 1303
     {
1304 1304
         EE_Error::doing_it_wrong(
1305
-            __CLASS__ . '::' . __FUNCTION__,
1305
+            __CLASS__.'::'.__FUNCTION__,
1306 1306
             sprintf(
1307 1307
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1308 1308
                 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
@@ -1370,13 +1370,13 @@  discard block
 block discarded – undo
1370 1370
     private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1371 1371
     {
1372 1372
         $reg_steps = $this->reg_steps();
1373
-        if (! is_array($reg_steps) || empty($reg_steps)) {
1373
+        if ( ! is_array($reg_steps) || empty($reg_steps)) {
1374 1374
             return false;
1375 1375
         }
1376 1376
         // loop thru reg steps array)
1377 1377
         foreach ($reg_steps as $slug => $reg_step_completed) {
1378 1378
             // if NOT checking ALL steps (only checking one step)
1379
-            if (! $check_all) {
1379
+            if ( ! $check_all) {
1380 1380
                 // and this is the one
1381 1381
                 if ($slug === $reg_step_slug) {
1382 1382
                     return $reg_step_completed;
@@ -1581,30 +1581,30 @@  discard block
 block discarded – undo
1581 1581
         // get reg steps array
1582 1582
         $txn_reg_steps = $this->reg_steps();
1583 1583
         // if reg step does NOT exist
1584
-        if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1584
+        if ( ! isset($txn_reg_steps[$reg_step_slug])) {
1585 1585
             return false;
1586 1586
         }
1587 1587
         // if  we're trying to complete a step that is already completed
1588
-        if ($txn_reg_steps[ $reg_step_slug ] === true) {
1588
+        if ($txn_reg_steps[$reg_step_slug] === true) {
1589 1589
             return true;
1590 1590
         }
1591 1591
         // if  we're trying to complete a step that hasn't even started
1592
-        if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1592
+        if ($status === true && $txn_reg_steps[$reg_step_slug] === false) {
1593 1593
             return false;
1594 1594
         }
1595 1595
         // if current status value matches the incoming value (no change)
1596 1596
         // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1597
-        if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1597
+        if ((int) $txn_reg_steps[$reg_step_slug] === (int) $status) {
1598 1598
             // this will happen in cases where multiple AJAX requests occur during the same step
1599 1599
             return true;
1600 1600
         }
1601 1601
         // if we're trying to set a start time, but it has already been set...
1602
-        if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1602
+        if (is_numeric($status) && is_numeric($txn_reg_steps[$reg_step_slug])) {
1603 1603
             // skip the update below, but don't return FALSE so that errors won't be displayed
1604 1604
             return true;
1605 1605
         }
1606 1606
         // update completed status
1607
-        $txn_reg_steps[ $reg_step_slug ] = $status;
1607
+        $txn_reg_steps[$reg_step_slug] = $status;
1608 1608
         $this->set_reg_steps($txn_reg_steps);
1609 1609
         $this->save();
1610 1610
         return true;
@@ -1628,7 +1628,7 @@  discard block
 block discarded – undo
1628 1628
     {
1629 1629
         // get reg steps array
1630 1630
         $txn_reg_steps = $this->reg_steps();
1631
-        unset($txn_reg_steps[ $reg_step_slug ]);
1631
+        unset($txn_reg_steps[$reg_step_slug]);
1632 1632
         $this->set_reg_steps($txn_reg_steps);
1633 1633
     }
1634 1634
 
@@ -1713,12 +1713,12 @@  discard block
 block discarded – undo
1713 1713
             return;
1714 1714
         }
1715 1715
         $payments = $this->get_many_related('Payment');
1716
-        if (! empty($payments)) {
1716
+        if ( ! empty($payments)) {
1717 1717
             foreach ($payments as $payment) {
1718 1718
                 if ($payment instanceof EE_Payment) {
1719 1719
                     // kk this TXN should NOT be abandoned
1720 1720
                     $this->update_status_based_on_total_paid();
1721
-                    if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1721
+                    if ( ! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1722 1722
                         EE_Error::add_attention(
1723 1723
                             sprintf(
1724 1724
                                 esc_html__(
Please login to merge, or discard this patch.
core/db_classes/EE_Payment.class.php 1 patch
Indentation   +873 added lines, -873 removed lines patch added patch discarded remove patch
@@ -11,877 +11,877 @@
 block discarded – undo
11 11
  */
12 12
 class EE_Payment extends EE_Base_Class implements EEI_Payment
13 13
 {
14
-    /**
15
-     * @param array  $props_n_values          incoming values
16
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
17
-     *                                        used.)
18
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
19
-     *                                        date_format and the second value is the time format
20
-     * @return EE_Payment
21
-     * @throws EE_Error|ReflectionException
22
-     */
23
-    public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
24
-    {
25
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
26
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
27
-    }
28
-
29
-
30
-    /**
31
-     * @param array  $props_n_values  incoming values from the database
32
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
33
-     *                                the website will be used.
34
-     * @return EE_Payment
35
-     * @throws EE_Error
36
-     */
37
-    public static function new_instance_from_db($props_n_values = [], $timezone = '')
38
-    {
39
-        return new self($props_n_values, true, $timezone);
40
-    }
41
-
42
-
43
-    /**
44
-     * Set Transaction ID
45
-     *
46
-     * @access public
47
-     * @param int $TXN_ID
48
-     * @throws EE_Error
49
-     */
50
-    public function set_transaction_id($TXN_ID = 0)
51
-    {
52
-        $this->set('TXN_ID', $TXN_ID);
53
-    }
54
-
55
-
56
-    /**
57
-     * Gets the transaction related to this payment
58
-     *
59
-     * @return EE_Transaction
60
-     * @throws EE_Error
61
-     */
62
-    public function transaction()
63
-    {
64
-        return $this->get_first_related('Transaction');
65
-    }
66
-
67
-
68
-    /**
69
-     * Set Status
70
-     *
71
-     * @access public
72
-     * @param string $STS_ID
73
-     * @throws EE_Error
74
-     */
75
-    public function set_status($STS_ID = '')
76
-    {
77
-        $this->set('STS_ID', $STS_ID);
78
-    }
79
-
80
-
81
-    /**
82
-     * Set Payment Timestamp
83
-     *
84
-     * @access public
85
-     * @param int $timestamp
86
-     * @throws EE_Error
87
-     */
88
-    public function set_timestamp($timestamp = 0)
89
-    {
90
-        $this->set('PAY_timestamp', $timestamp);
91
-    }
92
-
93
-
94
-    /**
95
-     * Set Payment Method
96
-     *
97
-     * @access public
98
-     * @param string $PAY_source
99
-     * @throws EE_Error
100
-     */
101
-    public function set_source($PAY_source = '')
102
-    {
103
-        $this->set('PAY_source', $PAY_source);
104
-    }
105
-
106
-
107
-    /**
108
-     * Set Payment Amount
109
-     *
110
-     * @access public
111
-     * @param float $amount
112
-     * @throws EE_Error
113
-     */
114
-    public function set_amount($amount = 0.00)
115
-    {
116
-        $this->set('PAY_amount', (float) $amount);
117
-    }
118
-
119
-
120
-    /**
121
-     * Set Payment Gateway Response
122
-     *
123
-     * @access public
124
-     * @param string $gateway_response
125
-     * @throws EE_Error
126
-     */
127
-    public function set_gateway_response($gateway_response = '')
128
-    {
129
-        $this->set('PAY_gateway_response', $gateway_response);
130
-    }
131
-
132
-
133
-    /**
134
-     * Returns the name of the payment method used on this payment (previously known merely as 'gateway')
135
-     * but since 4.6.0, payment methods are models and the payment keeps a foreign key to the payment method
136
-     * used on it
137
-     *
138
-     * @return string
139
-     * @throws EE_Error
140
-     * @deprecated
141
-     */
142
-    public function gateway()
143
-    {
144
-        EE_Error::doing_it_wrong(
145
-            'EE_Payment::gateway',
146
-            esc_html__(
147
-                'The method EE_Payment::gateway() has been deprecated. Consider instead using EE_Payment::payment_method()->name()',
148
-                'event_espresso'
149
-            ),
150
-            '4.6.0'
151
-        );
152
-        return $this->payment_method() ? $this->payment_method()->name() : esc_html__('Unknown', 'event_espresso');
153
-    }
154
-
155
-
156
-    /**
157
-     * Set Gateway Transaction ID
158
-     *
159
-     * @access public
160
-     * @param string $txn_id_chq_nmbr
161
-     * @throws EE_Error
162
-     */
163
-    public function set_txn_id_chq_nmbr($txn_id_chq_nmbr = '')
164
-    {
165
-        $this->set('PAY_txn_id_chq_nmbr', $txn_id_chq_nmbr);
166
-    }
167
-
168
-
169
-    /**
170
-     * Set Purchase Order Number
171
-     *
172
-     * @access public
173
-     * @param string $po_number
174
-     * @throws EE_Error
175
-     */
176
-    public function set_po_number($po_number = '')
177
-    {
178
-        $this->set('PAY_po_number', $po_number);
179
-    }
180
-
181
-
182
-    /**
183
-     * Set Extra Accounting Field
184
-     *
185
-     * @access public
186
-     * @param string $extra_accntng
187
-     * @throws EE_Error
188
-     */
189
-    public function set_extra_accntng($extra_accntng = '')
190
-    {
191
-        $this->set('PAY_extra_accntng', $extra_accntng);
192
-    }
193
-
194
-
195
-    /**
196
-     * Set Payment made via admin flag
197
-     *
198
-     * @access public
199
-     * @param bool $via_admin
200
-     * @throws EE_Error
201
-     */
202
-    public function set_payment_made_via_admin($via_admin = false)
203
-    {
204
-        if ($via_admin) {
205
-            $this->set('PAY_source', EEM_Payment_Method::scope_admin);
206
-        } else {
207
-            $this->set('PAY_source', EEM_Payment_Method::scope_cart);
208
-        }
209
-    }
210
-
211
-
212
-    /**
213
-     * Set Payment Details
214
-     *
215
-     * @access public
216
-     * @param string|array $details
217
-     * @throws EE_Error
218
-     */
219
-    public function set_details($details = '')
220
-    {
221
-        if (is_array($details)) {
222
-            array_walk_recursive($details, [$this, '_strip_all_tags_within_array']);
223
-        } else {
224
-            $details = wp_strip_all_tags($details);
225
-        }
226
-        $this->set('PAY_details', $details);
227
-    }
228
-
229
-
230
-    /**
231
-     * Sets redirect_url
232
-     *
233
-     * @param string $redirect_url
234
-     * @throws EE_Error
235
-     */
236
-    public function set_redirect_url($redirect_url)
237
-    {
238
-        $this->set('PAY_redirect_url', $redirect_url);
239
-    }
240
-
241
-
242
-    /**
243
-     * Sets redirect_args
244
-     *
245
-     * @param array $redirect_args
246
-     * @throws EE_Error
247
-     */
248
-    public function set_redirect_args($redirect_args)
249
-    {
250
-        $this->set('PAY_redirect_args', $redirect_args);
251
-    }
252
-
253
-
254
-    /**
255
-     * get Payment Transaction ID
256
-     *
257
-     * @access public
258
-     * @throws EE_Error
259
-     */
260
-    public function TXN_ID()
261
-    {
262
-        return $this->get('TXN_ID');
263
-    }
264
-
265
-
266
-    /**
267
-     * get Payment Status
268
-     *
269
-     * @access public
270
-     * @throws EE_Error
271
-     */
272
-    public function status()
273
-    {
274
-        return $this->get('STS_ID');
275
-    }
276
-
277
-
278
-    /**
279
-     * get Payment Status
280
-     *
281
-     * @access public
282
-     * @throws EE_Error
283
-     */
284
-    public function STS_ID()
285
-    {
286
-        return $this->get('STS_ID');
287
-    }
288
-
289
-
290
-    /**
291
-     * get Payment Timestamp
292
-     *
293
-     * @access public
294
-     * @param string $dt_frmt
295
-     * @param string $tm_frmt
296
-     * @return string
297
-     * @throws EE_Error
298
-     */
299
-    public function timestamp($dt_frmt = '', $tm_frmt = '')
300
-    {
301
-        return $this->get_i18n_datetime('PAY_timestamp', trim($dt_frmt . ' ' . $tm_frmt));
302
-    }
303
-
304
-
305
-    /**
306
-     * get Payment Source
307
-     *
308
-     * @access public
309
-     * @throws EE_Error
310
-     */
311
-    public function source()
312
-    {
313
-        return $this->get('PAY_source');
314
-    }
315
-
316
-
317
-    /**
318
-     * get Payment Amount
319
-     *
320
-     * @access public
321
-     * @return float
322
-     * @throws EE_Error
323
-     */
324
-    public function amount()
325
-    {
326
-        return (float) $this->get('PAY_amount');
327
-    }
328
-
329
-
330
-    /**
331
-     * @return mixed
332
-     * @throws EE_Error
333
-     */
334
-    public function amount_no_code()
335
-    {
336
-        return $this->get_pretty('PAY_amount', 'no_currency_code');
337
-    }
338
-
339
-
340
-    /**
341
-     * get Payment Gateway Response
342
-     *
343
-     * @access public
344
-     * @throws EE_Error
345
-     */
346
-    public function gateway_response()
347
-    {
348
-        return $this->get('PAY_gateway_response');
349
-    }
350
-
351
-
352
-    /**
353
-     * get Payment Gateway Transaction ID
354
-     *
355
-     * @access public
356
-     * @throws EE_Error
357
-     */
358
-    public function txn_id_chq_nmbr()
359
-    {
360
-        return $this->get('PAY_txn_id_chq_nmbr');
361
-    }
362
-
363
-
364
-    /**
365
-     * get Purchase Order Number
366
-     *
367
-     * @access public
368
-     * @throws EE_Error
369
-     */
370
-    public function po_number()
371
-    {
372
-        return $this->get('PAY_po_number');
373
-    }
374
-
375
-
376
-    /**
377
-     * get Extra Accounting Field
378
-     *
379
-     * @access public
380
-     * @throws EE_Error
381
-     */
382
-    public function extra_accntng()
383
-    {
384
-        return $this->get('PAY_extra_accntng');
385
-    }
386
-
387
-
388
-    /**
389
-     * get Payment made via admin source
390
-     *
391
-     * @access public
392
-     * @throws EE_Error
393
-     */
394
-    public function payment_made_via_admin()
395
-    {
396
-        return ($this->get('PAY_source') === EEM_Payment_Method::scope_admin);
397
-    }
398
-
399
-
400
-    /**
401
-     * get Payment Details
402
-     *
403
-     * @access public
404
-     * @throws EE_Error
405
-     */
406
-    public function details()
407
-    {
408
-        return $this->get('PAY_details');
409
-    }
410
-
411
-
412
-    /**
413
-     * Gets redirect_url
414
-     *
415
-     * @return string
416
-     * @throws EE_Error
417
-     */
418
-    public function redirect_url()
419
-    {
420
-        return $this->get('PAY_redirect_url');
421
-    }
422
-
423
-
424
-    /**
425
-     * Gets redirect_args
426
-     *
427
-     * @return array
428
-     * @throws EE_Error
429
-     */
430
-    public function redirect_args()
431
-    {
432
-        return $this->get('PAY_redirect_args');
433
-    }
434
-
435
-
436
-    /**
437
-     * echoes $this->pretty_status()
438
-     *
439
-     * @param bool $show_icons
440
-     * @return void
441
-     * @throws EE_Error
442
-     */
443
-    public function e_pretty_status($show_icons = false)
444
-    {
445
-        echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
446
-    }
447
-
448
-
449
-    /**
450
-     * returns a pretty version of the status, good for displaying to users
451
-     *
452
-     * @param bool $show_icons
453
-     * @return string
454
-     * @throws EE_Error
455
-     */
456
-    public function pretty_status($show_icons = false)
457
-    {
458
-        $status = EEM_Status::instance()->localized_status(
459
-            [$this->STS_ID() => esc_html__('unknown', 'event_espresso')],
460
-            false,
461
-            'sentence'
462
-        );
463
-        $icon   = '';
464
-        switch ($this->STS_ID()) {
465
-            case EEM_Payment::status_id_approved:
466
-                $icon = $show_icons
467
-                    ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>'
468
-                    : '';
469
-                break;
470
-            case EEM_Payment::status_id_pending:
471
-                $icon = $show_icons
472
-                    ? '<span class="dashicons dashicons-clock ee-icon-size-16 orange-text"></span>'
473
-                    : '';
474
-                break;
475
-            case EEM_Payment::status_id_cancelled:
476
-                $icon = $show_icons
477
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
478
-                    : '';
479
-                break;
480
-            case EEM_Payment::status_id_declined:
481
-                $icon = $show_icons
482
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
483
-                    : '';
484
-                break;
485
-        }
486
-        return $icon . $status[ $this->STS_ID() ];
487
-    }
488
-
489
-
490
-    /**
491
-     * For determining the status of the payment
492
-     *
493
-     * @return boolean whether the payment is approved or not
494
-     * @throws EE_Error
495
-     */
496
-    public function is_approved()
497
-    {
498
-        return $this->status_is(EEM_Payment::status_id_approved);
499
-    }
500
-
501
-
502
-    /**
503
-     * Generally determines if the status of this payment equals
504
-     * the $STS_ID string
505
-     *
506
-     * @param string $STS_ID an ID from the esp_status table/
507
-     *                       one of the status_id_* on the EEM_Payment model
508
-     * @return boolean whether the status of this payment equals the status id
509
-     * @throws EE_Error
510
-     */
511
-    protected function status_is($STS_ID)
512
-    {
513
-        return $STS_ID === $this->STS_ID() ? true : false;
514
-    }
515
-
516
-
517
-    /**
518
-     * For determining the status of the payment
519
-     *
520
-     * @return boolean whether the payment is pending or not
521
-     * @throws EE_Error
522
-     */
523
-    public function is_pending()
524
-    {
525
-        return $this->status_is(EEM_Payment::status_id_pending);
526
-    }
527
-
528
-
529
-    /**
530
-     * For determining the status of the payment
531
-     *
532
-     * @return boolean
533
-     * @throws EE_Error
534
-     */
535
-    public function is_cancelled()
536
-    {
537
-        return $this->status_is(EEM_Payment::status_id_cancelled);
538
-    }
539
-
540
-
541
-    /**
542
-     * For determining the status of the payment
543
-     *
544
-     * @return boolean
545
-     * @throws EE_Error
546
-     */
547
-    public function is_declined()
548
-    {
549
-        return $this->status_is(EEM_Payment::status_id_declined);
550
-    }
551
-
552
-
553
-    /**
554
-     * For determining the status of the payment
555
-     *
556
-     * @return boolean
557
-     * @throws EE_Error
558
-     */
559
-    public function is_failed()
560
-    {
561
-        return $this->status_is(EEM_Payment::status_id_failed);
562
-    }
563
-
564
-
565
-    /**
566
-     * For determining if the payment is actually a refund ( ie: has a negative value )
567
-     *
568
-     * @return boolean
569
-     * @throws EE_Error
570
-     */
571
-    public function is_a_refund()
572
-    {
573
-        return $this->amount() < 0;
574
-    }
575
-
576
-
577
-    /**
578
-     * Get the status object of this object
579
-     *
580
-     * @return EE_Status
581
-     * @throws EE_Error
582
-     */
583
-    public function status_obj()
584
-    {
585
-        return $this->get_first_related('Status');
586
-    }
587
-
588
-
589
-    /**
590
-     * Gets all the extra meta info on this payment
591
-     *
592
-     * @param array $query_params @see
593
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
594
-     * @return EE_Extra_Meta
595
-     * @throws EE_Error
596
-     */
597
-    public function extra_meta($query_params = [])
598
-    {
599
-        return $this->get_many_related('Extra_Meta', $query_params);
600
-    }
601
-
602
-
603
-    /**
604
-     * Gets the last-used payment method on this transaction
605
-     * (we COULD just use the last-made payment, but some payment methods, namely
606
-     * offline ones, dont' create payments)
607
-     *
608
-     * @return EE_Payment_Method
609
-     * @throws EE_Error
610
-     */
611
-    public function payment_method()
612
-    {
613
-        return $this->get_first_related('Payment_Method');
614
-    }
615
-
616
-
617
-    /**
618
-     * Gets the HTML for redirecting the user to an offsite gateway
619
-     * You can pass it special content to put inside the form, or use
620
-     * the default inner content (or possibly generate this all yourself using
621
-     * redirect_url() and redirect_args() or redirect_args_as_inputs()).
622
-     * Creates a POST request by default, but if no redirect args are specified, creates a GET request instead
623
-     * (and any querystring variables in the redirect_url are converted into html inputs
624
-     * so browsers submit them properly)
625
-     *
626
-     * @param string $inside_form_html
627
-     * @return string html
628
-     * @throws EE_Error
629
-     */
630
-    public function redirect_form($inside_form_html = null)
631
-    {
632
-        $redirect_url = $this->redirect_url();
633
-        if (! empty($redirect_url)) {
634
-            // what ? no inner form content?
635
-            if ($inside_form_html === null) {
636
-                $inside_form_html = EEH_HTML::p(
637
-                    sprintf(
638
-                        esc_html__(
639
-                            'If you are not automatically redirected to the payment website within 10 seconds... %1$s %2$s Click Here %3$s',
640
-                            'event_espresso'
641
-                        ),
642
-                        EEH_HTML::br(2),
643
-                        '<input type="submit" value="',
644
-                        '">'
645
-                    ),
646
-                    '',
647
-                    '',
648
-                    'text-align:center;'
649
-                );
650
-            }
651
-            $method = apply_filters(
652
-                'FHEE__EE_Payment__redirect_form__method',
653
-                $this->redirect_args() ? 'POST' : 'GET',
654
-                $this
655
-            );
656
-            // if it's a GET request, we need to remove all the GET params in the querystring
657
-            // and put them into the form instead
658
-            if ($method === 'GET') {
659
-                $querystring = parse_url($redirect_url, PHP_URL_QUERY);
660
-                $get_params  = null;
661
-                parse_str($querystring, $get_params);
662
-                $inside_form_html .= $this->_args_as_inputs($get_params);
663
-                $redirect_url     = str_replace('?' . $querystring, '', $redirect_url);
664
-            }
665
-            $form = EEH_HTML::nl(1)
666
-                    . '<form method="'
667
-                    . $method
668
-                    . '" name="gateway_form" action="'
669
-                    . $redirect_url
670
-                    . '">';
671
-            $form .= EEH_HTML::nl(1) . $this->redirect_args_as_inputs();
672
-            $form .= $inside_form_html;
673
-            $form .= EEH_HTML::nl(-1) . '</form>' . EEH_HTML::nl(-1);
674
-            return $form;
675
-        } else {
676
-            return null;
677
-        }
678
-    }
679
-
680
-
681
-    /**
682
-     * Changes all the name-value pairs of the redirect args into html inputs
683
-     * and returns the html as a string
684
-     *
685
-     * @return string
686
-     * @throws EE_Error
687
-     */
688
-    public function redirect_args_as_inputs()
689
-    {
690
-        return $this->_args_as_inputs($this->redirect_args());
691
-    }
692
-
693
-
694
-    /**
695
-     * Converts a 2d array of key-value pairs into html hidden inputs
696
-     * and returns the string of html
697
-     *
698
-     * @param array $args key-value pairs
699
-     * @return string
700
-     */
701
-    protected function _args_as_inputs($args)
702
-    {
703
-        $html = '';
704
-        if ($args !== null && is_array($args)) {
705
-            foreach ($args as $name => $value) {
706
-                $html .= $this->generateInput($name, $value);
707
-            }
708
-        }
709
-        return $html;
710
-    }
711
-
712
-
713
-    /**
714
-     * Converts either a single name and value or array of values into html hidden inputs
715
-     * and returns the string of html
716
-     *
717
-     * @param string       $name
718
-     * @param string|array $value
719
-     * @return string
720
-     */
721
-    private function generateInput($name, $value)
722
-    {
723
-        if (is_array($value)) {
724
-            $html = '';
725
-            $name = "{$name}[]";
726
-            foreach ($value as $array_value) {
727
-                $html .= $this->generateInput($name, $array_value);
728
-            }
729
-            return $html;
730
-        }
731
-        return EEH_HTML::nl()
732
-               . '<input type="hidden" name="' . $name . '"'
733
-               . ' value="' . esc_attr($value) . '"/>';
734
-    }
735
-
736
-
737
-    /**
738
-     * Returns the currency of the payment.
739
-     * (At the time of writing, this will always be the currency in the configuration;
740
-     * however in the future it is anticipated that this will be stored on the payment
741
-     * object itself)
742
-     *
743
-     * @return string for the currency code
744
-     */
745
-    public function currency_code()
746
-    {
747
-        return EE_Config::instance()->currency->code;
748
-    }
749
-
750
-
751
-    /**
752
-     * apply wp_strip_all_tags to all elements within an array
753
-     *
754
-     * @access private
755
-     * @param mixed $item
756
-     */
757
-    private function _strip_all_tags_within_array(&$item)
758
-    {
759
-        if (is_object($item)) {
760
-            $item = (array) $item;
761
-        }
762
-        if (is_array($item)) {
763
-            array_walk_recursive($item, [$this, '_strip_all_tags_within_array']);
764
-        } else {
765
-            $item = wp_strip_all_tags((string) $item);
766
-        }
767
-    }
768
-
769
-
770
-    /**
771
-     * Returns TRUE is this payment was set to approved during this request (or
772
-     * is approved and was created during this request). False otherwise.
773
-     *
774
-     * @return boolean
775
-     * @throws EE_Error
776
-     */
777
-    public function just_approved()
778
-    {
779
-        $original_status = EEH_Array::is_set(
780
-            $this->_props_n_values_provided_in_constructor,
781
-            'STS_ID',
782
-            $this->get_model()->field_settings_for('STS_ID')->get_default_value()
783
-        );
784
-        $current_status  = $this->status();
785
-        if (
786
-            $original_status !== EEM_Payment::status_id_approved
787
-            && $current_status === EEM_Payment::status_id_approved
788
-        ) {
789
-            return true;
790
-        } else {
791
-            return false;
792
-        }
793
-    }
794
-
795
-
796
-    /**
797
-     * Overrides parents' get_pretty() function just for legacy reasons
798
-     * (to allow ticket https://events.codebasehq.com/projects/event-espresso/tickets/7420)
799
-     *
800
-     * @param string $field_name
801
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
802
-     *                                (in cases where the same property may be used for different outputs
803
-     *                                - i.e. datetime, money etc.)
804
-     * @return mixed
805
-     * @throws EE_Error
806
-     */
807
-    public function get_pretty($field_name, $extra_cache_ref = null)
808
-    {
809
-        if ($field_name === 'PAY_gateway') {
810
-            return $this->payment_method() ? $this->payment_method()->name() : esc_html__('Unknown', 'event_espresso');
811
-        }
812
-        return $this->_get_cached_property($field_name, true, $extra_cache_ref);
813
-    }
814
-
815
-
816
-    /**
817
-     * Gets details regarding which registrations this payment was applied to
818
-     *
819
-     * @param array $query_params @see
820
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
821
-     * @return EE_Registration_Payment[]
822
-     * @throws EE_Error
823
-     */
824
-    public function registration_payments($query_params = [])
825
-    {
826
-        return $this->get_many_related('Registration_Payment', $query_params);
827
-    }
828
-
829
-
830
-    /**
831
-     * Gets the first event for this payment (it's possible that it could be for multiple)
832
-     *
833
-     * @return EE_Event|null
834
-     */
835
-    public function get_first_event()
836
-    {
837
-        $transaction = $this->transaction();
838
-        if ($transaction instanceof EE_Transaction) {
839
-            $primary_registrant = $transaction->primary_registration();
840
-            if ($primary_registrant instanceof EE_Registration) {
841
-                return $primary_registrant->event_obj();
842
-            }
843
-        }
844
-        return null;
845
-    }
846
-
847
-
848
-    /**
849
-     * Gets the name of the first event for which is being paid
850
-     *
851
-     * @return string
852
-     */
853
-    public function get_first_event_name()
854
-    {
855
-        $event = $this->get_first_event();
856
-        return $event instanceof EE_Event ? $event->name() : esc_html__('Event', 'event_espresso');
857
-    }
858
-
859
-
860
-    /**
861
-     * Returns the payment's transaction's primary registration
862
-     *
863
-     * @return EE_Registration|null
864
-     */
865
-    public function get_primary_registration()
866
-    {
867
-        if ($this->transaction() instanceof EE_Transaction) {
868
-            return $this->transaction()->primary_registration();
869
-        }
870
-        return null;
871
-    }
872
-
873
-
874
-    /**
875
-     * Gets the payment's transaction's primary registration's attendee, or null
876
-     *
877
-     * @return EE_Attendee|null
878
-     */
879
-    public function get_primary_attendee()
880
-    {
881
-        $primary_reg = $this->get_primary_registration();
882
-        if ($primary_reg instanceof EE_Registration) {
883
-            return $primary_reg->attendee();
884
-        }
885
-        return null;
886
-    }
14
+	/**
15
+	 * @param array  $props_n_values          incoming values
16
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
17
+	 *                                        used.)
18
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
19
+	 *                                        date_format and the second value is the time format
20
+	 * @return EE_Payment
21
+	 * @throws EE_Error|ReflectionException
22
+	 */
23
+	public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
24
+	{
25
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
26
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
27
+	}
28
+
29
+
30
+	/**
31
+	 * @param array  $props_n_values  incoming values from the database
32
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
33
+	 *                                the website will be used.
34
+	 * @return EE_Payment
35
+	 * @throws EE_Error
36
+	 */
37
+	public static function new_instance_from_db($props_n_values = [], $timezone = '')
38
+	{
39
+		return new self($props_n_values, true, $timezone);
40
+	}
41
+
42
+
43
+	/**
44
+	 * Set Transaction ID
45
+	 *
46
+	 * @access public
47
+	 * @param int $TXN_ID
48
+	 * @throws EE_Error
49
+	 */
50
+	public function set_transaction_id($TXN_ID = 0)
51
+	{
52
+		$this->set('TXN_ID', $TXN_ID);
53
+	}
54
+
55
+
56
+	/**
57
+	 * Gets the transaction related to this payment
58
+	 *
59
+	 * @return EE_Transaction
60
+	 * @throws EE_Error
61
+	 */
62
+	public function transaction()
63
+	{
64
+		return $this->get_first_related('Transaction');
65
+	}
66
+
67
+
68
+	/**
69
+	 * Set Status
70
+	 *
71
+	 * @access public
72
+	 * @param string $STS_ID
73
+	 * @throws EE_Error
74
+	 */
75
+	public function set_status($STS_ID = '')
76
+	{
77
+		$this->set('STS_ID', $STS_ID);
78
+	}
79
+
80
+
81
+	/**
82
+	 * Set Payment Timestamp
83
+	 *
84
+	 * @access public
85
+	 * @param int $timestamp
86
+	 * @throws EE_Error
87
+	 */
88
+	public function set_timestamp($timestamp = 0)
89
+	{
90
+		$this->set('PAY_timestamp', $timestamp);
91
+	}
92
+
93
+
94
+	/**
95
+	 * Set Payment Method
96
+	 *
97
+	 * @access public
98
+	 * @param string $PAY_source
99
+	 * @throws EE_Error
100
+	 */
101
+	public function set_source($PAY_source = '')
102
+	{
103
+		$this->set('PAY_source', $PAY_source);
104
+	}
105
+
106
+
107
+	/**
108
+	 * Set Payment Amount
109
+	 *
110
+	 * @access public
111
+	 * @param float $amount
112
+	 * @throws EE_Error
113
+	 */
114
+	public function set_amount($amount = 0.00)
115
+	{
116
+		$this->set('PAY_amount', (float) $amount);
117
+	}
118
+
119
+
120
+	/**
121
+	 * Set Payment Gateway Response
122
+	 *
123
+	 * @access public
124
+	 * @param string $gateway_response
125
+	 * @throws EE_Error
126
+	 */
127
+	public function set_gateway_response($gateway_response = '')
128
+	{
129
+		$this->set('PAY_gateway_response', $gateway_response);
130
+	}
131
+
132
+
133
+	/**
134
+	 * Returns the name of the payment method used on this payment (previously known merely as 'gateway')
135
+	 * but since 4.6.0, payment methods are models and the payment keeps a foreign key to the payment method
136
+	 * used on it
137
+	 *
138
+	 * @return string
139
+	 * @throws EE_Error
140
+	 * @deprecated
141
+	 */
142
+	public function gateway()
143
+	{
144
+		EE_Error::doing_it_wrong(
145
+			'EE_Payment::gateway',
146
+			esc_html__(
147
+				'The method EE_Payment::gateway() has been deprecated. Consider instead using EE_Payment::payment_method()->name()',
148
+				'event_espresso'
149
+			),
150
+			'4.6.0'
151
+		);
152
+		return $this->payment_method() ? $this->payment_method()->name() : esc_html__('Unknown', 'event_espresso');
153
+	}
154
+
155
+
156
+	/**
157
+	 * Set Gateway Transaction ID
158
+	 *
159
+	 * @access public
160
+	 * @param string $txn_id_chq_nmbr
161
+	 * @throws EE_Error
162
+	 */
163
+	public function set_txn_id_chq_nmbr($txn_id_chq_nmbr = '')
164
+	{
165
+		$this->set('PAY_txn_id_chq_nmbr', $txn_id_chq_nmbr);
166
+	}
167
+
168
+
169
+	/**
170
+	 * Set Purchase Order Number
171
+	 *
172
+	 * @access public
173
+	 * @param string $po_number
174
+	 * @throws EE_Error
175
+	 */
176
+	public function set_po_number($po_number = '')
177
+	{
178
+		$this->set('PAY_po_number', $po_number);
179
+	}
180
+
181
+
182
+	/**
183
+	 * Set Extra Accounting Field
184
+	 *
185
+	 * @access public
186
+	 * @param string $extra_accntng
187
+	 * @throws EE_Error
188
+	 */
189
+	public function set_extra_accntng($extra_accntng = '')
190
+	{
191
+		$this->set('PAY_extra_accntng', $extra_accntng);
192
+	}
193
+
194
+
195
+	/**
196
+	 * Set Payment made via admin flag
197
+	 *
198
+	 * @access public
199
+	 * @param bool $via_admin
200
+	 * @throws EE_Error
201
+	 */
202
+	public function set_payment_made_via_admin($via_admin = false)
203
+	{
204
+		if ($via_admin) {
205
+			$this->set('PAY_source', EEM_Payment_Method::scope_admin);
206
+		} else {
207
+			$this->set('PAY_source', EEM_Payment_Method::scope_cart);
208
+		}
209
+	}
210
+
211
+
212
+	/**
213
+	 * Set Payment Details
214
+	 *
215
+	 * @access public
216
+	 * @param string|array $details
217
+	 * @throws EE_Error
218
+	 */
219
+	public function set_details($details = '')
220
+	{
221
+		if (is_array($details)) {
222
+			array_walk_recursive($details, [$this, '_strip_all_tags_within_array']);
223
+		} else {
224
+			$details = wp_strip_all_tags($details);
225
+		}
226
+		$this->set('PAY_details', $details);
227
+	}
228
+
229
+
230
+	/**
231
+	 * Sets redirect_url
232
+	 *
233
+	 * @param string $redirect_url
234
+	 * @throws EE_Error
235
+	 */
236
+	public function set_redirect_url($redirect_url)
237
+	{
238
+		$this->set('PAY_redirect_url', $redirect_url);
239
+	}
240
+
241
+
242
+	/**
243
+	 * Sets redirect_args
244
+	 *
245
+	 * @param array $redirect_args
246
+	 * @throws EE_Error
247
+	 */
248
+	public function set_redirect_args($redirect_args)
249
+	{
250
+		$this->set('PAY_redirect_args', $redirect_args);
251
+	}
252
+
253
+
254
+	/**
255
+	 * get Payment Transaction ID
256
+	 *
257
+	 * @access public
258
+	 * @throws EE_Error
259
+	 */
260
+	public function TXN_ID()
261
+	{
262
+		return $this->get('TXN_ID');
263
+	}
264
+
265
+
266
+	/**
267
+	 * get Payment Status
268
+	 *
269
+	 * @access public
270
+	 * @throws EE_Error
271
+	 */
272
+	public function status()
273
+	{
274
+		return $this->get('STS_ID');
275
+	}
276
+
277
+
278
+	/**
279
+	 * get Payment Status
280
+	 *
281
+	 * @access public
282
+	 * @throws EE_Error
283
+	 */
284
+	public function STS_ID()
285
+	{
286
+		return $this->get('STS_ID');
287
+	}
288
+
289
+
290
+	/**
291
+	 * get Payment Timestamp
292
+	 *
293
+	 * @access public
294
+	 * @param string $dt_frmt
295
+	 * @param string $tm_frmt
296
+	 * @return string
297
+	 * @throws EE_Error
298
+	 */
299
+	public function timestamp($dt_frmt = '', $tm_frmt = '')
300
+	{
301
+		return $this->get_i18n_datetime('PAY_timestamp', trim($dt_frmt . ' ' . $tm_frmt));
302
+	}
303
+
304
+
305
+	/**
306
+	 * get Payment Source
307
+	 *
308
+	 * @access public
309
+	 * @throws EE_Error
310
+	 */
311
+	public function source()
312
+	{
313
+		return $this->get('PAY_source');
314
+	}
315
+
316
+
317
+	/**
318
+	 * get Payment Amount
319
+	 *
320
+	 * @access public
321
+	 * @return float
322
+	 * @throws EE_Error
323
+	 */
324
+	public function amount()
325
+	{
326
+		return (float) $this->get('PAY_amount');
327
+	}
328
+
329
+
330
+	/**
331
+	 * @return mixed
332
+	 * @throws EE_Error
333
+	 */
334
+	public function amount_no_code()
335
+	{
336
+		return $this->get_pretty('PAY_amount', 'no_currency_code');
337
+	}
338
+
339
+
340
+	/**
341
+	 * get Payment Gateway Response
342
+	 *
343
+	 * @access public
344
+	 * @throws EE_Error
345
+	 */
346
+	public function gateway_response()
347
+	{
348
+		return $this->get('PAY_gateway_response');
349
+	}
350
+
351
+
352
+	/**
353
+	 * get Payment Gateway Transaction ID
354
+	 *
355
+	 * @access public
356
+	 * @throws EE_Error
357
+	 */
358
+	public function txn_id_chq_nmbr()
359
+	{
360
+		return $this->get('PAY_txn_id_chq_nmbr');
361
+	}
362
+
363
+
364
+	/**
365
+	 * get Purchase Order Number
366
+	 *
367
+	 * @access public
368
+	 * @throws EE_Error
369
+	 */
370
+	public function po_number()
371
+	{
372
+		return $this->get('PAY_po_number');
373
+	}
374
+
375
+
376
+	/**
377
+	 * get Extra Accounting Field
378
+	 *
379
+	 * @access public
380
+	 * @throws EE_Error
381
+	 */
382
+	public function extra_accntng()
383
+	{
384
+		return $this->get('PAY_extra_accntng');
385
+	}
386
+
387
+
388
+	/**
389
+	 * get Payment made via admin source
390
+	 *
391
+	 * @access public
392
+	 * @throws EE_Error
393
+	 */
394
+	public function payment_made_via_admin()
395
+	{
396
+		return ($this->get('PAY_source') === EEM_Payment_Method::scope_admin);
397
+	}
398
+
399
+
400
+	/**
401
+	 * get Payment Details
402
+	 *
403
+	 * @access public
404
+	 * @throws EE_Error
405
+	 */
406
+	public function details()
407
+	{
408
+		return $this->get('PAY_details');
409
+	}
410
+
411
+
412
+	/**
413
+	 * Gets redirect_url
414
+	 *
415
+	 * @return string
416
+	 * @throws EE_Error
417
+	 */
418
+	public function redirect_url()
419
+	{
420
+		return $this->get('PAY_redirect_url');
421
+	}
422
+
423
+
424
+	/**
425
+	 * Gets redirect_args
426
+	 *
427
+	 * @return array
428
+	 * @throws EE_Error
429
+	 */
430
+	public function redirect_args()
431
+	{
432
+		return $this->get('PAY_redirect_args');
433
+	}
434
+
435
+
436
+	/**
437
+	 * echoes $this->pretty_status()
438
+	 *
439
+	 * @param bool $show_icons
440
+	 * @return void
441
+	 * @throws EE_Error
442
+	 */
443
+	public function e_pretty_status($show_icons = false)
444
+	{
445
+		echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
446
+	}
447
+
448
+
449
+	/**
450
+	 * returns a pretty version of the status, good for displaying to users
451
+	 *
452
+	 * @param bool $show_icons
453
+	 * @return string
454
+	 * @throws EE_Error
455
+	 */
456
+	public function pretty_status($show_icons = false)
457
+	{
458
+		$status = EEM_Status::instance()->localized_status(
459
+			[$this->STS_ID() => esc_html__('unknown', 'event_espresso')],
460
+			false,
461
+			'sentence'
462
+		);
463
+		$icon   = '';
464
+		switch ($this->STS_ID()) {
465
+			case EEM_Payment::status_id_approved:
466
+				$icon = $show_icons
467
+					? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>'
468
+					: '';
469
+				break;
470
+			case EEM_Payment::status_id_pending:
471
+				$icon = $show_icons
472
+					? '<span class="dashicons dashicons-clock ee-icon-size-16 orange-text"></span>'
473
+					: '';
474
+				break;
475
+			case EEM_Payment::status_id_cancelled:
476
+				$icon = $show_icons
477
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
478
+					: '';
479
+				break;
480
+			case EEM_Payment::status_id_declined:
481
+				$icon = $show_icons
482
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
483
+					: '';
484
+				break;
485
+		}
486
+		return $icon . $status[ $this->STS_ID() ];
487
+	}
488
+
489
+
490
+	/**
491
+	 * For determining the status of the payment
492
+	 *
493
+	 * @return boolean whether the payment is approved or not
494
+	 * @throws EE_Error
495
+	 */
496
+	public function is_approved()
497
+	{
498
+		return $this->status_is(EEM_Payment::status_id_approved);
499
+	}
500
+
501
+
502
+	/**
503
+	 * Generally determines if the status of this payment equals
504
+	 * the $STS_ID string
505
+	 *
506
+	 * @param string $STS_ID an ID from the esp_status table/
507
+	 *                       one of the status_id_* on the EEM_Payment model
508
+	 * @return boolean whether the status of this payment equals the status id
509
+	 * @throws EE_Error
510
+	 */
511
+	protected function status_is($STS_ID)
512
+	{
513
+		return $STS_ID === $this->STS_ID() ? true : false;
514
+	}
515
+
516
+
517
+	/**
518
+	 * For determining the status of the payment
519
+	 *
520
+	 * @return boolean whether the payment is pending or not
521
+	 * @throws EE_Error
522
+	 */
523
+	public function is_pending()
524
+	{
525
+		return $this->status_is(EEM_Payment::status_id_pending);
526
+	}
527
+
528
+
529
+	/**
530
+	 * For determining the status of the payment
531
+	 *
532
+	 * @return boolean
533
+	 * @throws EE_Error
534
+	 */
535
+	public function is_cancelled()
536
+	{
537
+		return $this->status_is(EEM_Payment::status_id_cancelled);
538
+	}
539
+
540
+
541
+	/**
542
+	 * For determining the status of the payment
543
+	 *
544
+	 * @return boolean
545
+	 * @throws EE_Error
546
+	 */
547
+	public function is_declined()
548
+	{
549
+		return $this->status_is(EEM_Payment::status_id_declined);
550
+	}
551
+
552
+
553
+	/**
554
+	 * For determining the status of the payment
555
+	 *
556
+	 * @return boolean
557
+	 * @throws EE_Error
558
+	 */
559
+	public function is_failed()
560
+	{
561
+		return $this->status_is(EEM_Payment::status_id_failed);
562
+	}
563
+
564
+
565
+	/**
566
+	 * For determining if the payment is actually a refund ( ie: has a negative value )
567
+	 *
568
+	 * @return boolean
569
+	 * @throws EE_Error
570
+	 */
571
+	public function is_a_refund()
572
+	{
573
+		return $this->amount() < 0;
574
+	}
575
+
576
+
577
+	/**
578
+	 * Get the status object of this object
579
+	 *
580
+	 * @return EE_Status
581
+	 * @throws EE_Error
582
+	 */
583
+	public function status_obj()
584
+	{
585
+		return $this->get_first_related('Status');
586
+	}
587
+
588
+
589
+	/**
590
+	 * Gets all the extra meta info on this payment
591
+	 *
592
+	 * @param array $query_params @see
593
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
594
+	 * @return EE_Extra_Meta
595
+	 * @throws EE_Error
596
+	 */
597
+	public function extra_meta($query_params = [])
598
+	{
599
+		return $this->get_many_related('Extra_Meta', $query_params);
600
+	}
601
+
602
+
603
+	/**
604
+	 * Gets the last-used payment method on this transaction
605
+	 * (we COULD just use the last-made payment, but some payment methods, namely
606
+	 * offline ones, dont' create payments)
607
+	 *
608
+	 * @return EE_Payment_Method
609
+	 * @throws EE_Error
610
+	 */
611
+	public function payment_method()
612
+	{
613
+		return $this->get_first_related('Payment_Method');
614
+	}
615
+
616
+
617
+	/**
618
+	 * Gets the HTML for redirecting the user to an offsite gateway
619
+	 * You can pass it special content to put inside the form, or use
620
+	 * the default inner content (or possibly generate this all yourself using
621
+	 * redirect_url() and redirect_args() or redirect_args_as_inputs()).
622
+	 * Creates a POST request by default, but if no redirect args are specified, creates a GET request instead
623
+	 * (and any querystring variables in the redirect_url are converted into html inputs
624
+	 * so browsers submit them properly)
625
+	 *
626
+	 * @param string $inside_form_html
627
+	 * @return string html
628
+	 * @throws EE_Error
629
+	 */
630
+	public function redirect_form($inside_form_html = null)
631
+	{
632
+		$redirect_url = $this->redirect_url();
633
+		if (! empty($redirect_url)) {
634
+			// what ? no inner form content?
635
+			if ($inside_form_html === null) {
636
+				$inside_form_html = EEH_HTML::p(
637
+					sprintf(
638
+						esc_html__(
639
+							'If you are not automatically redirected to the payment website within 10 seconds... %1$s %2$s Click Here %3$s',
640
+							'event_espresso'
641
+						),
642
+						EEH_HTML::br(2),
643
+						'<input type="submit" value="',
644
+						'">'
645
+					),
646
+					'',
647
+					'',
648
+					'text-align:center;'
649
+				);
650
+			}
651
+			$method = apply_filters(
652
+				'FHEE__EE_Payment__redirect_form__method',
653
+				$this->redirect_args() ? 'POST' : 'GET',
654
+				$this
655
+			);
656
+			// if it's a GET request, we need to remove all the GET params in the querystring
657
+			// and put them into the form instead
658
+			if ($method === 'GET') {
659
+				$querystring = parse_url($redirect_url, PHP_URL_QUERY);
660
+				$get_params  = null;
661
+				parse_str($querystring, $get_params);
662
+				$inside_form_html .= $this->_args_as_inputs($get_params);
663
+				$redirect_url     = str_replace('?' . $querystring, '', $redirect_url);
664
+			}
665
+			$form = EEH_HTML::nl(1)
666
+					. '<form method="'
667
+					. $method
668
+					. '" name="gateway_form" action="'
669
+					. $redirect_url
670
+					. '">';
671
+			$form .= EEH_HTML::nl(1) . $this->redirect_args_as_inputs();
672
+			$form .= $inside_form_html;
673
+			$form .= EEH_HTML::nl(-1) . '</form>' . EEH_HTML::nl(-1);
674
+			return $form;
675
+		} else {
676
+			return null;
677
+		}
678
+	}
679
+
680
+
681
+	/**
682
+	 * Changes all the name-value pairs of the redirect args into html inputs
683
+	 * and returns the html as a string
684
+	 *
685
+	 * @return string
686
+	 * @throws EE_Error
687
+	 */
688
+	public function redirect_args_as_inputs()
689
+	{
690
+		return $this->_args_as_inputs($this->redirect_args());
691
+	}
692
+
693
+
694
+	/**
695
+	 * Converts a 2d array of key-value pairs into html hidden inputs
696
+	 * and returns the string of html
697
+	 *
698
+	 * @param array $args key-value pairs
699
+	 * @return string
700
+	 */
701
+	protected function _args_as_inputs($args)
702
+	{
703
+		$html = '';
704
+		if ($args !== null && is_array($args)) {
705
+			foreach ($args as $name => $value) {
706
+				$html .= $this->generateInput($name, $value);
707
+			}
708
+		}
709
+		return $html;
710
+	}
711
+
712
+
713
+	/**
714
+	 * Converts either a single name and value or array of values into html hidden inputs
715
+	 * and returns the string of html
716
+	 *
717
+	 * @param string       $name
718
+	 * @param string|array $value
719
+	 * @return string
720
+	 */
721
+	private function generateInput($name, $value)
722
+	{
723
+		if (is_array($value)) {
724
+			$html = '';
725
+			$name = "{$name}[]";
726
+			foreach ($value as $array_value) {
727
+				$html .= $this->generateInput($name, $array_value);
728
+			}
729
+			return $html;
730
+		}
731
+		return EEH_HTML::nl()
732
+			   . '<input type="hidden" name="' . $name . '"'
733
+			   . ' value="' . esc_attr($value) . '"/>';
734
+	}
735
+
736
+
737
+	/**
738
+	 * Returns the currency of the payment.
739
+	 * (At the time of writing, this will always be the currency in the configuration;
740
+	 * however in the future it is anticipated that this will be stored on the payment
741
+	 * object itself)
742
+	 *
743
+	 * @return string for the currency code
744
+	 */
745
+	public function currency_code()
746
+	{
747
+		return EE_Config::instance()->currency->code;
748
+	}
749
+
750
+
751
+	/**
752
+	 * apply wp_strip_all_tags to all elements within an array
753
+	 *
754
+	 * @access private
755
+	 * @param mixed $item
756
+	 */
757
+	private function _strip_all_tags_within_array(&$item)
758
+	{
759
+		if (is_object($item)) {
760
+			$item = (array) $item;
761
+		}
762
+		if (is_array($item)) {
763
+			array_walk_recursive($item, [$this, '_strip_all_tags_within_array']);
764
+		} else {
765
+			$item = wp_strip_all_tags((string) $item);
766
+		}
767
+	}
768
+
769
+
770
+	/**
771
+	 * Returns TRUE is this payment was set to approved during this request (or
772
+	 * is approved and was created during this request). False otherwise.
773
+	 *
774
+	 * @return boolean
775
+	 * @throws EE_Error
776
+	 */
777
+	public function just_approved()
778
+	{
779
+		$original_status = EEH_Array::is_set(
780
+			$this->_props_n_values_provided_in_constructor,
781
+			'STS_ID',
782
+			$this->get_model()->field_settings_for('STS_ID')->get_default_value()
783
+		);
784
+		$current_status  = $this->status();
785
+		if (
786
+			$original_status !== EEM_Payment::status_id_approved
787
+			&& $current_status === EEM_Payment::status_id_approved
788
+		) {
789
+			return true;
790
+		} else {
791
+			return false;
792
+		}
793
+	}
794
+
795
+
796
+	/**
797
+	 * Overrides parents' get_pretty() function just for legacy reasons
798
+	 * (to allow ticket https://events.codebasehq.com/projects/event-espresso/tickets/7420)
799
+	 *
800
+	 * @param string $field_name
801
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
802
+	 *                                (in cases where the same property may be used for different outputs
803
+	 *                                - i.e. datetime, money etc.)
804
+	 * @return mixed
805
+	 * @throws EE_Error
806
+	 */
807
+	public function get_pretty($field_name, $extra_cache_ref = null)
808
+	{
809
+		if ($field_name === 'PAY_gateway') {
810
+			return $this->payment_method() ? $this->payment_method()->name() : esc_html__('Unknown', 'event_espresso');
811
+		}
812
+		return $this->_get_cached_property($field_name, true, $extra_cache_ref);
813
+	}
814
+
815
+
816
+	/**
817
+	 * Gets details regarding which registrations this payment was applied to
818
+	 *
819
+	 * @param array $query_params @see
820
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
821
+	 * @return EE_Registration_Payment[]
822
+	 * @throws EE_Error
823
+	 */
824
+	public function registration_payments($query_params = [])
825
+	{
826
+		return $this->get_many_related('Registration_Payment', $query_params);
827
+	}
828
+
829
+
830
+	/**
831
+	 * Gets the first event for this payment (it's possible that it could be for multiple)
832
+	 *
833
+	 * @return EE_Event|null
834
+	 */
835
+	public function get_first_event()
836
+	{
837
+		$transaction = $this->transaction();
838
+		if ($transaction instanceof EE_Transaction) {
839
+			$primary_registrant = $transaction->primary_registration();
840
+			if ($primary_registrant instanceof EE_Registration) {
841
+				return $primary_registrant->event_obj();
842
+			}
843
+		}
844
+		return null;
845
+	}
846
+
847
+
848
+	/**
849
+	 * Gets the name of the first event for which is being paid
850
+	 *
851
+	 * @return string
852
+	 */
853
+	public function get_first_event_name()
854
+	{
855
+		$event = $this->get_first_event();
856
+		return $event instanceof EE_Event ? $event->name() : esc_html__('Event', 'event_espresso');
857
+	}
858
+
859
+
860
+	/**
861
+	 * Returns the payment's transaction's primary registration
862
+	 *
863
+	 * @return EE_Registration|null
864
+	 */
865
+	public function get_primary_registration()
866
+	{
867
+		if ($this->transaction() instanceof EE_Transaction) {
868
+			return $this->transaction()->primary_registration();
869
+		}
870
+		return null;
871
+	}
872
+
873
+
874
+	/**
875
+	 * Gets the payment's transaction's primary registration's attendee, or null
876
+	 *
877
+	 * @return EE_Attendee|null
878
+	 */
879
+	public function get_primary_attendee()
880
+	{
881
+		$primary_reg = $this->get_primary_registration();
882
+		if ($primary_reg instanceof EE_Registration) {
883
+			return $primary_reg->attendee();
884
+		}
885
+		return null;
886
+	}
887 887
 }
Please login to merge, or discard this patch.
4_7_0_stages/EE_DMS_4_7_0_Registration_Payments.dmsstage.php 1 patch
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -10,218 +10,218 @@
 block discarded – undo
10 10
 class EE_DMS_4_7_0_Registration_Payments extends EE_Data_Migration_Script_Stage_Table
11 11
 {
12 12
 
13
-    protected string $_payment_table;
14
-
15
-    protected string $_registration_table;
16
-
17
-    protected string $_registration_payment_table;
18
-
19
-
20
-    public function __construct()
21
-    {
22
-        /** @type WPDB $wpdb */ global $wpdb;
23
-        $this->_pretty_name = esc_html__('Registration Payment Record Generation', 'event_espresso');
24
-        // define tables
25
-        $this->_old_table                  = $wpdb->prefix . 'esp_transaction';
26
-        $this->_payment_table              = $wpdb->prefix . 'esp_payment';
27
-        $this->_registration_table         = $wpdb->prefix . 'esp_registration';
28
-        $this->_registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
29
-        // build SQL WHERE clauses
30
-        $this->_extra_where_sql = "WHERE STS_ID IN ( 'TIN', 'TCM' ) AND TXN_Total != '0.000'";
31
-        parent::__construct();
32
-    }
33
-
34
-
35
-    /**
36
-     * @param array $old_row
37
-     * @return void
38
-     */
39
-    protected function _migrate_old_row($old_row)
40
-    {
41
-        /** @type WPDB $wpdb */ global $wpdb;
42
-        $TXN_ID = absint($old_row['TXN_ID']);
43
-        if (! $TXN_ID) {
44
-            $this->add_error(
45
-                sprintf(
46
-                    esc_html__('Invalid transaction with ID=%1$d. Error: "%2$s"', 'event_espresso'),
47
-                    $TXN_ID,
48
-                    $wpdb->last_error
49
-                )
50
-            );
51
-            return;
52
-        }
53
-        // get all payments for the TXN
54
-        $payments = $this->_get_payments($TXN_ID);
55
-        if (empty($payments)) {
56
-            return;
57
-        }
58
-        // then the registrants
59
-        $registrations = $this->_get_registrations($TXN_ID);
60
-        if (empty($registrations)) {
61
-            return;
62
-        }
63
-        // now loop thru each payment and apply it to each of the registrations
64
-        foreach ($payments as $payment) {
65
-            if ($payment->STS_ID === 'PAP' && $payment->PAY_amount > 0) {
66
-                $this->_process_registration_payments($payment, $registrations);
67
-            }
68
-        }
69
-    }
70
-
71
-
72
-    /**
73
-     * _get_registrations
74
-     *
75
-     * @param int $TXN_ID
76
-     * @return array
77
-     */
78
-    protected function _get_registrations(int $TXN_ID): array
79
-    {
80
-        /** @type WPDB $wpdb */ global $wpdb;
81
-        $SQL = "SELECT * FROM $this->_registration_table WHERE TXN_ID = %d AND STS_ID IN ( 'RPP', 'RAP' )";
82
-        return $wpdb->get_results($wpdb->prepare($SQL, $TXN_ID), OBJECT_K);
83
-    }
84
-
85
-
86
-    /**
87
-     * _get_payments
88
-     *
89
-     * @param int $TXN_ID
90
-     * @return array
91
-     */
92
-    protected function _get_payments(int $TXN_ID): array
93
-    {
94
-        /** @type WPDB $wpdb */ global $wpdb;
95
-        return $wpdb->get_results(
96
-            $wpdb->prepare("SELECT * FROM $this->_payment_table WHERE TXN_ID = %d", $TXN_ID),
97
-            OBJECT_K
98
-        );
99
-    }
100
-
101
-
102
-    /**
103
-     * _get_possibly_updated_REG_paid
104
-     *
105
-     * @param int $REG_ID
106
-     * @return float
107
-     */
108
-    protected function _get_possibly_updated_REG_paid(int $REG_ID): float
109
-    {
110
-        /** @type WPDB $wpdb */ global $wpdb;
111
-        return (float) $wpdb->get_var(
112
-            $wpdb->prepare("SELECT REG_paid FROM $this->_registration_table WHERE REG_ID = %d", $REG_ID)
113
-        );
114
-    }
115
-
116
-
117
-    /**
118
-     * _process_registration_payments
119
-     * basically a copy of the "Sequential Registration Payment Application Strategy"  logic
120
-     * currently in EventEspresso\core\services\payments\RegistrationPayments::processRegistrationPayments()
121
-     *
122
-     * @param stdClass $payment
123
-     * @param array    $registrations
124
-     * @return void
125
-     */
126
-    protected function _process_registration_payments(stdClass $payment, array $registrations = [])
127
-    {
128
-        // how much is available to apply to registrations?
129
-        $available_payment_amount = $payment->PAY_amount;
130
-        foreach ($registrations as $REG_ID => $registration) {
131
-            // nothing left, then we are done here?
132
-            if (! $available_payment_amount > 0) {
133
-                break;
134
-            }
135
-            // ensure REG_final_price has a valid value, and skip if it turns out to be zero
136
-            $registration->REG_final_price =
137
-                ! empty($registration->REG_final_price) ? (float) $registration->REG_final_price : 0.00;
138
-            if (! $registration->REG_final_price > 0) {
139
-                continue;
140
-            }
141
-            // because REG_paid may have been updated by a previous payment, we need to retrieve the value from the db
142
-            $registration->REG_paid = $this->_get_possibly_updated_REG_paid($REG_ID);
143
-            // calculate amount owing, and skip if it turns out to be zero
144
-            $owing = $registration->REG_final_price - $registration->REG_paid;
145
-            if (! $owing > 0) {
146
-                continue;
147
-            }
148
-            // don't allow payment amount to exceed the available payment amount, OR the amount owing
149
-            $payment_amount = min($available_payment_amount, $owing);
150
-            // update $available_payment_amount
151
-            $available_payment_amount = $available_payment_amount - $payment_amount;
152
-            // add relation between registration and payment and set amount
153
-            if ($this->_insert_registration_payment($registration->REG_ID, $payment->PAY_ID, (float) $payment_amount)) {
154
-                // calculate and set new REG_paid
155
-                $registration->REG_paid = $registration->REG_paid + $payment_amount;
156
-                $this->_update_registration_paid($registration->REG_ID, (float) $registration->REG_paid);
157
-            }
158
-        }
159
-    }
160
-
161
-
162
-    /**
163
-     * _insert_registration_payment
164
-     *
165
-     * @param int   $REG_ID
166
-     * @param int   $PAY_ID
167
-     * @param float $PAY_amount
168
-     * @return bool
169
-     */
170
-    protected function _insert_registration_payment(int $REG_ID = 0, int $PAY_ID = 0, float $PAY_amount = 0.00): bool
171
-    {
172
-        global $wpdb;
173
-        $success = $wpdb->insert(
174
-            $this->_registration_payment_table,
175
-            ['REG_ID' => $REG_ID, 'PAY_ID' => $PAY_ID, 'RPY_amount' => $PAY_amount,],  // data
176
-            ['%f']                                                                     // data format
177
-        );
178
-        if ($success === false) {
179
-            $this->add_error(
180
-                sprintf(
181
-                    esc_html__(
182
-                        'Could not update registration paid value for registration ID=%1$d because "%2$s"',
183
-                        'event_espresso'
184
-                    ),
185
-                    $REG_ID,
186
-                    $wpdb->last_error
187
-                )
188
-            );
189
-            return false;
190
-        }
191
-        return true;
192
-    }
193
-
194
-
195
-    /**
196
-     * _update_registration_paid
197
-     *
198
-     * @param int   $REG_ID
199
-     * @param float $REG_paid
200
-     * @return bool
201
-     */
202
-    protected function _update_registration_paid(int $REG_ID = 0, float $REG_paid = 0.00): bool
203
-    {
204
-        /** @type WPDB $wpdb */ global $wpdb;
205
-        $success = $wpdb->update(
206
-            $this->_registration_table,
207
-            ['REG_paid' => $REG_paid],  // data
208
-            ['REG_ID' => $REG_ID],      // where
209
-            ['%f'],                     // data format
210
-            ['%d']                      // where format
211
-        );
212
-        if ($success === false) {
213
-            $this->add_error(
214
-                sprintf(
215
-                    esc_html__(
216
-                        'Could not update registration paid value for registration ID=%1$d because "%2$s"',
217
-                        'event_espresso'
218
-                    ),
219
-                    $REG_ID,
220
-                    $wpdb->last_error
221
-                )
222
-            );
223
-            return false;
224
-        }
225
-        return true;
226
-    }
13
+	protected string $_payment_table;
14
+
15
+	protected string $_registration_table;
16
+
17
+	protected string $_registration_payment_table;
18
+
19
+
20
+	public function __construct()
21
+	{
22
+		/** @type WPDB $wpdb */ global $wpdb;
23
+		$this->_pretty_name = esc_html__('Registration Payment Record Generation', 'event_espresso');
24
+		// define tables
25
+		$this->_old_table                  = $wpdb->prefix . 'esp_transaction';
26
+		$this->_payment_table              = $wpdb->prefix . 'esp_payment';
27
+		$this->_registration_table         = $wpdb->prefix . 'esp_registration';
28
+		$this->_registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
29
+		// build SQL WHERE clauses
30
+		$this->_extra_where_sql = "WHERE STS_ID IN ( 'TIN', 'TCM' ) AND TXN_Total != '0.000'";
31
+		parent::__construct();
32
+	}
33
+
34
+
35
+	/**
36
+	 * @param array $old_row
37
+	 * @return void
38
+	 */
39
+	protected function _migrate_old_row($old_row)
40
+	{
41
+		/** @type WPDB $wpdb */ global $wpdb;
42
+		$TXN_ID = absint($old_row['TXN_ID']);
43
+		if (! $TXN_ID) {
44
+			$this->add_error(
45
+				sprintf(
46
+					esc_html__('Invalid transaction with ID=%1$d. Error: "%2$s"', 'event_espresso'),
47
+					$TXN_ID,
48
+					$wpdb->last_error
49
+				)
50
+			);
51
+			return;
52
+		}
53
+		// get all payments for the TXN
54
+		$payments = $this->_get_payments($TXN_ID);
55
+		if (empty($payments)) {
56
+			return;
57
+		}
58
+		// then the registrants
59
+		$registrations = $this->_get_registrations($TXN_ID);
60
+		if (empty($registrations)) {
61
+			return;
62
+		}
63
+		// now loop thru each payment and apply it to each of the registrations
64
+		foreach ($payments as $payment) {
65
+			if ($payment->STS_ID === 'PAP' && $payment->PAY_amount > 0) {
66
+				$this->_process_registration_payments($payment, $registrations);
67
+			}
68
+		}
69
+	}
70
+
71
+
72
+	/**
73
+	 * _get_registrations
74
+	 *
75
+	 * @param int $TXN_ID
76
+	 * @return array
77
+	 */
78
+	protected function _get_registrations(int $TXN_ID): array
79
+	{
80
+		/** @type WPDB $wpdb */ global $wpdb;
81
+		$SQL = "SELECT * FROM $this->_registration_table WHERE TXN_ID = %d AND STS_ID IN ( 'RPP', 'RAP' )";
82
+		return $wpdb->get_results($wpdb->prepare($SQL, $TXN_ID), OBJECT_K);
83
+	}
84
+
85
+
86
+	/**
87
+	 * _get_payments
88
+	 *
89
+	 * @param int $TXN_ID
90
+	 * @return array
91
+	 */
92
+	protected function _get_payments(int $TXN_ID): array
93
+	{
94
+		/** @type WPDB $wpdb */ global $wpdb;
95
+		return $wpdb->get_results(
96
+			$wpdb->prepare("SELECT * FROM $this->_payment_table WHERE TXN_ID = %d", $TXN_ID),
97
+			OBJECT_K
98
+		);
99
+	}
100
+
101
+
102
+	/**
103
+	 * _get_possibly_updated_REG_paid
104
+	 *
105
+	 * @param int $REG_ID
106
+	 * @return float
107
+	 */
108
+	protected function _get_possibly_updated_REG_paid(int $REG_ID): float
109
+	{
110
+		/** @type WPDB $wpdb */ global $wpdb;
111
+		return (float) $wpdb->get_var(
112
+			$wpdb->prepare("SELECT REG_paid FROM $this->_registration_table WHERE REG_ID = %d", $REG_ID)
113
+		);
114
+	}
115
+
116
+
117
+	/**
118
+	 * _process_registration_payments
119
+	 * basically a copy of the "Sequential Registration Payment Application Strategy"  logic
120
+	 * currently in EventEspresso\core\services\payments\RegistrationPayments::processRegistrationPayments()
121
+	 *
122
+	 * @param stdClass $payment
123
+	 * @param array    $registrations
124
+	 * @return void
125
+	 */
126
+	protected function _process_registration_payments(stdClass $payment, array $registrations = [])
127
+	{
128
+		// how much is available to apply to registrations?
129
+		$available_payment_amount = $payment->PAY_amount;
130
+		foreach ($registrations as $REG_ID => $registration) {
131
+			// nothing left, then we are done here?
132
+			if (! $available_payment_amount > 0) {
133
+				break;
134
+			}
135
+			// ensure REG_final_price has a valid value, and skip if it turns out to be zero
136
+			$registration->REG_final_price =
137
+				! empty($registration->REG_final_price) ? (float) $registration->REG_final_price : 0.00;
138
+			if (! $registration->REG_final_price > 0) {
139
+				continue;
140
+			}
141
+			// because REG_paid may have been updated by a previous payment, we need to retrieve the value from the db
142
+			$registration->REG_paid = $this->_get_possibly_updated_REG_paid($REG_ID);
143
+			// calculate amount owing, and skip if it turns out to be zero
144
+			$owing = $registration->REG_final_price - $registration->REG_paid;
145
+			if (! $owing > 0) {
146
+				continue;
147
+			}
148
+			// don't allow payment amount to exceed the available payment amount, OR the amount owing
149
+			$payment_amount = min($available_payment_amount, $owing);
150
+			// update $available_payment_amount
151
+			$available_payment_amount = $available_payment_amount - $payment_amount;
152
+			// add relation between registration and payment and set amount
153
+			if ($this->_insert_registration_payment($registration->REG_ID, $payment->PAY_ID, (float) $payment_amount)) {
154
+				// calculate and set new REG_paid
155
+				$registration->REG_paid = $registration->REG_paid + $payment_amount;
156
+				$this->_update_registration_paid($registration->REG_ID, (float) $registration->REG_paid);
157
+			}
158
+		}
159
+	}
160
+
161
+
162
+	/**
163
+	 * _insert_registration_payment
164
+	 *
165
+	 * @param int   $REG_ID
166
+	 * @param int   $PAY_ID
167
+	 * @param float $PAY_amount
168
+	 * @return bool
169
+	 */
170
+	protected function _insert_registration_payment(int $REG_ID = 0, int $PAY_ID = 0, float $PAY_amount = 0.00): bool
171
+	{
172
+		global $wpdb;
173
+		$success = $wpdb->insert(
174
+			$this->_registration_payment_table,
175
+			['REG_ID' => $REG_ID, 'PAY_ID' => $PAY_ID, 'RPY_amount' => $PAY_amount,],  // data
176
+			['%f']                                                                     // data format
177
+		);
178
+		if ($success === false) {
179
+			$this->add_error(
180
+				sprintf(
181
+					esc_html__(
182
+						'Could not update registration paid value for registration ID=%1$d because "%2$s"',
183
+						'event_espresso'
184
+					),
185
+					$REG_ID,
186
+					$wpdb->last_error
187
+				)
188
+			);
189
+			return false;
190
+		}
191
+		return true;
192
+	}
193
+
194
+
195
+	/**
196
+	 * _update_registration_paid
197
+	 *
198
+	 * @param int   $REG_ID
199
+	 * @param float $REG_paid
200
+	 * @return bool
201
+	 */
202
+	protected function _update_registration_paid(int $REG_ID = 0, float $REG_paid = 0.00): bool
203
+	{
204
+		/** @type WPDB $wpdb */ global $wpdb;
205
+		$success = $wpdb->update(
206
+			$this->_registration_table,
207
+			['REG_paid' => $REG_paid],  // data
208
+			['REG_ID' => $REG_ID],      // where
209
+			['%f'],                     // data format
210
+			['%d']                      // where format
211
+		);
212
+		if ($success === false) {
213
+			$this->add_error(
214
+				sprintf(
215
+					esc_html__(
216
+						'Could not update registration paid value for registration ID=%1$d because "%2$s"',
217
+						'event_espresso'
218
+					),
219
+					$REG_ID,
220
+					$wpdb->last_error
221
+				)
222
+			);
223
+			return false;
224
+		}
225
+		return true;
226
+	}
227 227
 }
Please login to merge, or discard this patch.
core/EE_Dependency_Map.core.php 1 patch
Indentation   +1194 added lines, -1194 removed lines patch added patch discarded remove patch
@@ -20,1198 +20,1198 @@
 block discarded – undo
20 20
  */
21 21
 class EE_Dependency_Map
22 22
 {
23
-    /**
24
-     * This means that the requested class dependency is not present in the dependency map
25
-     */
26
-    const not_registered = 0;
27
-
28
-    /**
29
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
-     */
31
-    const load_new_object = 1;
32
-
33
-    /**
34
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
-     */
37
-    const load_from_cache = 2;
38
-
39
-    /**
40
-     * When registering a dependency,
41
-     * this indicates to keep any existing dependencies that already exist,
42
-     * and simply discard any new dependencies declared in the incoming data
43
-     */
44
-    const KEEP_EXISTING_DEPENDENCIES = 0;
45
-
46
-    /**
47
-     * When registering a dependency,
48
-     * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
-     */
50
-    const OVERWRITE_DEPENDENCIES = 1;
51
-
52
-    protected static ?EE_Dependency_Map $_instance = null;
53
-
54
-    private ClassInterfaceCache $class_cache;
55
-
56
-    protected ?RequestInterface $request = null;
57
-
58
-    protected ?LegacyRequestInterface $legacy_request = null;
59
-
60
-    protected ?ResponseInterface $response = null;
61
-
62
-    protected ?LoaderInterface $loader = null;
63
-
64
-    protected array $_dependency_map = [];
65
-
66
-    protected array $_class_loaders = [];
67
-
68
-
69
-    /**
70
-     * EE_Dependency_Map constructor.
71
-     *
72
-     * @param ClassInterfaceCache $class_cache
73
-     */
74
-    protected function __construct(ClassInterfaceCache $class_cache)
75
-    {
76
-        $this->class_cache = $class_cache;
77
-        do_action('EE_Dependency_Map____construct', $this);
78
-    }
79
-
80
-
81
-    /**
82
-     * @return void
83
-     * @throws InvalidAliasException
84
-     */
85
-    public function initialize()
86
-    {
87
-        $this->_register_core_dependencies();
88
-        $this->_register_core_class_loaders();
89
-        $this->_register_core_aliases();
90
-    }
91
-
92
-
93
-    /**
94
-     * @singleton method used to instantiate class object
95
-     * @param ClassInterfaceCache|null $class_cache
96
-     * @return EE_Dependency_Map
97
-     */
98
-    public static function instance(ClassInterfaceCache $class_cache = null): EE_Dependency_Map
99
-    {
100
-        // check if class object is instantiated, and instantiated properly
101
-        if (
102
-            ! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
103
-            && $class_cache instanceof ClassInterfaceCache
104
-        ) {
105
-            EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
106
-        }
107
-        return EE_Dependency_Map::$_instance;
108
-    }
109
-
110
-
111
-    /**
112
-     * @param RequestInterface $request
113
-     */
114
-    public function setRequest(RequestInterface $request)
115
-    {
116
-        $this->request = $request;
117
-    }
118
-
119
-
120
-    /**
121
-     * @param LegacyRequestInterface $legacy_request
122
-     */
123
-    public function setLegacyRequest(LegacyRequestInterface $legacy_request)
124
-    {
125
-        $this->legacy_request = $legacy_request;
126
-    }
127
-
128
-
129
-    /**
130
-     * @param ResponseInterface $response
131
-     */
132
-    public function setResponse(ResponseInterface $response)
133
-    {
134
-        $this->response = $response;
135
-    }
136
-
137
-
138
-    /**
139
-     * @param LoaderInterface $loader
140
-     */
141
-    public function setLoader(LoaderInterface $loader)
142
-    {
143
-        $this->loader = $loader;
144
-    }
145
-
146
-
147
-    /**
148
-     * @param string $class
149
-     * @param array  $dependencies
150
-     * @param int    $overwrite
151
-     * @return bool
152
-     */
153
-    public static function register_dependencies(
154
-        string $class,
155
-        array $dependencies,
156
-        int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
157
-    ): bool {
158
-        return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
159
-    }
160
-
161
-
162
-    /**
163
-     * Assigns an array of class names and corresponding load sources (new or cached)
164
-     * to the class specified by the first parameter.
165
-     * IMPORTANT !!!
166
-     * The order of elements in the incoming $dependencies array MUST match
167
-     * the order of the constructor parameters for the class in question.
168
-     * This is especially important when overriding any existing dependencies that are registered.
169
-     * the third parameter controls whether any duplicate dependencies are overwritten or not.
170
-     *
171
-     * @param string $class
172
-     * @param array  $dependencies
173
-     * @param int    $overwrite
174
-     * @return bool
175
-     */
176
-    public function registerDependencies(
177
-        string $class,
178
-        array $dependencies,
179
-        int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
180
-    ): bool {
181
-        if (empty($dependencies)) {
182
-            return false;
183
-        }
184
-        $class      = trim($class, '\\');
185
-        $registered = false;
186
-        if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
187
-            EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
188
-        }
189
-        // we need to make sure that any aliases used when registering a dependency
190
-        // get resolved to the correct class name
191
-        foreach ($dependencies as $dependency => $load_source) {
192
-            $alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
193
-            if (
194
-                $overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
195
-                || ! isset(
196
-                    EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $dependency ],
197
-                    EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ]
198
-                )
199
-            ) {
200
-                unset($dependencies[ $dependency ]);
201
-                $dependencies[ $alias ] = $load_source;
202
-                $registered             = true;
203
-            }
204
-        }
205
-        // now add our two lists of dependencies together.
206
-        // using Union (+=) favours the arrays in precedence from left to right,
207
-        // so $dependencies is NOT overwritten because it is listed first
208
-        // ie: with A = B + C, entries in B take precedence over duplicate entries in C
209
-        // Union is way faster than array_merge() but should be used with caution...
210
-        // especially with numerically indexed arrays
211
-        $dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
212
-        // now we need to ensure that the resulting dependencies
213
-        // array only has the entries that are required for the class
214
-        // so first count how many dependencies were originally registered for the class
215
-        $dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
216
-        // if that count is non-zero (meaning dependencies were already registered)
217
-        EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
218
-            // then truncate the  final array to match that count
219
-            ? array_slice($dependencies, 0, $dependency_count)
220
-            // otherwise just take the incoming array because nothing previously existed
221
-            : $dependencies;
222
-        return $registered
223
-            || count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]) === count($dependencies);
224
-    }
225
-
226
-
227
-    /**
228
-     * @param string          $class_name
229
-     * @param callable|string $loader
230
-     * @param bool            $overwrite
231
-     * @return bool
232
-     * @throws DomainException
233
-     */
234
-    public static function register_class_loader(
235
-        string $class_name,
236
-        $loader = 'load_core',
237
-        bool $overwrite = false
238
-    ): bool {
239
-        return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader, $overwrite);
240
-    }
241
-
242
-
243
-    /**
244
-     * @param string         $class_name
245
-     * @param Closure|string $loader
246
-     * @param bool           $overwrite
247
-     * @return bool
248
-     * @throws DomainException
249
-     */
250
-    public function registerClassLoader(string $class_name, $loader = 'load_core', bool $overwrite = false): bool
251
-    {
252
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
253
-            throw new DomainException(
254
-                esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
255
-            );
256
-        }
257
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
258
-        if (
259
-            ! is_callable($loader)
260
-            && (
261
-                strpos($loader, 'load_') !== 0
262
-                || ! method_exists('EE_Registry', $loader)
263
-            )
264
-        ) {
265
-            throw new DomainException(
266
-                sprintf(
267
-                    esc_html__(
268
-                        '"%1$s" is not a valid loader method on EE_Registry.',
269
-                        'event_espresso'
270
-                    ),
271
-                    $loader
272
-                )
273
-            );
274
-        }
275
-        $class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
276
-        if ($overwrite || ! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
277
-            EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
278
-            return true;
279
-        }
280
-        return false;
281
-    }
282
-
283
-
284
-    /**
285
-     * @return array
286
-     */
287
-    public function dependency_map(): array
288
-    {
289
-        return $this->_dependency_map;
290
-    }
291
-
292
-
293
-    /**
294
-     * returns TRUE if dependency map contains a listing for the provided class name
295
-     *
296
-     * @param string $class_name
297
-     * @return boolean
298
-     */
299
-    public function has(string $class_name = ''): bool
300
-    {
301
-        // all legacy models have the same dependencies
302
-        if (strpos($class_name, 'EEM_') === 0) {
303
-            $class_name = 'LEGACY_MODELS';
304
-        }
305
-        return isset($this->_dependency_map[ $class_name ]);
306
-    }
307
-
308
-
309
-    /**
310
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
311
-     *
312
-     * @param string $class_name
313
-     * @param string $dependency
314
-     * @return bool
315
-     */
316
-    public function has_dependency_for_class(string $class_name = '', string $dependency = ''): bool
317
-    {
318
-        // all legacy models have the same dependencies
319
-        if (strpos($class_name, 'EEM_') === 0) {
320
-            $class_name = 'LEGACY_MODELS';
321
-        }
322
-        $dependency = $this->getFqnForAlias($dependency, $class_name);
323
-        return isset($this->_dependency_map[ $class_name ][ $dependency ]);
324
-    }
325
-
326
-
327
-    /**
328
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
329
-     *
330
-     * @param string $class_name
331
-     * @param string $dependency
332
-     * @return int
333
-     */
334
-    public function loading_strategy_for_class_dependency(string $class_name = '', string $dependency = ''): int
335
-    {
336
-        // all legacy models have the same dependencies
337
-        if (strpos($class_name, 'EEM_') === 0) {
338
-            $class_name = 'LEGACY_MODELS';
339
-        }
340
-        $dependency = $this->getFqnForAlias($dependency);
341
-        return $this->has_dependency_for_class($class_name, $dependency)
342
-            ? $this->_dependency_map[ $class_name ][ $dependency ]
343
-            : EE_Dependency_Map::not_registered;
344
-    }
345
-
346
-
347
-    /**
348
-     * @param string $class_name
349
-     * @return string | Closure
350
-     */
351
-    public function class_loader(string $class_name)
352
-    {
353
-        // all legacy models use load_model()
354
-        if (strpos($class_name, 'EEM_') === 0) {
355
-            return 'load_model';
356
-        }
357
-        // EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
358
-        // perform strpos() first to avoid loading regex every time we load a class
359
-        if (
360
-            strpos($class_name, 'EE_CPT_') === 0
361
-            && preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
362
-        ) {
363
-            return 'load_core';
364
-        }
365
-        $class_name = $this->getFqnForAlias($class_name);
366
-        return $this->_class_loaders[ $class_name ] ?? '';
367
-    }
368
-
369
-
370
-    /**
371
-     * @return array
372
-     */
373
-    public function class_loaders(): array
374
-    {
375
-        return $this->_class_loaders;
376
-    }
377
-
378
-
379
-    /**
380
-     * adds an alias for a classname
381
-     *
382
-     * @param string $fqcn      the class name that should be used (concrete class to replace interface)
383
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
384
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
385
-     * @throws InvalidAliasException
386
-     */
387
-    public function add_alias(string $fqcn, string $alias, string $for_class = '')
388
-    {
389
-        $this->class_cache->addAlias($fqcn, $alias, $for_class);
390
-    }
391
-
392
-
393
-    /**
394
-     * Returns TRUE if the provided fully qualified name IS an alias
395
-     * WHY?
396
-     * Because if a class is type hinting for a concretion,
397
-     * then why would we need to find another class to supply it?
398
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
399
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
400
-     * Don't go looking for some substitute.
401
-     * Whereas if a class is type hinting for an interface...
402
-     * then we need to find an actual class to use.
403
-     * So the interface IS the alias for some other FQN,
404
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
405
-     * represents some other class.
406
-     *
407
-     * @param string $fqn
408
-     * @param string $for_class
409
-     * @return bool
410
-     */
411
-    public function isAlias(string $fqn = '', string $for_class = ''): bool
412
-    {
413
-        return $this->class_cache->isAlias($fqn, $for_class);
414
-    }
415
-
416
-
417
-    /**
418
-     * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
419
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
420
-     *  for example:
421
-     *      if the following two entries were added to the _aliases array:
422
-     *          array(
423
-     *              'interface_alias'           => 'some\namespace\interface'
424
-     *              'some\namespace\interface'  => 'some\namespace\classname'
425
-     *          )
426
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
427
-     *      to load an instance of 'some\namespace\classname'
428
-     *
429
-     * @param string $alias
430
-     * @param string $for_class
431
-     * @return string
432
-     */
433
-    public function getFqnForAlias(string $alias = '', string $for_class = ''): string
434
-    {
435
-        return $this->class_cache->getFqnForAlias($alias, $for_class);
436
-    }
437
-
438
-
439
-    /**
440
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
441
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
442
-     * This is done by using the following class constants:
443
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
444
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
445
-     */
446
-    protected function _register_core_dependencies()
447
-    {
448
-        $this->_dependency_map = [
449
-            'EE_Admin'                                                                                                           => [
450
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
451
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
452
-            ],
453
-            'EE_Maintenance_Mode'                                                                                                => [
454
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
455
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
456
-            ],
457
-            'EE_Request_Handler'                                                                                                 => [
458
-                'EventEspresso\core\services\request\Request'  => EE_Dependency_Map::load_from_cache,
459
-                'EventEspresso\core\services\request\Response' => EE_Dependency_Map::load_from_cache,
460
-            ],
461
-            'EE_System'                                                                                                   => [
462
-                'EventEspresso\core\services\loaders\Loader'                   => EE_Dependency_Map::load_from_cache,
463
-                'EE_Maintenance_Mode'                                          => EE_Dependency_Map::load_from_cache,
464
-                'EE_Registry'                                                  => EE_Dependency_Map::load_from_cache,
465
-                'EventEspresso\core\services\request\Request'                  => EE_Dependency_Map::load_from_cache,
466
-                'EventEspresso\core\services\routing\Router'                   => EE_Dependency_Map::load_from_cache,
467
-                'EventEspresso\core\domain\services\capabilities\FeatureFlags' => EE_Dependency_Map::load_from_cache,
468
-            ],
469
-            'EE_Session'                                                                                                         => [
470
-                'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
471
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
472
-                'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
473
-                'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
474
-                'EventEspresso\core\services\encryption\Base64Encoder'     => EE_Dependency_Map::load_from_cache,
475
-            ],
476
-            'EventEspresso\core\services\session\SessionStartHandler'                                                            => [
477
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
478
-            ],
479
-            'EE_Cart'                                                                                                            => [
480
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
481
-            ],
482
-            'EE_Messenger_Collection_Loader'                                                                                     => [
483
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
484
-            ],
485
-            'EE_Message_Type_Collection_Loader'                                                                                  => [
486
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
487
-            ],
488
-            'EE_Message_Resource_Manager'                                                                                        => [
489
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
490
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
491
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
492
-            ],
493
-            'EE_Message_Factory'                                                                                                 => [
494
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
495
-            ],
496
-            'EE_messages'                                                                                                        => [
497
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
498
-            ],
499
-            'EE_Messages_Generator'                                                                                              => [
500
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
501
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
502
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
503
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
504
-            ],
505
-            'EE_Messages_Processor'                                                                                              => [
506
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
507
-            ],
508
-            'EE_Messages_Queue'                                                                                                  => [
509
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
510
-            ],
511
-            'EE_Messages_Template_Defaults'                                                                                      => [
512
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
513
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
514
-            ],
515
-            'EE_Message_To_Generate_From_Request'                                                                                => [
516
-                'EE_Message_Resource_Manager'                 => EE_Dependency_Map::load_from_cache,
517
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
518
-            ],
519
-            'EventEspresso\core\services\commands\CommandBus'                                                                    => [
520
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
521
-            ],
522
-            'EventEspresso\services\commands\CommandHandler'                                                                     => [
523
-                'EE_Registry'         => EE_Dependency_Map::load_from_cache,
524
-                'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
525
-            ],
526
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                         => [
527
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
528
-            ],
529
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                       => [
530
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
531
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
532
-            ],
533
-            'EventEspresso\core\services\commands\CommandFactory'                                                                => [
534
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
535
-            ],
536
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                         => [
537
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
538
-            ],
539
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                                => [
540
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
541
-            ],
542
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                            => [
543
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
544
-            ],
545
-            'EventEspresso\core\domain\services\commands\registration\CreateRegistrationCommandHandler'                          => [
546
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
547
-            ],
548
-            'EventEspresso\core\domain\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
549
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
550
-            ],
551
-            'EventEspresso\core\domain\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
552
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
553
-            ],
554
-            'EventEspresso\core\domain\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
555
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
556
-            ],
557
-            'EventEspresso\core\domain\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
558
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
559
-            ],
560
-            'EventEspresso\core\domain\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
561
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
562
-            ],
563
-            'EventEspresso\core\domain\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
564
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
565
-            ],
566
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                          => [
567
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
568
-            ],
569
-            'EventEspresso\core\domain\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
570
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
571
-            ],
572
-            'EventEspresso\core\domain\values\session\SessionLifespan'                                                           => [
573
-                'EventEspresso\core\domain\values\session\SessionLifespanOption' => EE_Dependency_Map::load_from_cache,
574
-            ],
575
-            'EventEspresso\caffeinated\admin\extend\registration_form\forms\SessionLifespanForm'                                 => [
576
-                'EventEspresso\core\domain\values\session\SessionLifespanOption' => EE_Dependency_Map::load_from_cache,
577
-                'EE_Registration_Config'                                         => EE_Dependency_Map::load_from_cache,
578
-            ],
579
-            'EventEspresso\caffeinated\admin\extend\registration_form\forms\SessionLifespanFormHandler'                          => [
580
-                'EventEspresso\core\domain\values\session\SessionLifespanOption' => EE_Dependency_Map::load_from_cache,
581
-                'EE_Config'                                                      => EE_Dependency_Map::load_from_cache,
582
-            ],
583
-            'EventEspresso\core\services\database\TableManager'                                                                  => [
584
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
585
-            ],
586
-            'EE_Data_Migration_Class_Base'                                                                                       => [
587
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
588
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
589
-            ],
590
-            'EE_DMS_Core_4_1_0'                                                                                                  => [
591
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
592
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
593
-            ],
594
-            'EE_DMS_Core_4_2_0'                                                                                                  => [
595
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
596
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
597
-            ],
598
-            'EE_DMS_Core_4_3_0'                                                                                                  => [
599
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
600
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
601
-            ],
602
-            'EE_DMS_Core_4_4_0'                                                                                                  => [
603
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
604
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
605
-            ],
606
-            'EE_DMS_Core_4_5_0'                                                                                                  => [
607
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
608
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
609
-            ],
610
-            'EE_DMS_Core_4_6_0'                                                                                                  => [
611
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
612
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
613
-            ],
614
-            'EE_DMS_Core_4_7_0'                                                                                                  => [
615
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
616
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
617
-            ],
618
-            'EE_DMS_Core_4_8_0'                                                                                                  => [
619
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
620
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
621
-            ],
622
-            'EE_DMS_Core_4_9_0'                                                                                                  => [
623
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
624
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
625
-            ],
626
-            'EE_DMS_Core_4_10_0'                                                                                                 => [
627
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
628
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
629
-                'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
630
-            ],
631
-            'EE_DMS_Core_5_0_0'                                                                                                  => [
632
-                'EE_DMS_Core_4_10_0'                                 => EE_Dependency_Map::load_from_cache,
633
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
634
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
635
-            ],
636
-            'EventEspresso\core\services\assets\I18nRegistry'                                                                    => [
637
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
638
-            ],
639
-            'EventEspresso\core\services\assets\Registry'                                                                        => [
640
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
641
-                'EventEspresso\core\services\assets\AssetManifest'   => EE_Dependency_Map::load_from_cache,
642
-            ],
643
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                                    => [
644
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
645
-            ],
646
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                                     => [
647
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
648
-            ],
649
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                               => [
650
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
651
-            ],
652
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                       => [
653
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
654
-            ],
655
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                                     => [
656
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
657
-            ],
658
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                               => [
659
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
660
-            ],
661
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                                      => [
662
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
663
-            ],
664
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                                => [
665
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
666
-            ],
667
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                          => [
668
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
669
-            ],
670
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                         => [
671
-                'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
672
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
673
-            ],
674
-            'EventEspresso\core\domain\values\EmailAddress'                                                                      => [
675
-                null,
676
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
677
-            ],
678
-            'EventEspresso\core\services\orm\ModelFieldFactory'                                                                  => [
679
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
680
-            ],
681
-            'LEGACY_MODELS'                                                                                                      => [
682
-                null,
683
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
684
-            ],
685
-            'EE_Module_Request_Router'                                                                                           => [
686
-                'EventEspresso\core\services\request\Request'             => EE_Dependency_Map::load_from_cache,
687
-                'EventEspresso\core\services\modules\ModuleRoutesManager' => EE_Dependency_Map::load_from_cache,
688
-            ],
689
-            'EE_Registration_Processor'                                                                                          => [
690
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
691
-            ],
692
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                             => [
693
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
694
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
695
-            ],
696
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                           => [
697
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
698
-                'EE_Session'             => EE_Dependency_Map::load_from_cache,
699
-            ],
700
-            'EventEspresso\modules\ticket_selector\DisplayTicketSelector'                                                        => [
701
-                'EventEspresso\core\domain\entities\users\CurrentUser' => EE_Dependency_Map::load_from_cache,
702
-                'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
703
-                'EE_Ticket_Selector_Config'                            => EE_Dependency_Map::load_from_cache,
704
-            ],
705
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                        => [
706
-                'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
707
-                'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
708
-                'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
709
-                'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
710
-                'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
711
-            ],
712
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelectorPostData'                                                => [
713
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
714
-                'EEM_Event'                                   => EE_Dependency_Map::load_from_cache,
715
-            ],
716
-            'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                            => [
717
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
718
-            ],
719
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                                     => [
720
-                'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
721
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
722
-            ],
723
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                       => [
724
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
725
-            ],
726
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                                      => [
727
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
728
-            ],
729
-            'EE_CPT_Strategy'                                                                                                    => [
730
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
731
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
732
-            ],
733
-            'EventEspresso\core\services\loaders\ObjectIdentifier'                                                               => [
734
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
735
-            ],
736
-            'EventEspresso\core\CPTs\CptQueryModifier'                                                                           => [
737
-                null,
738
-                null,
739
-                null,
740
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
741
-                'EventEspresso\core\services\request\Request'     => EE_Dependency_Map::load_from_cache,
742
-                'EventEspresso\core\services\loaders\Loader'      => EE_Dependency_Map::load_from_cache,
743
-            ],
744
-            'EventEspresso\core\services\dependencies\DependencyResolver'                                                        => [
745
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
746
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
747
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
748
-            ],
749
-            'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                                      => [
750
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
751
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
752
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
753
-            ],
754
-            'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                                 => [
755
-                'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
756
-                'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
757
-            ],
758
-            'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                                 => [
759
-                'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
760
-                'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
761
-            ],
762
-            'EventEspresso\core\services\request\files\FilesDataHandler'                                                         => [
763
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
764
-            ],
765
-            'EventEspresso\core\libraries\batch\BatchRequestProcessor'                                                           => [
766
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
767
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
768
-            ],
769
-            'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                       => [
770
-                'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
771
-                'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
772
-                'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
773
-                null,
774
-            ],
775
-            'EventEspresso\core\services\routing\RouteHandler'                                                                   => [
776
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
777
-                'EventEspresso\core\services\json\JsonDataNodeHandler'                => EE_Dependency_Map::load_from_cache,
778
-                'EventEspresso\core\services\loaders\Loader'                          => EE_Dependency_Map::load_from_cache,
779
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
780
-                'EventEspresso\core\services\routing\RouteCollection'                 => EE_Dependency_Map::load_from_cache,
781
-            ],
782
-            'EventEspresso\core\services\json\JsonDataNodeHandler'                                                               => [
783
-                'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
784
-            ],
785
-            'EventEspresso\core\services\routing\Router'                                                                         => [
786
-                'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
787
-                'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
788
-                'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
789
-            ],
790
-            'EventEspresso\core\services\assets\AssetManifest'                                                                   => [
791
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
792
-            ],
793
-            'EventEspresso\core\services\assets\AssetManifestFactory'                                                            => [
794
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
795
-            ],
796
-            'EventEspresso\core\services\assets\BaristaFactory'                                                                  => [
797
-                'EventEspresso\core\services\assets\AssetManifestFactory' => EE_Dependency_Map::load_from_cache,
798
-                'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
799
-            ],
800
-            'EventEspresso\core\domain\services\capabilities\FeatureFlagsConfig' => [
801
-                'EventEspresso\core\domain\Domain'                                    => EE_Dependency_Map::load_from_cache,
802
-                'EventEspresso\core\services\json\JsonDataHandler'                    => EE_Dependency_Map::load_from_cache,
803
-            ],
804
-            'EventEspresso\core\domain\services\capabilities\FeatureFlags'       => [
805
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
806
-                'EventEspresso\core\domain\services\capabilities\FeatureFlagsConfig'  => EE_Dependency_Map::load_from_cache,
807
-            ],
808
-            'EventEspresso\core\services\addon\AddonManager'                                                                     => [
809
-                'EventEspresso\core\services\addon\AddonCollection'              => EE_Dependency_Map::load_from_cache,
810
-                'EventEspresso\core\Psr4Autoloader'                              => EE_Dependency_Map::load_from_cache,
811
-                'EventEspresso\core\services\addon\api\v1\RegisterAddon'         => EE_Dependency_Map::load_from_cache,
812
-                'EventEspresso\core\services\addon\api\IncompatibleAddonHandler' => EE_Dependency_Map::load_from_cache,
813
-                'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'  => EE_Dependency_Map::load_from_cache,
814
-            ],
815
-            'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'                                                      => [
816
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
817
-            ],
818
-            'EventEspresso\core\libraries\batch\JobHandlers\ExecuteBatchDeletion'                                                => [
819
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
820
-            ],
821
-            'EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'                                                => [
822
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
823
-            ],
824
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'                                               => [
825
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
826
-                'EEM_Event'                                                   => EE_Dependency_Map::load_from_cache,
827
-                'EEM_Datetime'                                                => EE_Dependency_Map::load_from_cache,
828
-                'EEM_Registration'                                            => EE_Dependency_Map::load_from_cache,
829
-            ],
830
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'                                               => [
831
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
832
-            ],
833
-            'EventEspresso\core\services\request\CurrentPage'                                                                    => [
834
-                'EE_CPT_Strategy'                             => EE_Dependency_Map::load_from_cache,
835
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
836
-            ],
837
-            'EventEspresso\core\services\shortcodes\LegacyShortcodesManager'                                                     => [
838
-                'EE_Registry'                                     => EE_Dependency_Map::load_from_cache,
839
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
840
-            ],
841
-            'EventEspresso\core\services\shortcodes\ShortcodesManager'                                                           => [
842
-                'EventEspresso\core\services\shortcodes\LegacyShortcodesManager' => EE_Dependency_Map::load_from_cache,
843
-                'EventEspresso\core\services\request\CurrentPage'                => EE_Dependency_Map::load_from_cache,
844
-            ],
845
-            'EventEspresso\core\domain\entities\users\CurrentUser'                                                               => [
846
-                'EventEspresso\core\domain\entities\users\EventManagers' => EE_Dependency_Map::load_from_cache,
847
-            ],
848
-            'EventEspresso\core\services\form\meta\InputTypes'                                                                   => [
849
-                'EventEspresso\core\services\form\meta\inputs\Block'    => EE_Dependency_Map::load_from_cache,
850
-                'EventEspresso\core\services\form\meta\inputs\Button'   => EE_Dependency_Map::load_from_cache,
851
-                'EventEspresso\core\services\form\meta\inputs\DateTime' => EE_Dependency_Map::load_from_cache,
852
-                'EventEspresso\core\services\form\meta\inputs\Input'    => EE_Dependency_Map::load_from_cache,
853
-                'EventEspresso\core\services\form\meta\inputs\Number'   => EE_Dependency_Map::load_from_cache,
854
-                'EventEspresso\core\services\form\meta\inputs\Phone'    => EE_Dependency_Map::load_from_cache,
855
-                'EventEspresso\core\services\form\meta\inputs\Select'   => EE_Dependency_Map::load_from_cache,
856
-                'EventEspresso\core\services\form\meta\inputs\Text'     => EE_Dependency_Map::load_from_cache,
857
-            ],
858
-            'EventEspresso\core\domain\services\registration\form\v1\RegFormDependencyHandler'                                   => [
859
-                'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
860
-            ],
861
-            'EventEspresso\core\services\calculators\LineItemCalculator'                                                         => [
862
-                'EventEspresso\core\services\helpers\DecimalValues' => EE_Dependency_Map::load_from_cache,
863
-            ],
864
-            'EventEspresso\core\services\helpers\DecimalValues'                                                                  => [
865
-                'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
866
-            ],
867
-            'EE_Brewing_Regular'                                                                                                 => [
868
-                'EE_Dependency_Map'                                  => EE_Dependency_Map::load_from_cache,
869
-                'EventEspresso\core\services\loaders\Loader'         => EE_Dependency_Map::load_from_cache,
870
-                'EventEspresso\core\services\routing\RouteHandler'   => EE_Dependency_Map::load_from_cache,
871
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
872
-            ],
873
-            'EventEspresso\core\domain\services\messages\MessageTemplateRequestData'                                             => [
874
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
875
-            ],
876
-            'EventEspresso\core\domain\services\messages\MessageTemplateValidator'                                               => [
877
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
878
-            ],
879
-            'EventEspresso\core\domain\services\messages\MessageTemplateManager'                                                 => [
880
-                'EEM_Message_Template'                                                   => EE_Dependency_Map::load_from_cache,
881
-                'EEM_Message_Template_Group'                                             => EE_Dependency_Map::load_from_cache,
882
-                'EventEspresso\core\domain\services\messages\MessageTemplateRequestData' => EE_Dependency_Map::load_from_cache,
883
-                'EventEspresso\core\domain\services\messages\MessageTemplateValidator'   => EE_Dependency_Map::load_from_cache,
884
-                'EventEspresso\core\services\request\Request'                            => EE_Dependency_Map::load_from_cache,
885
-            ],
886
-            'EventEspresso\core\services\request\sanitizers\RequestSanitizer'                                                    => [
887
-                'EventEspresso\core\domain\services\validation\email\strategies\Basic' => EE_Dependency_Map::load_from_cache,
888
-            ],
889
-            'EE_CPT_Event_Strategy'                                                    => [
890
-                null,
891
-                null,
892
-                'EE_Template_Config' => EE_Dependency_Map::load_from_cache,
893
-            ],
894
-            'EventEspresso\core\domain\services\licensing\LicenseKeyFormInput'                                                    => [
895
-                'EventEspresso\core\services\licensing\PluginLicense'  => EE_Dependency_Map::not_registered,
896
-                'EventEspresso\core\services\licensing\LicenseManager' => EE_Dependency_Map::load_from_cache,
897
-            ],
898
-            'EventEspresso\core\services\payments\IpnHandler' => [
899
-                'EEM_Payment_Method'                                    => EE_Dependency_Map::not_registered,
900
-                'EEM_Transaction'                                       => EE_Dependency_Map::load_from_cache,
901
-                'EE_Core_Config'                                        => EE_Dependency_Map::load_from_cache,
902
-                'EE_Organization_Config'                                => EE_Dependency_Map::load_from_cache,
903
-                'EventEspresso\core\services\payments\PaymentProcessor' => EE_Dependency_Map::load_from_cache,
904
-            ],
905
-            'EventEspresso\core\services\payments\PaymentProcessor' => [
906
-                'EEM_Payment_Method'                                           => EE_Dependency_Map::not_registered,
907
-                'EEM_Transaction'                                              => EE_Dependency_Map::load_from_cache,
908
-                'EE_Organization_Config'                                       => EE_Dependency_Map::load_from_cache,
909
-                'EventEspresso\core\domain\services\capabilities\FeatureFlags' => EE_Dependency_Map::load_from_cache,
910
-                'EventEspresso\core\services\payments\PaymentProcessorFees'    => EE_Dependency_Map::load_from_cache,
911
-                'EventEspresso\core\services\payments\PostPaymentProcessor'    => EE_Dependency_Map::load_from_cache,
912
-                'EventEspresso\core\services\payments\RegistrationPayments'    => EE_Dependency_Map::load_from_cache,
913
-            ],
914
-            'EventEspresso\core\services\payments\PostPaymentProcessor' => [
915
-                'EE_Transaction_Processor' => EE_Dependency_Map::load_from_cache,
916
-            ],
917
-            'EventEspresso\core\services\payments\PaymentProcessorFees' => [
918
-                'EventEspresso\core\domain\values\gateways\GracePeriod'    => EE_Dependency_Map::load_from_cache,
919
-                'EventEspresso\core\domain\services\licensing\LicenseData' => EE_Dependency_Map::load_from_cache,
920
-            ],
921
-            'EventEspresso\core\domain\services\licensing\LicenseData'  => [
922
-                'EventEspresso\core\domain\Domain'                             => EE_Dependency_Map::load_from_cache,
923
-                'EventEspresso\core\domain\services\capabilities\FeatureFlags' => EE_Dependency_Map::load_from_cache,
924
-            ],
925
-            'EventEspresso\core\domain\services\licensing\LicenseDataEDD' => [
926
-                'EventEspresso\core\services\licensing\LicenseKeyData' => EE_Dependency_Map::load_from_cache,
927
-            ],
928
-            'EventEspresso\core\domain\services\licensing\LicenseDataPue' => [
929
-                'EE_Network_Core_Config' => EE_Dependency_Map::load_from_cache,
930
-            ],
931
-        ];
932
-    }
933
-
934
-
935
-    /**
936
-     * Registers how core classes are loaded.
937
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
938
-     *        'EE_Request_Handler' => 'load_core'
939
-     *        'EE_Messages_Queue'  => 'load_lib'
940
-     *        'EEH_Debug_Tools'    => 'load_helper'
941
-     * or, if greater control is required, by providing a custom closure. For example:
942
-     *        'Some_Class' => function () {
943
-     *            return new Some_Class();
944
-     *        },
945
-     * This is required for instantiating dependencies
946
-     * where an interface has been type hinted in a class constructor. For example:
947
-     *        'Required_Interface' => function () {
948
-     *            return new A_Class_That_Implements_Required_Interface();
949
-     *        },
950
-     */
951
-    protected function _register_core_class_loaders()
952
-    {
953
-        $this->_class_loaders = [
954
-            // load_core
955
-            'EE_Dependency_Map'                            => function () {
956
-                return $this;
957
-            },
958
-            'EE_Capabilities'                              => 'load_core',
959
-            'EE_Encryption'                                => 'load_core',
960
-            'EE_Front_Controller'                          => 'load_core',
961
-            'EE_Module_Request_Router'                     => 'load_core',
962
-            'EE_Registry'                                  => 'load_core',
963
-            'EE_Request'                                   => function () {
964
-                return $this->legacy_request;
965
-            },
966
-            'EventEspresso\core\services\request\Request'  => function () {
967
-                return $this->request;
968
-            },
969
-            'EventEspresso\core\services\request\Response' => function () {
970
-                return $this->response;
971
-            },
972
-            'EE_Base'                                      => 'load_core',
973
-            'EE_Request_Handler'                           => 'load_core',
974
-            'EE_Session'                                   => 'load_core',
975
-            'EE_Cron_Tasks'                                => 'load_core',
976
-            'EE_System'                                    => 'load_core',
977
-            'EE_Maintenance_Mode'                          => 'load_core',
978
-            'EE_Register_CPTs'                             => 'load_core',
979
-            'EE_Admin'                                     => 'load_core',
980
-            'EE_CPT_Strategy'                              => 'load_core',
981
-            // load_class
982
-            'EE_Registration_Processor'                    => 'load_class',
983
-            'EE_Transaction_Payments'                      => 'load_class',
984
-            'EE_Transaction_Processor'                     => 'load_class',
985
-            // load_lib
986
-            'EE_Message_Resource_Manager'                  => 'load_lib',
987
-            'EE_Message_Type_Collection'                   => 'load_lib',
988
-            'EE_Message_Type_Collection_Loader'            => 'load_lib',
989
-            'EE_Messenger_Collection'                      => 'load_lib',
990
-            'EE_Messenger_Collection_Loader'               => 'load_lib',
991
-            'EE_Messages_Processor'                        => 'load_lib',
992
-            'EE_Message_Repository'                        => 'load_lib',
993
-            'EE_Messages_Queue'                            => 'load_lib',
994
-            'EE_Messages_Data_Handler_Collection'          => 'load_lib',
995
-            'EE_Message_Template_Group_Collection'         => 'load_lib',
996
-            'EE_Payment_Method_Manager'                    => 'load_lib',
997
-            'EE_Payment_Processor'                         => 'load_core',
998
-            'EE_DMS_Core_4_1_0'                            => 'load_dms',
999
-            'EE_DMS_Core_4_2_0'                            => 'load_dms',
1000
-            'EE_DMS_Core_4_3_0'                            => 'load_dms',
1001
-            'EE_DMS_Core_4_5_0'                            => 'load_dms',
1002
-            'EE_DMS_Core_4_6_0'                            => 'load_dms',
1003
-            'EE_DMS_Core_4_7_0'                            => 'load_dms',
1004
-            'EE_DMS_Core_4_8_0'                            => 'load_dms',
1005
-            'EE_DMS_Core_4_9_0'                            => 'load_dms',
1006
-            'EE_DMS_Core_4_10_0'                           => 'load_dms',
1007
-            'EE_DMS_Core_5_0_0'                            => 'load_dms',
1008
-            'EE_Messages_Generator'                        => static function () {
1009
-                return EE_Registry::instance()->load_lib(
1010
-                    'Messages_Generator',
1011
-                    [],
1012
-                    false,
1013
-                    false
1014
-                );
1015
-            },
1016
-            'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
1017
-                return EE_Registry::instance()->load_lib(
1018
-                    'Messages_Template_Defaults',
1019
-                    $arguments,
1020
-                    false,
1021
-                    false
1022
-                );
1023
-            },
1024
-            // load_helper
1025
-            'EEH_Parse_Shortcodes'                         => static function () {
1026
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
1027
-                    return new EEH_Parse_Shortcodes();
1028
-                }
1029
-                return null;
1030
-            },
1031
-            'EE_Template_Config'                           => static function () {
1032
-                return EE_Config::instance()->template_settings;
1033
-            },
1034
-            'EE_Currency_Config'                           => static function () {
1035
-                return EE_Currency_Config::getCurrencyConfig();
1036
-            },
1037
-            'EE_Registration_Config'                       => static function () {
1038
-                return EE_Config::instance()->registration;
1039
-            },
1040
-            'EE_Core_Config'                               => static function () {
1041
-                return EE_Config::instance()->core;
1042
-            },
1043
-            'EventEspresso\core\services\loaders\Loader'   => static function () {
1044
-                return LoaderFactory::getLoader();
1045
-            },
1046
-            'EE_Network_Config'                            => static function () {
1047
-                return EE_Network_Config::instance();
1048
-            },
1049
-            'EE_Config'                                    => static function () {
1050
-                return EE_Config::instance();
1051
-            },
1052
-            'EventEspresso\core\domain\Domain'             => static function () {
1053
-                return DomainFactory::getEventEspressoCoreDomain();
1054
-            },
1055
-            'EE_Admin_Config'                              => static function () {
1056
-                return EE_Config::instance()->admin;
1057
-            },
1058
-            'EE_Organization_Config'                       => static function () {
1059
-                return EE_Config::instance()->organization;
1060
-            },
1061
-            'EE_Network_Core_Config'                       => static function () {
1062
-                return EE_Network_Config::instance()->core;
1063
-            },
1064
-            'EE_Environment_Config'                        => static function () {
1065
-                return EE_Config::instance()->environment;
1066
-            },
1067
-            'EED_Core_Rest_Api'                            => static function () {
1068
-                return EED_Core_Rest_Api::instance();
1069
-            },
1070
-            'WP_REST_Server'                               => static function () {
1071
-                return rest_get_server();
1072
-            },
1073
-            'EventEspresso\core\Psr4Autoloader'            => static function () {
1074
-                return EE_Psr4AutoloaderInit::psr4_loader();
1075
-            },
1076
-            'EE_Ticket_Selector_Config'                    => function () {
1077
-                return EE_Config::instance()->template_settings->EED_Ticket_Selector;
1078
-            },
1079
-        ];
1080
-    }
1081
-
1082
-
1083
-    /**
1084
-     * can be used for supplying alternate names for classes,
1085
-     * or for connecting interface names to instantiable classes
1086
-     *
1087
-     * @throws InvalidAliasException
1088
-     */
1089
-    protected function _register_core_aliases()
1090
-    {
1091
-        $aliases = [
1092
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1093
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1094
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1095
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1096
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1097
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1098
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1099
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1100
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1101
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1102
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\domain\services\commands\registration\CreateRegistrationCommand',
1103
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\domain\services\commands\registration\CopyRegistrationDetailsCommand',
1104
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\domain\services\commands\registration\CopyRegistrationPaymentsCommand',
1105
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\domain\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1106
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\domain\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1107
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\domain\services\commands\ticket\CreateTicketLineItemCommand',
1108
-            'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\domain\services\commands\transaction\CreateTransactionCommandHandler',
1109
-            'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\domain\services\commands\attendee\CreateAttendeeCommandHandler',
1110
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1111
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1112
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1113
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1114
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1115
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1116
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1117
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1118
-            'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1119
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1120
-            'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1121
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1122
-            'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1123
-            'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1124
-            'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1125
-            'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1126
-            'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1127
-            'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1128
-            'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1129
-            'Registration_Processor'                                                       => 'EE_Registration_Processor',
1130
-            'EventEspresso\core\services\assets\AssetManifestInterface'                    => 'EventEspresso\core\services\assets\AssetManifest',
1131
-        ];
1132
-        foreach ($aliases as $alias => $fqn) {
1133
-            if (is_array($fqn)) {
1134
-                foreach ($fqn as $class => $for_class) {
1135
-                    $this->class_cache->addAlias($class, $alias, $for_class);
1136
-                }
1137
-                continue;
1138
-            }
1139
-            $this->class_cache->addAlias($fqn, $alias);
1140
-        }
1141
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1142
-            $this->class_cache->addAlias(
1143
-                'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1144
-                'EventEspresso\core\services\notices\NoticeConverterInterface'
1145
-            );
1146
-        }
1147
-    }
1148
-
1149
-
1150
-    public function debug($for_class = '')
1151
-    {
1152
-        if (method_exists($this->class_cache, 'debug')) {
1153
-            $this->class_cache->debug($for_class);
1154
-        }
1155
-    }
1156
-
1157
-
1158
-    /**
1159
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1160
-     * request Primarily used by unit tests.
1161
-     */
1162
-    public function reset()
1163
-    {
1164
-        $this->_register_core_class_loaders();
1165
-        $this->_register_core_dependencies();
1166
-    }
1167
-
1168
-
1169
-    /**
1170
-     * PLZ NOTE: a better name for this method would be is_alias()
1171
-     * because it returns TRUE if the provided fully qualified name IS an alias
1172
-     * WHY?
1173
-     * Because if a class is type hinting for a concretion,
1174
-     * then why would we need to find another class to supply it?
1175
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1176
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1177
-     * Don't go looking for some substitute.
1178
-     * Whereas if a class is type hinting for an interface...
1179
-     * then we need to find an actual class to use.
1180
-     * So the interface IS the alias for some other FQN,
1181
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1182
-     * represents some other class.
1183
-     *
1184
-     * @param string $fqn
1185
-     * @param string $for_class
1186
-     * @return bool
1187
-     * @deprecated 4.9.62.p
1188
-     */
1189
-    public function has_alias(string $fqn = '', string $for_class = ''): bool
1190
-    {
1191
-        return $this->isAlias($fqn, $for_class);
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1197
-     * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1198
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
1199
-     *  for example:
1200
-     *      if the following two entries were added to the _aliases array:
1201
-     *          array(
1202
-     *              'interface_alias'           => 'some\namespace\interface'
1203
-     *              'some\namespace\interface'  => 'some\namespace\classname'
1204
-     *          )
1205
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1206
-     *      to load an instance of 'some\namespace\classname'
1207
-     *
1208
-     * @param string $alias
1209
-     * @param string $for_class
1210
-     * @return string
1211
-     * @deprecated 4.9.62.p
1212
-     */
1213
-    public function get_alias(string $alias = '', string $for_class = ''): string
1214
-    {
1215
-        return $this->getFqnForAlias($alias, $for_class);
1216
-    }
23
+	/**
24
+	 * This means that the requested class dependency is not present in the dependency map
25
+	 */
26
+	const not_registered = 0;
27
+
28
+	/**
29
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
+	 */
31
+	const load_new_object = 1;
32
+
33
+	/**
34
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
+	 */
37
+	const load_from_cache = 2;
38
+
39
+	/**
40
+	 * When registering a dependency,
41
+	 * this indicates to keep any existing dependencies that already exist,
42
+	 * and simply discard any new dependencies declared in the incoming data
43
+	 */
44
+	const KEEP_EXISTING_DEPENDENCIES = 0;
45
+
46
+	/**
47
+	 * When registering a dependency,
48
+	 * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
+	 */
50
+	const OVERWRITE_DEPENDENCIES = 1;
51
+
52
+	protected static ?EE_Dependency_Map $_instance = null;
53
+
54
+	private ClassInterfaceCache $class_cache;
55
+
56
+	protected ?RequestInterface $request = null;
57
+
58
+	protected ?LegacyRequestInterface $legacy_request = null;
59
+
60
+	protected ?ResponseInterface $response = null;
61
+
62
+	protected ?LoaderInterface $loader = null;
63
+
64
+	protected array $_dependency_map = [];
65
+
66
+	protected array $_class_loaders = [];
67
+
68
+
69
+	/**
70
+	 * EE_Dependency_Map constructor.
71
+	 *
72
+	 * @param ClassInterfaceCache $class_cache
73
+	 */
74
+	protected function __construct(ClassInterfaceCache $class_cache)
75
+	{
76
+		$this->class_cache = $class_cache;
77
+		do_action('EE_Dependency_Map____construct', $this);
78
+	}
79
+
80
+
81
+	/**
82
+	 * @return void
83
+	 * @throws InvalidAliasException
84
+	 */
85
+	public function initialize()
86
+	{
87
+		$this->_register_core_dependencies();
88
+		$this->_register_core_class_loaders();
89
+		$this->_register_core_aliases();
90
+	}
91
+
92
+
93
+	/**
94
+	 * @singleton method used to instantiate class object
95
+	 * @param ClassInterfaceCache|null $class_cache
96
+	 * @return EE_Dependency_Map
97
+	 */
98
+	public static function instance(ClassInterfaceCache $class_cache = null): EE_Dependency_Map
99
+	{
100
+		// check if class object is instantiated, and instantiated properly
101
+		if (
102
+			! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
103
+			&& $class_cache instanceof ClassInterfaceCache
104
+		) {
105
+			EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
106
+		}
107
+		return EE_Dependency_Map::$_instance;
108
+	}
109
+
110
+
111
+	/**
112
+	 * @param RequestInterface $request
113
+	 */
114
+	public function setRequest(RequestInterface $request)
115
+	{
116
+		$this->request = $request;
117
+	}
118
+
119
+
120
+	/**
121
+	 * @param LegacyRequestInterface $legacy_request
122
+	 */
123
+	public function setLegacyRequest(LegacyRequestInterface $legacy_request)
124
+	{
125
+		$this->legacy_request = $legacy_request;
126
+	}
127
+
128
+
129
+	/**
130
+	 * @param ResponseInterface $response
131
+	 */
132
+	public function setResponse(ResponseInterface $response)
133
+	{
134
+		$this->response = $response;
135
+	}
136
+
137
+
138
+	/**
139
+	 * @param LoaderInterface $loader
140
+	 */
141
+	public function setLoader(LoaderInterface $loader)
142
+	{
143
+		$this->loader = $loader;
144
+	}
145
+
146
+
147
+	/**
148
+	 * @param string $class
149
+	 * @param array  $dependencies
150
+	 * @param int    $overwrite
151
+	 * @return bool
152
+	 */
153
+	public static function register_dependencies(
154
+		string $class,
155
+		array $dependencies,
156
+		int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
157
+	): bool {
158
+		return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
159
+	}
160
+
161
+
162
+	/**
163
+	 * Assigns an array of class names and corresponding load sources (new or cached)
164
+	 * to the class specified by the first parameter.
165
+	 * IMPORTANT !!!
166
+	 * The order of elements in the incoming $dependencies array MUST match
167
+	 * the order of the constructor parameters for the class in question.
168
+	 * This is especially important when overriding any existing dependencies that are registered.
169
+	 * the third parameter controls whether any duplicate dependencies are overwritten or not.
170
+	 *
171
+	 * @param string $class
172
+	 * @param array  $dependencies
173
+	 * @param int    $overwrite
174
+	 * @return bool
175
+	 */
176
+	public function registerDependencies(
177
+		string $class,
178
+		array $dependencies,
179
+		int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
180
+	): bool {
181
+		if (empty($dependencies)) {
182
+			return false;
183
+		}
184
+		$class      = trim($class, '\\');
185
+		$registered = false;
186
+		if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
187
+			EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
188
+		}
189
+		// we need to make sure that any aliases used when registering a dependency
190
+		// get resolved to the correct class name
191
+		foreach ($dependencies as $dependency => $load_source) {
192
+			$alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
193
+			if (
194
+				$overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
195
+				|| ! isset(
196
+					EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $dependency ],
197
+					EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ]
198
+				)
199
+			) {
200
+				unset($dependencies[ $dependency ]);
201
+				$dependencies[ $alias ] = $load_source;
202
+				$registered             = true;
203
+			}
204
+		}
205
+		// now add our two lists of dependencies together.
206
+		// using Union (+=) favours the arrays in precedence from left to right,
207
+		// so $dependencies is NOT overwritten because it is listed first
208
+		// ie: with A = B + C, entries in B take precedence over duplicate entries in C
209
+		// Union is way faster than array_merge() but should be used with caution...
210
+		// especially with numerically indexed arrays
211
+		$dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
212
+		// now we need to ensure that the resulting dependencies
213
+		// array only has the entries that are required for the class
214
+		// so first count how many dependencies were originally registered for the class
215
+		$dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
216
+		// if that count is non-zero (meaning dependencies were already registered)
217
+		EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
218
+			// then truncate the  final array to match that count
219
+			? array_slice($dependencies, 0, $dependency_count)
220
+			// otherwise just take the incoming array because nothing previously existed
221
+			: $dependencies;
222
+		return $registered
223
+			|| count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]) === count($dependencies);
224
+	}
225
+
226
+
227
+	/**
228
+	 * @param string          $class_name
229
+	 * @param callable|string $loader
230
+	 * @param bool            $overwrite
231
+	 * @return bool
232
+	 * @throws DomainException
233
+	 */
234
+	public static function register_class_loader(
235
+		string $class_name,
236
+		$loader = 'load_core',
237
+		bool $overwrite = false
238
+	): bool {
239
+		return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader, $overwrite);
240
+	}
241
+
242
+
243
+	/**
244
+	 * @param string         $class_name
245
+	 * @param Closure|string $loader
246
+	 * @param bool           $overwrite
247
+	 * @return bool
248
+	 * @throws DomainException
249
+	 */
250
+	public function registerClassLoader(string $class_name, $loader = 'load_core', bool $overwrite = false): bool
251
+	{
252
+		if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
253
+			throw new DomainException(
254
+				esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
255
+			);
256
+		}
257
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
258
+		if (
259
+			! is_callable($loader)
260
+			&& (
261
+				strpos($loader, 'load_') !== 0
262
+				|| ! method_exists('EE_Registry', $loader)
263
+			)
264
+		) {
265
+			throw new DomainException(
266
+				sprintf(
267
+					esc_html__(
268
+						'"%1$s" is not a valid loader method on EE_Registry.',
269
+						'event_espresso'
270
+					),
271
+					$loader
272
+				)
273
+			);
274
+		}
275
+		$class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
276
+		if ($overwrite || ! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
277
+			EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
278
+			return true;
279
+		}
280
+		return false;
281
+	}
282
+
283
+
284
+	/**
285
+	 * @return array
286
+	 */
287
+	public function dependency_map(): array
288
+	{
289
+		return $this->_dependency_map;
290
+	}
291
+
292
+
293
+	/**
294
+	 * returns TRUE if dependency map contains a listing for the provided class name
295
+	 *
296
+	 * @param string $class_name
297
+	 * @return boolean
298
+	 */
299
+	public function has(string $class_name = ''): bool
300
+	{
301
+		// all legacy models have the same dependencies
302
+		if (strpos($class_name, 'EEM_') === 0) {
303
+			$class_name = 'LEGACY_MODELS';
304
+		}
305
+		return isset($this->_dependency_map[ $class_name ]);
306
+	}
307
+
308
+
309
+	/**
310
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
311
+	 *
312
+	 * @param string $class_name
313
+	 * @param string $dependency
314
+	 * @return bool
315
+	 */
316
+	public function has_dependency_for_class(string $class_name = '', string $dependency = ''): bool
317
+	{
318
+		// all legacy models have the same dependencies
319
+		if (strpos($class_name, 'EEM_') === 0) {
320
+			$class_name = 'LEGACY_MODELS';
321
+		}
322
+		$dependency = $this->getFqnForAlias($dependency, $class_name);
323
+		return isset($this->_dependency_map[ $class_name ][ $dependency ]);
324
+	}
325
+
326
+
327
+	/**
328
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
329
+	 *
330
+	 * @param string $class_name
331
+	 * @param string $dependency
332
+	 * @return int
333
+	 */
334
+	public function loading_strategy_for_class_dependency(string $class_name = '', string $dependency = ''): int
335
+	{
336
+		// all legacy models have the same dependencies
337
+		if (strpos($class_name, 'EEM_') === 0) {
338
+			$class_name = 'LEGACY_MODELS';
339
+		}
340
+		$dependency = $this->getFqnForAlias($dependency);
341
+		return $this->has_dependency_for_class($class_name, $dependency)
342
+			? $this->_dependency_map[ $class_name ][ $dependency ]
343
+			: EE_Dependency_Map::not_registered;
344
+	}
345
+
346
+
347
+	/**
348
+	 * @param string $class_name
349
+	 * @return string | Closure
350
+	 */
351
+	public function class_loader(string $class_name)
352
+	{
353
+		// all legacy models use load_model()
354
+		if (strpos($class_name, 'EEM_') === 0) {
355
+			return 'load_model';
356
+		}
357
+		// EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
358
+		// perform strpos() first to avoid loading regex every time we load a class
359
+		if (
360
+			strpos($class_name, 'EE_CPT_') === 0
361
+			&& preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
362
+		) {
363
+			return 'load_core';
364
+		}
365
+		$class_name = $this->getFqnForAlias($class_name);
366
+		return $this->_class_loaders[ $class_name ] ?? '';
367
+	}
368
+
369
+
370
+	/**
371
+	 * @return array
372
+	 */
373
+	public function class_loaders(): array
374
+	{
375
+		return $this->_class_loaders;
376
+	}
377
+
378
+
379
+	/**
380
+	 * adds an alias for a classname
381
+	 *
382
+	 * @param string $fqcn      the class name that should be used (concrete class to replace interface)
383
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
384
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
385
+	 * @throws InvalidAliasException
386
+	 */
387
+	public function add_alias(string $fqcn, string $alias, string $for_class = '')
388
+	{
389
+		$this->class_cache->addAlias($fqcn, $alias, $for_class);
390
+	}
391
+
392
+
393
+	/**
394
+	 * Returns TRUE if the provided fully qualified name IS an alias
395
+	 * WHY?
396
+	 * Because if a class is type hinting for a concretion,
397
+	 * then why would we need to find another class to supply it?
398
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
399
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
400
+	 * Don't go looking for some substitute.
401
+	 * Whereas if a class is type hinting for an interface...
402
+	 * then we need to find an actual class to use.
403
+	 * So the interface IS the alias for some other FQN,
404
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
405
+	 * represents some other class.
406
+	 *
407
+	 * @param string $fqn
408
+	 * @param string $for_class
409
+	 * @return bool
410
+	 */
411
+	public function isAlias(string $fqn = '', string $for_class = ''): bool
412
+	{
413
+		return $this->class_cache->isAlias($fqn, $for_class);
414
+	}
415
+
416
+
417
+	/**
418
+	 * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
419
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
420
+	 *  for example:
421
+	 *      if the following two entries were added to the _aliases array:
422
+	 *          array(
423
+	 *              'interface_alias'           => 'some\namespace\interface'
424
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
425
+	 *          )
426
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
427
+	 *      to load an instance of 'some\namespace\classname'
428
+	 *
429
+	 * @param string $alias
430
+	 * @param string $for_class
431
+	 * @return string
432
+	 */
433
+	public function getFqnForAlias(string $alias = '', string $for_class = ''): string
434
+	{
435
+		return $this->class_cache->getFqnForAlias($alias, $for_class);
436
+	}
437
+
438
+
439
+	/**
440
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
441
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
442
+	 * This is done by using the following class constants:
443
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
444
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
445
+	 */
446
+	protected function _register_core_dependencies()
447
+	{
448
+		$this->_dependency_map = [
449
+			'EE_Admin'                                                                                                           => [
450
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
451
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
452
+			],
453
+			'EE_Maintenance_Mode'                                                                                                => [
454
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
455
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
456
+			],
457
+			'EE_Request_Handler'                                                                                                 => [
458
+				'EventEspresso\core\services\request\Request'  => EE_Dependency_Map::load_from_cache,
459
+				'EventEspresso\core\services\request\Response' => EE_Dependency_Map::load_from_cache,
460
+			],
461
+			'EE_System'                                                                                                   => [
462
+				'EventEspresso\core\services\loaders\Loader'                   => EE_Dependency_Map::load_from_cache,
463
+				'EE_Maintenance_Mode'                                          => EE_Dependency_Map::load_from_cache,
464
+				'EE_Registry'                                                  => EE_Dependency_Map::load_from_cache,
465
+				'EventEspresso\core\services\request\Request'                  => EE_Dependency_Map::load_from_cache,
466
+				'EventEspresso\core\services\routing\Router'                   => EE_Dependency_Map::load_from_cache,
467
+				'EventEspresso\core\domain\services\capabilities\FeatureFlags' => EE_Dependency_Map::load_from_cache,
468
+			],
469
+			'EE_Session'                                                                                                         => [
470
+				'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
471
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
472
+				'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
473
+				'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
474
+				'EventEspresso\core\services\encryption\Base64Encoder'     => EE_Dependency_Map::load_from_cache,
475
+			],
476
+			'EventEspresso\core\services\session\SessionStartHandler'                                                            => [
477
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
478
+			],
479
+			'EE_Cart'                                                                                                            => [
480
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
481
+			],
482
+			'EE_Messenger_Collection_Loader'                                                                                     => [
483
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
484
+			],
485
+			'EE_Message_Type_Collection_Loader'                                                                                  => [
486
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
487
+			],
488
+			'EE_Message_Resource_Manager'                                                                                        => [
489
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
490
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
491
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
492
+			],
493
+			'EE_Message_Factory'                                                                                                 => [
494
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
495
+			],
496
+			'EE_messages'                                                                                                        => [
497
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
498
+			],
499
+			'EE_Messages_Generator'                                                                                              => [
500
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
501
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
502
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
503
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
504
+			],
505
+			'EE_Messages_Processor'                                                                                              => [
506
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
507
+			],
508
+			'EE_Messages_Queue'                                                                                                  => [
509
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
510
+			],
511
+			'EE_Messages_Template_Defaults'                                                                                      => [
512
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
513
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
514
+			],
515
+			'EE_Message_To_Generate_From_Request'                                                                                => [
516
+				'EE_Message_Resource_Manager'                 => EE_Dependency_Map::load_from_cache,
517
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
518
+			],
519
+			'EventEspresso\core\services\commands\CommandBus'                                                                    => [
520
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
521
+			],
522
+			'EventEspresso\services\commands\CommandHandler'                                                                     => [
523
+				'EE_Registry'         => EE_Dependency_Map::load_from_cache,
524
+				'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
525
+			],
526
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                         => [
527
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
528
+			],
529
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                       => [
530
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
531
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
532
+			],
533
+			'EventEspresso\core\services\commands\CommandFactory'                                                                => [
534
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
535
+			],
536
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                         => [
537
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
538
+			],
539
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                                => [
540
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
541
+			],
542
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                            => [
543
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
544
+			],
545
+			'EventEspresso\core\domain\services\commands\registration\CreateRegistrationCommandHandler'                          => [
546
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
547
+			],
548
+			'EventEspresso\core\domain\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
549
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
550
+			],
551
+			'EventEspresso\core\domain\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
552
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
553
+			],
554
+			'EventEspresso\core\domain\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
555
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
556
+			],
557
+			'EventEspresso\core\domain\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
558
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
559
+			],
560
+			'EventEspresso\core\domain\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
561
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
562
+			],
563
+			'EventEspresso\core\domain\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
564
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
565
+			],
566
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                          => [
567
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
568
+			],
569
+			'EventEspresso\core\domain\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
570
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
571
+			],
572
+			'EventEspresso\core\domain\values\session\SessionLifespan'                                                           => [
573
+				'EventEspresso\core\domain\values\session\SessionLifespanOption' => EE_Dependency_Map::load_from_cache,
574
+			],
575
+			'EventEspresso\caffeinated\admin\extend\registration_form\forms\SessionLifespanForm'                                 => [
576
+				'EventEspresso\core\domain\values\session\SessionLifespanOption' => EE_Dependency_Map::load_from_cache,
577
+				'EE_Registration_Config'                                         => EE_Dependency_Map::load_from_cache,
578
+			],
579
+			'EventEspresso\caffeinated\admin\extend\registration_form\forms\SessionLifespanFormHandler'                          => [
580
+				'EventEspresso\core\domain\values\session\SessionLifespanOption' => EE_Dependency_Map::load_from_cache,
581
+				'EE_Config'                                                      => EE_Dependency_Map::load_from_cache,
582
+			],
583
+			'EventEspresso\core\services\database\TableManager'                                                                  => [
584
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
585
+			],
586
+			'EE_Data_Migration_Class_Base'                                                                                       => [
587
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
588
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
589
+			],
590
+			'EE_DMS_Core_4_1_0'                                                                                                  => [
591
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
592
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
593
+			],
594
+			'EE_DMS_Core_4_2_0'                                                                                                  => [
595
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
596
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
597
+			],
598
+			'EE_DMS_Core_4_3_0'                                                                                                  => [
599
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
600
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
601
+			],
602
+			'EE_DMS_Core_4_4_0'                                                                                                  => [
603
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
604
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
605
+			],
606
+			'EE_DMS_Core_4_5_0'                                                                                                  => [
607
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
608
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
609
+			],
610
+			'EE_DMS_Core_4_6_0'                                                                                                  => [
611
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
612
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
613
+			],
614
+			'EE_DMS_Core_4_7_0'                                                                                                  => [
615
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
616
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
617
+			],
618
+			'EE_DMS_Core_4_8_0'                                                                                                  => [
619
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
620
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
621
+			],
622
+			'EE_DMS_Core_4_9_0'                                                                                                  => [
623
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
624
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
625
+			],
626
+			'EE_DMS_Core_4_10_0'                                                                                                 => [
627
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
628
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
629
+				'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
630
+			],
631
+			'EE_DMS_Core_5_0_0'                                                                                                  => [
632
+				'EE_DMS_Core_4_10_0'                                 => EE_Dependency_Map::load_from_cache,
633
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
634
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
635
+			],
636
+			'EventEspresso\core\services\assets\I18nRegistry'                                                                    => [
637
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
638
+			],
639
+			'EventEspresso\core\services\assets\Registry'                                                                        => [
640
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
641
+				'EventEspresso\core\services\assets\AssetManifest'   => EE_Dependency_Map::load_from_cache,
642
+			],
643
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                                    => [
644
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
645
+			],
646
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                                     => [
647
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
648
+			],
649
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                               => [
650
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
651
+			],
652
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                       => [
653
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
654
+			],
655
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                                     => [
656
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
657
+			],
658
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                               => [
659
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
660
+			],
661
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                                      => [
662
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
663
+			],
664
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                                => [
665
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
666
+			],
667
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                          => [
668
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
669
+			],
670
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                         => [
671
+				'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
672
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
673
+			],
674
+			'EventEspresso\core\domain\values\EmailAddress'                                                                      => [
675
+				null,
676
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
677
+			],
678
+			'EventEspresso\core\services\orm\ModelFieldFactory'                                                                  => [
679
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
680
+			],
681
+			'LEGACY_MODELS'                                                                                                      => [
682
+				null,
683
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
684
+			],
685
+			'EE_Module_Request_Router'                                                                                           => [
686
+				'EventEspresso\core\services\request\Request'             => EE_Dependency_Map::load_from_cache,
687
+				'EventEspresso\core\services\modules\ModuleRoutesManager' => EE_Dependency_Map::load_from_cache,
688
+			],
689
+			'EE_Registration_Processor'                                                                                          => [
690
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
691
+			],
692
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                             => [
693
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
694
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
695
+			],
696
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                           => [
697
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
698
+				'EE_Session'             => EE_Dependency_Map::load_from_cache,
699
+			],
700
+			'EventEspresso\modules\ticket_selector\DisplayTicketSelector'                                                        => [
701
+				'EventEspresso\core\domain\entities\users\CurrentUser' => EE_Dependency_Map::load_from_cache,
702
+				'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
703
+				'EE_Ticket_Selector_Config'                            => EE_Dependency_Map::load_from_cache,
704
+			],
705
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                        => [
706
+				'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
707
+				'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
708
+				'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
709
+				'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
710
+				'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
711
+			],
712
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelectorPostData'                                                => [
713
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
714
+				'EEM_Event'                                   => EE_Dependency_Map::load_from_cache,
715
+			],
716
+			'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                            => [
717
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
718
+			],
719
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                                     => [
720
+				'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
721
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
722
+			],
723
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                       => [
724
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
725
+			],
726
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                                      => [
727
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
728
+			],
729
+			'EE_CPT_Strategy'                                                                                                    => [
730
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
731
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
732
+			],
733
+			'EventEspresso\core\services\loaders\ObjectIdentifier'                                                               => [
734
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
735
+			],
736
+			'EventEspresso\core\CPTs\CptQueryModifier'                                                                           => [
737
+				null,
738
+				null,
739
+				null,
740
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
741
+				'EventEspresso\core\services\request\Request'     => EE_Dependency_Map::load_from_cache,
742
+				'EventEspresso\core\services\loaders\Loader'      => EE_Dependency_Map::load_from_cache,
743
+			],
744
+			'EventEspresso\core\services\dependencies\DependencyResolver'                                                        => [
745
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
746
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
747
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
748
+			],
749
+			'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                                      => [
750
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
751
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
752
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
753
+			],
754
+			'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                                 => [
755
+				'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
756
+				'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
757
+			],
758
+			'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                                 => [
759
+				'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
760
+				'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
761
+			],
762
+			'EventEspresso\core\services\request\files\FilesDataHandler'                                                         => [
763
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
764
+			],
765
+			'EventEspresso\core\libraries\batch\BatchRequestProcessor'                                                           => [
766
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
767
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
768
+			],
769
+			'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                       => [
770
+				'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
771
+				'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
772
+				'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
773
+				null,
774
+			],
775
+			'EventEspresso\core\services\routing\RouteHandler'                                                                   => [
776
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
777
+				'EventEspresso\core\services\json\JsonDataNodeHandler'                => EE_Dependency_Map::load_from_cache,
778
+				'EventEspresso\core\services\loaders\Loader'                          => EE_Dependency_Map::load_from_cache,
779
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
780
+				'EventEspresso\core\services\routing\RouteCollection'                 => EE_Dependency_Map::load_from_cache,
781
+			],
782
+			'EventEspresso\core\services\json\JsonDataNodeHandler'                                                               => [
783
+				'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
784
+			],
785
+			'EventEspresso\core\services\routing\Router'                                                                         => [
786
+				'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
787
+				'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
788
+				'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
789
+			],
790
+			'EventEspresso\core\services\assets\AssetManifest'                                                                   => [
791
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
792
+			],
793
+			'EventEspresso\core\services\assets\AssetManifestFactory'                                                            => [
794
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
795
+			],
796
+			'EventEspresso\core\services\assets\BaristaFactory'                                                                  => [
797
+				'EventEspresso\core\services\assets\AssetManifestFactory' => EE_Dependency_Map::load_from_cache,
798
+				'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
799
+			],
800
+			'EventEspresso\core\domain\services\capabilities\FeatureFlagsConfig' => [
801
+				'EventEspresso\core\domain\Domain'                                    => EE_Dependency_Map::load_from_cache,
802
+				'EventEspresso\core\services\json\JsonDataHandler'                    => EE_Dependency_Map::load_from_cache,
803
+			],
804
+			'EventEspresso\core\domain\services\capabilities\FeatureFlags'       => [
805
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
806
+				'EventEspresso\core\domain\services\capabilities\FeatureFlagsConfig'  => EE_Dependency_Map::load_from_cache,
807
+			],
808
+			'EventEspresso\core\services\addon\AddonManager'                                                                     => [
809
+				'EventEspresso\core\services\addon\AddonCollection'              => EE_Dependency_Map::load_from_cache,
810
+				'EventEspresso\core\Psr4Autoloader'                              => EE_Dependency_Map::load_from_cache,
811
+				'EventEspresso\core\services\addon\api\v1\RegisterAddon'         => EE_Dependency_Map::load_from_cache,
812
+				'EventEspresso\core\services\addon\api\IncompatibleAddonHandler' => EE_Dependency_Map::load_from_cache,
813
+				'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'  => EE_Dependency_Map::load_from_cache,
814
+			],
815
+			'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'                                                      => [
816
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
817
+			],
818
+			'EventEspresso\core\libraries\batch\JobHandlers\ExecuteBatchDeletion'                                                => [
819
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
820
+			],
821
+			'EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'                                                => [
822
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
823
+			],
824
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'                                               => [
825
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
826
+				'EEM_Event'                                                   => EE_Dependency_Map::load_from_cache,
827
+				'EEM_Datetime'                                                => EE_Dependency_Map::load_from_cache,
828
+				'EEM_Registration'                                            => EE_Dependency_Map::load_from_cache,
829
+			],
830
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'                                               => [
831
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
832
+			],
833
+			'EventEspresso\core\services\request\CurrentPage'                                                                    => [
834
+				'EE_CPT_Strategy'                             => EE_Dependency_Map::load_from_cache,
835
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
836
+			],
837
+			'EventEspresso\core\services\shortcodes\LegacyShortcodesManager'                                                     => [
838
+				'EE_Registry'                                     => EE_Dependency_Map::load_from_cache,
839
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
840
+			],
841
+			'EventEspresso\core\services\shortcodes\ShortcodesManager'                                                           => [
842
+				'EventEspresso\core\services\shortcodes\LegacyShortcodesManager' => EE_Dependency_Map::load_from_cache,
843
+				'EventEspresso\core\services\request\CurrentPage'                => EE_Dependency_Map::load_from_cache,
844
+			],
845
+			'EventEspresso\core\domain\entities\users\CurrentUser'                                                               => [
846
+				'EventEspresso\core\domain\entities\users\EventManagers' => EE_Dependency_Map::load_from_cache,
847
+			],
848
+			'EventEspresso\core\services\form\meta\InputTypes'                                                                   => [
849
+				'EventEspresso\core\services\form\meta\inputs\Block'    => EE_Dependency_Map::load_from_cache,
850
+				'EventEspresso\core\services\form\meta\inputs\Button'   => EE_Dependency_Map::load_from_cache,
851
+				'EventEspresso\core\services\form\meta\inputs\DateTime' => EE_Dependency_Map::load_from_cache,
852
+				'EventEspresso\core\services\form\meta\inputs\Input'    => EE_Dependency_Map::load_from_cache,
853
+				'EventEspresso\core\services\form\meta\inputs\Number'   => EE_Dependency_Map::load_from_cache,
854
+				'EventEspresso\core\services\form\meta\inputs\Phone'    => EE_Dependency_Map::load_from_cache,
855
+				'EventEspresso\core\services\form\meta\inputs\Select'   => EE_Dependency_Map::load_from_cache,
856
+				'EventEspresso\core\services\form\meta\inputs\Text'     => EE_Dependency_Map::load_from_cache,
857
+			],
858
+			'EventEspresso\core\domain\services\registration\form\v1\RegFormDependencyHandler'                                   => [
859
+				'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
860
+			],
861
+			'EventEspresso\core\services\calculators\LineItemCalculator'                                                         => [
862
+				'EventEspresso\core\services\helpers\DecimalValues' => EE_Dependency_Map::load_from_cache,
863
+			],
864
+			'EventEspresso\core\services\helpers\DecimalValues'                                                                  => [
865
+				'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
866
+			],
867
+			'EE_Brewing_Regular'                                                                                                 => [
868
+				'EE_Dependency_Map'                                  => EE_Dependency_Map::load_from_cache,
869
+				'EventEspresso\core\services\loaders\Loader'         => EE_Dependency_Map::load_from_cache,
870
+				'EventEspresso\core\services\routing\RouteHandler'   => EE_Dependency_Map::load_from_cache,
871
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
872
+			],
873
+			'EventEspresso\core\domain\services\messages\MessageTemplateRequestData'                                             => [
874
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
875
+			],
876
+			'EventEspresso\core\domain\services\messages\MessageTemplateValidator'                                               => [
877
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
878
+			],
879
+			'EventEspresso\core\domain\services\messages\MessageTemplateManager'                                                 => [
880
+				'EEM_Message_Template'                                                   => EE_Dependency_Map::load_from_cache,
881
+				'EEM_Message_Template_Group'                                             => EE_Dependency_Map::load_from_cache,
882
+				'EventEspresso\core\domain\services\messages\MessageTemplateRequestData' => EE_Dependency_Map::load_from_cache,
883
+				'EventEspresso\core\domain\services\messages\MessageTemplateValidator'   => EE_Dependency_Map::load_from_cache,
884
+				'EventEspresso\core\services\request\Request'                            => EE_Dependency_Map::load_from_cache,
885
+			],
886
+			'EventEspresso\core\services\request\sanitizers\RequestSanitizer'                                                    => [
887
+				'EventEspresso\core\domain\services\validation\email\strategies\Basic' => EE_Dependency_Map::load_from_cache,
888
+			],
889
+			'EE_CPT_Event_Strategy'                                                    => [
890
+				null,
891
+				null,
892
+				'EE_Template_Config' => EE_Dependency_Map::load_from_cache,
893
+			],
894
+			'EventEspresso\core\domain\services\licensing\LicenseKeyFormInput'                                                    => [
895
+				'EventEspresso\core\services\licensing\PluginLicense'  => EE_Dependency_Map::not_registered,
896
+				'EventEspresso\core\services\licensing\LicenseManager' => EE_Dependency_Map::load_from_cache,
897
+			],
898
+			'EventEspresso\core\services\payments\IpnHandler' => [
899
+				'EEM_Payment_Method'                                    => EE_Dependency_Map::not_registered,
900
+				'EEM_Transaction'                                       => EE_Dependency_Map::load_from_cache,
901
+				'EE_Core_Config'                                        => EE_Dependency_Map::load_from_cache,
902
+				'EE_Organization_Config'                                => EE_Dependency_Map::load_from_cache,
903
+				'EventEspresso\core\services\payments\PaymentProcessor' => EE_Dependency_Map::load_from_cache,
904
+			],
905
+			'EventEspresso\core\services\payments\PaymentProcessor' => [
906
+				'EEM_Payment_Method'                                           => EE_Dependency_Map::not_registered,
907
+				'EEM_Transaction'                                              => EE_Dependency_Map::load_from_cache,
908
+				'EE_Organization_Config'                                       => EE_Dependency_Map::load_from_cache,
909
+				'EventEspresso\core\domain\services\capabilities\FeatureFlags' => EE_Dependency_Map::load_from_cache,
910
+				'EventEspresso\core\services\payments\PaymentProcessorFees'    => EE_Dependency_Map::load_from_cache,
911
+				'EventEspresso\core\services\payments\PostPaymentProcessor'    => EE_Dependency_Map::load_from_cache,
912
+				'EventEspresso\core\services\payments\RegistrationPayments'    => EE_Dependency_Map::load_from_cache,
913
+			],
914
+			'EventEspresso\core\services\payments\PostPaymentProcessor' => [
915
+				'EE_Transaction_Processor' => EE_Dependency_Map::load_from_cache,
916
+			],
917
+			'EventEspresso\core\services\payments\PaymentProcessorFees' => [
918
+				'EventEspresso\core\domain\values\gateways\GracePeriod'    => EE_Dependency_Map::load_from_cache,
919
+				'EventEspresso\core\domain\services\licensing\LicenseData' => EE_Dependency_Map::load_from_cache,
920
+			],
921
+			'EventEspresso\core\domain\services\licensing\LicenseData'  => [
922
+				'EventEspresso\core\domain\Domain'                             => EE_Dependency_Map::load_from_cache,
923
+				'EventEspresso\core\domain\services\capabilities\FeatureFlags' => EE_Dependency_Map::load_from_cache,
924
+			],
925
+			'EventEspresso\core\domain\services\licensing\LicenseDataEDD' => [
926
+				'EventEspresso\core\services\licensing\LicenseKeyData' => EE_Dependency_Map::load_from_cache,
927
+			],
928
+			'EventEspresso\core\domain\services\licensing\LicenseDataPue' => [
929
+				'EE_Network_Core_Config' => EE_Dependency_Map::load_from_cache,
930
+			],
931
+		];
932
+	}
933
+
934
+
935
+	/**
936
+	 * Registers how core classes are loaded.
937
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
938
+	 *        'EE_Request_Handler' => 'load_core'
939
+	 *        'EE_Messages_Queue'  => 'load_lib'
940
+	 *        'EEH_Debug_Tools'    => 'load_helper'
941
+	 * or, if greater control is required, by providing a custom closure. For example:
942
+	 *        'Some_Class' => function () {
943
+	 *            return new Some_Class();
944
+	 *        },
945
+	 * This is required for instantiating dependencies
946
+	 * where an interface has been type hinted in a class constructor. For example:
947
+	 *        'Required_Interface' => function () {
948
+	 *            return new A_Class_That_Implements_Required_Interface();
949
+	 *        },
950
+	 */
951
+	protected function _register_core_class_loaders()
952
+	{
953
+		$this->_class_loaders = [
954
+			// load_core
955
+			'EE_Dependency_Map'                            => function () {
956
+				return $this;
957
+			},
958
+			'EE_Capabilities'                              => 'load_core',
959
+			'EE_Encryption'                                => 'load_core',
960
+			'EE_Front_Controller'                          => 'load_core',
961
+			'EE_Module_Request_Router'                     => 'load_core',
962
+			'EE_Registry'                                  => 'load_core',
963
+			'EE_Request'                                   => function () {
964
+				return $this->legacy_request;
965
+			},
966
+			'EventEspresso\core\services\request\Request'  => function () {
967
+				return $this->request;
968
+			},
969
+			'EventEspresso\core\services\request\Response' => function () {
970
+				return $this->response;
971
+			},
972
+			'EE_Base'                                      => 'load_core',
973
+			'EE_Request_Handler'                           => 'load_core',
974
+			'EE_Session'                                   => 'load_core',
975
+			'EE_Cron_Tasks'                                => 'load_core',
976
+			'EE_System'                                    => 'load_core',
977
+			'EE_Maintenance_Mode'                          => 'load_core',
978
+			'EE_Register_CPTs'                             => 'load_core',
979
+			'EE_Admin'                                     => 'load_core',
980
+			'EE_CPT_Strategy'                              => 'load_core',
981
+			// load_class
982
+			'EE_Registration_Processor'                    => 'load_class',
983
+			'EE_Transaction_Payments'                      => 'load_class',
984
+			'EE_Transaction_Processor'                     => 'load_class',
985
+			// load_lib
986
+			'EE_Message_Resource_Manager'                  => 'load_lib',
987
+			'EE_Message_Type_Collection'                   => 'load_lib',
988
+			'EE_Message_Type_Collection_Loader'            => 'load_lib',
989
+			'EE_Messenger_Collection'                      => 'load_lib',
990
+			'EE_Messenger_Collection_Loader'               => 'load_lib',
991
+			'EE_Messages_Processor'                        => 'load_lib',
992
+			'EE_Message_Repository'                        => 'load_lib',
993
+			'EE_Messages_Queue'                            => 'load_lib',
994
+			'EE_Messages_Data_Handler_Collection'          => 'load_lib',
995
+			'EE_Message_Template_Group_Collection'         => 'load_lib',
996
+			'EE_Payment_Method_Manager'                    => 'load_lib',
997
+			'EE_Payment_Processor'                         => 'load_core',
998
+			'EE_DMS_Core_4_1_0'                            => 'load_dms',
999
+			'EE_DMS_Core_4_2_0'                            => 'load_dms',
1000
+			'EE_DMS_Core_4_3_0'                            => 'load_dms',
1001
+			'EE_DMS_Core_4_5_0'                            => 'load_dms',
1002
+			'EE_DMS_Core_4_6_0'                            => 'load_dms',
1003
+			'EE_DMS_Core_4_7_0'                            => 'load_dms',
1004
+			'EE_DMS_Core_4_8_0'                            => 'load_dms',
1005
+			'EE_DMS_Core_4_9_0'                            => 'load_dms',
1006
+			'EE_DMS_Core_4_10_0'                           => 'load_dms',
1007
+			'EE_DMS_Core_5_0_0'                            => 'load_dms',
1008
+			'EE_Messages_Generator'                        => static function () {
1009
+				return EE_Registry::instance()->load_lib(
1010
+					'Messages_Generator',
1011
+					[],
1012
+					false,
1013
+					false
1014
+				);
1015
+			},
1016
+			'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
1017
+				return EE_Registry::instance()->load_lib(
1018
+					'Messages_Template_Defaults',
1019
+					$arguments,
1020
+					false,
1021
+					false
1022
+				);
1023
+			},
1024
+			// load_helper
1025
+			'EEH_Parse_Shortcodes'                         => static function () {
1026
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
1027
+					return new EEH_Parse_Shortcodes();
1028
+				}
1029
+				return null;
1030
+			},
1031
+			'EE_Template_Config'                           => static function () {
1032
+				return EE_Config::instance()->template_settings;
1033
+			},
1034
+			'EE_Currency_Config'                           => static function () {
1035
+				return EE_Currency_Config::getCurrencyConfig();
1036
+			},
1037
+			'EE_Registration_Config'                       => static function () {
1038
+				return EE_Config::instance()->registration;
1039
+			},
1040
+			'EE_Core_Config'                               => static function () {
1041
+				return EE_Config::instance()->core;
1042
+			},
1043
+			'EventEspresso\core\services\loaders\Loader'   => static function () {
1044
+				return LoaderFactory::getLoader();
1045
+			},
1046
+			'EE_Network_Config'                            => static function () {
1047
+				return EE_Network_Config::instance();
1048
+			},
1049
+			'EE_Config'                                    => static function () {
1050
+				return EE_Config::instance();
1051
+			},
1052
+			'EventEspresso\core\domain\Domain'             => static function () {
1053
+				return DomainFactory::getEventEspressoCoreDomain();
1054
+			},
1055
+			'EE_Admin_Config'                              => static function () {
1056
+				return EE_Config::instance()->admin;
1057
+			},
1058
+			'EE_Organization_Config'                       => static function () {
1059
+				return EE_Config::instance()->organization;
1060
+			},
1061
+			'EE_Network_Core_Config'                       => static function () {
1062
+				return EE_Network_Config::instance()->core;
1063
+			},
1064
+			'EE_Environment_Config'                        => static function () {
1065
+				return EE_Config::instance()->environment;
1066
+			},
1067
+			'EED_Core_Rest_Api'                            => static function () {
1068
+				return EED_Core_Rest_Api::instance();
1069
+			},
1070
+			'WP_REST_Server'                               => static function () {
1071
+				return rest_get_server();
1072
+			},
1073
+			'EventEspresso\core\Psr4Autoloader'            => static function () {
1074
+				return EE_Psr4AutoloaderInit::psr4_loader();
1075
+			},
1076
+			'EE_Ticket_Selector_Config'                    => function () {
1077
+				return EE_Config::instance()->template_settings->EED_Ticket_Selector;
1078
+			},
1079
+		];
1080
+	}
1081
+
1082
+
1083
+	/**
1084
+	 * can be used for supplying alternate names for classes,
1085
+	 * or for connecting interface names to instantiable classes
1086
+	 *
1087
+	 * @throws InvalidAliasException
1088
+	 */
1089
+	protected function _register_core_aliases()
1090
+	{
1091
+		$aliases = [
1092
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1093
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1094
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1095
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1096
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1097
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1098
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1099
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1100
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1101
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1102
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\domain\services\commands\registration\CreateRegistrationCommand',
1103
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\domain\services\commands\registration\CopyRegistrationDetailsCommand',
1104
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\domain\services\commands\registration\CopyRegistrationPaymentsCommand',
1105
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\domain\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1106
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\domain\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1107
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\domain\services\commands\ticket\CreateTicketLineItemCommand',
1108
+			'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\domain\services\commands\transaction\CreateTransactionCommandHandler',
1109
+			'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\domain\services\commands\attendee\CreateAttendeeCommandHandler',
1110
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1111
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1112
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1113
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1114
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1115
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1116
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1117
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1118
+			'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1119
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1120
+			'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1121
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1122
+			'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1123
+			'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1124
+			'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1125
+			'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1126
+			'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1127
+			'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1128
+			'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1129
+			'Registration_Processor'                                                       => 'EE_Registration_Processor',
1130
+			'EventEspresso\core\services\assets\AssetManifestInterface'                    => 'EventEspresso\core\services\assets\AssetManifest',
1131
+		];
1132
+		foreach ($aliases as $alias => $fqn) {
1133
+			if (is_array($fqn)) {
1134
+				foreach ($fqn as $class => $for_class) {
1135
+					$this->class_cache->addAlias($class, $alias, $for_class);
1136
+				}
1137
+				continue;
1138
+			}
1139
+			$this->class_cache->addAlias($fqn, $alias);
1140
+		}
1141
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1142
+			$this->class_cache->addAlias(
1143
+				'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1144
+				'EventEspresso\core\services\notices\NoticeConverterInterface'
1145
+			);
1146
+		}
1147
+	}
1148
+
1149
+
1150
+	public function debug($for_class = '')
1151
+	{
1152
+		if (method_exists($this->class_cache, 'debug')) {
1153
+			$this->class_cache->debug($for_class);
1154
+		}
1155
+	}
1156
+
1157
+
1158
+	/**
1159
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1160
+	 * request Primarily used by unit tests.
1161
+	 */
1162
+	public function reset()
1163
+	{
1164
+		$this->_register_core_class_loaders();
1165
+		$this->_register_core_dependencies();
1166
+	}
1167
+
1168
+
1169
+	/**
1170
+	 * PLZ NOTE: a better name for this method would be is_alias()
1171
+	 * because it returns TRUE if the provided fully qualified name IS an alias
1172
+	 * WHY?
1173
+	 * Because if a class is type hinting for a concretion,
1174
+	 * then why would we need to find another class to supply it?
1175
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1176
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1177
+	 * Don't go looking for some substitute.
1178
+	 * Whereas if a class is type hinting for an interface...
1179
+	 * then we need to find an actual class to use.
1180
+	 * So the interface IS the alias for some other FQN,
1181
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1182
+	 * represents some other class.
1183
+	 *
1184
+	 * @param string $fqn
1185
+	 * @param string $for_class
1186
+	 * @return bool
1187
+	 * @deprecated 4.9.62.p
1188
+	 */
1189
+	public function has_alias(string $fqn = '', string $for_class = ''): bool
1190
+	{
1191
+		return $this->isAlias($fqn, $for_class);
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1197
+	 * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1198
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
1199
+	 *  for example:
1200
+	 *      if the following two entries were added to the _aliases array:
1201
+	 *          array(
1202
+	 *              'interface_alias'           => 'some\namespace\interface'
1203
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
1204
+	 *          )
1205
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1206
+	 *      to load an instance of 'some\namespace\classname'
1207
+	 *
1208
+	 * @param string $alias
1209
+	 * @param string $for_class
1210
+	 * @return string
1211
+	 * @deprecated 4.9.62.p
1212
+	 */
1213
+	public function get_alias(string $alias = '', string $for_class = ''): string
1214
+	{
1215
+		return $this->getFqnForAlias($alias, $for_class);
1216
+	}
1217 1217
 }
Please login to merge, or discard this patch.
core/EE_Registry.core.php 2 patches
Indentation   +1700 added lines, -1700 removed lines patch added patch discarded remove patch
@@ -22,1704 +22,1704 @@
 block discarded – undo
22 22
  */
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25
-    private static ?EE_Registry $_instance = null;
26
-
27
-    protected EE_Dependency_Map $_dependency_map;
28
-
29
-    private Mirror $mirror;
30
-
31
-    private ClassInterfaceCache $class_cache;
32
-
33
-    private ObjectIdentifier $object_identifier;
34
-
35
-    protected array $_class_abbreviations = [];
36
-
37
-    public ?CommandBusInterface $BUS = null;
38
-
39
-    public ?EE_Cart $CART = null;
40
-
41
-    public ?EE_Config $CFG = null;
42
-
43
-    public ?EE_Network_Config $NET_CFG = null;
44
-
45
-    /**
46
-     * RegistryContainer for storing library classes in
47
-     *
48
-     * @var RegistryContainer|null $LIB
49
-     */
50
-    public ?RegistryContainer $LIB = null;
51
-
52
-    /**
53
-     * @var EE_Request_Handler|null $REQ
54
-     * @deprecated 4.10.14.p
55
-     */
56
-    public ?EE_Request_Handler $REQ = null;
57
-
58
-    public ?EE_Session $SSN = null;
59
-
60
-    /**
61
-     * @since 4.5.0
62
-     * @var EE_Capabilities|null $CAP
63
-     */
64
-    public ?EE_Capabilities$CAP = null;
65
-
66
-    /**
67
-     * @since 4.9.0
68
-     * @var EE_Message_Resource_Manager|null $MRM
69
-     */
70
-    public ?EE_Message_Resource_Manager $MRM = null;
71
-
72
-    public ?Registry $AssetsRegistry = null;
73
-
74
-    /**
75
-     * RegistryContainer for holding addons which have registered themselves to work with EE core
76
-     *
77
-     * @var RegistryContainer|EE_Addon[] $addons
78
-     */
79
-    public $addons = [];
80
-
81
-    /**
82
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
83
-     *
84
-     * @var EEM_Base[] $models
85
-     */
86
-    public array $models = [];
87
-
88
-    /**
89
-     * @var RegistryContainer|EED_Module[] $modules
90
-     */
91
-    public $modules = [];
92
-
93
-    /**
94
-     * @var RegistryContainer|EES_Shortcode[] $shortcodes
95
-     */
96
-    public $shortcodes = [];
97
-
98
-    /**
99
-     * @var RegistryContainer|WP_Widget[] $widgets
100
-     */
101
-    public $widgets = [];
102
-
103
-    /**
104
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
105
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
106
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
107
-     * classnames (eg "EEM_Event")
108
-     *
109
-     * @var array $non_abstract_db_models
110
-     */
111
-    public array $non_abstract_db_models = [];
112
-
113
-    /**
114
-     * internationalization for JS strings
115
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
116
-     *    in js file:  var translatedString = eei18n.string_key;
117
-     *
118
-     * @var array $i18n_js_strings
119
-     */
120
-    public static array $i18n_js_strings = [];
121
-
122
-    /**
123
-     * $main_file - path to espresso.php
124
-     *
125
-     * @var string $main_file
126
-     */
127
-    public string $main_file = '';
128
-
129
-    /**
130
-     * boolean flag to indicate whether to load/save dependencies from/to the cache
131
-     *
132
-     * @var bool $_cache_on
133
-     */
134
-    protected bool $_cache_on = true;
135
-
136
-
137
-    /**
138
-     * @singleton method used to instantiate class object
139
-     * @param EE_Dependency_Map|null   $dependency_map
140
-     * @param Mirror|null              $mirror
141
-     * @param ClassInterfaceCache|null $class_cache
142
-     * @param ObjectIdentifier|null    $object_identifier
143
-     * @return EE_Registry instance
144
-     */
145
-    public static function instance(
146
-        EE_Dependency_Map $dependency_map = null,
147
-        Mirror $mirror = null,
148
-        ClassInterfaceCache $class_cache = null,
149
-        ObjectIdentifier $object_identifier = null
150
-    ): EE_Registry {
151
-        // check if class object is instantiated
152
-        if (
153
-            ! self::$_instance instanceof EE_Registry
154
-            && $dependency_map instanceof EE_Dependency_Map
155
-            && $mirror instanceof Mirror
156
-            && $class_cache instanceof ClassInterfaceCache
157
-            && $object_identifier instanceof ObjectIdentifier
158
-        ) {
159
-            self::$_instance = new self(
160
-                $dependency_map,
161
-                $mirror,
162
-                $class_cache,
163
-                $object_identifier
164
-            );
165
-        }
166
-        return self::$_instance;
167
-    }
168
-
169
-
170
-    /**
171
-     * protected constructor to prevent direct creation
172
-     *
173
-     * @Constructor
174
-     * @param EE_Dependency_Map   $dependency_map
175
-     * @param Mirror              $mirror
176
-     * @param ClassInterfaceCache $class_cache
177
-     * @param ObjectIdentifier    $object_identifier
178
-     */
179
-    protected function __construct(
180
-        EE_Dependency_Map $dependency_map,
181
-        Mirror $mirror,
182
-        ClassInterfaceCache $class_cache,
183
-        ObjectIdentifier $object_identifier
184
-    ) {
185
-        $this->_dependency_map   = $dependency_map;
186
-        $this->mirror            = $mirror;
187
-        $this->class_cache       = $class_cache;
188
-        $this->object_identifier = $object_identifier;
189
-
190
-        $this->LIB        = new RegistryContainer();
191
-        $this->addons     = new RegistryContainer();
192
-        $this->modules    = new RegistryContainer();
193
-        $this->shortcodes = new RegistryContainer();
194
-        $this->widgets    = new RegistryContainer();
195
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', [$this, 'initialize']);
196
-    }
197
-
198
-
199
-    /**
200
-     * initialize
201
-     *
202
-     * @throws OutOfBoundsException
203
-     * @throws InvalidArgumentException
204
-     * @throws InvalidInterfaceException
205
-     * @throws InvalidDataTypeException
206
-     * @throws EE_Error
207
-     * @throws ReflectionException
208
-     */
209
-    public function initialize()
210
-    {
211
-        $this->_class_abbreviations = apply_filters(
212
-            'FHEE__EE_Registry____construct___class_abbreviations',
213
-            [
214
-                'EE_Config'                                       => 'CFG',
215
-                'EE_Session'                                      => 'SSN',
216
-                'EE_Capabilities'                                 => 'CAP',
217
-                'EE_Cart'                                         => 'CART',
218
-                'EE_Network_Config'                               => 'NET_CFG',
219
-                'EE_Request_Handler'                              => 'REQ',
220
-                'EE_Message_Resource_Manager'                     => 'MRM',
221
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
222
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
223
-            ]
224
-        );
225
-        $this->load_core('Base', [], true);
226
-        // add our request and response objects to the cache
227
-        $request_loader = $this->_dependency_map->class_loader(
228
-            'EventEspresso\core\services\request\Request'
229
-        );
230
-        $this->_set_cached_class(
231
-            $request_loader(),
232
-            'EventEspresso\core\services\request\Request'
233
-        );
234
-        $response_loader = $this->_dependency_map->class_loader(
235
-            'EventEspresso\core\services\request\Response'
236
-        );
237
-        $this->_set_cached_class(
238
-            $response_loader(),
239
-            'EventEspresso\core\services\request\Response'
240
-        );
241
-        add_action('AHEE__EE_System__set_hooks_for_core', [$this, 'init']);
242
-    }
243
-
244
-
245
-    /**
246
-     * @return void
247
-     */
248
-    public function init()
249
-    {
250
-        // Get current page protocol
251
-        $protocol = is_ssl() ? 'https://' : 'http://';
252
-        // Output admin-ajax.php URL with same protocol as current page
253
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
254
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
255
-    }
256
-
257
-
258
-    /**
259
-     * @return array
260
-     */
261
-    public static function sanitize_i18n_js_strings(): array
262
-    {
263
-        array_walk(EE_Registry::$i18n_js_strings, function (&$value) {
264
-            if (is_scalar($value)) {
265
-                $value = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
266
-                // replace all escaped instances of \n with actual new lines
267
-                $value = str_replace("\\n", "\n", $value);
268
-            }
269
-        });
270
-        // sort the array by key in a case-insensitive manner
271
-        ksort(EE_Registry::$i18n_js_strings, SORT_NATURAL | SORT_FLAG_CASE);
272
-        return EE_Registry::$i18n_js_strings;
273
-    }
274
-
275
-
276
-    /**
277
-     * localize_i18n_js_strings
278
-     *
279
-     * @return string
280
-     */
281
-    public static function localize_i18n_js_strings(): string
282
-    {
283
-        $i18n_js_strings = wp_json_encode(EE_Registry::sanitize_i18n_js_strings());
284
-        return "/* <![CDATA[ */ var eei18n = $i18n_js_strings; /* ]]> */";
285
-    }
286
-
287
-
288
-    /**
289
-     * @param mixed string | EED_Module $module
290
-     * @throws OutOfBoundsException
291
-     * @throws InvalidArgumentException
292
-     * @throws InvalidInterfaceException
293
-     * @throws InvalidDataTypeException
294
-     * @throws EE_Error
295
-     * @throws ReflectionException
296
-     */
297
-    public function add_module($module)
298
-    {
299
-        if ($module instanceof EED_Module) {
300
-            $module_class = get_class($module);
301
-            $this->modules->add($module_class, $module);
302
-        } else {
303
-            if (! class_exists('EE_Module_Request_Router', false)) {
304
-                $this->load_core('Module_Request_Router');
305
-            }
306
-            EE_Module_Request_Router::module_factory($module);
307
-        }
308
-    }
309
-
310
-
311
-    /**
312
-     * @param string $module_name
313
-     * @return mixed EED_Module | NULL
314
-     */
315
-    public function get_module(string $module_name = '')
316
-    {
317
-        return $this->modules->get($module_name);
318
-    }
319
-
320
-
321
-    /**
322
-     * loads core classes - must be singletons
323
-     *
324
-     * @param string $class_name - simple class name ie: session
325
-     * @param mixed  $arguments
326
-     * @param bool   $load_only
327
-     * @return bool|null|object
328
-     * @throws InvalidInterfaceException
329
-     * @throws InvalidDataTypeException
330
-     * @throws EE_Error
331
-     * @throws ReflectionException
332
-     * @throws InvalidArgumentException
333
-     */
334
-    public function load_core(string $class_name, $arguments = [], bool $load_only = false)
335
-    {
336
-        $core_paths = (array) apply_filters(
337
-            'FHEE__EE_Registry__load_core__core_paths',
338
-            [
339
-                EE_CORE,
340
-                EE_ADMIN,
341
-                EE_CPTS,
342
-                EE_CORE . 'CPTs/',
343
-                EE_CORE . 'data_migration_scripts/',
344
-                EE_CORE . 'request_stack/',
345
-                EE_CORE . 'middleware/',
346
-            ]
347
-        );
348
-        // retrieve instantiated class
349
-        return $this->_load(
350
-            $core_paths,
351
-            'EE_',
352
-            $class_name,
353
-            'core',
354
-            $arguments,
355
-            false,
356
-            true,
357
-            $load_only
358
-        );
359
-    }
360
-
361
-
362
-    /**
363
-     * loads service classes
364
-     *
365
-     * @param string $class_name - simple class name ie: session
366
-     * @param mixed  $arguments
367
-     * @param bool   $load_only
368
-     * @return bool|null|object
369
-     * @throws InvalidInterfaceException
370
-     * @throws InvalidDataTypeException
371
-     * @throws EE_Error
372
-     * @throws ReflectionException
373
-     * @throws InvalidArgumentException
374
-     * @deprecated  4.10.33.p
375
-     */
376
-    public function load_service(string $class_name, $arguments = [], bool $load_only = false)
377
-    {
378
-        $service_paths = (array) apply_filters(
379
-            'FHEE__EE_Registry__load_service__service_paths',
380
-            [
381
-                EE_CORE . 'services/',
382
-            ]
383
-        );
384
-        // retrieve instantiated class
385
-        return $this->_load(
386
-            $service_paths,
387
-            'EE_',
388
-            $class_name,
389
-            'class',
390
-            $arguments,
391
-            false,
392
-            true,
393
-            $load_only
394
-        );
395
-    }
396
-
397
-
398
-    /**
399
-     * loads data_migration_scripts
400
-     *
401
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
402
-     * @param mixed  $arguments
403
-     * @return bool|null|object
404
-     * @throws InvalidInterfaceException
405
-     * @throws InvalidDataTypeException
406
-     * @throws EE_Error
407
-     * @throws ReflectionException
408
-     * @throws InvalidArgumentException
409
-     */
410
-    public function load_dms(string $class_name, $arguments = [])
411
-    {
412
-        // retrieve instantiated class
413
-        return $this->_load(
414
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
415
-            'EE_DMS_',
416
-            $class_name,
417
-            'dms',
418
-            $arguments,
419
-            false,
420
-            false
421
-        );
422
-    }
423
-
424
-
425
-    /**
426
-     * loads object creating classes - must be singletons
427
-     *
428
-     * @param string $class_name - simple class name ie: attendee
429
-     * @param mixed  $arguments  - an array of arguments to pass to the class
430
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
431
-     *                           instantiate
432
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
433
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
434
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
435
-     *                           (default)
436
-     * @return EE_Base_Class|object|bool|null
437
-     * @throws InvalidInterfaceException
438
-     * @throws InvalidDataTypeException
439
-     * @throws EE_Error
440
-     * @throws ReflectionException
441
-     * @throws InvalidArgumentException
442
-     */
443
-    public function load_class(
444
-        string $class_name,
445
-        $arguments = [],
446
-        bool $from_db = false,
447
-        bool $cache = true,
448
-        bool $load_only = false
449
-    ) {
450
-        $paths = (array) apply_filters(
451
-            'FHEE__EE_Registry__load_class__paths',
452
-            [
453
-                EE_CORE,
454
-                EE_CLASSES,
455
-                EE_BUSINESS,
456
-            ]
457
-        );
458
-        // retrieve instantiated class
459
-        return $this->_load(
460
-            $paths,
461
-            'EE_',
462
-            $class_name,
463
-            'class',
464
-            $arguments,
465
-            $from_db,
466
-            $cache,
467
-            $load_only
468
-        );
469
-    }
470
-
471
-
472
-    /**
473
-     * loads helper classes - must be singletons
474
-     *
475
-     * @param string $class_name - simple class name ie: price
476
-     * @param mixed  $arguments
477
-     * @param bool   $load_only
478
-     * @return bool|null|object
479
-     * @throws InvalidInterfaceException
480
-     * @throws InvalidDataTypeException
481
-     * @throws EE_Error
482
-     * @throws ReflectionException
483
-     * @throws InvalidArgumentException
484
-     */
485
-    public function load_helper(string $class_name, $arguments = [], bool $load_only = true)
486
-    {
487
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
488
-        $helper_paths = (array) apply_filters('FHEE__EE_Registry__load_helper__helper_paths', [EE_HELPERS]);
489
-        // retrieve instantiated class
490
-        return $this->_load(
491
-            $helper_paths,
492
-            'EEH_',
493
-            $class_name,
494
-            'helper',
495
-            $arguments,
496
-            false,
497
-            true,
498
-            $load_only
499
-        );
500
-    }
501
-
502
-
503
-    /**
504
-     * loads core classes - must be singletons
505
-     *
506
-     * @param string $class_name - simple class name ie: session
507
-     * @param mixed  $arguments
508
-     * @param bool   $load_only
509
-     * @param bool   $cache      whether to cache the object or not.
510
-     * @return bool|null|object
511
-     * @throws InvalidInterfaceException
512
-     * @throws InvalidDataTypeException
513
-     * @throws EE_Error
514
-     * @throws ReflectionException
515
-     * @throws InvalidArgumentException
516
-     */
517
-    public function load_lib(string $class_name, $arguments = [], bool $load_only = false, bool $cache = true)
518
-    {
519
-        $paths = [
520
-            EE_LIBRARIES,
521
-            EE_LIBRARIES . 'messages/',
522
-            EE_LIBRARIES . 'shortcodes/',
523
-            EE_LIBRARIES . 'qtips/',
524
-            EE_LIBRARIES . 'payment_methods/',
525
-        ];
526
-        // retrieve instantiated class
527
-        return $this->_load(
528
-            $paths,
529
-            'EE_',
530
-            $class_name,
531
-            'lib',
532
-            $arguments,
533
-            false,
534
-            $cache,
535
-            $load_only
536
-        );
537
-    }
538
-
539
-
540
-    /**
541
-     * loads model classes - must be singletons
542
-     *
543
-     * @param string $class_name - simple class name ie: price
544
-     * @param mixed  $arguments
545
-     * @param bool   $load_only
546
-     * @return bool|null|object
547
-     * @throws InvalidInterfaceException
548
-     * @throws InvalidDataTypeException
549
-     * @throws EE_Error
550
-     * @throws ReflectionException
551
-     * @throws InvalidArgumentException
552
-     */
553
-    public function load_model(string $class_name, $arguments = [], bool $load_only = false)
554
-    {
555
-        $paths = (array) apply_filters(
556
-            'FHEE__EE_Registry__load_model__paths',
557
-            [
558
-                EE_MODELS,
559
-                EE_CORE,
560
-            ]
561
-        );
562
-        // retrieve instantiated class
563
-        return $this->_load(
564
-            $paths,
565
-            'EEM_',
566
-            $class_name,
567
-            'model',
568
-            $arguments,
569
-            false,
570
-            true,
571
-            $load_only
572
-        );
573
-    }
574
-
575
-
576
-    /**
577
-     * loads model classes - must be singletons
578
-     *
579
-     * @param string $class_name - simple class name ie: price
580
-     * @param mixed  $arguments
581
-     * @param bool   $load_only
582
-     * @return bool|null|object
583
-     * @throws InvalidInterfaceException
584
-     * @throws InvalidDataTypeException
585
-     * @throws EE_Error
586
-     * @throws ReflectionException
587
-     * @throws InvalidArgumentException
588
-     * @deprecated  4.10.33.p
589
-     */
590
-    public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
591
-    {
592
-        $paths = [
593
-            EE_MODELS . 'fields/',
594
-            EE_MODELS . 'helpers/',
595
-            EE_MODELS . 'relations/',
596
-            EE_MODELS . 'strategies/',
597
-        ];
598
-        // retrieve instantiated class
599
-        return $this->_load(
600
-            $paths,
601
-            'EE_',
602
-            $class_name,
603
-            '',
604
-            $arguments,
605
-            false,
606
-            true,
607
-            $load_only
608
-        );
609
-    }
610
-
611
-
612
-    /**
613
-     * Determines if $model_name is the name of an actual EE model.
614
-     *
615
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
616
-     * @return boolean
617
-     */
618
-    public function is_model_name(string $model_name): bool
619
-    {
620
-        return isset($this->models[ $model_name ]);
621
-    }
622
-
623
-
624
-    /**
625
-     * generic class loader
626
-     *
627
-     * @param string $path_to_file - directory path to file location, not including filename
628
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
629
-     * @param string $type         - file type - core? class? helper? model?
630
-     * @param mixed  $arguments
631
-     * @param bool   $load_only
632
-     * @return bool|null|object
633
-     * @throws InvalidInterfaceException
634
-     * @throws InvalidDataTypeException
635
-     * @throws EE_Error
636
-     * @throws ReflectionException
637
-     * @throws InvalidArgumentException
638
-     */
639
-    public function load_file(
640
-        string $path_to_file,
641
-        string $file_name,
642
-        string $type = '',
643
-        $arguments = [],
644
-        bool $load_only = true
645
-    ) {
646
-        // retrieve instantiated class
647
-        return $this->_load(
648
-            (array) $path_to_file,
649
-            '',
650
-            $file_name,
651
-            $type,
652
-            $arguments,
653
-            false,
654
-            true,
655
-            $load_only
656
-        );
657
-    }
658
-
659
-
660
-    /**
661
-     * @param string $path_to_file - directory path to file location, not including filename
662
-     * @param string $class_name   - full class name  ie:  My_Class
663
-     * @param string $type         - file type - core? class? helper? model?
664
-     * @param mixed  $arguments
665
-     * @param bool   $load_only
666
-     * @return bool|null|object
667
-     * @throws InvalidInterfaceException
668
-     * @throws InvalidDataTypeException
669
-     * @throws EE_Error
670
-     * @throws ReflectionException
671
-     * @throws InvalidArgumentException
672
-     * @deprecated  4.10.33.p
673
-     */
674
-    public function load_addon(
675
-        string $path_to_file,
676
-        string $class_name,
677
-        string $type = 'class',
678
-        $arguments = [],
679
-        bool $load_only = false
680
-    ) {
681
-        // retrieve instantiated class
682
-        return $this->_load(
683
-            (array) $path_to_file,
684
-            'addon',
685
-            $class_name,
686
-            $type,
687
-            $arguments,
688
-            false,
689
-            true,
690
-            $load_only
691
-        );
692
-    }
693
-
694
-
695
-    /**
696
-     * instantiates, caches, and automatically resolves dependencies
697
-     * for classes that use a Fully Qualified Class Name.
698
-     * if the class is not capable of being loaded using PSR-4 autoloading,
699
-     * then you need to use one of the existing load_*() methods
700
-     * which can resolve the classname and filepath from the passed arguments
701
-     *
702
-     * @param string      $class_name Fully Qualified Class Name
703
-     * @param array       $arguments  an argument, or array of arguments to pass to the class upon instantiation
704
-     * @param bool        $cache      whether to cache the instantiated object for reuse
705
-     * @param bool        $from_db    some classes are instantiated from the db
706
-     *                                and thus call a different method to instantiate
707
-     * @param bool        $load_only  if true, will only load the file, but will NOT instantiate an object
708
-     * @param bool|string $addon      if true, will cache the object in the EE_Registry->$addons array
709
-     * @return bool|null|mixed     null = failure to load or instantiate class object.
710
-     *                                object = class loaded and instantiated successfully.
711
-     *                                bool = fail or success when $load_only is true
712
-     * @throws InvalidInterfaceException
713
-     * @throws InvalidDataTypeException
714
-     * @throws EE_Error
715
-     * @throws ReflectionException
716
-     * @throws InvalidArgumentException
717
-     */
718
-    public function create(
719
-        string $class_name = '',
720
-        array $arguments = [],
721
-        bool $cache = false,
722
-        bool $from_db = false,
723
-        bool $load_only = false,
724
-        bool $addon = false
725
-    ) {
726
-        $class_name   = ltrim($class_name, '\\');
727
-        $class_name   = $this->class_cache->getFqnForAlias($class_name);
728
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
729
-        // if a non-FQCN was passed, then
730
-        // verifyClassExists() might return an object
731
-        // or it could return null if the class just could not be found anywhere
732
-        if ($class_exists instanceof $class_name || $class_exists === null) {
733
-            // either way, return the results
734
-            return $class_exists;
735
-        }
736
-        $class_name = $class_exists;
737
-        // if we're only loading the class and it already exists, then let's just return true immediately
738
-        if ($load_only) {
739
-            return true;
740
-        }
741
-        $addon = $addon ? 'addon' : '';
742
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
743
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
744
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
745
-        if ($this->_cache_on && $cache) {
746
-            // return object if it's already cached
747
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
748
-            if ($cached_class !== null) {
749
-                return $cached_class;
750
-            }
751
-        }                                                           // obtain the loader method from the dependency map
752
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
753
-        if ($loader instanceof Closure) {
754
-            $class_obj = $loader($arguments);
755
-        } else {
756
-            if ($loader && method_exists($this, $loader)) {
757
-                $class_obj = $this->{$loader}($class_name, $arguments);
758
-            } else {
759
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
760
-            }
761
-        }
762
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
763
-            // save it for later... kinda like gum  { : $
764
-            $this->_set_cached_class(
765
-                $class_obj,
766
-                $class_name,
767
-                $addon,
768
-                $from_db,
769
-                $arguments
770
-            );
771
-        }
772
-        $this->_cache_on = true;
773
-        return $class_obj;
774
-    }
775
-
776
-
777
-    /**
778
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
779
-     *
780
-     * @param string|mixed $class_name
781
-     * @param array        $arguments
782
-     * @param int          $attempt
783
-     * @return mixed
784
-     */
785
-    private function loadOrVerifyClassExists($class_name, array $arguments, int $attempt = 1)
786
-    {
787
-        if (is_object($class_name) || class_exists($class_name)) {
788
-            return $class_name;
789
-        }
790
-        switch ($attempt) {
791
-            case 1:
792
-                // if it's a FQCN then maybe the class is registered with a preceding \
793
-                $class_name = strpos($class_name, '\\') !== false
794
-                    ? '\\' . ltrim($class_name, '\\')
795
-                    : $class_name;
796
-                break;
797
-            case 2:
798
-                //
799
-                $loader = $this->_dependency_map->class_loader($class_name);
800
-                if ($loader && method_exists($this, $loader)) {
801
-                    return $this->{$loader}($class_name, $arguments);
802
-                }
803
-                break;
804
-            case 3:
805
-            default:
806
-                return null;
807
-        }
808
-        $attempt++;
809
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
810
-    }
811
-
812
-
813
-    /**
814
-     * instantiates, caches, and injects dependencies for classes
815
-     *
816
-     * @param array  $file_paths         an array of paths to folders to look in
817
-     * @param string $class_prefix       EE  or EEM or... ???
818
-     * @param string $class_name         $class name
819
-     * @param string $type               file type - core? class? helper? model?
820
-     * @param mixed  $arguments          an argument or array of arguments to pass to the class upon instantiation
821
-     * @param bool   $from_db            some classes are instantiated from the db
822
-     *                                   and thus call a different method to instantiate
823
-     * @param bool   $cache              whether to cache the instantiated object for reuse
824
-     * @param bool   $load_only          if true, will only load the file, but will NOT instantiate an object
825
-     * @return bool|null|object          null   = failure to load or instantiate class object.
826
-     *                                   object = class loaded and instantiated successfully.
827
-     *                                   bool   = fail or success when $load_only is true
828
-     * @throws EE_Error
829
-     * @throws ReflectionException
830
-     * @throws InvalidInterfaceException
831
-     * @throws InvalidDataTypeException
832
-     * @throws InvalidArgumentException
833
-     */
834
-    protected function _load(
835
-        array $file_paths = [],
836
-        string $class_prefix = 'EE_',
837
-        string $class_name = '',
838
-        string $type = 'class',
839
-        array $arguments = [],
840
-        bool $from_db = false,
841
-        bool $cache = true,
842
-        bool $load_only = false
843
-    ) {
844
-        $class_name = ltrim($class_name, '\\');
845
-        // strip php file extension
846
-        $class_name = str_replace('.php', '', trim($class_name));
847
-        // does the class have a prefix ?
848
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
849
-            // make sure $class_prefix is uppercase
850
-            $class_prefix = strtoupper(trim($class_prefix));
851
-            // add class prefix ONCE!!!
852
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
853
-        }
854
-        $class_name   = $this->class_cache->getFqnForAlias($class_name);
855
-        $class_exists = class_exists($class_name, false);
856
-        // if we're only loading the class and it already exists, then let's just return true immediately
857
-        if ($load_only && $class_exists) {
858
-            return true;
859
-        }
860
-        $arguments = is_array($arguments) ? $arguments : [$arguments];
861
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
862
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
863
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
864
-        if ($this->_cache_on && $cache && ! $load_only) {
865
-            // return object if it's already cached
866
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
867
-            if ($cached_class !== null) {
868
-                return $cached_class;
869
-            }
870
-        }
871
-        // if the class doesn't already exist.. then we need to try and find the file and load it
872
-        if (! $class_exists) {
873
-            // get full path to file
874
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
875
-            // load the file
876
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
877
-            // if we are only loading a file but NOT instantiating an object
878
-            // then return boolean for whether class was loaded or not
879
-            if ($load_only) {
880
-                return $loaded;
881
-            }
882
-            // if an object was expected but loading failed, then return nothing
883
-            if (! $loaded) {
884
-                return null;
885
-            }
886
-        }
887
-        // instantiate the requested object
888
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
889
-        if ($this->_cache_on && $cache) {
890
-            // save it for later... kinda like gum  { : $
891
-            $this->_set_cached_class(
892
-                $class_obj,
893
-                $class_name,
894
-                $class_prefix,
895
-                $from_db,
896
-                $arguments
897
-            );
898
-        }
899
-        $this->_cache_on = true;
900
-        return $class_obj;
901
-    }
902
-
903
-
904
-    /**
905
-     * @param string $class_name
906
-     * @param string $default have to specify something, but not anything that will conflict
907
-     * @return mixed|string
908
-     */
909
-    protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
910
-    {
911
-        return $this->_class_abbreviations[ $class_name ] ?? $default;
912
-    }
913
-
914
-
915
-    /**
916
-     * attempts to find a cached version of the requested class
917
-     * by looking in the following places:
918
-     *        $this->{$class_abbreviation}            ie:    $this->CART
919
-     *        $this->{$class_name}                        ie:    $this->Some_Class
920
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
921
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
922
-     *
923
-     * @param string $class_name
924
-     * @param string $class_prefix
925
-     * @param array  $arguments
926
-     * @return mixed
927
-     */
928
-    protected function _get_cached_class(
929
-        string $class_name,
930
-        string $class_prefix = '',
931
-        array $arguments = []
932
-    ) {
933
-        if ($class_name === 'EE_Registry') {
934
-            return $this;
935
-        }
936
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
937
-        // check if class has already been loaded, and return it if it has been
938
-        if (isset($this->{$class_abbreviation})) {
939
-            return $this->{$class_abbreviation};
940
-        }
941
-        $class_name = str_replace('\\', '_', $class_name);
942
-        if (isset($this->{$class_name})) {
943
-            return $this->{$class_name};
944
-        }
945
-        if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
946
-            return $this->addons->get($class_name);
947
-        }
948
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
949
-        if ($this->LIB->has($object_identifier)) {
950
-            return $this->LIB->get($object_identifier);
951
-        }
952
-        foreach ($this->LIB as $key => $object) {
953
-            if (
954
-                // request does not contain new arguments and therefore no args identifier
955
-                ! $this->object_identifier->hasArguments($object_identifier)
956
-                // but previously cached class with args was found
957
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
958
-            ) {
959
-                return $object;
960
-            }
961
-        }
962
-        return null;
963
-    }
964
-
965
-
966
-    /**
967
-     * removes a cached version of the requested class
968
-     *
969
-     * @param string  $class_name
970
-     * @param boolean $addon
971
-     * @param array   $arguments
972
-     * @return boolean
973
-     */
974
-    public function clear_cached_class(
975
-        string $class_name,
976
-        bool $addon = false,
977
-        array $arguments = []
978
-    ): bool {
979
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
980
-        // check if class has already been loaded, and return it if it has been
981
-        if (isset($this->{$class_abbreviation})) {
982
-            $this->{$class_abbreviation} = null;
983
-            return true;
984
-        }
985
-        $class_name = str_replace('\\', '_', $class_name);
986
-        if (isset($this->{$class_name})) {
987
-            $this->{$class_name} = null;
988
-            return true;
989
-        }
990
-        if ($addon && $this->addons->has($class_name)) {
991
-            $this->addons->remove($class_name);
992
-            return true;
993
-        }
994
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
995
-        if ($this->LIB->has($class_name)) {
996
-            $this->LIB->remove($class_name);
997
-            return true;
998
-        }
999
-        return false;
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     * _set_cached_class
1005
-     * attempts to cache the instantiated class locally
1006
-     * in one of the following places, in the following order:
1007
-     *        $this->{class_abbreviation}   ie:    $this->CART
1008
-     *        $this->{$class_name}          ie:    $this->Some_Class
1009
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1010
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1011
-     *
1012
-     * @param object $class_obj
1013
-     * @param string $class_name
1014
-     * @param string $class_prefix
1015
-     * @param bool   $from_db
1016
-     * @param array  $arguments
1017
-     * @return void
1018
-     */
1019
-    protected function _set_cached_class(
1020
-        $class_obj,
1021
-        string $class_name,
1022
-        string $class_prefix = '',
1023
-        bool $from_db = false,
1024
-        array $arguments = []
1025
-    ) {
1026
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1027
-            return;
1028
-        }
1029
-        // return newly instantiated class
1030
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1031
-        if ($class_abbreviation) {
1032
-            $this->{$class_abbreviation} = $class_obj;
1033
-            return;
1034
-        }
1035
-        $class_name = str_replace('\\', '_', $class_name);
1036
-        if (property_exists($this, $class_name)) {
1037
-            $this->{$class_name} = $class_obj;
1038
-            return;
1039
-        }
1040
-        if ($class_prefix === 'addon') {
1041
-            $this->addons->add($class_name, $class_obj);
1042
-            return;
1043
-        }
1044
-        if (! $from_db) {
1045
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1046
-            $this->LIB->add($class_name, $class_obj);
1047
-        }
1048
-    }
1049
-
1050
-
1051
-    /**
1052
-     * attempts to find a full valid filepath for the requested class.
1053
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1054
-     * then returns that path if the target file has been found and is readable
1055
-     *
1056
-     * @param string $class_name
1057
-     * @param string $type
1058
-     * @param array  $file_paths
1059
-     * @return string | bool
1060
-     */
1061
-    protected function _resolve_path(string $class_name, string $type = '', array $file_paths = [])
1062
-    {
1063
-        // make sure $file_paths is an array
1064
-        $file_paths = is_array($file_paths)
1065
-            ? $file_paths
1066
-            : [$file_paths];
1067
-        // cycle thru paths
1068
-        foreach ($file_paths as $key => $file_path) {
1069
-            // convert all separators to proper /, if no filepath, then use EE_CLASSES
1070
-            $file_path = $file_path
1071
-                ? str_replace(['/', '\\'], '/', $file_path)
1072
-                : EE_CLASSES;
1073
-            // prep file type
1074
-            $type = ! empty($type)
1075
-                ? trim($type, '.') . '.'
1076
-                : '';
1077
-            // build full file path
1078
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1079
-            // does the file exist and can be read ?
1080
-            if (is_readable($file_paths[ $key ])) {
1081
-                return $file_paths[ $key ];
1082
-            }
1083
-        }
1084
-        return false;
1085
-    }
1086
-
1087
-
1088
-    /**
1089
-     * basically just performs a require_once()
1090
-     * but with some error handling
1091
-     *
1092
-     * @param string $path
1093
-     * @param string $class_name
1094
-     * @param string $type
1095
-     * @param array  $file_paths
1096
-     * @return bool
1097
-     * @throws EE_Error
1098
-     * @throws ReflectionException
1099
-     */
1100
-    protected function _require_file(string $path, string $class_name, string $type = '', array $file_paths = []): bool
1101
-    {
1102
-        $this->resolve_legacy_class_parent($class_name);
1103
-        // don't give up! you gotta...
1104
-        try {
1105
-            // does the file exist and can it be read ?
1106
-            if (! $path) {
1107
-                // just in case the file has already been autoloaded,
1108
-                // but discrepancies in the naming schema are preventing it from
1109
-                // being loaded via one of the EE_Registry::load_*() methods,
1110
-                // then let's try one last hail mary before throwing an exception
1111
-                // and call class_exists() again, but with autoloading turned ON
1112
-                if (class_exists($class_name)) {
1113
-                    return true;
1114
-                }
1115
-                // so sorry, can't find the file
1116
-                throw new EE_Error(
1117
-                    sprintf(
1118
-                        esc_html__(
1119
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1120
-                            'event_espresso'
1121
-                        ),
1122
-                        trim($type, '.'),
1123
-                        $class_name,
1124
-                        '<br />' . implode(',<br />', $file_paths)
1125
-                    )
1126
-                );
1127
-            }
1128
-            // get the file
1129
-            require_once($path);
1130
-            // if the class isn't already declared somewhere
1131
-            if (class_exists($class_name, false) === false) {
1132
-                // so sorry, not a class
1133
-                throw new EE_Error(
1134
-                    sprintf(
1135
-                        esc_html__(
1136
-                            'The %s file %s does not appear to contain the %s Class.',
1137
-                            'event_espresso'
1138
-                        ),
1139
-                        $type,
1140
-                        $path,
1141
-                        $class_name
1142
-                    )
1143
-                );
1144
-            }
1145
-        } catch (EE_Error $e) {
1146
-            $e->get_error();
1147
-            return false;
1148
-        }
1149
-        return true;
1150
-    }
1151
-
1152
-
1153
-    /**
1154
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1155
-     * before their class declaration in order to ensure that the parent class was loaded.
1156
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1157
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1158
-     *
1159
-     * @param string $class_name
1160
-     */
1161
-    protected function resolve_legacy_class_parent(string $class_name = '')
1162
-    {
1163
-        try {
1164
-            $legacy_parent_class_map = [
1165
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1166
-            ];
1167
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1168
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1169
-            }
1170
-        } catch (Exception $exception) {
1171
-        }
1172
-    }
1173
-
1174
-
1175
-    /**
1176
-     * _create_object
1177
-     * Attempts to instantiate the requested class via any of the
1178
-     * commonly used instantiation methods employed throughout EE.
1179
-     * The priority for instantiation is as follows:
1180
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1181
-     *        - model objects via their 'new_instance_from_db' method
1182
-     *        - model objects via their 'new_instance' method
1183
-     *        - "singleton" classes" via their 'instance' method
1184
-     *    - standard instantiable classes via their __constructor
1185
-     * Prior to instantiation, if the classname exists in the dependency_map,
1186
-     * then the constructor for the requested class will be examined to determine
1187
-     * if any dependencies exist, and if they can be injected.
1188
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1189
-     *
1190
-     * @param string $class_name
1191
-     * @param array  $arguments
1192
-     * @param string $type
1193
-     * @param bool   $from_db
1194
-     * @return null|object|bool
1195
-     * @throws InvalidArgumentException
1196
-     * @throws InvalidInterfaceException
1197
-     * @throws EE_Error
1198
-     * @throws ReflectionException
1199
-     * @throws InvalidDataTypeException
1200
-     */
1201
-    protected function _create_object(
1202
-        string $class_name,
1203
-        array $arguments = [],
1204
-        string $type = '',
1205
-        bool $from_db = false
1206
-    ) {
1207
-        // create reflection
1208
-        $reflector = $this->mirror->getReflectionClass($class_name);
1209
-        // make sure arguments are an array
1210
-        $arguments = is_array($arguments)
1211
-            ? $arguments
1212
-            : [$arguments];
1213
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1214
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1215
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1216
-            ? $arguments
1217
-            : [$arguments];
1218
-        // attempt to inject dependencies ?
1219
-        if ($this->_dependency_map->has($class_name)) {
1220
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1221
-        }
1222
-        // instantiate the class if possible
1223
-        if ($reflector->isAbstract()) {
1224
-            // nothing to instantiate, loading file was enough
1225
-            // does not throw an exception so $instantiation_mode is unused
1226
-            // $instantiation_mode = "1) no constructor abstract class";
1227
-            return true;
1228
-        }
1229
-        if (
1230
-            empty($arguments)
1231
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1232
-            && $reflector->isInstantiable()
1233
-        ) {
1234
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1235
-            // $instantiation_mode = "2) no constructor but instantiable";
1236
-            return $reflector->newInstance();
1237
-        }
1238
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1239
-            // $instantiation_mode = "3) new_instance_from_db()";
1240
-            return call_user_func_array([$class_name, 'new_instance_from_db'], $arguments);
1241
-        }
1242
-        if (method_exists($class_name, 'new_instance')) {
1243
-            // $instantiation_mode = "4) new_instance()";
1244
-            return call_user_func_array([$class_name, 'new_instance'], $arguments);
1245
-        }
1246
-        if (method_exists($class_name, 'instance')) {
1247
-            // $instantiation_mode = "5) instance()";
1248
-            return call_user_func_array([$class_name, 'instance'], $arguments);
1249
-        }
1250
-        if ($reflector->isInstantiable()) {
1251
-            $args_passed_count = count($arguments);
1252
-            $args_required_count = count($this->mirror->getRequiredParameters($class_name));
1253
-            if ($args_passed_count < $args_required_count) {
1254
-                throw new RuntimeException(
1255
-                    sprintf(
1256
-                        __(
1257
-                            'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1258
-                            'event_espresso'
1259
-                        ),
1260
-                        $class_name,
1261
-                        $args_required_count,
1262
-                        $args_passed_count
1263
-                    )
1264
-                );
1265
-            }
1266
-            // $instantiation_mode = "6) constructor";
1267
-            return $reflector->newInstanceArgs($arguments);
1268
-        }
1269
-        // heh ? something's not right !
1270
-        throw new EE_Error(
1271
-            sprintf(
1272
-                esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1273
-                $type,
1274
-                $class_name
1275
-            )
1276
-        );
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1282
-     * @param array $array
1283
-     * @return bool
1284
-     */
1285
-    protected function _array_is_numerically_and_sequentially_indexed(array $array): bool
1286
-    {
1287
-        return empty($array) || array_keys($array) === range(0, count($array) - 1);
1288
-    }
1289
-
1290
-
1291
-    /**
1292
-     * _resolve_dependencies
1293
-     * examines the constructor for the requested class to determine
1294
-     * if any dependencies exist, and if they can be injected.
1295
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1296
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1297
-     * For example:
1298
-     *        if attempting to load a class "Foo" with the following constructor:
1299
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1300
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1301
-     *        but only IF they are NOT already present in the incoming arguments array,
1302
-     *        and the correct classes can be loaded
1303
-     *
1304
-     * @param ReflectionClass $reflector
1305
-     * @param string          $class_name
1306
-     * @param array           $arguments
1307
-     * @return array
1308
-     * @throws InvalidArgumentException
1309
-     * @throws InvalidDataTypeException
1310
-     * @throws InvalidInterfaceException
1311
-     * @throws ReflectionException
1312
-     */
1313
-    protected function _resolve_dependencies(
1314
-        ReflectionClass $reflector,
1315
-        string $class_name,
1316
-        array $arguments = []
1317
-    ): array {
1318
-        // let's examine the constructor
1319
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1320
-        // whu? huh? nothing?
1321
-        if (! $constructor) {
1322
-            return $arguments;
1323
-        }
1324
-        // get constructor parameters
1325
-        $params = $this->mirror->getParametersFromReflection($reflector);
1326
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1327
-        $argument_keys = array_keys($arguments);
1328
-        // now loop thru all the constructors' expected parameters
1329
-        foreach ($params as $index => $param) {
1330
-            try {
1331
-                // is this a dependency for a specific class ?
1332
-                $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1333
-            } catch (ReflectionException $exception) {
1334
-                // uh-oh... most likely a legacy class that has not been autoloaded
1335
-                // let's try to derive the classname from what we have now
1336
-                // and hope that the property var name is close to the class name
1337
-                $param_class = $param->getName();
1338
-                $param_class = str_replace('_', ' ', $param_class);
1339
-                $param_class = ucwords($param_class);
1340
-                $param_class = str_replace(' ', '_', $param_class);
1341
-            }
1342
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1343
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1344
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1345
-                : $param_class;
1346
-            if (
1347
-                // param is not even a class
1348
-                ($param_class === null || $this->parameterIsPrimitive($param_class))
1349
-                // and something already exists in the incoming arguments for this param
1350
-                && array_key_exists($index, $argument_keys)
1351
-                && isset($arguments[ $argument_keys[ $index ] ])
1352
-            ) {
1353
-                // so let's skip this argument and move on to the next
1354
-                continue;
1355
-            }
1356
-            // parameter is type hinted as a class
1357
-            if ($param_class !== null) {
1358
-                // parameter exists as an incoming argument, AND it's the correct class
1359
-                if (
1360
-                    array_key_exists($index, $argument_keys)
1361
-                    && isset($arguments[ $argument_keys[ $index ] ])
1362
-                    && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1363
-                ) {
1364
-                    // skip this argument and move on to the next
1365
-                    continue;
1366
-                }
1367
-                // parameter should be injected
1368
-                if ($this->_dependency_map->has_dependency_for_class($class_name, $param_class)) {
1369
-                    $arguments = $this->_resolve_dependency(
1370
-                        $class_name,
1371
-                        $param_class,
1372
-                        $arguments,
1373
-                        $index
1374
-                    );
1375
-                }
1376
-            }
1377
-            if (empty($arguments[ $index ])) {
1378
-                $default_value = $this->mirror->getParameterDefaultValue(
1379
-                    $param,
1380
-                    $class_name,
1381
-                    $index
1382
-                );
1383
-                // if there's no default value, and the incoming argument is an array (albeit empty), then use that
1384
-                $arguments[ $index ] = $default_value === null
1385
-                                       && isset($arguments[ $index ])
1386
-                                       && is_array($arguments[ $index ])
1387
-                    ? $arguments[ $index ]
1388
-                    : $default_value;
1389
-            }
1390
-        }
1391
-        return $arguments;
1392
-    }
1393
-
1394
-
1395
-    /**
1396
-     * @param string $class_name
1397
-     * @param string $param_class
1398
-     * @param array  $arguments
1399
-     * @param mixed  $index
1400
-     * @return array
1401
-     * @throws InvalidArgumentException
1402
-     * @throws InvalidInterfaceException
1403
-     * @throws InvalidDataTypeException
1404
-     */
1405
-    protected function _resolve_dependency(string $class_name, string $param_class, array $arguments, $index): array
1406
-    {
1407
-        $dependency = null;
1408
-        // should dependency be loaded from cache ?
1409
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1410
-            $class_name,
1411
-            $param_class
1412
-        );
1413
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1414
-        // we might have a dependency...
1415
-        // let's MAYBE try and find it in our cache if that's what's been requested
1416
-        $cached_class = $cache_on
1417
-            ? $this->_get_cached_class($param_class)
1418
-            : null;
1419
-        // and grab it if it exists
1420
-        if ($cached_class instanceof $param_class) {
1421
-            $dependency = $cached_class;
1422
-        } elseif ($param_class !== $class_name) {
1423
-            // obtain the loader method from the dependency map
1424
-            $loader = $this->_dependency_map->class_loader($param_class);
1425
-            // is loader a custom closure ?
1426
-            if ($loader instanceof Closure) {
1427
-                $dependency = $loader($arguments);
1428
-            } else {
1429
-                // set the cache on property for the recursive loading call
1430
-                $this->_cache_on = $cache_on;
1431
-                // if not, then let's try and load it via the registry
1432
-                if ($loader && method_exists($this, $loader)) {
1433
-                    $dependency = $this->{$loader}($param_class);
1434
-                } else {
1435
-                    $dependency = LoaderFactory::getLoader()->load(
1436
-                        $param_class,
1437
-                        [],
1438
-                        $cache_on
1439
-                    );
1440
-                }
1441
-            }
1442
-        }
1443
-        // did we successfully find the correct dependency ?
1444
-        if ($dependency instanceof $param_class) {
1445
-            // then let's inject it into the incoming array of arguments at the correct location
1446
-            $arguments[ $index ] = $dependency;
1447
-        }
1448
-        return $arguments;
1449
-    }
1450
-
1451
-
1452
-    /**
1453
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1454
-     *
1455
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1456
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1457
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1458
-     * @param array  $arguments
1459
-     * @return object
1460
-     */
1461
-    public static function factory(string $classname, array $arguments = [])
1462
-    {
1463
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1464
-        if ($loader instanceof Closure) {
1465
-            return $loader($arguments);
1466
-        }
1467
-        if (method_exists(self::instance(), $loader)) {
1468
-            return self::instance()->{$loader}($classname, $arguments);
1469
-        }
1470
-        return null;
1471
-    }
1472
-
1473
-
1474
-    /**
1475
-     * Gets the addon by its class name
1476
-     *
1477
-     * @param string $class_name
1478
-     * @return EE_Addon
1479
-     */
1480
-    public function getAddon(string $class_name): ?EE_Addon
1481
-    {
1482
-        $class_name = str_replace('\\', '_', $class_name);
1483
-        return $this->addons->{$class_name} ?? null;
1484
-    }
1485
-
1486
-
1487
-    /**
1488
-     * removes the addon from the internal cache
1489
-     *
1490
-     * @param string $class_name
1491
-     * @return void
1492
-     */
1493
-    public function removeAddon(string $class_name)
1494
-    {
1495
-        $class_name = str_replace('\\', '_', $class_name);
1496
-        $this->addons->remove($class_name);
1497
-    }
1498
-
1499
-
1500
-    /**
1501
-     * Gets the addon by its name/slug (not classname. For that, just
1502
-     * use the get_addon() method above
1503
-     *
1504
-     * @param string $name
1505
-     * @return EE_Addon
1506
-     */
1507
-    public function get_addon_by_name(string $name): ?EE_Addon
1508
-    {
1509
-        foreach ($this->addons as $addon) {
1510
-            if ($addon->name() === $name) {
1511
-                return $addon;
1512
-            }
1513
-        }
1514
-        return null;
1515
-    }
1516
-
1517
-
1518
-    /**
1519
-     * Gets an array of all the registered addons, where the keys are their names.
1520
-     * (ie, what each returns for their name() function)
1521
-     * They're already available on EE_Registry::instance()->addons as properties,
1522
-     * where each property's name is the addon's classname,
1523
-     * So if you just want to get the addon by classname,
1524
-     * OR use the get_addon() method above.
1525
-     * PLEASE  NOTE:
1526
-     * addons with Fully Qualified Class Names
1527
-     * have had the namespace separators converted to underscores,
1528
-     * so a classname like Fully\Qualified\ClassName
1529
-     * would have been converted to Fully_Qualified_ClassName
1530
-     *
1531
-     * @return EE_Addon[] where the KEYS are the addon's name()
1532
-     */
1533
-    public function get_addons_by_name(): array
1534
-    {
1535
-        $addons = [];
1536
-        foreach ($this->addons as $addon) {
1537
-            $addons[ $addon->name() ] = $addon;
1538
-        }
1539
-        return $addons;
1540
-    }
1541
-
1542
-
1543
-    /**
1544
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1545
-     * a stale copy of it around
1546
-     *
1547
-     * @param string $model_name
1548
-     * @return EEM_Base
1549
-     * @throws EE_Error
1550
-     * @throws ReflectionException
1551
-     */
1552
-    public function reset_model(string $model_name): ?EEM_Base
1553
-    {
1554
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1555
-            ? "EEM_$model_name"
1556
-            : $model_name;
1557
-        if (! $this->LIB->has($model_class_name)) {
1558
-            return null;
1559
-        }
1560
-        $model = $this->LIB->get($model_class_name);
1561
-        if (! $model instanceof EEM_Base) {
1562
-            return null;
1563
-        }
1564
-        // get that model reset it and make sure we nuke the old reference to it
1565
-        if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1566
-            $this->LIB->remove($model_class_name);
1567
-            $this->LIB->add($model_class_name, $model->reset());
1568
-        } else {
1569
-            throw new EE_Error(
1570
-                sprintf(
1571
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1572
-                    $model_name
1573
-                )
1574
-            );
1575
-        }
1576
-        return $model;
1577
-    }
1578
-
1579
-
1580
-    /**
1581
-     * Resets the registry.
1582
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1583
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1584
-     * - $_dependency_map
1585
-     * - $_class_abbreviations
1586
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1587
-     * - $REQ:  Still on the same request so no need to change.
1588
-     * - $CAP: There is no site specific state in the EE_Capability class.
1589
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1590
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1591
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1592
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1593
-     *             switch or on the restore.
1594
-     * - $modules
1595
-     * - $shortcodes
1596
-     * - $widgets
1597
-     *
1598
-     * @param boolean $hard             [deprecated]
1599
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1600
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1601
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1602
-     * @param bool    $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1603
-     *                                  client
1604
-     *                                  code instead can just change the model context to a different blog id if
1605
-     *                                  necessary
1606
-     * @return EE_Registry
1607
-     * @throws EE_Error
1608
-     * @throws ReflectionException
1609
-     */
1610
-    public static function reset(bool $hard = false, bool $reinstantiate = true, bool $reset_models = true): EE_Registry
1611
-    {
1612
-        $instance            = self::instance();
1613
-        $instance->_cache_on = true;
1614
-        // reset some "special" classes
1615
-        EEH_Activation::reset();
1616
-        $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1617
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1618
-        $instance->CART = null;
1619
-        $instance->MRM = null;
1620
-        // messages reset
1621
-        EED_Messages::reset();
1622
-        // handle of objects cached on LIB
1623
-        foreach (['LIB', 'modules'] as $cache) {
1624
-            foreach ($instance->{$cache} as $class_name => $class) {
1625
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1626
-                    unset($instance->{$cache}->{$class_name});
1627
-                }
1628
-            }
1629
-        }
1630
-        return $instance;
1631
-    }
1632
-
1633
-
1634
-    /**
1635
-     * if passed object implements ResettableInterface, then call it's reset() method
1636
-     * if passed object implements InterminableInterface, then return false,
1637
-     * to indicate that it should NOT be cleared from the Registry cache
1638
-     *
1639
-     * @param      $object
1640
-     * @param bool $reset_models
1641
-     * @return bool returns true if cached object should be unset
1642
-     * @throws EE_Error
1643
-     * @throws ReflectionException
1644
-     */
1645
-    private static function _reset_and_unset_object($object, bool $reset_models): bool
1646
-    {
1647
-        if (! is_object($object)) {
1648
-            // don't unset anything that's not an object
1649
-            return false;
1650
-        }
1651
-        if ($object instanceof EED_Module) {
1652
-            $object::reset();
1653
-            // don't unset modules
1654
-            return false;
1655
-        }
1656
-        if ($object instanceof ResettableInterface) {
1657
-            if ($object instanceof EEM_Base) {
1658
-                if ($reset_models) {
1659
-                    $object->reset();
1660
-                    return true;
1661
-                }
1662
-                return false;
1663
-            }
1664
-            $object->reset();
1665
-            return true;
1666
-        }
1667
-        if (! $object instanceof InterminableInterface) {
1668
-            return true;
1669
-        }
1670
-        return false;
1671
-    }
1672
-
1673
-
1674
-    /**
1675
-     * Gets all the custom post type models defined
1676
-     *
1677
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1678
-     */
1679
-    public function cpt_models(): array
1680
-    {
1681
-        $cpt_models = [];
1682
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1683
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1684
-                $cpt_models[ $short_name ] = $classname;
1685
-            }
1686
-        }
1687
-        return $cpt_models;
1688
-    }
1689
-
1690
-
1691
-    /**
1692
-     * @return EE_Config
1693
-     */
1694
-    public static function CFG(): EE_Config
1695
-    {
1696
-        return self::instance()->CFG;
1697
-    }
1698
-
1699
-
1700
-    /**
1701
-     * @param string $class_name
1702
-     * @return ReflectionClass
1703
-     * @throws ReflectionException
1704
-     * @throws InvalidDataTypeException
1705
-     * @deprecated 4.9.62.p
1706
-     */
1707
-    public function get_ReflectionClass(string $class_name): ReflectionClass
1708
-    {
1709
-        return $this->mirror->getReflectionClass($class_name);
1710
-    }
1711
-
1712
-    private function parameterIsPrimitive(?string $param_class): bool
1713
-    {
1714
-        return in_array(
1715
-            $param_class,
1716
-            [
1717
-                'array',
1718
-                'bool',
1719
-                'float',
1720
-                'int',
1721
-                'string',
1722
-            ]
1723
-        );
1724
-    }
25
+	private static ?EE_Registry $_instance = null;
26
+
27
+	protected EE_Dependency_Map $_dependency_map;
28
+
29
+	private Mirror $mirror;
30
+
31
+	private ClassInterfaceCache $class_cache;
32
+
33
+	private ObjectIdentifier $object_identifier;
34
+
35
+	protected array $_class_abbreviations = [];
36
+
37
+	public ?CommandBusInterface $BUS = null;
38
+
39
+	public ?EE_Cart $CART = null;
40
+
41
+	public ?EE_Config $CFG = null;
42
+
43
+	public ?EE_Network_Config $NET_CFG = null;
44
+
45
+	/**
46
+	 * RegistryContainer for storing library classes in
47
+	 *
48
+	 * @var RegistryContainer|null $LIB
49
+	 */
50
+	public ?RegistryContainer $LIB = null;
51
+
52
+	/**
53
+	 * @var EE_Request_Handler|null $REQ
54
+	 * @deprecated 4.10.14.p
55
+	 */
56
+	public ?EE_Request_Handler $REQ = null;
57
+
58
+	public ?EE_Session $SSN = null;
59
+
60
+	/**
61
+	 * @since 4.5.0
62
+	 * @var EE_Capabilities|null $CAP
63
+	 */
64
+	public ?EE_Capabilities$CAP = null;
65
+
66
+	/**
67
+	 * @since 4.9.0
68
+	 * @var EE_Message_Resource_Manager|null $MRM
69
+	 */
70
+	public ?EE_Message_Resource_Manager $MRM = null;
71
+
72
+	public ?Registry $AssetsRegistry = null;
73
+
74
+	/**
75
+	 * RegistryContainer for holding addons which have registered themselves to work with EE core
76
+	 *
77
+	 * @var RegistryContainer|EE_Addon[] $addons
78
+	 */
79
+	public $addons = [];
80
+
81
+	/**
82
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
83
+	 *
84
+	 * @var EEM_Base[] $models
85
+	 */
86
+	public array $models = [];
87
+
88
+	/**
89
+	 * @var RegistryContainer|EED_Module[] $modules
90
+	 */
91
+	public $modules = [];
92
+
93
+	/**
94
+	 * @var RegistryContainer|EES_Shortcode[] $shortcodes
95
+	 */
96
+	public $shortcodes = [];
97
+
98
+	/**
99
+	 * @var RegistryContainer|WP_Widget[] $widgets
100
+	 */
101
+	public $widgets = [];
102
+
103
+	/**
104
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
105
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
106
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
107
+	 * classnames (eg "EEM_Event")
108
+	 *
109
+	 * @var array $non_abstract_db_models
110
+	 */
111
+	public array $non_abstract_db_models = [];
112
+
113
+	/**
114
+	 * internationalization for JS strings
115
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
116
+	 *    in js file:  var translatedString = eei18n.string_key;
117
+	 *
118
+	 * @var array $i18n_js_strings
119
+	 */
120
+	public static array $i18n_js_strings = [];
121
+
122
+	/**
123
+	 * $main_file - path to espresso.php
124
+	 *
125
+	 * @var string $main_file
126
+	 */
127
+	public string $main_file = '';
128
+
129
+	/**
130
+	 * boolean flag to indicate whether to load/save dependencies from/to the cache
131
+	 *
132
+	 * @var bool $_cache_on
133
+	 */
134
+	protected bool $_cache_on = true;
135
+
136
+
137
+	/**
138
+	 * @singleton method used to instantiate class object
139
+	 * @param EE_Dependency_Map|null   $dependency_map
140
+	 * @param Mirror|null              $mirror
141
+	 * @param ClassInterfaceCache|null $class_cache
142
+	 * @param ObjectIdentifier|null    $object_identifier
143
+	 * @return EE_Registry instance
144
+	 */
145
+	public static function instance(
146
+		EE_Dependency_Map $dependency_map = null,
147
+		Mirror $mirror = null,
148
+		ClassInterfaceCache $class_cache = null,
149
+		ObjectIdentifier $object_identifier = null
150
+	): EE_Registry {
151
+		// check if class object is instantiated
152
+		if (
153
+			! self::$_instance instanceof EE_Registry
154
+			&& $dependency_map instanceof EE_Dependency_Map
155
+			&& $mirror instanceof Mirror
156
+			&& $class_cache instanceof ClassInterfaceCache
157
+			&& $object_identifier instanceof ObjectIdentifier
158
+		) {
159
+			self::$_instance = new self(
160
+				$dependency_map,
161
+				$mirror,
162
+				$class_cache,
163
+				$object_identifier
164
+			);
165
+		}
166
+		return self::$_instance;
167
+	}
168
+
169
+
170
+	/**
171
+	 * protected constructor to prevent direct creation
172
+	 *
173
+	 * @Constructor
174
+	 * @param EE_Dependency_Map   $dependency_map
175
+	 * @param Mirror              $mirror
176
+	 * @param ClassInterfaceCache $class_cache
177
+	 * @param ObjectIdentifier    $object_identifier
178
+	 */
179
+	protected function __construct(
180
+		EE_Dependency_Map $dependency_map,
181
+		Mirror $mirror,
182
+		ClassInterfaceCache $class_cache,
183
+		ObjectIdentifier $object_identifier
184
+	) {
185
+		$this->_dependency_map   = $dependency_map;
186
+		$this->mirror            = $mirror;
187
+		$this->class_cache       = $class_cache;
188
+		$this->object_identifier = $object_identifier;
189
+
190
+		$this->LIB        = new RegistryContainer();
191
+		$this->addons     = new RegistryContainer();
192
+		$this->modules    = new RegistryContainer();
193
+		$this->shortcodes = new RegistryContainer();
194
+		$this->widgets    = new RegistryContainer();
195
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', [$this, 'initialize']);
196
+	}
197
+
198
+
199
+	/**
200
+	 * initialize
201
+	 *
202
+	 * @throws OutOfBoundsException
203
+	 * @throws InvalidArgumentException
204
+	 * @throws InvalidInterfaceException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws EE_Error
207
+	 * @throws ReflectionException
208
+	 */
209
+	public function initialize()
210
+	{
211
+		$this->_class_abbreviations = apply_filters(
212
+			'FHEE__EE_Registry____construct___class_abbreviations',
213
+			[
214
+				'EE_Config'                                       => 'CFG',
215
+				'EE_Session'                                      => 'SSN',
216
+				'EE_Capabilities'                                 => 'CAP',
217
+				'EE_Cart'                                         => 'CART',
218
+				'EE_Network_Config'                               => 'NET_CFG',
219
+				'EE_Request_Handler'                              => 'REQ',
220
+				'EE_Message_Resource_Manager'                     => 'MRM',
221
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
222
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
223
+			]
224
+		);
225
+		$this->load_core('Base', [], true);
226
+		// add our request and response objects to the cache
227
+		$request_loader = $this->_dependency_map->class_loader(
228
+			'EventEspresso\core\services\request\Request'
229
+		);
230
+		$this->_set_cached_class(
231
+			$request_loader(),
232
+			'EventEspresso\core\services\request\Request'
233
+		);
234
+		$response_loader = $this->_dependency_map->class_loader(
235
+			'EventEspresso\core\services\request\Response'
236
+		);
237
+		$this->_set_cached_class(
238
+			$response_loader(),
239
+			'EventEspresso\core\services\request\Response'
240
+		);
241
+		add_action('AHEE__EE_System__set_hooks_for_core', [$this, 'init']);
242
+	}
243
+
244
+
245
+	/**
246
+	 * @return void
247
+	 */
248
+	public function init()
249
+	{
250
+		// Get current page protocol
251
+		$protocol = is_ssl() ? 'https://' : 'http://';
252
+		// Output admin-ajax.php URL with same protocol as current page
253
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
254
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
255
+	}
256
+
257
+
258
+	/**
259
+	 * @return array
260
+	 */
261
+	public static function sanitize_i18n_js_strings(): array
262
+	{
263
+		array_walk(EE_Registry::$i18n_js_strings, function (&$value) {
264
+			if (is_scalar($value)) {
265
+				$value = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
266
+				// replace all escaped instances of \n with actual new lines
267
+				$value = str_replace("\\n", "\n", $value);
268
+			}
269
+		});
270
+		// sort the array by key in a case-insensitive manner
271
+		ksort(EE_Registry::$i18n_js_strings, SORT_NATURAL | SORT_FLAG_CASE);
272
+		return EE_Registry::$i18n_js_strings;
273
+	}
274
+
275
+
276
+	/**
277
+	 * localize_i18n_js_strings
278
+	 *
279
+	 * @return string
280
+	 */
281
+	public static function localize_i18n_js_strings(): string
282
+	{
283
+		$i18n_js_strings = wp_json_encode(EE_Registry::sanitize_i18n_js_strings());
284
+		return "/* <![CDATA[ */ var eei18n = $i18n_js_strings; /* ]]> */";
285
+	}
286
+
287
+
288
+	/**
289
+	 * @param mixed string | EED_Module $module
290
+	 * @throws OutOfBoundsException
291
+	 * @throws InvalidArgumentException
292
+	 * @throws InvalidInterfaceException
293
+	 * @throws InvalidDataTypeException
294
+	 * @throws EE_Error
295
+	 * @throws ReflectionException
296
+	 */
297
+	public function add_module($module)
298
+	{
299
+		if ($module instanceof EED_Module) {
300
+			$module_class = get_class($module);
301
+			$this->modules->add($module_class, $module);
302
+		} else {
303
+			if (! class_exists('EE_Module_Request_Router', false)) {
304
+				$this->load_core('Module_Request_Router');
305
+			}
306
+			EE_Module_Request_Router::module_factory($module);
307
+		}
308
+	}
309
+
310
+
311
+	/**
312
+	 * @param string $module_name
313
+	 * @return mixed EED_Module | NULL
314
+	 */
315
+	public function get_module(string $module_name = '')
316
+	{
317
+		return $this->modules->get($module_name);
318
+	}
319
+
320
+
321
+	/**
322
+	 * loads core classes - must be singletons
323
+	 *
324
+	 * @param string $class_name - simple class name ie: session
325
+	 * @param mixed  $arguments
326
+	 * @param bool   $load_only
327
+	 * @return bool|null|object
328
+	 * @throws InvalidInterfaceException
329
+	 * @throws InvalidDataTypeException
330
+	 * @throws EE_Error
331
+	 * @throws ReflectionException
332
+	 * @throws InvalidArgumentException
333
+	 */
334
+	public function load_core(string $class_name, $arguments = [], bool $load_only = false)
335
+	{
336
+		$core_paths = (array) apply_filters(
337
+			'FHEE__EE_Registry__load_core__core_paths',
338
+			[
339
+				EE_CORE,
340
+				EE_ADMIN,
341
+				EE_CPTS,
342
+				EE_CORE . 'CPTs/',
343
+				EE_CORE . 'data_migration_scripts/',
344
+				EE_CORE . 'request_stack/',
345
+				EE_CORE . 'middleware/',
346
+			]
347
+		);
348
+		// retrieve instantiated class
349
+		return $this->_load(
350
+			$core_paths,
351
+			'EE_',
352
+			$class_name,
353
+			'core',
354
+			$arguments,
355
+			false,
356
+			true,
357
+			$load_only
358
+		);
359
+	}
360
+
361
+
362
+	/**
363
+	 * loads service classes
364
+	 *
365
+	 * @param string $class_name - simple class name ie: session
366
+	 * @param mixed  $arguments
367
+	 * @param bool   $load_only
368
+	 * @return bool|null|object
369
+	 * @throws InvalidInterfaceException
370
+	 * @throws InvalidDataTypeException
371
+	 * @throws EE_Error
372
+	 * @throws ReflectionException
373
+	 * @throws InvalidArgumentException
374
+	 * @deprecated  4.10.33.p
375
+	 */
376
+	public function load_service(string $class_name, $arguments = [], bool $load_only = false)
377
+	{
378
+		$service_paths = (array) apply_filters(
379
+			'FHEE__EE_Registry__load_service__service_paths',
380
+			[
381
+				EE_CORE . 'services/',
382
+			]
383
+		);
384
+		// retrieve instantiated class
385
+		return $this->_load(
386
+			$service_paths,
387
+			'EE_',
388
+			$class_name,
389
+			'class',
390
+			$arguments,
391
+			false,
392
+			true,
393
+			$load_only
394
+		);
395
+	}
396
+
397
+
398
+	/**
399
+	 * loads data_migration_scripts
400
+	 *
401
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
402
+	 * @param mixed  $arguments
403
+	 * @return bool|null|object
404
+	 * @throws InvalidInterfaceException
405
+	 * @throws InvalidDataTypeException
406
+	 * @throws EE_Error
407
+	 * @throws ReflectionException
408
+	 * @throws InvalidArgumentException
409
+	 */
410
+	public function load_dms(string $class_name, $arguments = [])
411
+	{
412
+		// retrieve instantiated class
413
+		return $this->_load(
414
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
415
+			'EE_DMS_',
416
+			$class_name,
417
+			'dms',
418
+			$arguments,
419
+			false,
420
+			false
421
+		);
422
+	}
423
+
424
+
425
+	/**
426
+	 * loads object creating classes - must be singletons
427
+	 *
428
+	 * @param string $class_name - simple class name ie: attendee
429
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
430
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
431
+	 *                           instantiate
432
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
433
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
434
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
435
+	 *                           (default)
436
+	 * @return EE_Base_Class|object|bool|null
437
+	 * @throws InvalidInterfaceException
438
+	 * @throws InvalidDataTypeException
439
+	 * @throws EE_Error
440
+	 * @throws ReflectionException
441
+	 * @throws InvalidArgumentException
442
+	 */
443
+	public function load_class(
444
+		string $class_name,
445
+		$arguments = [],
446
+		bool $from_db = false,
447
+		bool $cache = true,
448
+		bool $load_only = false
449
+	) {
450
+		$paths = (array) apply_filters(
451
+			'FHEE__EE_Registry__load_class__paths',
452
+			[
453
+				EE_CORE,
454
+				EE_CLASSES,
455
+				EE_BUSINESS,
456
+			]
457
+		);
458
+		// retrieve instantiated class
459
+		return $this->_load(
460
+			$paths,
461
+			'EE_',
462
+			$class_name,
463
+			'class',
464
+			$arguments,
465
+			$from_db,
466
+			$cache,
467
+			$load_only
468
+		);
469
+	}
470
+
471
+
472
+	/**
473
+	 * loads helper classes - must be singletons
474
+	 *
475
+	 * @param string $class_name - simple class name ie: price
476
+	 * @param mixed  $arguments
477
+	 * @param bool   $load_only
478
+	 * @return bool|null|object
479
+	 * @throws InvalidInterfaceException
480
+	 * @throws InvalidDataTypeException
481
+	 * @throws EE_Error
482
+	 * @throws ReflectionException
483
+	 * @throws InvalidArgumentException
484
+	 */
485
+	public function load_helper(string $class_name, $arguments = [], bool $load_only = true)
486
+	{
487
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
488
+		$helper_paths = (array) apply_filters('FHEE__EE_Registry__load_helper__helper_paths', [EE_HELPERS]);
489
+		// retrieve instantiated class
490
+		return $this->_load(
491
+			$helper_paths,
492
+			'EEH_',
493
+			$class_name,
494
+			'helper',
495
+			$arguments,
496
+			false,
497
+			true,
498
+			$load_only
499
+		);
500
+	}
501
+
502
+
503
+	/**
504
+	 * loads core classes - must be singletons
505
+	 *
506
+	 * @param string $class_name - simple class name ie: session
507
+	 * @param mixed  $arguments
508
+	 * @param bool   $load_only
509
+	 * @param bool   $cache      whether to cache the object or not.
510
+	 * @return bool|null|object
511
+	 * @throws InvalidInterfaceException
512
+	 * @throws InvalidDataTypeException
513
+	 * @throws EE_Error
514
+	 * @throws ReflectionException
515
+	 * @throws InvalidArgumentException
516
+	 */
517
+	public function load_lib(string $class_name, $arguments = [], bool $load_only = false, bool $cache = true)
518
+	{
519
+		$paths = [
520
+			EE_LIBRARIES,
521
+			EE_LIBRARIES . 'messages/',
522
+			EE_LIBRARIES . 'shortcodes/',
523
+			EE_LIBRARIES . 'qtips/',
524
+			EE_LIBRARIES . 'payment_methods/',
525
+		];
526
+		// retrieve instantiated class
527
+		return $this->_load(
528
+			$paths,
529
+			'EE_',
530
+			$class_name,
531
+			'lib',
532
+			$arguments,
533
+			false,
534
+			$cache,
535
+			$load_only
536
+		);
537
+	}
538
+
539
+
540
+	/**
541
+	 * loads model classes - must be singletons
542
+	 *
543
+	 * @param string $class_name - simple class name ie: price
544
+	 * @param mixed  $arguments
545
+	 * @param bool   $load_only
546
+	 * @return bool|null|object
547
+	 * @throws InvalidInterfaceException
548
+	 * @throws InvalidDataTypeException
549
+	 * @throws EE_Error
550
+	 * @throws ReflectionException
551
+	 * @throws InvalidArgumentException
552
+	 */
553
+	public function load_model(string $class_name, $arguments = [], bool $load_only = false)
554
+	{
555
+		$paths = (array) apply_filters(
556
+			'FHEE__EE_Registry__load_model__paths',
557
+			[
558
+				EE_MODELS,
559
+				EE_CORE,
560
+			]
561
+		);
562
+		// retrieve instantiated class
563
+		return $this->_load(
564
+			$paths,
565
+			'EEM_',
566
+			$class_name,
567
+			'model',
568
+			$arguments,
569
+			false,
570
+			true,
571
+			$load_only
572
+		);
573
+	}
574
+
575
+
576
+	/**
577
+	 * loads model classes - must be singletons
578
+	 *
579
+	 * @param string $class_name - simple class name ie: price
580
+	 * @param mixed  $arguments
581
+	 * @param bool   $load_only
582
+	 * @return bool|null|object
583
+	 * @throws InvalidInterfaceException
584
+	 * @throws InvalidDataTypeException
585
+	 * @throws EE_Error
586
+	 * @throws ReflectionException
587
+	 * @throws InvalidArgumentException
588
+	 * @deprecated  4.10.33.p
589
+	 */
590
+	public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
591
+	{
592
+		$paths = [
593
+			EE_MODELS . 'fields/',
594
+			EE_MODELS . 'helpers/',
595
+			EE_MODELS . 'relations/',
596
+			EE_MODELS . 'strategies/',
597
+		];
598
+		// retrieve instantiated class
599
+		return $this->_load(
600
+			$paths,
601
+			'EE_',
602
+			$class_name,
603
+			'',
604
+			$arguments,
605
+			false,
606
+			true,
607
+			$load_only
608
+		);
609
+	}
610
+
611
+
612
+	/**
613
+	 * Determines if $model_name is the name of an actual EE model.
614
+	 *
615
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
616
+	 * @return boolean
617
+	 */
618
+	public function is_model_name(string $model_name): bool
619
+	{
620
+		return isset($this->models[ $model_name ]);
621
+	}
622
+
623
+
624
+	/**
625
+	 * generic class loader
626
+	 *
627
+	 * @param string $path_to_file - directory path to file location, not including filename
628
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
629
+	 * @param string $type         - file type - core? class? helper? model?
630
+	 * @param mixed  $arguments
631
+	 * @param bool   $load_only
632
+	 * @return bool|null|object
633
+	 * @throws InvalidInterfaceException
634
+	 * @throws InvalidDataTypeException
635
+	 * @throws EE_Error
636
+	 * @throws ReflectionException
637
+	 * @throws InvalidArgumentException
638
+	 */
639
+	public function load_file(
640
+		string $path_to_file,
641
+		string $file_name,
642
+		string $type = '',
643
+		$arguments = [],
644
+		bool $load_only = true
645
+	) {
646
+		// retrieve instantiated class
647
+		return $this->_load(
648
+			(array) $path_to_file,
649
+			'',
650
+			$file_name,
651
+			$type,
652
+			$arguments,
653
+			false,
654
+			true,
655
+			$load_only
656
+		);
657
+	}
658
+
659
+
660
+	/**
661
+	 * @param string $path_to_file - directory path to file location, not including filename
662
+	 * @param string $class_name   - full class name  ie:  My_Class
663
+	 * @param string $type         - file type - core? class? helper? model?
664
+	 * @param mixed  $arguments
665
+	 * @param bool   $load_only
666
+	 * @return bool|null|object
667
+	 * @throws InvalidInterfaceException
668
+	 * @throws InvalidDataTypeException
669
+	 * @throws EE_Error
670
+	 * @throws ReflectionException
671
+	 * @throws InvalidArgumentException
672
+	 * @deprecated  4.10.33.p
673
+	 */
674
+	public function load_addon(
675
+		string $path_to_file,
676
+		string $class_name,
677
+		string $type = 'class',
678
+		$arguments = [],
679
+		bool $load_only = false
680
+	) {
681
+		// retrieve instantiated class
682
+		return $this->_load(
683
+			(array) $path_to_file,
684
+			'addon',
685
+			$class_name,
686
+			$type,
687
+			$arguments,
688
+			false,
689
+			true,
690
+			$load_only
691
+		);
692
+	}
693
+
694
+
695
+	/**
696
+	 * instantiates, caches, and automatically resolves dependencies
697
+	 * for classes that use a Fully Qualified Class Name.
698
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
699
+	 * then you need to use one of the existing load_*() methods
700
+	 * which can resolve the classname and filepath from the passed arguments
701
+	 *
702
+	 * @param string      $class_name Fully Qualified Class Name
703
+	 * @param array       $arguments  an argument, or array of arguments to pass to the class upon instantiation
704
+	 * @param bool        $cache      whether to cache the instantiated object for reuse
705
+	 * @param bool        $from_db    some classes are instantiated from the db
706
+	 *                                and thus call a different method to instantiate
707
+	 * @param bool        $load_only  if true, will only load the file, but will NOT instantiate an object
708
+	 * @param bool|string $addon      if true, will cache the object in the EE_Registry->$addons array
709
+	 * @return bool|null|mixed     null = failure to load or instantiate class object.
710
+	 *                                object = class loaded and instantiated successfully.
711
+	 *                                bool = fail or success when $load_only is true
712
+	 * @throws InvalidInterfaceException
713
+	 * @throws InvalidDataTypeException
714
+	 * @throws EE_Error
715
+	 * @throws ReflectionException
716
+	 * @throws InvalidArgumentException
717
+	 */
718
+	public function create(
719
+		string $class_name = '',
720
+		array $arguments = [],
721
+		bool $cache = false,
722
+		bool $from_db = false,
723
+		bool $load_only = false,
724
+		bool $addon = false
725
+	) {
726
+		$class_name   = ltrim($class_name, '\\');
727
+		$class_name   = $this->class_cache->getFqnForAlias($class_name);
728
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
729
+		// if a non-FQCN was passed, then
730
+		// verifyClassExists() might return an object
731
+		// or it could return null if the class just could not be found anywhere
732
+		if ($class_exists instanceof $class_name || $class_exists === null) {
733
+			// either way, return the results
734
+			return $class_exists;
735
+		}
736
+		$class_name = $class_exists;
737
+		// if we're only loading the class and it already exists, then let's just return true immediately
738
+		if ($load_only) {
739
+			return true;
740
+		}
741
+		$addon = $addon ? 'addon' : '';
742
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
743
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
744
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
745
+		if ($this->_cache_on && $cache) {
746
+			// return object if it's already cached
747
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
748
+			if ($cached_class !== null) {
749
+				return $cached_class;
750
+			}
751
+		}                                                           // obtain the loader method from the dependency map
752
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
753
+		if ($loader instanceof Closure) {
754
+			$class_obj = $loader($arguments);
755
+		} else {
756
+			if ($loader && method_exists($this, $loader)) {
757
+				$class_obj = $this->{$loader}($class_name, $arguments);
758
+			} else {
759
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
760
+			}
761
+		}
762
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
763
+			// save it for later... kinda like gum  { : $
764
+			$this->_set_cached_class(
765
+				$class_obj,
766
+				$class_name,
767
+				$addon,
768
+				$from_db,
769
+				$arguments
770
+			);
771
+		}
772
+		$this->_cache_on = true;
773
+		return $class_obj;
774
+	}
775
+
776
+
777
+	/**
778
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
779
+	 *
780
+	 * @param string|mixed $class_name
781
+	 * @param array        $arguments
782
+	 * @param int          $attempt
783
+	 * @return mixed
784
+	 */
785
+	private function loadOrVerifyClassExists($class_name, array $arguments, int $attempt = 1)
786
+	{
787
+		if (is_object($class_name) || class_exists($class_name)) {
788
+			return $class_name;
789
+		}
790
+		switch ($attempt) {
791
+			case 1:
792
+				// if it's a FQCN then maybe the class is registered with a preceding \
793
+				$class_name = strpos($class_name, '\\') !== false
794
+					? '\\' . ltrim($class_name, '\\')
795
+					: $class_name;
796
+				break;
797
+			case 2:
798
+				//
799
+				$loader = $this->_dependency_map->class_loader($class_name);
800
+				if ($loader && method_exists($this, $loader)) {
801
+					return $this->{$loader}($class_name, $arguments);
802
+				}
803
+				break;
804
+			case 3:
805
+			default:
806
+				return null;
807
+		}
808
+		$attempt++;
809
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
810
+	}
811
+
812
+
813
+	/**
814
+	 * instantiates, caches, and injects dependencies for classes
815
+	 *
816
+	 * @param array  $file_paths         an array of paths to folders to look in
817
+	 * @param string $class_prefix       EE  or EEM or... ???
818
+	 * @param string $class_name         $class name
819
+	 * @param string $type               file type - core? class? helper? model?
820
+	 * @param mixed  $arguments          an argument or array of arguments to pass to the class upon instantiation
821
+	 * @param bool   $from_db            some classes are instantiated from the db
822
+	 *                                   and thus call a different method to instantiate
823
+	 * @param bool   $cache              whether to cache the instantiated object for reuse
824
+	 * @param bool   $load_only          if true, will only load the file, but will NOT instantiate an object
825
+	 * @return bool|null|object          null   = failure to load or instantiate class object.
826
+	 *                                   object = class loaded and instantiated successfully.
827
+	 *                                   bool   = fail or success when $load_only is true
828
+	 * @throws EE_Error
829
+	 * @throws ReflectionException
830
+	 * @throws InvalidInterfaceException
831
+	 * @throws InvalidDataTypeException
832
+	 * @throws InvalidArgumentException
833
+	 */
834
+	protected function _load(
835
+		array $file_paths = [],
836
+		string $class_prefix = 'EE_',
837
+		string $class_name = '',
838
+		string $type = 'class',
839
+		array $arguments = [],
840
+		bool $from_db = false,
841
+		bool $cache = true,
842
+		bool $load_only = false
843
+	) {
844
+		$class_name = ltrim($class_name, '\\');
845
+		// strip php file extension
846
+		$class_name = str_replace('.php', '', trim($class_name));
847
+		// does the class have a prefix ?
848
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
849
+			// make sure $class_prefix is uppercase
850
+			$class_prefix = strtoupper(trim($class_prefix));
851
+			// add class prefix ONCE!!!
852
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
853
+		}
854
+		$class_name   = $this->class_cache->getFqnForAlias($class_name);
855
+		$class_exists = class_exists($class_name, false);
856
+		// if we're only loading the class and it already exists, then let's just return true immediately
857
+		if ($load_only && $class_exists) {
858
+			return true;
859
+		}
860
+		$arguments = is_array($arguments) ? $arguments : [$arguments];
861
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
862
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
863
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
864
+		if ($this->_cache_on && $cache && ! $load_only) {
865
+			// return object if it's already cached
866
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
867
+			if ($cached_class !== null) {
868
+				return $cached_class;
869
+			}
870
+		}
871
+		// if the class doesn't already exist.. then we need to try and find the file and load it
872
+		if (! $class_exists) {
873
+			// get full path to file
874
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
875
+			// load the file
876
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
877
+			// if we are only loading a file but NOT instantiating an object
878
+			// then return boolean for whether class was loaded or not
879
+			if ($load_only) {
880
+				return $loaded;
881
+			}
882
+			// if an object was expected but loading failed, then return nothing
883
+			if (! $loaded) {
884
+				return null;
885
+			}
886
+		}
887
+		// instantiate the requested object
888
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
889
+		if ($this->_cache_on && $cache) {
890
+			// save it for later... kinda like gum  { : $
891
+			$this->_set_cached_class(
892
+				$class_obj,
893
+				$class_name,
894
+				$class_prefix,
895
+				$from_db,
896
+				$arguments
897
+			);
898
+		}
899
+		$this->_cache_on = true;
900
+		return $class_obj;
901
+	}
902
+
903
+
904
+	/**
905
+	 * @param string $class_name
906
+	 * @param string $default have to specify something, but not anything that will conflict
907
+	 * @return mixed|string
908
+	 */
909
+	protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
910
+	{
911
+		return $this->_class_abbreviations[ $class_name ] ?? $default;
912
+	}
913
+
914
+
915
+	/**
916
+	 * attempts to find a cached version of the requested class
917
+	 * by looking in the following places:
918
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
919
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
920
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
921
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
922
+	 *
923
+	 * @param string $class_name
924
+	 * @param string $class_prefix
925
+	 * @param array  $arguments
926
+	 * @return mixed
927
+	 */
928
+	protected function _get_cached_class(
929
+		string $class_name,
930
+		string $class_prefix = '',
931
+		array $arguments = []
932
+	) {
933
+		if ($class_name === 'EE_Registry') {
934
+			return $this;
935
+		}
936
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
937
+		// check if class has already been loaded, and return it if it has been
938
+		if (isset($this->{$class_abbreviation})) {
939
+			return $this->{$class_abbreviation};
940
+		}
941
+		$class_name = str_replace('\\', '_', $class_name);
942
+		if (isset($this->{$class_name})) {
943
+			return $this->{$class_name};
944
+		}
945
+		if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
946
+			return $this->addons->get($class_name);
947
+		}
948
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
949
+		if ($this->LIB->has($object_identifier)) {
950
+			return $this->LIB->get($object_identifier);
951
+		}
952
+		foreach ($this->LIB as $key => $object) {
953
+			if (
954
+				// request does not contain new arguments and therefore no args identifier
955
+				! $this->object_identifier->hasArguments($object_identifier)
956
+				// but previously cached class with args was found
957
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
958
+			) {
959
+				return $object;
960
+			}
961
+		}
962
+		return null;
963
+	}
964
+
965
+
966
+	/**
967
+	 * removes a cached version of the requested class
968
+	 *
969
+	 * @param string  $class_name
970
+	 * @param boolean $addon
971
+	 * @param array   $arguments
972
+	 * @return boolean
973
+	 */
974
+	public function clear_cached_class(
975
+		string $class_name,
976
+		bool $addon = false,
977
+		array $arguments = []
978
+	): bool {
979
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
980
+		// check if class has already been loaded, and return it if it has been
981
+		if (isset($this->{$class_abbreviation})) {
982
+			$this->{$class_abbreviation} = null;
983
+			return true;
984
+		}
985
+		$class_name = str_replace('\\', '_', $class_name);
986
+		if (isset($this->{$class_name})) {
987
+			$this->{$class_name} = null;
988
+			return true;
989
+		}
990
+		if ($addon && $this->addons->has($class_name)) {
991
+			$this->addons->remove($class_name);
992
+			return true;
993
+		}
994
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
995
+		if ($this->LIB->has($class_name)) {
996
+			$this->LIB->remove($class_name);
997
+			return true;
998
+		}
999
+		return false;
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 * _set_cached_class
1005
+	 * attempts to cache the instantiated class locally
1006
+	 * in one of the following places, in the following order:
1007
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1008
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1009
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1010
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1011
+	 *
1012
+	 * @param object $class_obj
1013
+	 * @param string $class_name
1014
+	 * @param string $class_prefix
1015
+	 * @param bool   $from_db
1016
+	 * @param array  $arguments
1017
+	 * @return void
1018
+	 */
1019
+	protected function _set_cached_class(
1020
+		$class_obj,
1021
+		string $class_name,
1022
+		string $class_prefix = '',
1023
+		bool $from_db = false,
1024
+		array $arguments = []
1025
+	) {
1026
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1027
+			return;
1028
+		}
1029
+		// return newly instantiated class
1030
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1031
+		if ($class_abbreviation) {
1032
+			$this->{$class_abbreviation} = $class_obj;
1033
+			return;
1034
+		}
1035
+		$class_name = str_replace('\\', '_', $class_name);
1036
+		if (property_exists($this, $class_name)) {
1037
+			$this->{$class_name} = $class_obj;
1038
+			return;
1039
+		}
1040
+		if ($class_prefix === 'addon') {
1041
+			$this->addons->add($class_name, $class_obj);
1042
+			return;
1043
+		}
1044
+		if (! $from_db) {
1045
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1046
+			$this->LIB->add($class_name, $class_obj);
1047
+		}
1048
+	}
1049
+
1050
+
1051
+	/**
1052
+	 * attempts to find a full valid filepath for the requested class.
1053
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1054
+	 * then returns that path if the target file has been found and is readable
1055
+	 *
1056
+	 * @param string $class_name
1057
+	 * @param string $type
1058
+	 * @param array  $file_paths
1059
+	 * @return string | bool
1060
+	 */
1061
+	protected function _resolve_path(string $class_name, string $type = '', array $file_paths = [])
1062
+	{
1063
+		// make sure $file_paths is an array
1064
+		$file_paths = is_array($file_paths)
1065
+			? $file_paths
1066
+			: [$file_paths];
1067
+		// cycle thru paths
1068
+		foreach ($file_paths as $key => $file_path) {
1069
+			// convert all separators to proper /, if no filepath, then use EE_CLASSES
1070
+			$file_path = $file_path
1071
+				? str_replace(['/', '\\'], '/', $file_path)
1072
+				: EE_CLASSES;
1073
+			// prep file type
1074
+			$type = ! empty($type)
1075
+				? trim($type, '.') . '.'
1076
+				: '';
1077
+			// build full file path
1078
+			$file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1079
+			// does the file exist and can be read ?
1080
+			if (is_readable($file_paths[ $key ])) {
1081
+				return $file_paths[ $key ];
1082
+			}
1083
+		}
1084
+		return false;
1085
+	}
1086
+
1087
+
1088
+	/**
1089
+	 * basically just performs a require_once()
1090
+	 * but with some error handling
1091
+	 *
1092
+	 * @param string $path
1093
+	 * @param string $class_name
1094
+	 * @param string $type
1095
+	 * @param array  $file_paths
1096
+	 * @return bool
1097
+	 * @throws EE_Error
1098
+	 * @throws ReflectionException
1099
+	 */
1100
+	protected function _require_file(string $path, string $class_name, string $type = '', array $file_paths = []): bool
1101
+	{
1102
+		$this->resolve_legacy_class_parent($class_name);
1103
+		// don't give up! you gotta...
1104
+		try {
1105
+			// does the file exist and can it be read ?
1106
+			if (! $path) {
1107
+				// just in case the file has already been autoloaded,
1108
+				// but discrepancies in the naming schema are preventing it from
1109
+				// being loaded via one of the EE_Registry::load_*() methods,
1110
+				// then let's try one last hail mary before throwing an exception
1111
+				// and call class_exists() again, but with autoloading turned ON
1112
+				if (class_exists($class_name)) {
1113
+					return true;
1114
+				}
1115
+				// so sorry, can't find the file
1116
+				throw new EE_Error(
1117
+					sprintf(
1118
+						esc_html__(
1119
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1120
+							'event_espresso'
1121
+						),
1122
+						trim($type, '.'),
1123
+						$class_name,
1124
+						'<br />' . implode(',<br />', $file_paths)
1125
+					)
1126
+				);
1127
+			}
1128
+			// get the file
1129
+			require_once($path);
1130
+			// if the class isn't already declared somewhere
1131
+			if (class_exists($class_name, false) === false) {
1132
+				// so sorry, not a class
1133
+				throw new EE_Error(
1134
+					sprintf(
1135
+						esc_html__(
1136
+							'The %s file %s does not appear to contain the %s Class.',
1137
+							'event_espresso'
1138
+						),
1139
+						$type,
1140
+						$path,
1141
+						$class_name
1142
+					)
1143
+				);
1144
+			}
1145
+		} catch (EE_Error $e) {
1146
+			$e->get_error();
1147
+			return false;
1148
+		}
1149
+		return true;
1150
+	}
1151
+
1152
+
1153
+	/**
1154
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1155
+	 * before their class declaration in order to ensure that the parent class was loaded.
1156
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1157
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1158
+	 *
1159
+	 * @param string $class_name
1160
+	 */
1161
+	protected function resolve_legacy_class_parent(string $class_name = '')
1162
+	{
1163
+		try {
1164
+			$legacy_parent_class_map = [
1165
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1166
+			];
1167
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1168
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1169
+			}
1170
+		} catch (Exception $exception) {
1171
+		}
1172
+	}
1173
+
1174
+
1175
+	/**
1176
+	 * _create_object
1177
+	 * Attempts to instantiate the requested class via any of the
1178
+	 * commonly used instantiation methods employed throughout EE.
1179
+	 * The priority for instantiation is as follows:
1180
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1181
+	 *        - model objects via their 'new_instance_from_db' method
1182
+	 *        - model objects via their 'new_instance' method
1183
+	 *        - "singleton" classes" via their 'instance' method
1184
+	 *    - standard instantiable classes via their __constructor
1185
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1186
+	 * then the constructor for the requested class will be examined to determine
1187
+	 * if any dependencies exist, and if they can be injected.
1188
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1189
+	 *
1190
+	 * @param string $class_name
1191
+	 * @param array  $arguments
1192
+	 * @param string $type
1193
+	 * @param bool   $from_db
1194
+	 * @return null|object|bool
1195
+	 * @throws InvalidArgumentException
1196
+	 * @throws InvalidInterfaceException
1197
+	 * @throws EE_Error
1198
+	 * @throws ReflectionException
1199
+	 * @throws InvalidDataTypeException
1200
+	 */
1201
+	protected function _create_object(
1202
+		string $class_name,
1203
+		array $arguments = [],
1204
+		string $type = '',
1205
+		bool $from_db = false
1206
+	) {
1207
+		// create reflection
1208
+		$reflector = $this->mirror->getReflectionClass($class_name);
1209
+		// make sure arguments are an array
1210
+		$arguments = is_array($arguments)
1211
+			? $arguments
1212
+			: [$arguments];
1213
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1214
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1215
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1216
+			? $arguments
1217
+			: [$arguments];
1218
+		// attempt to inject dependencies ?
1219
+		if ($this->_dependency_map->has($class_name)) {
1220
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1221
+		}
1222
+		// instantiate the class if possible
1223
+		if ($reflector->isAbstract()) {
1224
+			// nothing to instantiate, loading file was enough
1225
+			// does not throw an exception so $instantiation_mode is unused
1226
+			// $instantiation_mode = "1) no constructor abstract class";
1227
+			return true;
1228
+		}
1229
+		if (
1230
+			empty($arguments)
1231
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1232
+			&& $reflector->isInstantiable()
1233
+		) {
1234
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1235
+			// $instantiation_mode = "2) no constructor but instantiable";
1236
+			return $reflector->newInstance();
1237
+		}
1238
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1239
+			// $instantiation_mode = "3) new_instance_from_db()";
1240
+			return call_user_func_array([$class_name, 'new_instance_from_db'], $arguments);
1241
+		}
1242
+		if (method_exists($class_name, 'new_instance')) {
1243
+			// $instantiation_mode = "4) new_instance()";
1244
+			return call_user_func_array([$class_name, 'new_instance'], $arguments);
1245
+		}
1246
+		if (method_exists($class_name, 'instance')) {
1247
+			// $instantiation_mode = "5) instance()";
1248
+			return call_user_func_array([$class_name, 'instance'], $arguments);
1249
+		}
1250
+		if ($reflector->isInstantiable()) {
1251
+			$args_passed_count = count($arguments);
1252
+			$args_required_count = count($this->mirror->getRequiredParameters($class_name));
1253
+			if ($args_passed_count < $args_required_count) {
1254
+				throw new RuntimeException(
1255
+					sprintf(
1256
+						__(
1257
+							'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1258
+							'event_espresso'
1259
+						),
1260
+						$class_name,
1261
+						$args_required_count,
1262
+						$args_passed_count
1263
+					)
1264
+				);
1265
+			}
1266
+			// $instantiation_mode = "6) constructor";
1267
+			return $reflector->newInstanceArgs($arguments);
1268
+		}
1269
+		// heh ? something's not right !
1270
+		throw new EE_Error(
1271
+			sprintf(
1272
+				esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1273
+				$type,
1274
+				$class_name
1275
+			)
1276
+		);
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1282
+	 * @param array $array
1283
+	 * @return bool
1284
+	 */
1285
+	protected function _array_is_numerically_and_sequentially_indexed(array $array): bool
1286
+	{
1287
+		return empty($array) || array_keys($array) === range(0, count($array) - 1);
1288
+	}
1289
+
1290
+
1291
+	/**
1292
+	 * _resolve_dependencies
1293
+	 * examines the constructor for the requested class to determine
1294
+	 * if any dependencies exist, and if they can be injected.
1295
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1296
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1297
+	 * For example:
1298
+	 *        if attempting to load a class "Foo" with the following constructor:
1299
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1300
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1301
+	 *        but only IF they are NOT already present in the incoming arguments array,
1302
+	 *        and the correct classes can be loaded
1303
+	 *
1304
+	 * @param ReflectionClass $reflector
1305
+	 * @param string          $class_name
1306
+	 * @param array           $arguments
1307
+	 * @return array
1308
+	 * @throws InvalidArgumentException
1309
+	 * @throws InvalidDataTypeException
1310
+	 * @throws InvalidInterfaceException
1311
+	 * @throws ReflectionException
1312
+	 */
1313
+	protected function _resolve_dependencies(
1314
+		ReflectionClass $reflector,
1315
+		string $class_name,
1316
+		array $arguments = []
1317
+	): array {
1318
+		// let's examine the constructor
1319
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1320
+		// whu? huh? nothing?
1321
+		if (! $constructor) {
1322
+			return $arguments;
1323
+		}
1324
+		// get constructor parameters
1325
+		$params = $this->mirror->getParametersFromReflection($reflector);
1326
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1327
+		$argument_keys = array_keys($arguments);
1328
+		// now loop thru all the constructors' expected parameters
1329
+		foreach ($params as $index => $param) {
1330
+			try {
1331
+				// is this a dependency for a specific class ?
1332
+				$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1333
+			} catch (ReflectionException $exception) {
1334
+				// uh-oh... most likely a legacy class that has not been autoloaded
1335
+				// let's try to derive the classname from what we have now
1336
+				// and hope that the property var name is close to the class name
1337
+				$param_class = $param->getName();
1338
+				$param_class = str_replace('_', ' ', $param_class);
1339
+				$param_class = ucwords($param_class);
1340
+				$param_class = str_replace(' ', '_', $param_class);
1341
+			}
1342
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1343
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1344
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1345
+				: $param_class;
1346
+			if (
1347
+				// param is not even a class
1348
+				($param_class === null || $this->parameterIsPrimitive($param_class))
1349
+				// and something already exists in the incoming arguments for this param
1350
+				&& array_key_exists($index, $argument_keys)
1351
+				&& isset($arguments[ $argument_keys[ $index ] ])
1352
+			) {
1353
+				// so let's skip this argument and move on to the next
1354
+				continue;
1355
+			}
1356
+			// parameter is type hinted as a class
1357
+			if ($param_class !== null) {
1358
+				// parameter exists as an incoming argument, AND it's the correct class
1359
+				if (
1360
+					array_key_exists($index, $argument_keys)
1361
+					&& isset($arguments[ $argument_keys[ $index ] ])
1362
+					&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1363
+				) {
1364
+					// skip this argument and move on to the next
1365
+					continue;
1366
+				}
1367
+				// parameter should be injected
1368
+				if ($this->_dependency_map->has_dependency_for_class($class_name, $param_class)) {
1369
+					$arguments = $this->_resolve_dependency(
1370
+						$class_name,
1371
+						$param_class,
1372
+						$arguments,
1373
+						$index
1374
+					);
1375
+				}
1376
+			}
1377
+			if (empty($arguments[ $index ])) {
1378
+				$default_value = $this->mirror->getParameterDefaultValue(
1379
+					$param,
1380
+					$class_name,
1381
+					$index
1382
+				);
1383
+				// if there's no default value, and the incoming argument is an array (albeit empty), then use that
1384
+				$arguments[ $index ] = $default_value === null
1385
+									   && isset($arguments[ $index ])
1386
+									   && is_array($arguments[ $index ])
1387
+					? $arguments[ $index ]
1388
+					: $default_value;
1389
+			}
1390
+		}
1391
+		return $arguments;
1392
+	}
1393
+
1394
+
1395
+	/**
1396
+	 * @param string $class_name
1397
+	 * @param string $param_class
1398
+	 * @param array  $arguments
1399
+	 * @param mixed  $index
1400
+	 * @return array
1401
+	 * @throws InvalidArgumentException
1402
+	 * @throws InvalidInterfaceException
1403
+	 * @throws InvalidDataTypeException
1404
+	 */
1405
+	protected function _resolve_dependency(string $class_name, string $param_class, array $arguments, $index): array
1406
+	{
1407
+		$dependency = null;
1408
+		// should dependency be loaded from cache ?
1409
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1410
+			$class_name,
1411
+			$param_class
1412
+		);
1413
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1414
+		// we might have a dependency...
1415
+		// let's MAYBE try and find it in our cache if that's what's been requested
1416
+		$cached_class = $cache_on
1417
+			? $this->_get_cached_class($param_class)
1418
+			: null;
1419
+		// and grab it if it exists
1420
+		if ($cached_class instanceof $param_class) {
1421
+			$dependency = $cached_class;
1422
+		} elseif ($param_class !== $class_name) {
1423
+			// obtain the loader method from the dependency map
1424
+			$loader = $this->_dependency_map->class_loader($param_class);
1425
+			// is loader a custom closure ?
1426
+			if ($loader instanceof Closure) {
1427
+				$dependency = $loader($arguments);
1428
+			} else {
1429
+				// set the cache on property for the recursive loading call
1430
+				$this->_cache_on = $cache_on;
1431
+				// if not, then let's try and load it via the registry
1432
+				if ($loader && method_exists($this, $loader)) {
1433
+					$dependency = $this->{$loader}($param_class);
1434
+				} else {
1435
+					$dependency = LoaderFactory::getLoader()->load(
1436
+						$param_class,
1437
+						[],
1438
+						$cache_on
1439
+					);
1440
+				}
1441
+			}
1442
+		}
1443
+		// did we successfully find the correct dependency ?
1444
+		if ($dependency instanceof $param_class) {
1445
+			// then let's inject it into the incoming array of arguments at the correct location
1446
+			$arguments[ $index ] = $dependency;
1447
+		}
1448
+		return $arguments;
1449
+	}
1450
+
1451
+
1452
+	/**
1453
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1454
+	 *
1455
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1456
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1457
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1458
+	 * @param array  $arguments
1459
+	 * @return object
1460
+	 */
1461
+	public static function factory(string $classname, array $arguments = [])
1462
+	{
1463
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1464
+		if ($loader instanceof Closure) {
1465
+			return $loader($arguments);
1466
+		}
1467
+		if (method_exists(self::instance(), $loader)) {
1468
+			return self::instance()->{$loader}($classname, $arguments);
1469
+		}
1470
+		return null;
1471
+	}
1472
+
1473
+
1474
+	/**
1475
+	 * Gets the addon by its class name
1476
+	 *
1477
+	 * @param string $class_name
1478
+	 * @return EE_Addon
1479
+	 */
1480
+	public function getAddon(string $class_name): ?EE_Addon
1481
+	{
1482
+		$class_name = str_replace('\\', '_', $class_name);
1483
+		return $this->addons->{$class_name} ?? null;
1484
+	}
1485
+
1486
+
1487
+	/**
1488
+	 * removes the addon from the internal cache
1489
+	 *
1490
+	 * @param string $class_name
1491
+	 * @return void
1492
+	 */
1493
+	public function removeAddon(string $class_name)
1494
+	{
1495
+		$class_name = str_replace('\\', '_', $class_name);
1496
+		$this->addons->remove($class_name);
1497
+	}
1498
+
1499
+
1500
+	/**
1501
+	 * Gets the addon by its name/slug (not classname. For that, just
1502
+	 * use the get_addon() method above
1503
+	 *
1504
+	 * @param string $name
1505
+	 * @return EE_Addon
1506
+	 */
1507
+	public function get_addon_by_name(string $name): ?EE_Addon
1508
+	{
1509
+		foreach ($this->addons as $addon) {
1510
+			if ($addon->name() === $name) {
1511
+				return $addon;
1512
+			}
1513
+		}
1514
+		return null;
1515
+	}
1516
+
1517
+
1518
+	/**
1519
+	 * Gets an array of all the registered addons, where the keys are their names.
1520
+	 * (ie, what each returns for their name() function)
1521
+	 * They're already available on EE_Registry::instance()->addons as properties,
1522
+	 * where each property's name is the addon's classname,
1523
+	 * So if you just want to get the addon by classname,
1524
+	 * OR use the get_addon() method above.
1525
+	 * PLEASE  NOTE:
1526
+	 * addons with Fully Qualified Class Names
1527
+	 * have had the namespace separators converted to underscores,
1528
+	 * so a classname like Fully\Qualified\ClassName
1529
+	 * would have been converted to Fully_Qualified_ClassName
1530
+	 *
1531
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1532
+	 */
1533
+	public function get_addons_by_name(): array
1534
+	{
1535
+		$addons = [];
1536
+		foreach ($this->addons as $addon) {
1537
+			$addons[ $addon->name() ] = $addon;
1538
+		}
1539
+		return $addons;
1540
+	}
1541
+
1542
+
1543
+	/**
1544
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1545
+	 * a stale copy of it around
1546
+	 *
1547
+	 * @param string $model_name
1548
+	 * @return EEM_Base
1549
+	 * @throws EE_Error
1550
+	 * @throws ReflectionException
1551
+	 */
1552
+	public function reset_model(string $model_name): ?EEM_Base
1553
+	{
1554
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1555
+			? "EEM_$model_name"
1556
+			: $model_name;
1557
+		if (! $this->LIB->has($model_class_name)) {
1558
+			return null;
1559
+		}
1560
+		$model = $this->LIB->get($model_class_name);
1561
+		if (! $model instanceof EEM_Base) {
1562
+			return null;
1563
+		}
1564
+		// get that model reset it and make sure we nuke the old reference to it
1565
+		if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1566
+			$this->LIB->remove($model_class_name);
1567
+			$this->LIB->add($model_class_name, $model->reset());
1568
+		} else {
1569
+			throw new EE_Error(
1570
+				sprintf(
1571
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1572
+					$model_name
1573
+				)
1574
+			);
1575
+		}
1576
+		return $model;
1577
+	}
1578
+
1579
+
1580
+	/**
1581
+	 * Resets the registry.
1582
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1583
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1584
+	 * - $_dependency_map
1585
+	 * - $_class_abbreviations
1586
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1587
+	 * - $REQ:  Still on the same request so no need to change.
1588
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1589
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1590
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1591
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1592
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1593
+	 *             switch or on the restore.
1594
+	 * - $modules
1595
+	 * - $shortcodes
1596
+	 * - $widgets
1597
+	 *
1598
+	 * @param boolean $hard             [deprecated]
1599
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1600
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1601
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1602
+	 * @param bool    $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1603
+	 *                                  client
1604
+	 *                                  code instead can just change the model context to a different blog id if
1605
+	 *                                  necessary
1606
+	 * @return EE_Registry
1607
+	 * @throws EE_Error
1608
+	 * @throws ReflectionException
1609
+	 */
1610
+	public static function reset(bool $hard = false, bool $reinstantiate = true, bool $reset_models = true): EE_Registry
1611
+	{
1612
+		$instance            = self::instance();
1613
+		$instance->_cache_on = true;
1614
+		// reset some "special" classes
1615
+		EEH_Activation::reset();
1616
+		$hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1617
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1618
+		$instance->CART = null;
1619
+		$instance->MRM = null;
1620
+		// messages reset
1621
+		EED_Messages::reset();
1622
+		// handle of objects cached on LIB
1623
+		foreach (['LIB', 'modules'] as $cache) {
1624
+			foreach ($instance->{$cache} as $class_name => $class) {
1625
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1626
+					unset($instance->{$cache}->{$class_name});
1627
+				}
1628
+			}
1629
+		}
1630
+		return $instance;
1631
+	}
1632
+
1633
+
1634
+	/**
1635
+	 * if passed object implements ResettableInterface, then call it's reset() method
1636
+	 * if passed object implements InterminableInterface, then return false,
1637
+	 * to indicate that it should NOT be cleared from the Registry cache
1638
+	 *
1639
+	 * @param      $object
1640
+	 * @param bool $reset_models
1641
+	 * @return bool returns true if cached object should be unset
1642
+	 * @throws EE_Error
1643
+	 * @throws ReflectionException
1644
+	 */
1645
+	private static function _reset_and_unset_object($object, bool $reset_models): bool
1646
+	{
1647
+		if (! is_object($object)) {
1648
+			// don't unset anything that's not an object
1649
+			return false;
1650
+		}
1651
+		if ($object instanceof EED_Module) {
1652
+			$object::reset();
1653
+			// don't unset modules
1654
+			return false;
1655
+		}
1656
+		if ($object instanceof ResettableInterface) {
1657
+			if ($object instanceof EEM_Base) {
1658
+				if ($reset_models) {
1659
+					$object->reset();
1660
+					return true;
1661
+				}
1662
+				return false;
1663
+			}
1664
+			$object->reset();
1665
+			return true;
1666
+		}
1667
+		if (! $object instanceof InterminableInterface) {
1668
+			return true;
1669
+		}
1670
+		return false;
1671
+	}
1672
+
1673
+
1674
+	/**
1675
+	 * Gets all the custom post type models defined
1676
+	 *
1677
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1678
+	 */
1679
+	public function cpt_models(): array
1680
+	{
1681
+		$cpt_models = [];
1682
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1683
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1684
+				$cpt_models[ $short_name ] = $classname;
1685
+			}
1686
+		}
1687
+		return $cpt_models;
1688
+	}
1689
+
1690
+
1691
+	/**
1692
+	 * @return EE_Config
1693
+	 */
1694
+	public static function CFG(): EE_Config
1695
+	{
1696
+		return self::instance()->CFG;
1697
+	}
1698
+
1699
+
1700
+	/**
1701
+	 * @param string $class_name
1702
+	 * @return ReflectionClass
1703
+	 * @throws ReflectionException
1704
+	 * @throws InvalidDataTypeException
1705
+	 * @deprecated 4.9.62.p
1706
+	 */
1707
+	public function get_ReflectionClass(string $class_name): ReflectionClass
1708
+	{
1709
+		return $this->mirror->getReflectionClass($class_name);
1710
+	}
1711
+
1712
+	private function parameterIsPrimitive(?string $param_class): bool
1713
+	{
1714
+		return in_array(
1715
+			$param_class,
1716
+			[
1717
+				'array',
1718
+				'bool',
1719
+				'float',
1720
+				'int',
1721
+				'string',
1722
+			]
1723
+		);
1724
+	}
1725 1725
 }
Please login to merge, or discard this patch.
Spacing   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
      */
261 261
     public static function sanitize_i18n_js_strings(): array
262 262
     {
263
-        array_walk(EE_Registry::$i18n_js_strings, function (&$value) {
263
+        array_walk(EE_Registry::$i18n_js_strings, function(&$value) {
264 264
             if (is_scalar($value)) {
265 265
                 $value = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
266 266
                 // replace all escaped instances of \n with actual new lines
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
             $module_class = get_class($module);
301 301
             $this->modules->add($module_class, $module);
302 302
         } else {
303
-            if (! class_exists('EE_Module_Request_Router', false)) {
303
+            if ( ! class_exists('EE_Module_Request_Router', false)) {
304 304
                 $this->load_core('Module_Request_Router');
305 305
             }
306 306
             EE_Module_Request_Router::module_factory($module);
@@ -339,10 +339,10 @@  discard block
 block discarded – undo
339 339
                 EE_CORE,
340 340
                 EE_ADMIN,
341 341
                 EE_CPTS,
342
-                EE_CORE . 'CPTs/',
343
-                EE_CORE . 'data_migration_scripts/',
344
-                EE_CORE . 'request_stack/',
345
-                EE_CORE . 'middleware/',
342
+                EE_CORE.'CPTs/',
343
+                EE_CORE.'data_migration_scripts/',
344
+                EE_CORE.'request_stack/',
345
+                EE_CORE.'middleware/',
346 346
             ]
347 347
         );
348 348
         // retrieve instantiated class
@@ -378,7 +378,7 @@  discard block
 block discarded – undo
378 378
         $service_paths = (array) apply_filters(
379 379
             'FHEE__EE_Registry__load_service__service_paths',
380 380
             [
381
-                EE_CORE . 'services/',
381
+                EE_CORE.'services/',
382 382
             ]
383 383
         );
384 384
         // retrieve instantiated class
@@ -518,10 +518,10 @@  discard block
 block discarded – undo
518 518
     {
519 519
         $paths = [
520 520
             EE_LIBRARIES,
521
-            EE_LIBRARIES . 'messages/',
522
-            EE_LIBRARIES . 'shortcodes/',
523
-            EE_LIBRARIES . 'qtips/',
524
-            EE_LIBRARIES . 'payment_methods/',
521
+            EE_LIBRARIES.'messages/',
522
+            EE_LIBRARIES.'shortcodes/',
523
+            EE_LIBRARIES.'qtips/',
524
+            EE_LIBRARIES.'payment_methods/',
525 525
         ];
526 526
         // retrieve instantiated class
527 527
         return $this->_load(
@@ -590,10 +590,10 @@  discard block
 block discarded – undo
590 590
     public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
591 591
     {
592 592
         $paths = [
593
-            EE_MODELS . 'fields/',
594
-            EE_MODELS . 'helpers/',
595
-            EE_MODELS . 'relations/',
596
-            EE_MODELS . 'strategies/',
593
+            EE_MODELS.'fields/',
594
+            EE_MODELS.'helpers/',
595
+            EE_MODELS.'relations/',
596
+            EE_MODELS.'strategies/',
597 597
         ];
598 598
         // retrieve instantiated class
599 599
         return $this->_load(
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
      */
618 618
     public function is_model_name(string $model_name): bool
619 619
     {
620
-        return isset($this->models[ $model_name ]);
620
+        return isset($this->models[$model_name]);
621 621
     }
622 622
 
623 623
 
@@ -749,7 +749,7 @@  discard block
 block discarded – undo
749 749
                 return $cached_class;
750 750
             }
751 751
         }                                                           // obtain the loader method from the dependency map
752
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
752
+        $loader = $this->_dependency_map->class_loader($class_name); // instantiate the requested object
753 753
         if ($loader instanceof Closure) {
754 754
             $class_obj = $loader($arguments);
755 755
         } else {
@@ -791,7 +791,7 @@  discard block
 block discarded – undo
791 791
             case 1:
792 792
                 // if it's a FQCN then maybe the class is registered with a preceding \
793 793
                 $class_name = strpos($class_name, '\\') !== false
794
-                    ? '\\' . ltrim($class_name, '\\')
794
+                    ? '\\'.ltrim($class_name, '\\')
795 795
                     : $class_name;
796 796
                 break;
797 797
             case 2:
@@ -845,11 +845,11 @@  discard block
 block discarded – undo
845 845
         // strip php file extension
846 846
         $class_name = str_replace('.php', '', trim($class_name));
847 847
         // does the class have a prefix ?
848
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
848
+        if ( ! empty($class_prefix) && $class_prefix !== 'addon') {
849 849
             // make sure $class_prefix is uppercase
850 850
             $class_prefix = strtoupper(trim($class_prefix));
851 851
             // add class prefix ONCE!!!
852
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
852
+            $class_name = $class_prefix.str_replace($class_prefix, '', $class_name);
853 853
         }
854 854
         $class_name   = $this->class_cache->getFqnForAlias($class_name);
855 855
         $class_exists = class_exists($class_name, false);
@@ -869,7 +869,7 @@  discard block
 block discarded – undo
869 869
             }
870 870
         }
871 871
         // if the class doesn't already exist.. then we need to try and find the file and load it
872
-        if (! $class_exists) {
872
+        if ( ! $class_exists) {
873 873
             // get full path to file
874 874
             $path = $this->_resolve_path($class_name, $type, $file_paths);
875 875
             // load the file
@@ -880,7 +880,7 @@  discard block
 block discarded – undo
880 880
                 return $loaded;
881 881
             }
882 882
             // if an object was expected but loading failed, then return nothing
883
-            if (! $loaded) {
883
+            if ( ! $loaded) {
884 884
                 return null;
885 885
             }
886 886
         }
@@ -908,7 +908,7 @@  discard block
 block discarded – undo
908 908
      */
909 909
     protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
910 910
     {
911
-        return $this->_class_abbreviations[ $class_name ] ?? $default;
911
+        return $this->_class_abbreviations[$class_name] ?? $default;
912 912
     }
913 913
 
914 914
 
@@ -1041,7 +1041,7 @@  discard block
 block discarded – undo
1041 1041
             $this->addons->add($class_name, $class_obj);
1042 1042
             return;
1043 1043
         }
1044
-        if (! $from_db) {
1044
+        if ( ! $from_db) {
1045 1045
             $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1046 1046
             $this->LIB->add($class_name, $class_obj);
1047 1047
         }
@@ -1072,13 +1072,13 @@  discard block
 block discarded – undo
1072 1072
                 : EE_CLASSES;
1073 1073
             // prep file type
1074 1074
             $type = ! empty($type)
1075
-                ? trim($type, '.') . '.'
1075
+                ? trim($type, '.').'.'
1076 1076
                 : '';
1077 1077
             // build full file path
1078
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1078
+            $file_paths[$key] = rtrim($file_path, '/').'/'.$class_name.'.'.$type.'php';
1079 1079
             // does the file exist and can be read ?
1080
-            if (is_readable($file_paths[ $key ])) {
1081
-                return $file_paths[ $key ];
1080
+            if (is_readable($file_paths[$key])) {
1081
+                return $file_paths[$key];
1082 1082
             }
1083 1083
         }
1084 1084
         return false;
@@ -1103,7 +1103,7 @@  discard block
 block discarded – undo
1103 1103
         // don't give up! you gotta...
1104 1104
         try {
1105 1105
             // does the file exist and can it be read ?
1106
-            if (! $path) {
1106
+            if ( ! $path) {
1107 1107
                 // just in case the file has already been autoloaded,
1108 1108
                 // but discrepancies in the naming schema are preventing it from
1109 1109
                 // being loaded via one of the EE_Registry::load_*() methods,
@@ -1121,7 +1121,7 @@  discard block
 block discarded – undo
1121 1121
                         ),
1122 1122
                         trim($type, '.'),
1123 1123
                         $class_name,
1124
-                        '<br />' . implode(',<br />', $file_paths)
1124
+                        '<br />'.implode(',<br />', $file_paths)
1125 1125
                     )
1126 1126
                 );
1127 1127
             }
@@ -1164,8 +1164,8 @@  discard block
 block discarded – undo
1164 1164
             $legacy_parent_class_map = [
1165 1165
                 'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1166 1166
             ];
1167
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1168
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1167
+            if (isset($legacy_parent_class_map[$class_name])) {
1168
+                require_once EE_PLUGIN_DIR_PATH.$legacy_parent_class_map[$class_name];
1169 1169
             }
1170 1170
         } catch (Exception $exception) {
1171 1171
         }
@@ -1318,7 +1318,7 @@  discard block
 block discarded – undo
1318 1318
         // let's examine the constructor
1319 1319
         $constructor = $this->mirror->getConstructorFromReflection($reflector);
1320 1320
         // whu? huh? nothing?
1321
-        if (! $constructor) {
1321
+        if ( ! $constructor) {
1322 1322
             return $arguments;
1323 1323
         }
1324 1324
         // get constructor parameters
@@ -1348,7 +1348,7 @@  discard block
 block discarded – undo
1348 1348
                 ($param_class === null || $this->parameterIsPrimitive($param_class))
1349 1349
                 // and something already exists in the incoming arguments for this param
1350 1350
                 && array_key_exists($index, $argument_keys)
1351
-                && isset($arguments[ $argument_keys[ $index ] ])
1351
+                && isset($arguments[$argument_keys[$index]])
1352 1352
             ) {
1353 1353
                 // so let's skip this argument and move on to the next
1354 1354
                 continue;
@@ -1358,8 +1358,8 @@  discard block
 block discarded – undo
1358 1358
                 // parameter exists as an incoming argument, AND it's the correct class
1359 1359
                 if (
1360 1360
                     array_key_exists($index, $argument_keys)
1361
-                    && isset($arguments[ $argument_keys[ $index ] ])
1362
-                    && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1361
+                    && isset($arguments[$argument_keys[$index]])
1362
+                    && $arguments[$argument_keys[$index]] instanceof $param_class
1363 1363
                 ) {
1364 1364
                     // skip this argument and move on to the next
1365 1365
                     continue;
@@ -1374,17 +1374,17 @@  discard block
 block discarded – undo
1374 1374
                     );
1375 1375
                 }
1376 1376
             }
1377
-            if (empty($arguments[ $index ])) {
1377
+            if (empty($arguments[$index])) {
1378 1378
                 $default_value = $this->mirror->getParameterDefaultValue(
1379 1379
                     $param,
1380 1380
                     $class_name,
1381 1381
                     $index
1382 1382
                 );
1383 1383
                 // if there's no default value, and the incoming argument is an array (albeit empty), then use that
1384
-                $arguments[ $index ] = $default_value === null
1385
-                                       && isset($arguments[ $index ])
1386
-                                       && is_array($arguments[ $index ])
1387
-                    ? $arguments[ $index ]
1384
+                $arguments[$index] = $default_value === null
1385
+                                       && isset($arguments[$index])
1386
+                                       && is_array($arguments[$index])
1387
+                    ? $arguments[$index]
1388 1388
                     : $default_value;
1389 1389
             }
1390 1390
         }
@@ -1443,7 +1443,7 @@  discard block
 block discarded – undo
1443 1443
         // did we successfully find the correct dependency ?
1444 1444
         if ($dependency instanceof $param_class) {
1445 1445
             // then let's inject it into the incoming array of arguments at the correct location
1446
-            $arguments[ $index ] = $dependency;
1446
+            $arguments[$index] = $dependency;
1447 1447
         }
1448 1448
         return $arguments;
1449 1449
     }
@@ -1534,7 +1534,7 @@  discard block
 block discarded – undo
1534 1534
     {
1535 1535
         $addons = [];
1536 1536
         foreach ($this->addons as $addon) {
1537
-            $addons[ $addon->name() ] = $addon;
1537
+            $addons[$addon->name()] = $addon;
1538 1538
         }
1539 1539
         return $addons;
1540 1540
     }
@@ -1554,11 +1554,11 @@  discard block
 block discarded – undo
1554 1554
         $model_class_name = strpos($model_name, 'EEM_') !== 0
1555 1555
             ? "EEM_$model_name"
1556 1556
             : $model_name;
1557
-        if (! $this->LIB->has($model_class_name)) {
1557
+        if ( ! $this->LIB->has($model_class_name)) {
1558 1558
             return null;
1559 1559
         }
1560 1560
         $model = $this->LIB->get($model_class_name);
1561
-        if (! $model instanceof EEM_Base) {
1561
+        if ( ! $model instanceof EEM_Base) {
1562 1562
             return null;
1563 1563
         }
1564 1564
         // get that model reset it and make sure we nuke the old reference to it
@@ -1644,7 +1644,7 @@  discard block
 block discarded – undo
1644 1644
      */
1645 1645
     private static function _reset_and_unset_object($object, bool $reset_models): bool
1646 1646
     {
1647
-        if (! is_object($object)) {
1647
+        if ( ! is_object($object)) {
1648 1648
             // don't unset anything that's not an object
1649 1649
             return false;
1650 1650
         }
@@ -1664,7 +1664,7 @@  discard block
 block discarded – undo
1664 1664
             $object->reset();
1665 1665
             return true;
1666 1666
         }
1667
-        if (! $object instanceof InterminableInterface) {
1667
+        if ( ! $object instanceof InterminableInterface) {
1668 1668
             return true;
1669 1669
         }
1670 1670
         return false;
@@ -1681,7 +1681,7 @@  discard block
 block discarded – undo
1681 1681
         $cpt_models = [];
1682 1682
         foreach ($this->non_abstract_db_models as $short_name => $classname) {
1683 1683
             if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1684
-                $cpt_models[ $short_name ] = $classname;
1684
+                $cpt_models[$short_name] = $classname;
1685 1685
             }
1686 1686
         }
1687 1687
         return $cpt_models;
Please login to merge, or discard this patch.
core/helpers/EEH_Template.helper.php 2 patches
Indentation   +953 added lines, -953 removed lines patch added patch discarded remove patch
@@ -9,36 +9,36 @@  discard block
 block discarded – undo
9 9
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
10 10
 
11 11
 if (! function_exists('espresso_get_template_part')) {
12
-    /**
13
-     * espresso_get_template_part
14
-     * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
15
-     * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
16
-     *
17
-     * @param string $slug The slug name for the generic template.
18
-     * @param string $name The name of the specialised template.
19
-     */
20
-    function espresso_get_template_part($slug = '', $name = '')
21
-    {
22
-        EEH_Template::get_template_part($slug, $name);
23
-    }
12
+	/**
13
+	 * espresso_get_template_part
14
+	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
15
+	 * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
16
+	 *
17
+	 * @param string $slug The slug name for the generic template.
18
+	 * @param string $name The name of the specialised template.
19
+	 */
20
+	function espresso_get_template_part($slug = '', $name = '')
21
+	{
22
+		EEH_Template::get_template_part($slug, $name);
23
+	}
24 24
 }
25 25
 
26 26
 
27 27
 if (! function_exists('espresso_get_object_css_class')) {
28
-    /**
29
-     * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30
-     *
31
-     * @param EE_Base_Class $object the EE object the css class is being generated for
32
-     * @param string        $prefix added to the beginning of the generated class
33
-     * @param string        $suffix added to the end of the generated class
34
-     * @return string
35
-     * @throws EE_Error
36
-     * @throws ReflectionException
37
-     */
38
-    function espresso_get_object_css_class($object = null, $prefix = '', $suffix = '')
39
-    {
40
-        return EEH_Template::get_object_css_class($object, $prefix, $suffix);
41
-    }
28
+	/**
29
+	 * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30
+	 *
31
+	 * @param EE_Base_Class $object the EE object the css class is being generated for
32
+	 * @param string        $prefix added to the beginning of the generated class
33
+	 * @param string        $suffix added to the end of the generated class
34
+	 * @return string
35
+	 * @throws EE_Error
36
+	 * @throws ReflectionException
37
+	 */
38
+	function espresso_get_object_css_class($object = null, $prefix = '', $suffix = '')
39
+	{
40
+		return EEH_Template::get_object_css_class($object, $prefix, $suffix);
41
+	}
42 42
 }
43 43
 
44 44
 
@@ -52,661 +52,661 @@  discard block
 block discarded – undo
52 52
  */
53 53
 class EEH_Template
54 54
 {
55
-    private static array $_espresso_themes = [];
56
-
57
-
58
-    /**
59
-     *    is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
60
-     *
61
-     * @return boolean
62
-     */
63
-    public static function is_espresso_theme()
64
-    {
65
-        return wp_get_theme()->get('TextDomain') === 'event_espresso';
66
-    }
67
-
68
-
69
-    /**
70
-     *    load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then
71
-     *    load its functions.php file ( if not already loaded )
72
-     *
73
-     * @return void
74
-     */
75
-    public static function load_espresso_theme_functions()
76
-    {
77
-        if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
-            if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
-                require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
80
-            }
81
-        }
82
-    }
83
-
84
-
85
-    /**
86
-     *    get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
87
-     *
88
-     * @return array
89
-     */
90
-    public static function get_espresso_themes(): array
91
-    {
92
-        if (empty(EEH_Template::$_espresso_themes)) {
93
-            $espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
94
-            if (empty($espresso_themes)) {
95
-                return [];
96
-            }
97
-            if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
-                unset($espresso_themes[ $key ]);
99
-            }
100
-            EEH_Template::$_espresso_themes = [];
101
-            foreach ($espresso_themes as $espresso_theme) {
102
-                EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
103
-            }
104
-        }
105
-        return EEH_Template::$_espresso_themes;
106
-    }
107
-
108
-
109
-    /**
110
-     * EEH_Template::get_template_part
111
-     * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead,
112
-     * and doesn't add base versions of files so not a very useful function at all except that it adds familiarity PLUS
113
-     * filtering based off of the entire template part name
114
-     *
115
-     * @param string $slug The slug name for the generic template.
116
-     * @param string $name The name of the specialised template.
117
-     * @param array  $template_args
118
-     * @param bool   $return_string
119
-     * @return string        the html output for the formatted money value
120
-     */
121
-    public static function get_template_part(
122
-        $slug = '',
123
-        $name = '',
124
-        $template_args = [],
125
-        $return_string = false
126
-    ) {
127
-        do_action("get_template_part_$slug-$name", $slug, $name);
128
-        $template = $slug;
129
-        $name      = (string) $name;
130
-        if ($name != '') {
131
-            $template .= "-$name";
132
-        }
133
-        $template .= ".php";
134
-        // allow template parts to be turned off via something like:
135
-        // add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
136
-        if (apply_filters("FHEE__EEH_Template__get_template_part__display__{$slug}_$name", true)) {
137
-            return EEH_Template::locate_template($template, $template_args, true, $return_string);
138
-        }
139
-        return '';
140
-    }
141
-
142
-
143
-    /**
144
-     *    locate_template
145
-     *    locate a template file by looking in the following places, in the following order:
146
-     *        <server path up to>/wp-content/themes/<current active WordPress theme>/
147
-     *        <assumed full absolute server path>
148
-     *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
149
-     *        <server path up to>/wp-content/uploads/espresso/templates/
150
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
151
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
152
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/
153
-     *    as soon as the template is found in one of these locations, it will be returned or loaded
154
-     *        Example:
155
-     *          You are using the WordPress Twenty Sixteen theme,
156
-     *        and you want to customize the "some-event.template.php" template,
157
-     *          which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
158
-     *          Assuming WP is installed on your server in the "/home/public_html/" folder,
159
-     *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
160
-     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
161
-     *        /relative/path/to/some-event.template.php
162
-     *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
163
-     *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
164
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
165
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
167
-     *          Had you passed an absolute path to your template that was in some other location,
168
-     *        ie: "/absolute/path/to/some-event.template.php"
169
-     *          then the search would have been :
170
-     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
171
-     *        /absolute/path/to/some-event.template.php
172
-     *          and stopped there upon finding it in the second location
173
-     *
174
-     * @param array|string $templates       array of template file names including extension (or just a single string)
175
-     * @param array        $template_args   an array of arguments to be extracted for use in the template
176
-     * @param boolean      $load            whether to pass the located template path on to the
177
-     *                                      EEH_Template::display_template() method or simply return it
178
-     * @param boolean      $return_string   whether to send output immediately to screen, or capture and return as a
179
-     *                                      string
180
-     * @param boolean      $check_if_custom If TRUE, this flags this method to return boolean for whether this will
181
-     *                                      generate a custom template or not. Used in places where you don't actually
182
-     *                                      load the template, you just want to know if there's a custom version of it.
183
-     * @return string|true
184
-     * @throws DomainException
185
-     * @throws InvalidArgumentException
186
-     * @throws InvalidDataTypeException
187
-     * @throws InvalidInterfaceException
188
-     */
189
-    public static function locate_template(
190
-        $templates = [],
191
-        array $template_args = [],
192
-        bool $load = true,
193
-        bool $return_string = true,
194
-        bool $check_if_custom = false
195
-    ) {
196
-        $cache_id      = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
197
-        $template_path = TemplateCache::get($cache_id);
198
-        $template_path = $template_path ?: self::resolveTemplatePath($cache_id, (array) $templates, $check_if_custom);
199
-
200
-        if ($check_if_custom && ! empty($template_path)) {
201
-            return true;
202
-        }
203
-
204
-        // if we got it and you want to see it...
205
-        if ($template_path && $load && ! $check_if_custom) {
206
-            if ($return_string) {
207
-                return EEH_Template::display_template($template_path, $template_args, true);
208
-            }
209
-            EEH_Template::display_template($template_path, $template_args);
210
-        }
211
-        return $check_if_custom && ! empty($template_path) ? true : $template_path;
212
-    }
213
-
214
-
215
-    /**
216
-     * Resolves the path of a template by checking various possible locations.
217
-     *
218
-     * This method checks for the existence of a template in several locations,
219
-     * including the current theme folder, the uploads directory, and the plugin's own template directory.
220
-     * It uses the provided cache ID to store and retrieve the resolved path from a cache for performance.
221
-     * If the template is not found in any of the checked locations, an empty string is returned.
222
-     *
223
-     * @param string $cache_id        The ID used for caching the resolved path.
224
-     * @param array  $templates       An array of template file names to search for.
225
-     * @param bool $check_if_custom   If true, the method will only check if a custom template exists
226
-     *                                and won't include core plugin folders.
227
-     * @return string The resolved template path, or an empty string if the template was not found.
228
-     * @since 5.0.21.p
229
-     */
230
-    private static function resolveTemplatePath(string $cache_id, array $templates, bool $check_if_custom): string
231
-    {
232
-        // first use WP locate_template to check for template in the current theme folder
233
-        $template_path = $templates ? locate_template($templates) : '';
234
-        // not in the theme
235
-        if (empty($template_path)) {
236
-            // not even a template to look for ?
237
-            if (empty($templates)) {
238
-                $loader = LoaderFactory::getLoader();
239
-                /** @var RequestInterface $request */
240
-                $request = $loader->getShared(RequestInterface::class);
241
-                // get post_type
242
-                $post_type = $request->getRequestParam('post_type');
243
-                /** @var CustomPostTypeDefinitions $custom_post_types */
244
-                $custom_post_types = $loader->getShared(CustomPostTypeDefinitions::class);
245
-                // get array of EE Custom Post Types
246
-                $EE_CPTs = $custom_post_types->getDefinitions();
247
-                // build template name based on request
248
-                if (isset($EE_CPTs[ $post_type ])) {
249
-                    $archive_or_single = is_archive() ? 'archive' : '';
250
-                    $archive_or_single = is_single() ? 'single' : $archive_or_single;
251
-                    $templates[]       = $archive_or_single . '-' . $post_type . '.php';
252
-                }
253
-            }
254
-            // currently active EE template theme
255
-            $current_theme = EE_Config::get_current_theme();
256
-            // array of paths to folders that may contain templates
257
-            $template_folder_paths = [];
258
-
259
-            // add core plugin folders for checking only if we're not $check_if_custom
260
-            if (! $check_if_custom) {
261
-                $core_paths            = [
262
-                    // in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
-                    EE_PUBLIC . $current_theme,
264
-                    // in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
-                    EE_TEMPLATES . $current_theme,
266
-                    // or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267
-                    EE_PLUGIN_DIR_PATH,
268
-                ];
269
-                $template_folder_paths = array_merge($template_folder_paths, $core_paths);
270
-            }
271
-
272
-            // now filter that array
273
-            $template_folder_paths = (array) apply_filters(
274
-                'FHEE__EEH_Template__locate_template__template_folder_paths',
275
-                $template_folder_paths
276
-            );
277
-
278
-            // array to hold all possible template paths
279
-            $full_template_paths = [];
280
-            $file_name           = '';
281
-
282
-            // loop through $templates
283
-            foreach ($templates as $template) {
284
-                // normalize directory separators
285
-                $template                      = EEH_File::standardise_directory_separators($template);
286
-                $file_name                     = basename($template);
287
-                $template_path_minus_file_name = substr($template, 0, (strlen($file_name) * -1));
288
-                // while looping through all template folder paths
289
-                foreach ($template_folder_paths as $template_folder_path) {
290
-                    // normalize directory separators
291
-                    $template_folder_path = EEH_File::standardise_directory_separators($template_folder_path);
292
-                    // determine if any common base path exists between the two paths
293
-                    $common_base_path = EEH_Template::_find_common_base_path(
294
-                        [$template_folder_path, $template_path_minus_file_name]
295
-                    );
296
-                    if ($common_base_path !== '') {
297
-                        // both paths have a common base, so just tack the filename onto our search path
298
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
299
-                    } else {
300
-                        // no common base path, so let's just concatenate
301
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
302
-                    }
303
-                    // build up our template locations array by adding our resolved paths
304
-                    $full_template_paths[] = $resolved_path;
305
-                }
306
-                // if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307
-                array_unshift($full_template_paths, $template);
308
-                // path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
-                array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
310
-            }
311
-            // filter final array of full template paths
312
-            $full_template_paths = apply_filters(
313
-                'FHEE__EEH_Template__locate_template__full_template_paths',
314
-                $full_template_paths,
315
-                $file_name
316
-            );
317
-            // now loop through our final array of template location paths and check each location
318
-            foreach ((array) $full_template_paths as $full_template_path) {
319
-                if (is_readable($full_template_path)) {
320
-                    $template_path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $full_template_path);
321
-                    TemplateCache::set($cache_id, $template_path);
322
-                    break;
323
-                }
324
-            }
325
-        }
326
-
327
-        // Display a deprecated notice if the template file is located in the WordPress uploads directory
328
-        if (strpos($template_path, 'wp-content/uploads/espresso') !== false) {
329
-            EE_Error::doing_it_wrong(
330
-                __CLASS__,
331
-                esc_html__(
332
-                    'The use of the WordPress uploads directory as a location to override template files has been deprecated.',
333
-                    'event_espresso'
334
-                ),
335
-                '5.0.0'
336
-            );
337
-        }
338
-
339
-        // hook that can be used to display the full template path that will be used
340
-        do_action('AHEE__EEH_Template__locate_template__full_template_path', $template_path);
341
-
342
-        return $template_path;
343
-    }
344
-
345
-
346
-    /**
347
-     * _find_common_base_path
348
-     * given two paths, this determines if there is a common base path between the two
349
-     *
350
-     * @param array $paths
351
-     * @return string
352
-     */
353
-    protected static function _find_common_base_path($paths)
354
-    {
355
-        $last_offset      = 0;
356
-        $common_base_path = '';
357
-        while (($index = strpos($paths[0], '/', $last_offset)) !== false) {
358
-            $dir_length = $index - $last_offset + 1;
359
-            $directory  = substr($paths[0], $last_offset, $dir_length);
360
-            foreach ($paths as $path) {
361
-                if (substr($path, $last_offset, $dir_length) != $directory) {
362
-                    return $common_base_path;
363
-                }
364
-            }
365
-            $common_base_path .= $directory;
366
-            $last_offset      = $index + 1;
367
-        }
368
-        return substr($common_base_path, 0, -1);
369
-    }
370
-
371
-
372
-    /**
373
-     * load and display a template
374
-     *
375
-     * @param bool|string $template_path    server path to the file to be loaded, including file name and extension
376
-     * @param array       $template_args    an array of arguments to be extracted for use in the template
377
-     * @param boolean     $return_string    whether to send output immediately to screen, or capture and return as a
378
-     *                                      string
379
-     * @param bool        $throw_exceptions if set to true, will throw an exception if the template is either
380
-     *                                      not found or is not readable
381
-     * @return string
382
-     * @throws DomainException
383
-     */
384
-    public static function display_template(
385
-        $template_path = '',
386
-        $template_args = [],
387
-        $return_string = false,
388
-        $throw_exceptions = false
389
-    ) {
390
-        /**
391
-         * These two filters are intended for last minute changes to templates being loaded and/or template arg
392
-         * modifications.  NOTE... modifying these things can cause breakage as most templates running through
393
-         * the display_template method are templates we DON'T want modified (usually because of js
394
-         * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
395
-         * using this.
396
-         *
397
-         * @since 4.6.0
398
-         */
399
-        $template_path = (string) apply_filters('FHEE__EEH_Template__display_template__template_path', $template_path);
400
-        $template_args = (array) apply_filters('FHEE__EEH_Template__display_template__template_args', $template_args);
401
-
402
-        // you gimme nuttin - YOU GET NUTTIN !!
403
-        if (! $template_path || ! is_readable($template_path)) {
404
-            // ignore whether template is accessible ?
405
-            if ($throw_exceptions) {
406
-                throw new DomainException(
407
-                    esc_html__('Invalid, unreadable, or missing file.', 'event_espresso')
408
-                );
409
-            }
410
-            return '';
411
-        }
412
-
413
-        extract($template_args, EXTR_SKIP);
414
-        // because we might want to return a string, we are going to capture the output
415
-        ob_start();
416
-        include($template_path);
417
-        $template = ob_get_clean();
418
-
419
-        if ($return_string) {
420
-            return $template;
421
-        }
422
-        echo wp_kses($template, AllowedTags::getWithFullTags());
423
-        return '';
424
-    }
425
-
426
-
427
-    /**
428
-     * get_object_css_class - attempts to generate a css class based on the type of EE object passed
429
-     *
430
-     * @param EE_Base_Class $object the EE object the css class is being generated for
431
-     * @param string        $prefix added to the beginning of the generated class
432
-     * @param string        $suffix added to the end of the generated class
433
-     * @return string
434
-     * @throws EE_Error
435
-     * @throws ReflectionException
436
-     */
437
-    public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
438
-    {
439
-        // in the beginning...
440
-        $prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
441
-        // da muddle
442
-        $class = '';
443
-        // the end
444
-        $suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
445
-        // is the passed object an EE object ?
446
-        if ($object instanceof EE_Base_Class) {
447
-            // grab the exact type of object
448
-            $obj_class = get_class($object);
449
-            // depending on the type of object...
450
-            // no specifics just yet...
451
-            $class = strtolower(str_replace('_', '-', $obj_class));
452
-            $class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
453
-        }
454
-        return $prefix . $class . $suffix;
455
-    }
456
-
457
-
458
-    /**
459
-     * EEH_Template::format_currency
460
-     * This helper takes a raw float value and formats it according to the default config country currency settings, or
461
-     * the country currency settings from the supplied country ISO code
462
-     *
463
-     * @param float   $amount       raw money value
464
-     * @param boolean $return_raw   whether to return the formatted float value only with no currency sign or code
465
-     * @param boolean $display_code whether to display the country code (USD). Default = TRUE
466
-     * @param string  $CNT_ISO      2-letter ISO code for a country
467
-     * @param string  $cur_code_span_class
468
-     * @return string        the html output for the formatted money value
469
-     */
470
-    public static function format_currency(
471
-        $amount = null,
472
-        $return_raw = false,
473
-        $display_code = true,
474
-        $CNT_ISO = '',
475
-        $cur_code_span_class = 'currency-code'
476
-    ) {
477
-        // ensure amount was received
478
-        if ($amount === null) {
479
-            $msg = esc_html__('In order to format currency, an amount needs to be passed.', 'event_espresso');
480
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
-            return '';
482
-        }
483
-        // ensure amount is float
484
-        $amount  = (float) apply_filters('FHEE__EEH_Template__format_currency__raw_amount', (float) $amount);
485
-        $CNT_ISO = apply_filters('FHEE__EEH_Template__format_currency__CNT_ISO', $CNT_ISO, $amount);
486
-        // filter raw amount (allows 0.00 to be changed to "free" for example)
487
-        $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
488
-        // still a number, or was amount converted to a string like "free" ?
489
-        if (! is_float($amount_formatted)) {
490
-            return esc_html($amount_formatted);
491
-        }
492
-        try {
493
-            // was a country ISO code passed ? if so generate currency config object for that country
494
-            $mny = $CNT_ISO !== '' ? new EE_Currency_Config($CNT_ISO) : null;
495
-        } catch (Exception $e) {
496
-            // eat exception
497
-            $mny = null;
498
-        }
499
-        // verify results
500
-        if (! $mny instanceof EE_Currency_Config) {
501
-            // set default config country currency settings
502
-            $mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
503
-                ? EE_Registry::instance()->CFG->currency
504
-                : new EE_Currency_Config();
505
-        }
506
-        // format float
507
-        $amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
508
-        // add formatting ?
509
-        if (! $return_raw) {
510
-            // add currency sign
511
-            if ($mny->sign_b4) {
512
-                if ($amount >= 0) {
513
-                    $amount_formatted = $mny->sign . $amount_formatted;
514
-                } else {
515
-                    $amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
516
-                }
517
-            } else {
518
-                $amount_formatted = $amount_formatted . $mny->sign;
519
-            }
520
-
521
-            // filter to allow global setting of display_code
522
-            $display_code = (bool) apply_filters(
523
-                'FHEE__EEH_Template__format_currency__display_code',
524
-                $display_code
525
-            );
526
-
527
-            // add currency code ?
528
-            $amount_formatted = $display_code
529
-                ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
530
-                : $amount_formatted;
531
-        }
532
-        // filter results
533
-        $amount_formatted = apply_filters(
534
-            'FHEE__EEH_Template__format_currency__amount_formatted',
535
-            $amount_formatted,
536
-            $mny,
537
-            $return_raw
538
-        );
539
-        // clean up vars
540
-        unset($mny);
541
-        // return formatted currency amount
542
-        return $amount_formatted;
543
-    }
544
-
545
-
546
-    /**
547
-     * This function is used for outputting the localized label for a given status id in the schema requested (and
548
-     * possibly plural).  The intended use of this function is only for cases where wanting a label outside of a
549
-     * related status model or model object (i.e. in documentation etc.)
550
-     *
551
-     * @param string  $status_id  Status ID matching a registered status in the esp_status table.  If there is no
552
-     *                            match, then 'Unknown' will be returned.
553
-     * @param boolean $plural     Whether to return plural or not
554
-     * @param string  $schema     'UPPER', 'lower', or 'Sentence'
555
-     * @return string             The localized label for the status id.
556
-     * @throws EE_Error
557
-     */
558
-    public static function pretty_status($status_id, $plural = false, $schema = 'upper')
559
-    {
560
-        $status = EEM_Status::instance()->localized_status(
561
-            [$status_id => esc_html__('unknown', 'event_espresso')],
562
-            $plural,
563
-            $schema
564
-        );
565
-        return $status[ $status_id ];
566
-    }
567
-
568
-
569
-    /**
570
-     * This helper just returns a button or link for the given parameters
571
-     *
572
-     * @param string $url   the url for the link, note that `esc_url` will be called on it
573
-     * @param string $label What is the label you want displayed for the button
574
-     * @param string $class what class is used for the button (defaults to 'button--primary')
575
-     * @param string $icon
576
-     * @param string $title
577
-     * @return string the html output for the button
578
-     */
579
-    public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
580
-    {
581
-        $icon_html = '';
582
-        if (! empty($icon)) {
583
-            $dashicons = preg_split("(ee-icon |dashicons )", $icon);
584
-            $dashicons = array_filter($dashicons);
585
-            $count     = count($dashicons);
586
-            $icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
587
-            foreach ($dashicons as $dashicon) {
588
-                $type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
-                $icon_html .= '<span class="' . $type . $dashicon . '"></span>';
590
-            }
591
-            $icon_html .= $count > 1 ? '</span>' : '';
592
-        }
593
-        // sanitize & escape
594
-        $id    = sanitize_title_with_dashes($label);
595
-        $url   = esc_url_raw($url);
596
-        $class = esc_attr($class);
597
-        $title = esc_attr($title);
598
-        $class .= $title ? ' ee-aria-tooltip' : '';
599
-        $title = $title ? " aria-label='{$title}'" : '';
600
-        $label = esc_html($label);
601
-        return "<a id='{$id}' href='{$url}' class='{$class}'{$title}>{$icon_html}{$label}</a>";
602
-    }
603
-
604
-
605
-    /**
606
-     * This returns a generated link that will load the related help tab on admin pages.
607
-     *
608
-     * @param string      $help_tab_id the id for the connected help tab
609
-     * @param bool|string $page        The page identifier for the page the help tab is on
610
-     * @param bool|string $action      The action (route) for the admin page the help tab is on.
611
-     * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
612
-     * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
613
-     * @return string              generated link
614
-     */
615
-    public static function get_help_tab_link(
616
-        $help_tab_id,
617
-        $page = false,
618
-        $action = false,
619
-        $icon_style = false,
620
-        $help_text = false
621
-    ) {
622
-        /** @var RequestInterface $request */
623
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
624
-        $page    = $page ?: $request->getRequestParam('page', '', 'key');
625
-        $action  = $action ?: $request->getRequestParam('action', 'default', 'key');
626
-
627
-
628
-        $help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
629
-        $icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
630
-        $help_text    = ! $help_text ? '' : $help_text;
631
-        return '
55
+	private static array $_espresso_themes = [];
56
+
57
+
58
+	/**
59
+	 *    is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
60
+	 *
61
+	 * @return boolean
62
+	 */
63
+	public static function is_espresso_theme()
64
+	{
65
+		return wp_get_theme()->get('TextDomain') === 'event_espresso';
66
+	}
67
+
68
+
69
+	/**
70
+	 *    load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then
71
+	 *    load its functions.php file ( if not already loaded )
72
+	 *
73
+	 * @return void
74
+	 */
75
+	public static function load_espresso_theme_functions()
76
+	{
77
+		if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
+			if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
+				require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
80
+			}
81
+		}
82
+	}
83
+
84
+
85
+	/**
86
+	 *    get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
87
+	 *
88
+	 * @return array
89
+	 */
90
+	public static function get_espresso_themes(): array
91
+	{
92
+		if (empty(EEH_Template::$_espresso_themes)) {
93
+			$espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
94
+			if (empty($espresso_themes)) {
95
+				return [];
96
+			}
97
+			if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
+				unset($espresso_themes[ $key ]);
99
+			}
100
+			EEH_Template::$_espresso_themes = [];
101
+			foreach ($espresso_themes as $espresso_theme) {
102
+				EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
103
+			}
104
+		}
105
+		return EEH_Template::$_espresso_themes;
106
+	}
107
+
108
+
109
+	/**
110
+	 * EEH_Template::get_template_part
111
+	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead,
112
+	 * and doesn't add base versions of files so not a very useful function at all except that it adds familiarity PLUS
113
+	 * filtering based off of the entire template part name
114
+	 *
115
+	 * @param string $slug The slug name for the generic template.
116
+	 * @param string $name The name of the specialised template.
117
+	 * @param array  $template_args
118
+	 * @param bool   $return_string
119
+	 * @return string        the html output for the formatted money value
120
+	 */
121
+	public static function get_template_part(
122
+		$slug = '',
123
+		$name = '',
124
+		$template_args = [],
125
+		$return_string = false
126
+	) {
127
+		do_action("get_template_part_$slug-$name", $slug, $name);
128
+		$template = $slug;
129
+		$name      = (string) $name;
130
+		if ($name != '') {
131
+			$template .= "-$name";
132
+		}
133
+		$template .= ".php";
134
+		// allow template parts to be turned off via something like:
135
+		// add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
136
+		if (apply_filters("FHEE__EEH_Template__get_template_part__display__{$slug}_$name", true)) {
137
+			return EEH_Template::locate_template($template, $template_args, true, $return_string);
138
+		}
139
+		return '';
140
+	}
141
+
142
+
143
+	/**
144
+	 *    locate_template
145
+	 *    locate a template file by looking in the following places, in the following order:
146
+	 *        <server path up to>/wp-content/themes/<current active WordPress theme>/
147
+	 *        <assumed full absolute server path>
148
+	 *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
149
+	 *        <server path up to>/wp-content/uploads/espresso/templates/
150
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
151
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
152
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/
153
+	 *    as soon as the template is found in one of these locations, it will be returned or loaded
154
+	 *        Example:
155
+	 *          You are using the WordPress Twenty Sixteen theme,
156
+	 *        and you want to customize the "some-event.template.php" template,
157
+	 *          which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
158
+	 *          Assuming WP is installed on your server in the "/home/public_html/" folder,
159
+	 *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
160
+	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
161
+	 *        /relative/path/to/some-event.template.php
162
+	 *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
163
+	 *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
164
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
165
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
167
+	 *          Had you passed an absolute path to your template that was in some other location,
168
+	 *        ie: "/absolute/path/to/some-event.template.php"
169
+	 *          then the search would have been :
170
+	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
171
+	 *        /absolute/path/to/some-event.template.php
172
+	 *          and stopped there upon finding it in the second location
173
+	 *
174
+	 * @param array|string $templates       array of template file names including extension (or just a single string)
175
+	 * @param array        $template_args   an array of arguments to be extracted for use in the template
176
+	 * @param boolean      $load            whether to pass the located template path on to the
177
+	 *                                      EEH_Template::display_template() method or simply return it
178
+	 * @param boolean      $return_string   whether to send output immediately to screen, or capture and return as a
179
+	 *                                      string
180
+	 * @param boolean      $check_if_custom If TRUE, this flags this method to return boolean for whether this will
181
+	 *                                      generate a custom template or not. Used in places where you don't actually
182
+	 *                                      load the template, you just want to know if there's a custom version of it.
183
+	 * @return string|true
184
+	 * @throws DomainException
185
+	 * @throws InvalidArgumentException
186
+	 * @throws InvalidDataTypeException
187
+	 * @throws InvalidInterfaceException
188
+	 */
189
+	public static function locate_template(
190
+		$templates = [],
191
+		array $template_args = [],
192
+		bool $load = true,
193
+		bool $return_string = true,
194
+		bool $check_if_custom = false
195
+	) {
196
+		$cache_id      = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
197
+		$template_path = TemplateCache::get($cache_id);
198
+		$template_path = $template_path ?: self::resolveTemplatePath($cache_id, (array) $templates, $check_if_custom);
199
+
200
+		if ($check_if_custom && ! empty($template_path)) {
201
+			return true;
202
+		}
203
+
204
+		// if we got it and you want to see it...
205
+		if ($template_path && $load && ! $check_if_custom) {
206
+			if ($return_string) {
207
+				return EEH_Template::display_template($template_path, $template_args, true);
208
+			}
209
+			EEH_Template::display_template($template_path, $template_args);
210
+		}
211
+		return $check_if_custom && ! empty($template_path) ? true : $template_path;
212
+	}
213
+
214
+
215
+	/**
216
+	 * Resolves the path of a template by checking various possible locations.
217
+	 *
218
+	 * This method checks for the existence of a template in several locations,
219
+	 * including the current theme folder, the uploads directory, and the plugin's own template directory.
220
+	 * It uses the provided cache ID to store and retrieve the resolved path from a cache for performance.
221
+	 * If the template is not found in any of the checked locations, an empty string is returned.
222
+	 *
223
+	 * @param string $cache_id        The ID used for caching the resolved path.
224
+	 * @param array  $templates       An array of template file names to search for.
225
+	 * @param bool $check_if_custom   If true, the method will only check if a custom template exists
226
+	 *                                and won't include core plugin folders.
227
+	 * @return string The resolved template path, or an empty string if the template was not found.
228
+	 * @since 5.0.21.p
229
+	 */
230
+	private static function resolveTemplatePath(string $cache_id, array $templates, bool $check_if_custom): string
231
+	{
232
+		// first use WP locate_template to check for template in the current theme folder
233
+		$template_path = $templates ? locate_template($templates) : '';
234
+		// not in the theme
235
+		if (empty($template_path)) {
236
+			// not even a template to look for ?
237
+			if (empty($templates)) {
238
+				$loader = LoaderFactory::getLoader();
239
+				/** @var RequestInterface $request */
240
+				$request = $loader->getShared(RequestInterface::class);
241
+				// get post_type
242
+				$post_type = $request->getRequestParam('post_type');
243
+				/** @var CustomPostTypeDefinitions $custom_post_types */
244
+				$custom_post_types = $loader->getShared(CustomPostTypeDefinitions::class);
245
+				// get array of EE Custom Post Types
246
+				$EE_CPTs = $custom_post_types->getDefinitions();
247
+				// build template name based on request
248
+				if (isset($EE_CPTs[ $post_type ])) {
249
+					$archive_or_single = is_archive() ? 'archive' : '';
250
+					$archive_or_single = is_single() ? 'single' : $archive_or_single;
251
+					$templates[]       = $archive_or_single . '-' . $post_type . '.php';
252
+				}
253
+			}
254
+			// currently active EE template theme
255
+			$current_theme = EE_Config::get_current_theme();
256
+			// array of paths to folders that may contain templates
257
+			$template_folder_paths = [];
258
+
259
+			// add core plugin folders for checking only if we're not $check_if_custom
260
+			if (! $check_if_custom) {
261
+				$core_paths            = [
262
+					// in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
+					EE_PUBLIC . $current_theme,
264
+					// in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
+					EE_TEMPLATES . $current_theme,
266
+					// or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267
+					EE_PLUGIN_DIR_PATH,
268
+				];
269
+				$template_folder_paths = array_merge($template_folder_paths, $core_paths);
270
+			}
271
+
272
+			// now filter that array
273
+			$template_folder_paths = (array) apply_filters(
274
+				'FHEE__EEH_Template__locate_template__template_folder_paths',
275
+				$template_folder_paths
276
+			);
277
+
278
+			// array to hold all possible template paths
279
+			$full_template_paths = [];
280
+			$file_name           = '';
281
+
282
+			// loop through $templates
283
+			foreach ($templates as $template) {
284
+				// normalize directory separators
285
+				$template                      = EEH_File::standardise_directory_separators($template);
286
+				$file_name                     = basename($template);
287
+				$template_path_minus_file_name = substr($template, 0, (strlen($file_name) * -1));
288
+				// while looping through all template folder paths
289
+				foreach ($template_folder_paths as $template_folder_path) {
290
+					// normalize directory separators
291
+					$template_folder_path = EEH_File::standardise_directory_separators($template_folder_path);
292
+					// determine if any common base path exists between the two paths
293
+					$common_base_path = EEH_Template::_find_common_base_path(
294
+						[$template_folder_path, $template_path_minus_file_name]
295
+					);
296
+					if ($common_base_path !== '') {
297
+						// both paths have a common base, so just tack the filename onto our search path
298
+						$resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
299
+					} else {
300
+						// no common base path, so let's just concatenate
301
+						$resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
302
+					}
303
+					// build up our template locations array by adding our resolved paths
304
+					$full_template_paths[] = $resolved_path;
305
+				}
306
+				// if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307
+				array_unshift($full_template_paths, $template);
308
+				// path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
+				array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
310
+			}
311
+			// filter final array of full template paths
312
+			$full_template_paths = apply_filters(
313
+				'FHEE__EEH_Template__locate_template__full_template_paths',
314
+				$full_template_paths,
315
+				$file_name
316
+			);
317
+			// now loop through our final array of template location paths and check each location
318
+			foreach ((array) $full_template_paths as $full_template_path) {
319
+				if (is_readable($full_template_path)) {
320
+					$template_path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $full_template_path);
321
+					TemplateCache::set($cache_id, $template_path);
322
+					break;
323
+				}
324
+			}
325
+		}
326
+
327
+		// Display a deprecated notice if the template file is located in the WordPress uploads directory
328
+		if (strpos($template_path, 'wp-content/uploads/espresso') !== false) {
329
+			EE_Error::doing_it_wrong(
330
+				__CLASS__,
331
+				esc_html__(
332
+					'The use of the WordPress uploads directory as a location to override template files has been deprecated.',
333
+					'event_espresso'
334
+				),
335
+				'5.0.0'
336
+			);
337
+		}
338
+
339
+		// hook that can be used to display the full template path that will be used
340
+		do_action('AHEE__EEH_Template__locate_template__full_template_path', $template_path);
341
+
342
+		return $template_path;
343
+	}
344
+
345
+
346
+	/**
347
+	 * _find_common_base_path
348
+	 * given two paths, this determines if there is a common base path between the two
349
+	 *
350
+	 * @param array $paths
351
+	 * @return string
352
+	 */
353
+	protected static function _find_common_base_path($paths)
354
+	{
355
+		$last_offset      = 0;
356
+		$common_base_path = '';
357
+		while (($index = strpos($paths[0], '/', $last_offset)) !== false) {
358
+			$dir_length = $index - $last_offset + 1;
359
+			$directory  = substr($paths[0], $last_offset, $dir_length);
360
+			foreach ($paths as $path) {
361
+				if (substr($path, $last_offset, $dir_length) != $directory) {
362
+					return $common_base_path;
363
+				}
364
+			}
365
+			$common_base_path .= $directory;
366
+			$last_offset      = $index + 1;
367
+		}
368
+		return substr($common_base_path, 0, -1);
369
+	}
370
+
371
+
372
+	/**
373
+	 * load and display a template
374
+	 *
375
+	 * @param bool|string $template_path    server path to the file to be loaded, including file name and extension
376
+	 * @param array       $template_args    an array of arguments to be extracted for use in the template
377
+	 * @param boolean     $return_string    whether to send output immediately to screen, or capture and return as a
378
+	 *                                      string
379
+	 * @param bool        $throw_exceptions if set to true, will throw an exception if the template is either
380
+	 *                                      not found or is not readable
381
+	 * @return string
382
+	 * @throws DomainException
383
+	 */
384
+	public static function display_template(
385
+		$template_path = '',
386
+		$template_args = [],
387
+		$return_string = false,
388
+		$throw_exceptions = false
389
+	) {
390
+		/**
391
+		 * These two filters are intended for last minute changes to templates being loaded and/or template arg
392
+		 * modifications.  NOTE... modifying these things can cause breakage as most templates running through
393
+		 * the display_template method are templates we DON'T want modified (usually because of js
394
+		 * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
395
+		 * using this.
396
+		 *
397
+		 * @since 4.6.0
398
+		 */
399
+		$template_path = (string) apply_filters('FHEE__EEH_Template__display_template__template_path', $template_path);
400
+		$template_args = (array) apply_filters('FHEE__EEH_Template__display_template__template_args', $template_args);
401
+
402
+		// you gimme nuttin - YOU GET NUTTIN !!
403
+		if (! $template_path || ! is_readable($template_path)) {
404
+			// ignore whether template is accessible ?
405
+			if ($throw_exceptions) {
406
+				throw new DomainException(
407
+					esc_html__('Invalid, unreadable, or missing file.', 'event_espresso')
408
+				);
409
+			}
410
+			return '';
411
+		}
412
+
413
+		extract($template_args, EXTR_SKIP);
414
+		// because we might want to return a string, we are going to capture the output
415
+		ob_start();
416
+		include($template_path);
417
+		$template = ob_get_clean();
418
+
419
+		if ($return_string) {
420
+			return $template;
421
+		}
422
+		echo wp_kses($template, AllowedTags::getWithFullTags());
423
+		return '';
424
+	}
425
+
426
+
427
+	/**
428
+	 * get_object_css_class - attempts to generate a css class based on the type of EE object passed
429
+	 *
430
+	 * @param EE_Base_Class $object the EE object the css class is being generated for
431
+	 * @param string        $prefix added to the beginning of the generated class
432
+	 * @param string        $suffix added to the end of the generated class
433
+	 * @return string
434
+	 * @throws EE_Error
435
+	 * @throws ReflectionException
436
+	 */
437
+	public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
438
+	{
439
+		// in the beginning...
440
+		$prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
441
+		// da muddle
442
+		$class = '';
443
+		// the end
444
+		$suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
445
+		// is the passed object an EE object ?
446
+		if ($object instanceof EE_Base_Class) {
447
+			// grab the exact type of object
448
+			$obj_class = get_class($object);
449
+			// depending on the type of object...
450
+			// no specifics just yet...
451
+			$class = strtolower(str_replace('_', '-', $obj_class));
452
+			$class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
453
+		}
454
+		return $prefix . $class . $suffix;
455
+	}
456
+
457
+
458
+	/**
459
+	 * EEH_Template::format_currency
460
+	 * This helper takes a raw float value and formats it according to the default config country currency settings, or
461
+	 * the country currency settings from the supplied country ISO code
462
+	 *
463
+	 * @param float   $amount       raw money value
464
+	 * @param boolean $return_raw   whether to return the formatted float value only with no currency sign or code
465
+	 * @param boolean $display_code whether to display the country code (USD). Default = TRUE
466
+	 * @param string  $CNT_ISO      2-letter ISO code for a country
467
+	 * @param string  $cur_code_span_class
468
+	 * @return string        the html output for the formatted money value
469
+	 */
470
+	public static function format_currency(
471
+		$amount = null,
472
+		$return_raw = false,
473
+		$display_code = true,
474
+		$CNT_ISO = '',
475
+		$cur_code_span_class = 'currency-code'
476
+	) {
477
+		// ensure amount was received
478
+		if ($amount === null) {
479
+			$msg = esc_html__('In order to format currency, an amount needs to be passed.', 'event_espresso');
480
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
+			return '';
482
+		}
483
+		// ensure amount is float
484
+		$amount  = (float) apply_filters('FHEE__EEH_Template__format_currency__raw_amount', (float) $amount);
485
+		$CNT_ISO = apply_filters('FHEE__EEH_Template__format_currency__CNT_ISO', $CNT_ISO, $amount);
486
+		// filter raw amount (allows 0.00 to be changed to "free" for example)
487
+		$amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
488
+		// still a number, or was amount converted to a string like "free" ?
489
+		if (! is_float($amount_formatted)) {
490
+			return esc_html($amount_formatted);
491
+		}
492
+		try {
493
+			// was a country ISO code passed ? if so generate currency config object for that country
494
+			$mny = $CNT_ISO !== '' ? new EE_Currency_Config($CNT_ISO) : null;
495
+		} catch (Exception $e) {
496
+			// eat exception
497
+			$mny = null;
498
+		}
499
+		// verify results
500
+		if (! $mny instanceof EE_Currency_Config) {
501
+			// set default config country currency settings
502
+			$mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
503
+				? EE_Registry::instance()->CFG->currency
504
+				: new EE_Currency_Config();
505
+		}
506
+		// format float
507
+		$amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
508
+		// add formatting ?
509
+		if (! $return_raw) {
510
+			// add currency sign
511
+			if ($mny->sign_b4) {
512
+				if ($amount >= 0) {
513
+					$amount_formatted = $mny->sign . $amount_formatted;
514
+				} else {
515
+					$amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
516
+				}
517
+			} else {
518
+				$amount_formatted = $amount_formatted . $mny->sign;
519
+			}
520
+
521
+			// filter to allow global setting of display_code
522
+			$display_code = (bool) apply_filters(
523
+				'FHEE__EEH_Template__format_currency__display_code',
524
+				$display_code
525
+			);
526
+
527
+			// add currency code ?
528
+			$amount_formatted = $display_code
529
+				? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
530
+				: $amount_formatted;
531
+		}
532
+		// filter results
533
+		$amount_formatted = apply_filters(
534
+			'FHEE__EEH_Template__format_currency__amount_formatted',
535
+			$amount_formatted,
536
+			$mny,
537
+			$return_raw
538
+		);
539
+		// clean up vars
540
+		unset($mny);
541
+		// return formatted currency amount
542
+		return $amount_formatted;
543
+	}
544
+
545
+
546
+	/**
547
+	 * This function is used for outputting the localized label for a given status id in the schema requested (and
548
+	 * possibly plural).  The intended use of this function is only for cases where wanting a label outside of a
549
+	 * related status model or model object (i.e. in documentation etc.)
550
+	 *
551
+	 * @param string  $status_id  Status ID matching a registered status in the esp_status table.  If there is no
552
+	 *                            match, then 'Unknown' will be returned.
553
+	 * @param boolean $plural     Whether to return plural or not
554
+	 * @param string  $schema     'UPPER', 'lower', or 'Sentence'
555
+	 * @return string             The localized label for the status id.
556
+	 * @throws EE_Error
557
+	 */
558
+	public static function pretty_status($status_id, $plural = false, $schema = 'upper')
559
+	{
560
+		$status = EEM_Status::instance()->localized_status(
561
+			[$status_id => esc_html__('unknown', 'event_espresso')],
562
+			$plural,
563
+			$schema
564
+		);
565
+		return $status[ $status_id ];
566
+	}
567
+
568
+
569
+	/**
570
+	 * This helper just returns a button or link for the given parameters
571
+	 *
572
+	 * @param string $url   the url for the link, note that `esc_url` will be called on it
573
+	 * @param string $label What is the label you want displayed for the button
574
+	 * @param string $class what class is used for the button (defaults to 'button--primary')
575
+	 * @param string $icon
576
+	 * @param string $title
577
+	 * @return string the html output for the button
578
+	 */
579
+	public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
580
+	{
581
+		$icon_html = '';
582
+		if (! empty($icon)) {
583
+			$dashicons = preg_split("(ee-icon |dashicons )", $icon);
584
+			$dashicons = array_filter($dashicons);
585
+			$count     = count($dashicons);
586
+			$icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
587
+			foreach ($dashicons as $dashicon) {
588
+				$type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
+				$icon_html .= '<span class="' . $type . $dashicon . '"></span>';
590
+			}
591
+			$icon_html .= $count > 1 ? '</span>' : '';
592
+		}
593
+		// sanitize & escape
594
+		$id    = sanitize_title_with_dashes($label);
595
+		$url   = esc_url_raw($url);
596
+		$class = esc_attr($class);
597
+		$title = esc_attr($title);
598
+		$class .= $title ? ' ee-aria-tooltip' : '';
599
+		$title = $title ? " aria-label='{$title}'" : '';
600
+		$label = esc_html($label);
601
+		return "<a id='{$id}' href='{$url}' class='{$class}'{$title}>{$icon_html}{$label}</a>";
602
+	}
603
+
604
+
605
+	/**
606
+	 * This returns a generated link that will load the related help tab on admin pages.
607
+	 *
608
+	 * @param string      $help_tab_id the id for the connected help tab
609
+	 * @param bool|string $page        The page identifier for the page the help tab is on
610
+	 * @param bool|string $action      The action (route) for the admin page the help tab is on.
611
+	 * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
612
+	 * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
613
+	 * @return string              generated link
614
+	 */
615
+	public static function get_help_tab_link(
616
+		$help_tab_id,
617
+		$page = false,
618
+		$action = false,
619
+		$icon_style = false,
620
+		$help_text = false
621
+	) {
622
+		/** @var RequestInterface $request */
623
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
624
+		$page    = $page ?: $request->getRequestParam('page', '', 'key');
625
+		$action  = $action ?: $request->getRequestParam('action', 'default', 'key');
626
+
627
+
628
+		$help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
629
+		$icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
630
+		$help_text    = ! $help_text ? '' : $help_text;
631
+		return '
632 632
             <a id="' . esc_attr($help_tab_lnk) . '"
633 633
                class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon) . '"
634 634
                aria-label="' . esc_attr__(
635
-                'Click to open the \'Help\' tab for more information about this feature.',
636
-                'event_espresso'
637
-            ) . '"
635
+				'Click to open the \'Help\' tab for more information about this feature.',
636
+				'event_espresso'
637
+			) . '"
638 638
             >
639 639
                 ' . wp_kses($help_text, AllowedTags::getAllowedTags()) . '
640 640
             </a>';
641
-    }
642
-
643
-
644
-    /**
645
-     * This is a helper method to generate a status legend for a given status array.
646
-     * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods
647
-     * status_array.
648
-     *
649
-     * @param array  $status_array   array of statuses that will make up the legend. In format:
650
-     *                               array(
651
-     *                               'status_item' => 'status_name'
652
-     *                               )
653
-     * @param string $active_status  This is used to indicate what the active status is IF that is to be highlighted in
654
-     *                               the legend.
655
-     * @return string               html structure for status.
656
-     * @throws EE_Error
657
-     */
658
-    public static function status_legend($status_array, $active_status = '')
659
-    {
660
-        if (! is_array($status_array)) {
661
-            throw new EE_Error(
662
-                esc_html__(
663
-                    'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
664
-                    'event_espresso'
665
-                )
666
-            );
667
-        }
668
-
669
-        $content = '
641
+	}
642
+
643
+
644
+	/**
645
+	 * This is a helper method to generate a status legend for a given status array.
646
+	 * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods
647
+	 * status_array.
648
+	 *
649
+	 * @param array  $status_array   array of statuses that will make up the legend. In format:
650
+	 *                               array(
651
+	 *                               'status_item' => 'status_name'
652
+	 *                               )
653
+	 * @param string $active_status  This is used to indicate what the active status is IF that is to be highlighted in
654
+	 *                               the legend.
655
+	 * @return string               html structure for status.
656
+	 * @throws EE_Error
657
+	 */
658
+	public static function status_legend($status_array, $active_status = '')
659
+	{
660
+		if (! is_array($status_array)) {
661
+			throw new EE_Error(
662
+				esc_html__(
663
+					'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
664
+					'event_espresso'
665
+				)
666
+			);
667
+		}
668
+
669
+		$content = '
670 670
             <div class="ee-list-table-legend-container">
671 671
                 <h4 class="status-legend-title">
672 672
                     ' . esc_html__('Status Legend', 'event_espresso') . '
673 673
                 </h4>
674 674
                 <dl class="ee-list-table-legend">';
675 675
 
676
-        foreach ($status_array as $item => $status) {
677
-            $active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
678
-            $content      .= '
676
+		foreach ($status_array as $item => $status) {
677
+			$active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
678
+			$content      .= '
679 679
                     <dt id="' . esc_attr('ee-legend-item-tooltip-' . $item) . '" ' . $active_class . '>
680 680
                         <span class="' . esc_attr('ee-status-legend ee-status-bg--' . $status) . '"></span>
681 681
                         <span class="ee-legend-description">
682 682
                             ' . EEH_Template::pretty_status($status, false, 'sentence') . '
683 683
                         </span>
684 684
                     </dt>';
685
-        }
685
+		}
686 686
 
687
-        $content .= '
687
+		$content .= '
688 688
                 </dl>
689 689
             </div>
690 690
 ';
691
-        return $content;
692
-    }
693
-
694
-
695
-    /**
696
-     * Gets HTML for laying out a deeply-nested array (and objects) in a format
697
-     * that's nice for presenting in the wp admin
698
-     *
699
-     * @param mixed $data
700
-     * @return string
701
-     */
702
-    public static function layout_array_as_table($data)
703
-    {
704
-        if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
705
-            $data = (array) $data;
706
-        }
707
-        ob_start();
708
-        if (is_array($data)) {
709
-            if (EEH_Array::is_associative_array($data)) { ?>
691
+		return $content;
692
+	}
693
+
694
+
695
+	/**
696
+	 * Gets HTML for laying out a deeply-nested array (and objects) in a format
697
+	 * that's nice for presenting in the wp admin
698
+	 *
699
+	 * @param mixed $data
700
+	 * @return string
701
+	 */
702
+	public static function layout_array_as_table($data)
703
+	{
704
+		if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
705
+			$data = (array) $data;
706
+		}
707
+		ob_start();
708
+		if (is_array($data)) {
709
+			if (EEH_Array::is_associative_array($data)) { ?>
710 710
                 <table class="widefat">
711 711
                     <tbody>
712 712
                         <?php foreach ($data as $data_key => $data_values) { ?>
@@ -724,304 +724,304 @@  discard block
 block discarded – undo
724 724
             <?php } else { ?>
725 725
                 <ul>
726 726
                     <?php
727
-                    foreach ($data as $datum) {
728
-                        echo "<li>";
729
-                        echo self::layout_array_as_table($datum);
730
-                        echo "</li>";
731
-                    } ?>
727
+					foreach ($data as $datum) {
728
+						echo "<li>";
729
+						echo self::layout_array_as_table($datum);
730
+						echo "</li>";
731
+					} ?>
732 732
                 </ul>
733 733
             <?php }
734
-        } else {
735
-            // simple value
736
-            echo esc_html($data);
737
-        }
738
-        return ob_get_clean();
739
-    }
740
-
741
-
742
-    /**
743
-     * wrapper for self::get_paging_html() that simply echos the generated paging html
744
-     *
745
-     * @param        $total_items
746
-     * @param        $current
747
-     * @param        $per_page
748
-     * @param        $url
749
-     * @param bool   $show_num_field
750
-     * @param string $paged_arg_name
751
-     * @param array  $items_label
752
-     * @see   self:get_paging_html() for argument docs.
753
-     * @since 4.4.0
754
-     */
755
-    public static function paging_html(
756
-        $total_items,
757
-        $current,
758
-        $per_page,
759
-        $url,
760
-        $show_num_field = true,
761
-        $paged_arg_name = 'paged',
762
-        $items_label = []
763
-    ) {
764
-        echo self::get_paging_html(
765
-            $total_items,
766
-            $current,
767
-            $per_page,
768
-            $url,
769
-            $show_num_field,
770
-            $paged_arg_name,
771
-            $items_label
772
-        );
773
-    }
774
-
775
-
776
-    /**
777
-     * A method for generating paging similar to WP_List_Table
778
-     *
779
-     * @param int    $total_items       How many total items there are to page.
780
-     * @param int    $current           What the current page is.
781
-     * @param int    $per_page          How many items per page.
782
-     * @param string $url               What the base url for page links is.
783
-     * @param bool   $show_num_field    Whether to show the input for changing page number.
784
-     * @param string $paged_arg_name    The name of the key for the paged query argument.
785
-     * @param array  $items_label       An array of singular/plural values for the items label:
786
-     *                                  array(
787
-     *                                  'single' => 'item',
788
-     *                                  'plural' => 'items'
789
-     *                                  )
790
-     * @return  string
791
-     * @since    4.4.0
792
-     * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
793
-     */
794
-    public static function get_paging_html(
795
-        int $total_items,
796
-        int $current,
797
-        int $per_page,
798
-        string $url,
799
-        bool $show_num_field = true,
800
-        string $paged_arg_name = 'paged',
801
-        array $items_label = [],
802
-        string $button_size = 'small'
803
-    ): string {
804
-        $page_links     = [];
805
-        $paged_arg_name = empty($paged_arg_name) ? 'paged' : sanitize_key($paged_arg_name);
806
-
807
-        // filter items_label
808
-        $items_label = apply_filters(
809
-            'FHEE__EEH_Template__get_paging_html__items_label',
810
-            $items_label
811
-        );
812
-
813
-        if (
814
-            empty($items_label)
815
-            || ! is_array($items_label)
816
-            || ! isset($items_label['single'])
817
-            || ! isset($items_label['plural'])
818
-        ) {
819
-            $items_label = [
820
-                'single' => esc_html__('1 item', 'event_espresso'),
821
-                'plural' => esc_html__('%s items', 'event_espresso'),
822
-            ];
823
-        } else {
824
-            $items_label = [
825
-                'single' => '1 ' . esc_html($items_label['single']),
826
-                'plural' => '%s ' . esc_html($items_label['plural']),
827
-            ];
828
-        }
829
-
830
-        $total_pages = (int) ceil($total_items / $per_page);
831
-
832
-        if ($total_pages <= 1) {
833
-            return '';
834
-        }
835
-
836
-        $item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
837
-
838
-        $output = '<span class="displaying-num">' . $item_label . '</span>';
839
-
840
-        $disable_first = $current === 1 ? 'disabled' : '';
841
-        $disable_last  = $current === $total_pages ? 'disabled' : '';
842
-
843
-        $button_size    = in_array($button_size, ['tiny', 'small', 'default', 'big']) ? $button_size : 'small';
844
-        $button_classes = "button button--secondary button--icon-only button--$button_size";
845
-
846
-        $page_links[] = sprintf(
847
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
848
-            esc_attr("first-page $button_classes $disable_first"),
849
-            esc_attr__('Go to the first page', 'event_espresso'),
850
-            esc_url_raw(remove_query_arg($paged_arg_name, $url)),
851
-            '&laquo;'
852
-        );
853
-
854
-        $page_links[] = sprintf(
855
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
856
-            esc_attr("prev-page $button_classes $disable_first"),
857
-            esc_attr__('Go to the previous page', 'event_espresso'),
858
-            esc_url_raw(add_query_arg($paged_arg_name, max(1, $current - 1), $url)),
859
-            '&lsaquo;'
860
-        );
861
-
862
-        $html_current_page = $show_num_field
863
-            ? sprintf(
864
-                "<input class='current-page ee-input-size--small' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
865
-                esc_attr__('Current page', 'event_espresso'),
866
-                esc_attr($current),
867
-                strlen($total_pages)
868
-            )
869
-            : $current;
870
-
871
-        $html_total_pages = sprintf(
872
-            '<span class="total-pages">%s</span>',
873
-            number_format_i18n($total_pages)
874
-        );
875
-        $page_links[]     = sprintf(
876
-            _x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
877
-            "{$html_current_page}<span class='paging-input-of'>",
878
-            "</span>{$html_total_pages}",
879
-            '<span class="paging-input">',
880
-            '</span>'
881
-        );
882
-
883
-        $page_links[] = sprintf(
884
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
885
-            esc_attr("next-page $button_classes $disable_last"),
886
-            esc_attr__('Go to the next page', 'event_espresso'),
887
-            esc_url_raw(add_query_arg($paged_arg_name, min($total_pages, $current + 1), $url)),
888
-            '&rsaquo;'
889
-        );
890
-
891
-        $page_links[] = sprintf(
892
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
893
-            esc_attr("last-page $button_classes $disable_last"),
894
-            esc_attr__('Go to the last page', 'event_espresso'),
895
-            esc_url_raw(add_query_arg($paged_arg_name, $total_pages, $url)),
896
-            '&raquo;'
897
-        );
898
-
899
-        $output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
900
-
901
-        $page_class = ' no-pages';
902
-        if ($total_pages) {
903
-            $page_class = $total_pages < 2 ? ' one-page' : '';
904
-        }
905
-
906
-        return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
907
-    }
908
-
909
-
910
-    /**
911
-     * @param string $wrap_class
912
-     * @param string $wrap_id
913
-     * @param array  $query_args
914
-     * @return string
915
-     */
916
-    public static function powered_by_event_espresso(
917
-        string $wrap_class = '',
918
-        string $wrap_id = '',
919
-        array $query_args = []
920
-    ): string {
921
-        $request = LoaderFactory::getShared(RequestInterface::class);
922
-        if (
923
-            $request->isActivation()
924
-            || strpos($request->requestUri(true), 'wp-admin/update.php') !== false
925
-        ){
926
-            return '';
927
-        }
928
-        $cache_id = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
929
-        $cache    = TemplateCache::get($cache_id);
930
-        if ($cache) {
931
-            return $cache;
932
-        }
933
-
934
-        $admin = is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX);
935
-        if (
936
-            ! $admin
937
-            && ! apply_filters(
938
-                'FHEE__EEH_Template__powered_by_event_espresso__show_reg_footer',
939
-                EE_Registry::instance()->CFG->admin->show_reg_footer
940
-            )
941
-        ) {
942
-            return '';
943
-        }
944
-        $tag        = $admin ? 'span' : 'div';
945
-        $attributes = ! empty($wrap_id) ? " id=\"{$wrap_id}\"" : '';
946
-        $wrap_class = $admin ? "{$wrap_class} float-left" : $wrap_class;
947
-        $attributes .= ! empty($wrap_class)
948
-            ? " class=\"{$wrap_class} powered-by-event-espresso-credit\""
949
-            : ' class="powered-by-event-espresso-credit"';
950
-        $query_args = array_merge(
951
-            [
952
-                'ap_id'        => EE_Registry::instance()->CFG->admin->affiliate_id(),
953
-                'utm_source'   => 'powered_by_event_espresso',
954
-                'utm_medium'   => 'link',
955
-                'utm_campaign' => 'powered_by',
956
-            ],
957
-            $query_args
958
-        );
959
-        $powered_by = apply_filters(
960
-            'FHEE__EEH_Template__powered_by_event_espresso_text',
961
-            $admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
962
-        );
963
-        $url        = add_query_arg($query_args, 'https://eventespresso.com/');
964
-        $url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
965
-        $template   = (string) apply_filters(
966
-            'FHEE__EEH_Template__powered_by_event_espresso__html',
967
-            sprintf(
968
-                esc_html_x(
969
-                    '%3$s%1$sOnline event registration and ticketing powered by %2$s%3$s',
970
-                    'Online event registration and ticketing powered by [link to eventespresso.com]',
971
-                    'event_espresso'
972
-                ),
973
-                "<$tag$attributes>",
974
-                "<a href=\"$url\" target=\"_blank\" rel=\"nofollow\">$powered_by</a></$tag>",
975
-                $admin ? '' : '<br />'
976
-            ),
977
-            $wrap_class,
978
-            $wrap_id
979
-        );
980
-        TemplateCache::set($cache_id, $template);
981
-        return $template;
982
-    }
983
-
984
-
985
-    /**
986
-     * @param string $image_name
987
-     * @return string|null
988
-     * @since   4.10.14.p
989
-     */
990
-    public static function getScreenshotUrl($image_name)
991
-    {
992
-        return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
993
-    }
734
+		} else {
735
+			// simple value
736
+			echo esc_html($data);
737
+		}
738
+		return ob_get_clean();
739
+	}
740
+
741
+
742
+	/**
743
+	 * wrapper for self::get_paging_html() that simply echos the generated paging html
744
+	 *
745
+	 * @param        $total_items
746
+	 * @param        $current
747
+	 * @param        $per_page
748
+	 * @param        $url
749
+	 * @param bool   $show_num_field
750
+	 * @param string $paged_arg_name
751
+	 * @param array  $items_label
752
+	 * @see   self:get_paging_html() for argument docs.
753
+	 * @since 4.4.0
754
+	 */
755
+	public static function paging_html(
756
+		$total_items,
757
+		$current,
758
+		$per_page,
759
+		$url,
760
+		$show_num_field = true,
761
+		$paged_arg_name = 'paged',
762
+		$items_label = []
763
+	) {
764
+		echo self::get_paging_html(
765
+			$total_items,
766
+			$current,
767
+			$per_page,
768
+			$url,
769
+			$show_num_field,
770
+			$paged_arg_name,
771
+			$items_label
772
+		);
773
+	}
774
+
775
+
776
+	/**
777
+	 * A method for generating paging similar to WP_List_Table
778
+	 *
779
+	 * @param int    $total_items       How many total items there are to page.
780
+	 * @param int    $current           What the current page is.
781
+	 * @param int    $per_page          How many items per page.
782
+	 * @param string $url               What the base url for page links is.
783
+	 * @param bool   $show_num_field    Whether to show the input for changing page number.
784
+	 * @param string $paged_arg_name    The name of the key for the paged query argument.
785
+	 * @param array  $items_label       An array of singular/plural values for the items label:
786
+	 *                                  array(
787
+	 *                                  'single' => 'item',
788
+	 *                                  'plural' => 'items'
789
+	 *                                  )
790
+	 * @return  string
791
+	 * @since    4.4.0
792
+	 * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
793
+	 */
794
+	public static function get_paging_html(
795
+		int $total_items,
796
+		int $current,
797
+		int $per_page,
798
+		string $url,
799
+		bool $show_num_field = true,
800
+		string $paged_arg_name = 'paged',
801
+		array $items_label = [],
802
+		string $button_size = 'small'
803
+	): string {
804
+		$page_links     = [];
805
+		$paged_arg_name = empty($paged_arg_name) ? 'paged' : sanitize_key($paged_arg_name);
806
+
807
+		// filter items_label
808
+		$items_label = apply_filters(
809
+			'FHEE__EEH_Template__get_paging_html__items_label',
810
+			$items_label
811
+		);
812
+
813
+		if (
814
+			empty($items_label)
815
+			|| ! is_array($items_label)
816
+			|| ! isset($items_label['single'])
817
+			|| ! isset($items_label['plural'])
818
+		) {
819
+			$items_label = [
820
+				'single' => esc_html__('1 item', 'event_espresso'),
821
+				'plural' => esc_html__('%s items', 'event_espresso'),
822
+			];
823
+		} else {
824
+			$items_label = [
825
+				'single' => '1 ' . esc_html($items_label['single']),
826
+				'plural' => '%s ' . esc_html($items_label['plural']),
827
+			];
828
+		}
829
+
830
+		$total_pages = (int) ceil($total_items / $per_page);
831
+
832
+		if ($total_pages <= 1) {
833
+			return '';
834
+		}
835
+
836
+		$item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
837
+
838
+		$output = '<span class="displaying-num">' . $item_label . '</span>';
839
+
840
+		$disable_first = $current === 1 ? 'disabled' : '';
841
+		$disable_last  = $current === $total_pages ? 'disabled' : '';
842
+
843
+		$button_size    = in_array($button_size, ['tiny', 'small', 'default', 'big']) ? $button_size : 'small';
844
+		$button_classes = "button button--secondary button--icon-only button--$button_size";
845
+
846
+		$page_links[] = sprintf(
847
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
848
+			esc_attr("first-page $button_classes $disable_first"),
849
+			esc_attr__('Go to the first page', 'event_espresso'),
850
+			esc_url_raw(remove_query_arg($paged_arg_name, $url)),
851
+			'&laquo;'
852
+		);
853
+
854
+		$page_links[] = sprintf(
855
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
856
+			esc_attr("prev-page $button_classes $disable_first"),
857
+			esc_attr__('Go to the previous page', 'event_espresso'),
858
+			esc_url_raw(add_query_arg($paged_arg_name, max(1, $current - 1), $url)),
859
+			'&lsaquo;'
860
+		);
861
+
862
+		$html_current_page = $show_num_field
863
+			? sprintf(
864
+				"<input class='current-page ee-input-size--small' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
865
+				esc_attr__('Current page', 'event_espresso'),
866
+				esc_attr($current),
867
+				strlen($total_pages)
868
+			)
869
+			: $current;
870
+
871
+		$html_total_pages = sprintf(
872
+			'<span class="total-pages">%s</span>',
873
+			number_format_i18n($total_pages)
874
+		);
875
+		$page_links[]     = sprintf(
876
+			_x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
877
+			"{$html_current_page}<span class='paging-input-of'>",
878
+			"</span>{$html_total_pages}",
879
+			'<span class="paging-input">',
880
+			'</span>'
881
+		);
882
+
883
+		$page_links[] = sprintf(
884
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
885
+			esc_attr("next-page $button_classes $disable_last"),
886
+			esc_attr__('Go to the next page', 'event_espresso'),
887
+			esc_url_raw(add_query_arg($paged_arg_name, min($total_pages, $current + 1), $url)),
888
+			'&rsaquo;'
889
+		);
890
+
891
+		$page_links[] = sprintf(
892
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
893
+			esc_attr("last-page $button_classes $disable_last"),
894
+			esc_attr__('Go to the last page', 'event_espresso'),
895
+			esc_url_raw(add_query_arg($paged_arg_name, $total_pages, $url)),
896
+			'&raquo;'
897
+		);
898
+
899
+		$output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
900
+
901
+		$page_class = ' no-pages';
902
+		if ($total_pages) {
903
+			$page_class = $total_pages < 2 ? ' one-page' : '';
904
+		}
905
+
906
+		return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
907
+	}
908
+
909
+
910
+	/**
911
+	 * @param string $wrap_class
912
+	 * @param string $wrap_id
913
+	 * @param array  $query_args
914
+	 * @return string
915
+	 */
916
+	public static function powered_by_event_espresso(
917
+		string $wrap_class = '',
918
+		string $wrap_id = '',
919
+		array $query_args = []
920
+	): string {
921
+		$request = LoaderFactory::getShared(RequestInterface::class);
922
+		if (
923
+			$request->isActivation()
924
+			|| strpos($request->requestUri(true), 'wp-admin/update.php') !== false
925
+		){
926
+			return '';
927
+		}
928
+		$cache_id = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
929
+		$cache    = TemplateCache::get($cache_id);
930
+		if ($cache) {
931
+			return $cache;
932
+		}
933
+
934
+		$admin = is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX);
935
+		if (
936
+			! $admin
937
+			&& ! apply_filters(
938
+				'FHEE__EEH_Template__powered_by_event_espresso__show_reg_footer',
939
+				EE_Registry::instance()->CFG->admin->show_reg_footer
940
+			)
941
+		) {
942
+			return '';
943
+		}
944
+		$tag        = $admin ? 'span' : 'div';
945
+		$attributes = ! empty($wrap_id) ? " id=\"{$wrap_id}\"" : '';
946
+		$wrap_class = $admin ? "{$wrap_class} float-left" : $wrap_class;
947
+		$attributes .= ! empty($wrap_class)
948
+			? " class=\"{$wrap_class} powered-by-event-espresso-credit\""
949
+			: ' class="powered-by-event-espresso-credit"';
950
+		$query_args = array_merge(
951
+			[
952
+				'ap_id'        => EE_Registry::instance()->CFG->admin->affiliate_id(),
953
+				'utm_source'   => 'powered_by_event_espresso',
954
+				'utm_medium'   => 'link',
955
+				'utm_campaign' => 'powered_by',
956
+			],
957
+			$query_args
958
+		);
959
+		$powered_by = apply_filters(
960
+			'FHEE__EEH_Template__powered_by_event_espresso_text',
961
+			$admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
962
+		);
963
+		$url        = add_query_arg($query_args, 'https://eventespresso.com/');
964
+		$url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
965
+		$template   = (string) apply_filters(
966
+			'FHEE__EEH_Template__powered_by_event_espresso__html',
967
+			sprintf(
968
+				esc_html_x(
969
+					'%3$s%1$sOnline event registration and ticketing powered by %2$s%3$s',
970
+					'Online event registration and ticketing powered by [link to eventespresso.com]',
971
+					'event_espresso'
972
+				),
973
+				"<$tag$attributes>",
974
+				"<a href=\"$url\" target=\"_blank\" rel=\"nofollow\">$powered_by</a></$tag>",
975
+				$admin ? '' : '<br />'
976
+			),
977
+			$wrap_class,
978
+			$wrap_id
979
+		);
980
+		TemplateCache::set($cache_id, $template);
981
+		return $template;
982
+	}
983
+
984
+
985
+	/**
986
+	 * @param string $image_name
987
+	 * @return string|null
988
+	 * @since   4.10.14.p
989
+	 */
990
+	public static function getScreenshotUrl($image_name)
991
+	{
992
+		return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
993
+	}
994 994
 }
995 995
 
996 996
 
997 997
 if (! function_exists('espresso_pagination')) {
998
-    /**
999
-     *    espresso_pagination
1000
-     *
1001
-     * @access    public
1002
-     * @return    void
1003
-     */
1004
-    function espresso_pagination()
1005
-    {
1006
-        global $wp_query;
1007
-        $big        = 999999999; // need an unlikely integer
1008
-        $pagination = paginate_links(
1009
-            [
1010
-                'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
1011
-                'format'       => '?paged=%#%',
1012
-                'current'      => max(1, get_query_var('paged')),
1013
-                'total'        => $wp_query->max_num_pages,
1014
-                'show_all'     => true,
1015
-                'end_size'     => 10,
1016
-                'mid_size'     => 6,
1017
-                'prev_next'    => true,
1018
-                'prev_text'    => esc_html__('&lsaquo; PREV', 'event_espresso'),
1019
-                'next_text'    => esc_html__('NEXT &rsaquo;', 'event_espresso'),
1020
-                'type'         => 'plain',
1021
-                'add_args'     => false,
1022
-                'add_fragment' => '',
1023
-            ]
1024
-        );
1025
-        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1026
-    }
998
+	/**
999
+	 *    espresso_pagination
1000
+	 *
1001
+	 * @access    public
1002
+	 * @return    void
1003
+	 */
1004
+	function espresso_pagination()
1005
+	{
1006
+		global $wp_query;
1007
+		$big        = 999999999; // need an unlikely integer
1008
+		$pagination = paginate_links(
1009
+			[
1010
+				'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
1011
+				'format'       => '?paged=%#%',
1012
+				'current'      => max(1, get_query_var('paged')),
1013
+				'total'        => $wp_query->max_num_pages,
1014
+				'show_all'     => true,
1015
+				'end_size'     => 10,
1016
+				'mid_size'     => 6,
1017
+				'prev_next'    => true,
1018
+				'prev_text'    => esc_html__('&lsaquo; PREV', 'event_espresso'),
1019
+				'next_text'    => esc_html__('NEXT &rsaquo;', 'event_espresso'),
1020
+				'type'         => 'plain',
1021
+				'add_args'     => false,
1022
+				'add_fragment' => '',
1023
+			]
1024
+		);
1025
+		echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1026
+	}
1027 1027
 }
Please login to merge, or discard this patch.
Spacing   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -8,7 +8,7 @@  discard block
 block discarded – undo
8 8
 use EventEspresso\core\services\request\RequestInterface;
9 9
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
10 10
 
11
-if (! function_exists('espresso_get_template_part')) {
11
+if ( ! function_exists('espresso_get_template_part')) {
12 12
     /**
13 13
      * espresso_get_template_part
14 14
      * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
 }
25 25
 
26 26
 
27
-if (! function_exists('espresso_get_object_css_class')) {
27
+if ( ! function_exists('espresso_get_object_css_class')) {
28 28
     /**
29 29
      * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30 30
      *
@@ -74,9 +74,9 @@  discard block
 block discarded – undo
74 74
      */
75 75
     public static function load_espresso_theme_functions()
76 76
     {
77
-        if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
-            if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
-                require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
77
+        if ( ! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
+            if (is_readable(EE_PUBLIC.EE_Config::get_current_theme().'/functions.php')) {
79
+                require_once(EE_PUBLIC.EE_Config::get_current_theme().'/functions.php');
80 80
             }
81 81
         }
82 82
     }
@@ -90,16 +90,16 @@  discard block
 block discarded – undo
90 90
     public static function get_espresso_themes(): array
91 91
     {
92 92
         if (empty(EEH_Template::$_espresso_themes)) {
93
-            $espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
93
+            $espresso_themes = glob(EE_PUBLIC.'*', GLOB_ONLYDIR);
94 94
             if (empty($espresso_themes)) {
95 95
                 return [];
96 96
             }
97 97
             if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
-                unset($espresso_themes[ $key ]);
98
+                unset($espresso_themes[$key]);
99 99
             }
100 100
             EEH_Template::$_espresso_themes = [];
101 101
             foreach ($espresso_themes as $espresso_theme) {
102
-                EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
102
+                EEH_Template::$_espresso_themes[basename($espresso_theme)] = $espresso_theme;
103 103
             }
104 104
         }
105 105
         return EEH_Template::$_espresso_themes;
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
     ) {
127 127
         do_action("get_template_part_$slug-$name", $slug, $name);
128 128
         $template = $slug;
129
-        $name      = (string) $name;
129
+        $name = (string) $name;
130 130
         if ($name != '') {
131 131
             $template .= "-$name";
132 132
         }
@@ -245,10 +245,10 @@  discard block
 block discarded – undo
245 245
                 // get array of EE Custom Post Types
246 246
                 $EE_CPTs = $custom_post_types->getDefinitions();
247 247
                 // build template name based on request
248
-                if (isset($EE_CPTs[ $post_type ])) {
248
+                if (isset($EE_CPTs[$post_type])) {
249 249
                     $archive_or_single = is_archive() ? 'archive' : '';
250 250
                     $archive_or_single = is_single() ? 'single' : $archive_or_single;
251
-                    $templates[]       = $archive_or_single . '-' . $post_type . '.php';
251
+                    $templates[]       = $archive_or_single.'-'.$post_type.'.php';
252 252
                 }
253 253
             }
254 254
             // currently active EE template theme
@@ -257,12 +257,12 @@  discard block
 block discarded – undo
257 257
             $template_folder_paths = [];
258 258
 
259 259
             // add core plugin folders for checking only if we're not $check_if_custom
260
-            if (! $check_if_custom) {
261
-                $core_paths            = [
260
+            if ( ! $check_if_custom) {
261
+                $core_paths = [
262 262
                     // in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
-                    EE_PUBLIC . $current_theme,
263
+                    EE_PUBLIC.$current_theme,
264 264
                     // in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
-                    EE_TEMPLATES . $current_theme,
265
+                    EE_TEMPLATES.$current_theme,
266 266
                     // or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267 267
                     EE_PLUGIN_DIR_PATH,
268 268
                 ];
@@ -295,10 +295,10 @@  discard block
 block discarded – undo
295 295
                     );
296 296
                     if ($common_base_path !== '') {
297 297
                         // both paths have a common base, so just tack the filename onto our search path
298
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
298
+                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path).$file_name;
299 299
                     } else {
300 300
                         // no common base path, so let's just concatenate
301
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
301
+                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path).$template;
302 302
                     }
303 303
                     // build up our template locations array by adding our resolved paths
304 304
                     $full_template_paths[] = $resolved_path;
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
                 // if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307 307
                 array_unshift($full_template_paths, $template);
308 308
                 // path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
-                array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
309
+                array_unshift($full_template_paths, get_stylesheet_directory().'/'.$file_name);
310 310
             }
311 311
             // filter final array of full template paths
312 312
             $full_template_paths = apply_filters(
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
                 }
364 364
             }
365 365
             $common_base_path .= $directory;
366
-            $last_offset      = $index + 1;
366
+            $last_offset = $index + 1;
367 367
         }
368 368
         return substr($common_base_path, 0, -1);
369 369
     }
@@ -400,7 +400,7 @@  discard block
 block discarded – undo
400 400
         $template_args = (array) apply_filters('FHEE__EEH_Template__display_template__template_args', $template_args);
401 401
 
402 402
         // you gimme nuttin - YOU GET NUTTIN !!
403
-        if (! $template_path || ! is_readable($template_path)) {
403
+        if ( ! $template_path || ! is_readable($template_path)) {
404 404
             // ignore whether template is accessible ?
405 405
             if ($throw_exceptions) {
406 406
                 throw new DomainException(
@@ -437,11 +437,11 @@  discard block
 block discarded – undo
437 437
     public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
438 438
     {
439 439
         // in the beginning...
440
-        $prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
440
+        $prefix = ! empty($prefix) ? rtrim($prefix, '-').'-' : '';
441 441
         // da muddle
442 442
         $class = '';
443 443
         // the end
444
-        $suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
444
+        $suffix = ! empty($suffix) ? '-'.ltrim($suffix, '-') : '';
445 445
         // is the passed object an EE object ?
446 446
         if ($object instanceof EE_Base_Class) {
447 447
             // grab the exact type of object
@@ -449,9 +449,9 @@  discard block
 block discarded – undo
449 449
             // depending on the type of object...
450 450
             // no specifics just yet...
451 451
             $class = strtolower(str_replace('_', '-', $obj_class));
452
-            $class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
452
+            $class .= method_exists($obj_class, 'name') ? '-'.sanitize_title($object->name()) : '';
453 453
         }
454
-        return $prefix . $class . $suffix;
454
+        return $prefix.$class.$suffix;
455 455
     }
456 456
 
457 457
 
@@ -486,7 +486,7 @@  discard block
 block discarded – undo
486 486
         // filter raw amount (allows 0.00 to be changed to "free" for example)
487 487
         $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
488 488
         // still a number, or was amount converted to a string like "free" ?
489
-        if (! is_float($amount_formatted)) {
489
+        if ( ! is_float($amount_formatted)) {
490 490
             return esc_html($amount_formatted);
491 491
         }
492 492
         try {
@@ -497,7 +497,7 @@  discard block
 block discarded – undo
497 497
             $mny = null;
498 498
         }
499 499
         // verify results
500
-        if (! $mny instanceof EE_Currency_Config) {
500
+        if ( ! $mny instanceof EE_Currency_Config) {
501 501
             // set default config country currency settings
502 502
             $mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
503 503
                 ? EE_Registry::instance()->CFG->currency
@@ -506,16 +506,16 @@  discard block
 block discarded – undo
506 506
         // format float
507 507
         $amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
508 508
         // add formatting ?
509
-        if (! $return_raw) {
509
+        if ( ! $return_raw) {
510 510
             // add currency sign
511 511
             if ($mny->sign_b4) {
512 512
                 if ($amount >= 0) {
513
-                    $amount_formatted = $mny->sign . $amount_formatted;
513
+                    $amount_formatted = $mny->sign.$amount_formatted;
514 514
                 } else {
515
-                    $amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
515
+                    $amount_formatted = '-'.$mny->sign.str_replace('-', '', $amount_formatted);
516 516
                 }
517 517
             } else {
518
-                $amount_formatted = $amount_formatted . $mny->sign;
518
+                $amount_formatted = $amount_formatted.$mny->sign;
519 519
             }
520 520
 
521 521
             // filter to allow global setting of display_code
@@ -526,7 +526,7 @@  discard block
 block discarded – undo
526 526
 
527 527
             // add currency code ?
528 528
             $amount_formatted = $display_code
529
-                ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
529
+                ? $amount_formatted.' <span class="'.$cur_code_span_class.'">'.$mny->code.'</span>'
530 530
                 : $amount_formatted;
531 531
         }
532 532
         // filter results
@@ -562,7 +562,7 @@  discard block
 block discarded – undo
562 562
             $plural,
563 563
             $schema
564 564
         );
565
-        return $status[ $status_id ];
565
+        return $status[$status_id];
566 566
     }
567 567
 
568 568
 
@@ -579,14 +579,14 @@  discard block
 block discarded – undo
579 579
     public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
580 580
     {
581 581
         $icon_html = '';
582
-        if (! empty($icon)) {
582
+        if ( ! empty($icon)) {
583 583
             $dashicons = preg_split("(ee-icon |dashicons )", $icon);
584 584
             $dashicons = array_filter($dashicons);
585 585
             $count     = count($dashicons);
586 586
             $icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
587 587
             foreach ($dashicons as $dashicon) {
588
-                $type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
-                $icon_html .= '<span class="' . $type . $dashicon . '"></span>';
588
+                $type = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
+                $icon_html .= '<span class="'.$type.$dashicon.'"></span>';
590 590
             }
591 591
             $icon_html .= $count > 1 ? '</span>' : '';
592 592
         }
@@ -625,18 +625,18 @@  discard block
 block discarded – undo
625 625
         $action  = $action ?: $request->getRequestParam('action', 'default', 'key');
626 626
 
627 627
 
628
-        $help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
628
+        $help_tab_lnk = $page.'-'.$action.'-'.$help_tab_id;
629 629
         $icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
630 630
         $help_text    = ! $help_text ? '' : $help_text;
631 631
         return '
632
-            <a id="' . esc_attr($help_tab_lnk) . '"
633
-               class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon) . '"
632
+            <a id="' . esc_attr($help_tab_lnk).'"
633
+               class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon).'"
634 634
                aria-label="' . esc_attr__(
635 635
                 'Click to open the \'Help\' tab for more information about this feature.',
636 636
                 'event_espresso'
637
-            ) . '"
637
+            ).'"
638 638
             >
639
-                ' . wp_kses($help_text, AllowedTags::getAllowedTags()) . '
639
+                ' . wp_kses($help_text, AllowedTags::getAllowedTags()).'
640 640
             </a>';
641 641
     }
642 642
 
@@ -657,7 +657,7 @@  discard block
 block discarded – undo
657 657
      */
658 658
     public static function status_legend($status_array, $active_status = '')
659 659
     {
660
-        if (! is_array($status_array)) {
660
+        if ( ! is_array($status_array)) {
661 661
             throw new EE_Error(
662 662
                 esc_html__(
663 663
                     'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
@@ -669,17 +669,17 @@  discard block
 block discarded – undo
669 669
         $content = '
670 670
             <div class="ee-list-table-legend-container">
671 671
                 <h4 class="status-legend-title">
672
-                    ' . esc_html__('Status Legend', 'event_espresso') . '
672
+                    ' . esc_html__('Status Legend', 'event_espresso').'
673 673
                 </h4>
674 674
                 <dl class="ee-list-table-legend">';
675 675
 
676 676
         foreach ($status_array as $item => $status) {
677 677
             $active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
678
-            $content      .= '
679
-                    <dt id="' . esc_attr('ee-legend-item-tooltip-' . $item) . '" ' . $active_class . '>
680
-                        <span class="' . esc_attr('ee-status-legend ee-status-bg--' . $status) . '"></span>
678
+            $content .= '
679
+                    <dt id="' . esc_attr('ee-legend-item-tooltip-'.$item).'" '.$active_class.'>
680
+                        <span class="' . esc_attr('ee-status-legend ee-status-bg--'.$status).'"></span>
681 681
                         <span class="ee-legend-description">
682
-                            ' . EEH_Template::pretty_status($status, false, 'sentence') . '
682
+                            ' . EEH_Template::pretty_status($status, false, 'sentence').'
683 683
                         </span>
684 684
                     </dt>';
685 685
         }
@@ -822,8 +822,8 @@  discard block
 block discarded – undo
822 822
             ];
823 823
         } else {
824 824
             $items_label = [
825
-                'single' => '1 ' . esc_html($items_label['single']),
826
-                'plural' => '%s ' . esc_html($items_label['plural']),
825
+                'single' => '1 '.esc_html($items_label['single']),
826
+                'plural' => '%s '.esc_html($items_label['plural']),
827 827
             ];
828 828
         }
829 829
 
@@ -835,7 +835,7 @@  discard block
 block discarded – undo
835 835
 
836 836
         $item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
837 837
 
838
-        $output = '<span class="displaying-num">' . $item_label . '</span>';
838
+        $output = '<span class="displaying-num">'.$item_label.'</span>';
839 839
 
840 840
         $disable_first = $current === 1 ? 'disabled' : '';
841 841
         $disable_last  = $current === $total_pages ? 'disabled' : '';
@@ -872,7 +872,7 @@  discard block
 block discarded – undo
872 872
             '<span class="total-pages">%s</span>',
873 873
             number_format_i18n($total_pages)
874 874
         );
875
-        $page_links[]     = sprintf(
875
+        $page_links[] = sprintf(
876 876
             _x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
877 877
             "{$html_current_page}<span class='paging-input-of'>",
878 878
             "</span>{$html_total_pages}",
@@ -896,14 +896,14 @@  discard block
 block discarded – undo
896 896
             '&raquo;'
897 897
         );
898 898
 
899
-        $output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
899
+        $output .= "\n".'<span class="pagination-links">'.join("\n", $page_links).'</span>';
900 900
 
901 901
         $page_class = ' no-pages';
902 902
         if ($total_pages) {
903 903
             $page_class = $total_pages < 2 ? ' one-page' : '';
904 904
         }
905 905
 
906
-        return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
906
+        return '<div class="tablenav"><div class="tablenav-pages'.$page_class.'">'.$output.'</div></div>';
907 907
     }
908 908
 
909 909
 
@@ -922,7 +922,7 @@  discard block
 block discarded – undo
922 922
         if (
923 923
             $request->isActivation()
924 924
             || strpos($request->requestUri(true), 'wp-admin/update.php') !== false
925
-        ){
925
+        ) {
926 926
             return '';
927 927
         }
928 928
         $cache_id = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
         );
959 959
         $powered_by = apply_filters(
960 960
             'FHEE__EEH_Template__powered_by_event_espresso_text',
961
-            $admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
961
+            $admin ? 'Event Espresso - '.EVENT_ESPRESSO_VERSION : 'Event Espresso'
962 962
         );
963 963
         $url        = add_query_arg($query_args, 'https://eventespresso.com/');
964 964
         $url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
@@ -989,12 +989,12 @@  discard block
 block discarded – undo
989 989
      */
990 990
     public static function getScreenshotUrl($image_name)
991 991
     {
992
-        return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
992
+        return esc_url_raw(EE_GLOBAL_ASSETS_URL.'images/screenshots/'.$image_name.'.jpg');
993 993
     }
994 994
 }
995 995
 
996 996
 
997
-if (! function_exists('espresso_pagination')) {
997
+if ( ! function_exists('espresso_pagination')) {
998 998
     /**
999 999
      *    espresso_pagination
1000 1000
      *
@@ -1022,6 +1022,6 @@  discard block
 block discarded – undo
1022 1022
                 'add_fragment' => '',
1023 1023
             ]
1024 1024
         );
1025
-        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1025
+        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">'.$pagination.'</div>' : '';
1026 1026
     }
1027 1027
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/payment_methods/BillingInfoSanitizer.php 1 patch
Indentation   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -21,35 +21,35 @@
 block discarded – undo
21 21
  */
22 22
 class BillingInfoSanitizer
23 23
 {
24
-    /**
25
-     * @param EE_Form_Section_Proper $form_section
26
-     * @param bool                   $found_cc_data
27
-     * @return bool|mixed
28
-     * @throws EE_Error
29
-     */
30
-    public static function displaySanitizedBillingInfo(EE_Form_Section_Proper $form_section, bool $found_cc_data = false)
31
-    {
32
-        foreach ($form_section->subsections() as $subsection) {
33
-            if ($subsection instanceof EE_Form_Input_Base) {
34
-                if (
35
-                    $subsection->get_sensitive_data_removal_strategy() instanceof EE_All_Sensitive_Data_Removal
36
-                    || $subsection->get_sensitive_data_removal_strategy() instanceof EE_CCV_Sensitive_Data_Removal
37
-                    || $subsection->get_display_strategy() instanceof EE_Hidden_Display_Strategy
38
-                ) {
39
-                    continue;
40
-                }
41
-                if ($subsection->get_sensitive_data_removal_strategy() instanceof EE_Credit_Card_Sensitive_Data_Removal) {
42
-                    $found_cc_data = true;
43
-                }
44
-                $subsection->add_html_label_class('admin-side-mbox-label-spn lt-grey-txt');
45
-                echo wp_kses($subsection->get_html_for_label(), AllowedTags::getWithFormTags());
46
-                echo "<span class='admin-side-mbox-value-spn'>";
47
-                echo wp_kses($subsection->pretty_value(), AllowedTags::getWithFormTags());
48
-                echo "</span>";
49
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
50
-                $found_cc_data = BillingInfoSanitizer::displaySanitizedBillingInfo($subsection, $found_cc_data);
51
-            }
52
-        }
53
-        return $found_cc_data;
54
-    }
24
+	/**
25
+	 * @param EE_Form_Section_Proper $form_section
26
+	 * @param bool                   $found_cc_data
27
+	 * @return bool|mixed
28
+	 * @throws EE_Error
29
+	 */
30
+	public static function displaySanitizedBillingInfo(EE_Form_Section_Proper $form_section, bool $found_cc_data = false)
31
+	{
32
+		foreach ($form_section->subsections() as $subsection) {
33
+			if ($subsection instanceof EE_Form_Input_Base) {
34
+				if (
35
+					$subsection->get_sensitive_data_removal_strategy() instanceof EE_All_Sensitive_Data_Removal
36
+					|| $subsection->get_sensitive_data_removal_strategy() instanceof EE_CCV_Sensitive_Data_Removal
37
+					|| $subsection->get_display_strategy() instanceof EE_Hidden_Display_Strategy
38
+				) {
39
+					continue;
40
+				}
41
+				if ($subsection->get_sensitive_data_removal_strategy() instanceof EE_Credit_Card_Sensitive_Data_Removal) {
42
+					$found_cc_data = true;
43
+				}
44
+				$subsection->add_html_label_class('admin-side-mbox-label-spn lt-grey-txt');
45
+				echo wp_kses($subsection->get_html_for_label(), AllowedTags::getWithFormTags());
46
+				echo "<span class='admin-side-mbox-value-spn'>";
47
+				echo wp_kses($subsection->pretty_value(), AllowedTags::getWithFormTags());
48
+				echo "</span>";
49
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
50
+				$found_cc_data = BillingInfoSanitizer::displaySanitizedBillingInfo($subsection, $found_cc_data);
51
+			}
52
+		}
53
+		return $found_cc_data;
54
+	}
55 55
 }
Please login to merge, or discard this patch.
form_sections/payment_methods/EE_Billing_Attendee_Info_Form.form.php 1 patch
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -13,227 +13,227 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Billing_Attendee_Info_Form extends EE_Billing_Info_Form
15 15
 {
16
-    /**
17
-     *
18
-     * @param EE_Payment_Method $payment_method
19
-     * @param array             $options_array @see EE_Form_Section_Proper::__construct()
20
-     * @throws EE_Error
21
-     * @throws ReflectionException
22
-     */
23
-    public function __construct(EE_Payment_Method $payment_method, $options_array = [])
24
-    {
25
-        $options_array['subsections'] = array_merge(
26
-            [
27
-                'first_name' => new EE_Text_Input(
28
-                    [
29
-                        'required'        => true,
30
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-fname',
31
-                        'html_label_text' => esc_html__('First Name', 'event_espresso'),
32
-                    ]
33
-                ),
34
-                'last_name'  => new EE_Text_Input(
35
-                    [
36
-                        'required'        => true,
37
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-lname',
38
-                        'html_label_text' => esc_html__('Last Name', 'event_espresso'),
39
-                    ]
40
-                ),
41
-                'email'      => new EE_Email_Input(
42
-                    [
43
-                        'required'        => true,
44
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-email',
45
-                        'html_label_text' => esc_html__('Email', 'event_espresso'),
46
-                    ]
47
-                ),
48
-                'address'    => new EE_Text_Input(
49
-                    [
50
-                        'html_label_text' => esc_html__('Address', 'event_espresso'),
51
-                        'required'        => true,
52
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-address',
53
-                    ]
54
-                ),
55
-                'address2'   => new EE_Text_Input(
56
-                    [
57
-                        'html_label_text' => esc_html__('Address 2', 'event_espresso'),
58
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-address2',
59
-                    ]
60
-                ),
61
-                'city'       => new EE_Text_Input(
62
-                    [
63
-                        'required'        => true,
64
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-city',
65
-                        'html_label_text' => esc_html__('City', 'event_espresso'),
66
-                    ]
67
-                ),
68
-                'state'      => apply_filters(
69
-                    'FHEE__EE_Billing_Attendee_Info_Form__state_field',
70
-                    new EE_State_Select_Input(
71
-                        null, [
72
-                        'required'        => true,
73
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-state',
74
-                        'html_label_text' => esc_html__('State', 'event_espresso'),
75
-                    ]
76
-                    )
77
-                ),
78
-                'country'    => apply_filters(
79
-                    'FHEE__EE_Billing_Attendee_Info_Form__country_field',
80
-                    new EE_Country_Select_Input(
81
-                        null, [
82
-                        'required'        => true,
83
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-country',
84
-                        'html_label_text' => esc_html__('Country', 'event_espresso'),
85
-                    ]
86
-                    )
87
-                ),
88
-                'zip'        => new EE_Text_Input(
89
-                    [
90
-                        'required'        => true,
91
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-zip',
92
-                        'html_label_text' => esc_html__('Zip', 'event_espresso'),
93
-                    ]
94
-                ),
95
-                'phone'      => new EE_Text_Input(
96
-                    [
97
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-phone',
98
-                        'html_label_text' => esc_html__('Phone', 'event_espresso'),
99
-                    ]
100
-                ),
101
-            ],
102
-            $options_array['subsections'] ?? []
103
-        );
16
+	/**
17
+	 *
18
+	 * @param EE_Payment_Method $payment_method
19
+	 * @param array             $options_array @see EE_Form_Section_Proper::__construct()
20
+	 * @throws EE_Error
21
+	 * @throws ReflectionException
22
+	 */
23
+	public function __construct(EE_Payment_Method $payment_method, $options_array = [])
24
+	{
25
+		$options_array['subsections'] = array_merge(
26
+			[
27
+				'first_name' => new EE_Text_Input(
28
+					[
29
+						'required'        => true,
30
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-fname',
31
+						'html_label_text' => esc_html__('First Name', 'event_espresso'),
32
+					]
33
+				),
34
+				'last_name'  => new EE_Text_Input(
35
+					[
36
+						'required'        => true,
37
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-lname',
38
+						'html_label_text' => esc_html__('Last Name', 'event_espresso'),
39
+					]
40
+				),
41
+				'email'      => new EE_Email_Input(
42
+					[
43
+						'required'        => true,
44
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-email',
45
+						'html_label_text' => esc_html__('Email', 'event_espresso'),
46
+					]
47
+				),
48
+				'address'    => new EE_Text_Input(
49
+					[
50
+						'html_label_text' => esc_html__('Address', 'event_espresso'),
51
+						'required'        => true,
52
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-address',
53
+					]
54
+				),
55
+				'address2'   => new EE_Text_Input(
56
+					[
57
+						'html_label_text' => esc_html__('Address 2', 'event_espresso'),
58
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-address2',
59
+					]
60
+				),
61
+				'city'       => new EE_Text_Input(
62
+					[
63
+						'required'        => true,
64
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-city',
65
+						'html_label_text' => esc_html__('City', 'event_espresso'),
66
+					]
67
+				),
68
+				'state'      => apply_filters(
69
+					'FHEE__EE_Billing_Attendee_Info_Form__state_field',
70
+					new EE_State_Select_Input(
71
+						null, [
72
+						'required'        => true,
73
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-state',
74
+						'html_label_text' => esc_html__('State', 'event_espresso'),
75
+					]
76
+					)
77
+				),
78
+				'country'    => apply_filters(
79
+					'FHEE__EE_Billing_Attendee_Info_Form__country_field',
80
+					new EE_Country_Select_Input(
81
+						null, [
82
+						'required'        => true,
83
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-country',
84
+						'html_label_text' => esc_html__('Country', 'event_espresso'),
85
+					]
86
+					)
87
+				),
88
+				'zip'        => new EE_Text_Input(
89
+					[
90
+						'required'        => true,
91
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-zip',
92
+						'html_label_text' => esc_html__('Zip', 'event_espresso'),
93
+					]
94
+				),
95
+				'phone'      => new EE_Text_Input(
96
+					[
97
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-phone',
98
+						'html_label_text' => esc_html__('Phone', 'event_espresso'),
99
+					]
100
+				),
101
+			],
102
+			$options_array['subsections'] ?? []
103
+		);
104 104
 
105
-        parent::__construct($payment_method, $options_array);
106
-    }
105
+		parent::__construct($payment_method, $options_array);
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * Sets the defaults for the billing form according to the attendee's details
111
-     *
112
-     * @param EE_Attendee $attendee
113
-     * @throws EE_Error
114
-     * @throws ReflectionException
115
-     */
116
-    public function populate_from_attendee(EE_Attendee $attendee)
117
-    {
118
-        /** @var $attendee EE_Attendee */
119
-        $attendee = EEM_Attendee::instance()->ensure_is_obj($attendee);
120
-        $this->populate_defaults(
121
-            apply_filters(
122
-                'FHEE__EE_Billing_Attendee_Info_Form__populate_from_attendee',
123
-                [
124
-                    'first_name' => $attendee->fname(),
125
-                    'last_name'  => $attendee->lname(),
126
-                    'email'      => $attendee->email(),
127
-                    'address'    => $attendee->address(),
128
-                    'address2'   => $attendee->address2(),
129
-                    'city'       => $attendee->city(),
130
-                    'state'      => $this->getAttendeeStateValueForForm($attendee),
131
-                    'country'    => $attendee->country_ID(),
132
-                    'zip'        => $attendee->zip(),
133
-                    'phone'      => $attendee->phone(),
134
-                ],
135
-                $attendee,
136
-                $this
137
-            )
138
-        );
139
-    }
109
+	/**
110
+	 * Sets the defaults for the billing form according to the attendee's details
111
+	 *
112
+	 * @param EE_Attendee $attendee
113
+	 * @throws EE_Error
114
+	 * @throws ReflectionException
115
+	 */
116
+	public function populate_from_attendee(EE_Attendee $attendee)
117
+	{
118
+		/** @var $attendee EE_Attendee */
119
+		$attendee = EEM_Attendee::instance()->ensure_is_obj($attendee);
120
+		$this->populate_defaults(
121
+			apply_filters(
122
+				'FHEE__EE_Billing_Attendee_Info_Form__populate_from_attendee',
123
+				[
124
+					'first_name' => $attendee->fname(),
125
+					'last_name'  => $attendee->lname(),
126
+					'email'      => $attendee->email(),
127
+					'address'    => $attendee->address(),
128
+					'address2'   => $attendee->address2(),
129
+					'city'       => $attendee->city(),
130
+					'state'      => $this->getAttendeeStateValueForForm($attendee),
131
+					'country'    => $attendee->country_ID(),
132
+					'zip'        => $attendee->zip(),
133
+					'phone'      => $attendee->phone(),
134
+				],
135
+				$attendee,
136
+				$this
137
+			)
138
+		);
139
+	}
140 140
 
141 141
 
142
-    /**
143
-     * Gets the default value to use for the billing form's state value.
144
-     *
145
-     * @param EE_Attendee $attendee
146
-     * @return string
147
-     * @throws EE_Error
148
-     * @throws ReflectionException
149
-     * @since 4.10.0.p
150
-     */
151
-    protected function getAttendeeStateValueForForm(EE_Attendee $attendee): string
152
-    {
153
-        // If the state input was removed, just return a blank string.
154
-        if (! $this->has_subsection('state')) {
155
-            return '';
156
-        }
157
-        $state_input = $this->get_input('state', false);
158
-        if ($state_input instanceof EE_State_Select_Input) {
159
-            $state_field_to_use = $state_input->valueFieldName();
160
-        } else {
161
-            $state_field_to_use = 'STA_ID';
162
-        }
163
-        switch ($state_field_to_use) {
164
-            case 'STA_abbrev':
165
-                $state_value = $attendee->state_abbrev();
166
-                break;
167
-            case 'STA_name':
168
-                $state_value = $attendee->state_name();
169
-                break;
170
-            default:
171
-                $state_value = $attendee->state_ID();
172
-        }
173
-        return $state_value;
174
-    }
142
+	/**
143
+	 * Gets the default value to use for the billing form's state value.
144
+	 *
145
+	 * @param EE_Attendee $attendee
146
+	 * @return string
147
+	 * @throws EE_Error
148
+	 * @throws ReflectionException
149
+	 * @since 4.10.0.p
150
+	 */
151
+	protected function getAttendeeStateValueForForm(EE_Attendee $attendee): string
152
+	{
153
+		// If the state input was removed, just return a blank string.
154
+		if (! $this->has_subsection('state')) {
155
+			return '';
156
+		}
157
+		$state_input = $this->get_input('state', false);
158
+		if ($state_input instanceof EE_State_Select_Input) {
159
+			$state_field_to_use = $state_input->valueFieldName();
160
+		} else {
161
+			$state_field_to_use = 'STA_ID';
162
+		}
163
+		switch ($state_field_to_use) {
164
+			case 'STA_abbrev':
165
+				$state_value = $attendee->state_abbrev();
166
+				break;
167
+			case 'STA_name':
168
+				$state_value = $attendee->state_name();
169
+				break;
170
+			default:
171
+				$state_value = $attendee->state_ID();
172
+		}
173
+		return $state_value;
174
+	}
175 175
 
176 176
 
177
-    /**
178
-     * copy_billing_form_data_to_attendee
179
-     * copies info from the billing form to the attendee's details
180
-     *
181
-     * @param EE_Attendee $attendee the attendee object to copy details to
182
-     * @return EE_Attendee
183
-     * @throws EE_Error
184
-     */
185
-    public function copy_billing_form_data_to_attendee(EE_Attendee $attendee): EE_Attendee
186
-    {
187
-        // grab billing form data
188
-        $data = $this->valid_data();
177
+	/**
178
+	 * copy_billing_form_data_to_attendee
179
+	 * copies info from the billing form to the attendee's details
180
+	 *
181
+	 * @param EE_Attendee $attendee the attendee object to copy details to
182
+	 * @return EE_Attendee
183
+	 * @throws EE_Error
184
+	 */
185
+	public function copy_billing_form_data_to_attendee(EE_Attendee $attendee): EE_Attendee
186
+	{
187
+		// grab billing form data
188
+		$data = $this->valid_data();
189 189
 
190
-        $fields_and_setters = [
191
-            'first_name' => 'set_fname',
192
-            'last_name'  => 'set_lname',
193
-            'email'      => 'set_email',
194
-            'address'    => 'set_address',
195
-            'address2'   => 'set_address2',
196
-            'city'       => 'set_city',
197
-            'state'      => 'set_state',
198
-            'country'    => 'set_country',
199
-            'zip'        => 'set_zip',
200
-            'phone'      => 'set_phone',
201
-        ];
202
-        foreach ($fields_and_setters as $field => $setter) {
203
-            if (! empty($data[ $field ]) && method_exists($attendee, $setter)) {
204
-                $attendee->{$setter}($data[ $field ]);
205
-            }
206
-        }
207
-        return $attendee;
208
-    }
190
+		$fields_and_setters = [
191
+			'first_name' => 'set_fname',
192
+			'last_name'  => 'set_lname',
193
+			'email'      => 'set_email',
194
+			'address'    => 'set_address',
195
+			'address2'   => 'set_address2',
196
+			'city'       => 'set_city',
197
+			'state'      => 'set_state',
198
+			'country'    => 'set_country',
199
+			'zip'        => 'set_zip',
200
+			'phone'      => 'set_phone',
201
+		];
202
+		foreach ($fields_and_setters as $field => $setter) {
203
+			if (! empty($data[ $field ]) && method_exists($attendee, $setter)) {
204
+				$attendee->{$setter}($data[ $field ]);
205
+			}
206
+		}
207
+		return $attendee;
208
+	}
209 209
 
210 210
 
211
-    /**
212
-     * create_attendee_from_billing_form_data
213
-     * uses info from the billing form to create a new attendee
214
-     *
215
-     * @return EE_Attendee
216
-     * @throws EE_Error
217
-     * @throws ReflectionException
218
-     */
219
-    public function create_attendee_from_billing_form_data()
220
-    {
221
-        // grab billing form data
222
-        $data = $this->valid_data();
223
-        return EE_Attendee::new_instance(
224
-            [
225
-                'ATT_fname'    => ! empty($data['first_name']) ? $data['first_name'] : '',
226
-                'ATT_lname'    => ! empty($data['last_name']) ? $data['last_name'] : '',
227
-                'ATT_email'    => ! empty($data['email']) ? $data['email'] : '',
228
-                'ATT_address'  => ! empty($data['address']) ? $data['address'] : '',
229
-                'ATT_address2' => ! empty($data['address2']) ? $data['address2'] : '',
230
-                'ATT_city'     => ! empty($data['city']) ? $data['city'] : '',
231
-                'STA_ID'       => ! empty($data['state']) ? $data['state'] : '',
232
-                'CNT_ISO'      => ! empty($data['country']) ? $data['country'] : '',
233
-                'ATT_zip'      => ! empty($data['zip']) ? $data['zip'] : '',
234
-                'ATT_phone'    => ! empty($data['phone']) ? $data['phone'] : '',
235
-            ]
236
-        );
237
-    }
211
+	/**
212
+	 * create_attendee_from_billing_form_data
213
+	 * uses info from the billing form to create a new attendee
214
+	 *
215
+	 * @return EE_Attendee
216
+	 * @throws EE_Error
217
+	 * @throws ReflectionException
218
+	 */
219
+	public function create_attendee_from_billing_form_data()
220
+	{
221
+		// grab billing form data
222
+		$data = $this->valid_data();
223
+		return EE_Attendee::new_instance(
224
+			[
225
+				'ATT_fname'    => ! empty($data['first_name']) ? $data['first_name'] : '',
226
+				'ATT_lname'    => ! empty($data['last_name']) ? $data['last_name'] : '',
227
+				'ATT_email'    => ! empty($data['email']) ? $data['email'] : '',
228
+				'ATT_address'  => ! empty($data['address']) ? $data['address'] : '',
229
+				'ATT_address2' => ! empty($data['address2']) ? $data['address2'] : '',
230
+				'ATT_city'     => ! empty($data['city']) ? $data['city'] : '',
231
+				'STA_ID'       => ! empty($data['state']) ? $data['state'] : '',
232
+				'CNT_ISO'      => ! empty($data['country']) ? $data['country'] : '',
233
+				'ATT_zip'      => ! empty($data['zip']) ? $data['zip'] : '',
234
+				'ATT_phone'    => ! empty($data['phone']) ? $data['phone'] : '',
235
+			]
236
+		);
237
+	}
238 238
 }
239 239
 // End of file EE_Billing_Attendee_Info_Form.form.php
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Datepicker_Input.php 1 patch
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -9,79 +9,79 @@
 block discarded – undo
9 9
  */
10 10
 class EE_Datepicker_Input extends EE_Form_Input_Base
11 11
 {
12
-    private bool $use_jquery_ui;
12
+	private bool $use_jquery_ui;
13 13
 
14 14
 
15
-    /**
16
-     * @param array $input_settings
17
-     */
18
-    public function __construct($input_settings = [], $use_jquery_ui = false)
19
-    {
20
-        $this->use_jquery_ui = (bool) apply_filters('FHEE__EE_Datepicker_Input__use_jquery_ui', $use_jquery_ui);
21
-        $type                = $this->use_jquery_ui ? 'datepicker' : 'date';
22
-        $this->_set_display_strategy(new EE_Text_Input_Display_Strategy($type));
23
-        $this->_set_normalization_strategy(new EE_Text_Normalization());
24
-        // we could do better for validation, but at least verify its plaintext
25
-        $this->_add_validation_strategy(
26
-            new EE_Plaintext_Validation_Strategy($input_settings['validation_error_message'] ?? null)
27
-        );
28
-        parent::__construct($input_settings);
29
-        $this->set_html_class($this->html_class() . " $type");
15
+	/**
16
+	 * @param array $input_settings
17
+	 */
18
+	public function __construct($input_settings = [], $use_jquery_ui = false)
19
+	{
20
+		$this->use_jquery_ui = (bool) apply_filters('FHEE__EE_Datepicker_Input__use_jquery_ui', $use_jquery_ui);
21
+		$type                = $this->use_jquery_ui ? 'datepicker' : 'date';
22
+		$this->_set_display_strategy(new EE_Text_Input_Display_Strategy($type));
23
+		$this->_set_normalization_strategy(new EE_Text_Normalization());
24
+		// we could do better for validation, but at least verify its plaintext
25
+		$this->_add_validation_strategy(
26
+			new EE_Plaintext_Validation_Strategy($input_settings['validation_error_message'] ?? null)
27
+		);
28
+		parent::__construct($input_settings);
29
+		$this->set_html_class($this->html_class() . " $type");
30 30
 
31
-        if ($this->use_jquery_ui) {
32
-            // add some style and make it dance
33
-            add_action('wp_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
34
-            add_action('admin_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
35
-        }
36
-    }
31
+		if ($this->use_jquery_ui) {
32
+			// add some style and make it dance
33
+			add_action('wp_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
34
+			add_action('admin_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
35
+		}
36
+	}
37 37
 
38 38
 
39
-    /**
40
-     *    enqueue_styles_and_scripts
41
-     *
42
-     * @access        public
43
-     * @return        void
44
-     */
45
-    public static function enqueue_styles_and_scripts()
46
-    {
47
-        // load css
48
-        wp_register_style(
49
-            'espresso-ui-theme',
50
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
51
-            [],
52
-            EVENT_ESPRESSO_VERSION
53
-        );
54
-        wp_enqueue_style('espresso-ui-theme');
55
-    }
39
+	/**
40
+	 *    enqueue_styles_and_scripts
41
+	 *
42
+	 * @access        public
43
+	 * @return        void
44
+	 */
45
+	public static function enqueue_styles_and_scripts()
46
+	{
47
+		// load css
48
+		wp_register_style(
49
+			'espresso-ui-theme',
50
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
51
+			[],
52
+			EVENT_ESPRESSO_VERSION
53
+		);
54
+		wp_enqueue_style('espresso-ui-theme');
55
+	}
56 56
 
57 57
 
58
-    /**
59
-     * converts the raw value into a date strimg in the format Y-m-d
60
-     * unless we're using jquery ui, in which case we just return the raw value
61
-     *
62
-     * @return string
63
-     * @throws Exception
64
-     */
65
-    public function raw_value_in_form(): string
66
-    {
67
-        $raw_value = $this->raw_value();
68
-        if ($this->use_jquery_ui || ! $raw_value) {
69
-            return parent::raw_value_in_form();
70
-        }
71
-        // load the CURRENT WordPress date format and try that
72
-        $date = DateTime::createFromFormat(get_option('date_format', 'Y-m-d'), $raw_value);
73
-        if ($date instanceof DateTime) {
74
-            return $date->format('Y-m-d');
75
-        }
76
-        // nope? ok check if date format can just be parsed as is
77
-        $timestamp = strtotime($raw_value);
78
-        if ($timestamp) {
79
-            $date = date('Y-m-d', $timestamp);
80
-            if ($date) {
81
-                return $date;
82
-            }
83
-        }
84
-        // ... errr... ok... just return the raw value
85
-        return $raw_value;
86
-    }
58
+	/**
59
+	 * converts the raw value into a date strimg in the format Y-m-d
60
+	 * unless we're using jquery ui, in which case we just return the raw value
61
+	 *
62
+	 * @return string
63
+	 * @throws Exception
64
+	 */
65
+	public function raw_value_in_form(): string
66
+	{
67
+		$raw_value = $this->raw_value();
68
+		if ($this->use_jquery_ui || ! $raw_value) {
69
+			return parent::raw_value_in_form();
70
+		}
71
+		// load the CURRENT WordPress date format and try that
72
+		$date = DateTime::createFromFormat(get_option('date_format', 'Y-m-d'), $raw_value);
73
+		if ($date instanceof DateTime) {
74
+			return $date->format('Y-m-d');
75
+		}
76
+		// nope? ok check if date format can just be parsed as is
77
+		$timestamp = strtotime($raw_value);
78
+		if ($timestamp) {
79
+			$date = date('Y-m-d', $timestamp);
80
+			if ($date) {
81
+				return $date;
82
+			}
83
+		}
84
+		// ... errr... ok... just return the raw value
85
+		return $raw_value;
86
+	}
87 87
 }
Please login to merge, or discard this patch.