Completed
Branch BUG/fix-ee-rest-debug-headers (1355bc)
by
unknown
03:29 queued 18s
created
core/db_classes/EE_Attendee.class.php 2 patches
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -36,16 +36,16 @@  discard block
 block discarded – undo
36 36
      */
37 37
     protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
38 38
     {
39
-        if (! isset($fieldValues['ATT_full_name'])) {
40
-            $fname = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
39
+        if ( ! isset($fieldValues['ATT_full_name'])) {
40
+            $fname = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'].' ' : '';
41 41
             $lname = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
42
-            $fieldValues['ATT_full_name'] = $fname . $lname;
42
+            $fieldValues['ATT_full_name'] = $fname.$lname;
43 43
         }
44
-        if (! isset($fieldValues['ATT_slug'])) {
44
+        if ( ! isset($fieldValues['ATT_slug'])) {
45 45
             // $fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
46 46
             $fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
47 47
         }
48
-        if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
48
+        if ( ! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
49 49
             $fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
50 50
         }
51 51
         parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
@@ -325,7 +325,7 @@  discard block
 block discarded – undo
325 325
         $initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
326 326
         foreach ($initial_address_fields as $address_field_name) {
327 327
             $address_fields_value = $this->get($address_field_name);
328
-            if (! empty($address_fields_value)) {
328
+            if ( ! empty($address_fields_value)) {
329 329
                 $full_address_array[] = $address_fields_value;
330 330
             }
331 331
         }
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
         }
341 341
         // lastly get the xip
342 342
         $zip_value = $this->zip();
343
-        if (! empty($zip_value)) {
343
+        if ( ! empty($zip_value)) {
344 344
             $full_address_array[] = $zip_value;
345 345
         }
346 346
         return $full_address_array;
@@ -622,18 +622,18 @@  discard block
 block discarded – undo
622 622
     public function billing_info_for_payment_method($payment_method)
623 623
     {
624 624
         $pm_type = $payment_method->type_obj();
625
-        if (! $pm_type instanceof EE_PMT_Base) {
625
+        if ( ! $pm_type instanceof EE_PMT_Base) {
626 626
             return null;
627 627
         }
628 628
         $billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
629
-        if (! $billing_info) {
629
+        if ( ! $billing_info) {
630 630
             return null;
631 631
         }
632 632
         $billing_form = $pm_type->billing_form();
633 633
         // double-check the form isn't totally hidden, in which case pretend there is no form
634 634
         $form_totally_hidden = true;
635 635
         foreach ($billing_form->inputs_in_subsections() as $input) {
636
-            if (! $input->get_display_strategy() instanceof EE_Hidden_Display_Strategy) {
636
+            if ( ! $input->get_display_strategy() instanceof EE_Hidden_Display_Strategy) {
637 637
                 $form_totally_hidden = false;
638 638
                 break;
639 639
             }
@@ -660,7 +660,7 @@  discard block
 block discarded – undo
660 660
     public function get_billing_info_postmeta_name($payment_method)
661 661
     {
662 662
         if ($payment_method->type_obj() instanceof EE_PMT_Base) {
663
-            return 'billing_info_' . $payment_method->type_obj()->system_name();
663
+            return 'billing_info_'.$payment_method->type_obj()->system_name();
664 664
         }
665 665
         return null;
666 666
     }
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
      */
678 678
     public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
679 679
     {
680
-        if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
680
+        if ( ! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
681 681
             EE_Error::add_error(esc_html__('Cannot save billing info because there is none.', 'event_espresso'));
682 682
             return false;
683 683
         }
Please login to merge, or discard this patch.
Indentation   +742 added lines, -742 removed lines patch added patch discarded remove patch
@@ -24,746 +24,746 @@
 block discarded – undo
24 24
  */
25 25
 class EE_Attendee extends EE_CPT_Base implements EEI_Contact, EEI_Address, EEI_Admin_Links, EEI_Attendee
26 26
 {
27
-    /**
28
-     * Sets some dynamic defaults
29
-     *
30
-     * @param array  $fieldValues
31
-     * @param bool   $bydb
32
-     * @param string $timezone
33
-     * @param array  $date_formats
34
-     * @throws EE_Error
35
-     */
36
-    protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
37
-    {
38
-        if (! isset($fieldValues['ATT_full_name'])) {
39
-            $fname = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
40
-            $lname = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
41
-            $fieldValues['ATT_full_name'] = $fname . $lname;
42
-        }
43
-        if (! isset($fieldValues['ATT_slug'])) {
44
-            // $fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
45
-            $fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
46
-        }
47
-        if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
48
-            $fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
49
-        }
50
-        parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
51
-    }
52
-
53
-
54
-    /**
55
-     * @param array  $props_n_values          incoming values
56
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
57
-     *                                        used.)
58
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
59
-     *                                        date_format and the second value is the time format
60
-     * @return EE_Attendee
61
-     * @throws EE_Error
62
-     */
63
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
64
-    {
65
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
66
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
67
-    }
68
-
69
-
70
-    /**
71
-     * @param array  $props_n_values  incoming values from the database
72
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
73
-     *                                the website will be used.
74
-     * @return EE_Attendee
75
-     */
76
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
77
-    {
78
-        return new self($props_n_values, true, $timezone);
79
-    }
80
-
81
-
82
-    /**
83
-     *        Set Attendee First Name
84
-     *
85
-     * @access        public
86
-     * @param string $fname
87
-     * @throws EE_Error
88
-     */
89
-    public function set_fname($fname = '')
90
-    {
91
-        $this->set('ATT_fname', $fname);
92
-    }
93
-
94
-
95
-    /**
96
-     *        Set Attendee Last Name
97
-     *
98
-     * @access        public
99
-     * @param string $lname
100
-     * @throws EE_Error
101
-     */
102
-    public function set_lname($lname = '')
103
-    {
104
-        $this->set('ATT_lname', $lname);
105
-    }
106
-
107
-
108
-    /**
109
-     *        Set Attendee Address
110
-     *
111
-     * @access        public
112
-     * @param string $address
113
-     * @throws EE_Error
114
-     */
115
-    public function set_address($address = '')
116
-    {
117
-        $this->set('ATT_address', $address);
118
-    }
119
-
120
-
121
-    /**
122
-     *        Set Attendee Address2
123
-     *
124
-     * @access        public
125
-     * @param        string $address2
126
-     * @throws EE_Error
127
-     */
128
-    public function set_address2($address2 = '')
129
-    {
130
-        $this->set('ATT_address2', $address2);
131
-    }
132
-
133
-
134
-    /**
135
-     *        Set Attendee City
136
-     *
137
-     * @access        public
138
-     * @param        string $city
139
-     * @throws EE_Error
140
-     */
141
-    public function set_city($city = '')
142
-    {
143
-        $this->set('ATT_city', $city);
144
-    }
145
-
146
-
147
-    /**
148
-     *        Set Attendee State ID
149
-     *
150
-     * @access        public
151
-     * @param        int $STA_ID
152
-     * @throws EE_Error
153
-     */
154
-    public function set_state($STA_ID = 0)
155
-    {
156
-        $this->set('STA_ID', $STA_ID);
157
-    }
158
-
159
-
160
-    /**
161
-     *        Set Attendee Country ISO Code
162
-     *
163
-     * @access        public
164
-     * @param        string $CNT_ISO
165
-     * @throws EE_Error
166
-     */
167
-    public function set_country($CNT_ISO = '')
168
-    {
169
-        $this->set('CNT_ISO', $CNT_ISO);
170
-    }
171
-
172
-
173
-    /**
174
-     *        Set Attendee Zip/Postal Code
175
-     *
176
-     * @access        public
177
-     * @param        string $zip
178
-     * @throws EE_Error
179
-     */
180
-    public function set_zip($zip = '')
181
-    {
182
-        $this->set('ATT_zip', $zip);
183
-    }
184
-
185
-
186
-    /**
187
-     *        Set Attendee Email Address
188
-     *
189
-     * @access        public
190
-     * @param        string $email
191
-     * @throws EE_Error
192
-     */
193
-    public function set_email($email = '')
194
-    {
195
-        $this->set('ATT_email', $email);
196
-    }
197
-
198
-
199
-    /**
200
-     *        Set Attendee Phone
201
-     *
202
-     * @access        public
203
-     * @param        string $phone
204
-     * @throws EE_Error
205
-     */
206
-    public function set_phone($phone = '')
207
-    {
208
-        $this->set('ATT_phone', $phone);
209
-    }
210
-
211
-
212
-    /**
213
-     *        set deleted
214
-     *
215
-     * @access        public
216
-     * @param        bool $ATT_deleted
217
-     * @throws EE_Error
218
-     */
219
-    public function set_deleted($ATT_deleted = false)
220
-    {
221
-        $this->set('ATT_deleted', $ATT_deleted);
222
-    }
223
-
224
-
225
-    /**
226
-     * Returns the value for the post_author id saved with the cpt
227
-     *
228
-     * @since 4.5.0
229
-     * @return int
230
-     * @throws EE_Error
231
-     */
232
-    public function wp_user()
233
-    {
234
-        return $this->get('ATT_author');
235
-    }
236
-
237
-
238
-    /**
239
-     *        get Attendee First Name
240
-     *
241
-     * @access        public
242
-     * @return string
243
-     * @throws EE_Error
244
-     */
245
-    public function fname()
246
-    {
247
-        return $this->get('ATT_fname');
248
-    }
249
-
250
-
251
-    /**
252
-     * echoes out the attendee's first name
253
-     *
254
-     * @return void
255
-     * @throws EE_Error
256
-     */
257
-    public function e_full_name()
258
-    {
259
-        echo esc_html($this->full_name());
260
-    }
261
-
262
-
263
-    /**
264
-     * Returns the first and last name concatenated together with a space.
265
-     *
266
-     * @param bool $apply_html_entities
267
-     * @return string
268
-     * @throws EE_Error
269
-     */
270
-    public function full_name($apply_html_entities = false)
271
-    {
272
-        $full_name = array(
273
-            $this->fname(),
274
-            $this->lname(),
275
-        );
276
-        $full_name = array_filter($full_name);
277
-        $full_name = implode(' ', $full_name);
278
-        return $apply_html_entities ? htmlentities($full_name, ENT_QUOTES, 'UTF-8') : $full_name;
279
-    }
280
-
281
-
282
-    /**
283
-     * This returns the value of the `ATT_full_name` field which is usually equivalent to calling `full_name()` unless
284
-     * the post_title field has been directly modified in the db for the post (espresso_attendees post type) for this
285
-     * attendee.
286
-     *
287
-     * @param bool $apply_html_entities
288
-     * @return string
289
-     * @throws EE_Error
290
-     */
291
-    public function ATT_full_name($apply_html_entities = false)
292
-    {
293
-        return $apply_html_entities
294
-            ? htmlentities($this->get('ATT_full_name'), ENT_QUOTES, 'UTF-8')
295
-            : $this->get('ATT_full_name');
296
-    }
297
-
298
-
299
-    /**
300
-     *        get Attendee Last Name
301
-     *
302
-     * @access        public
303
-     * @return string
304
-     * @throws EE_Error
305
-     */
306
-    public function lname()
307
-    {
308
-        return $this->get('ATT_lname');
309
-    }
310
-
311
-
312
-    /**
313
-     * Gets the attendee's full address as an array so client code can decide hwo to display it
314
-     *
315
-     * @return array numerically indexed, with each part of the address that is known.
316
-     * Eg, if the user only responded to state and country,
317
-     * it would be array(0=>'Alabama',1=>'USA')
318
-     * @return array
319
-     * @throws EE_Error
320
-     */
321
-    public function full_address_as_array()
322
-    {
323
-        $full_address_array = array();
324
-        $initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
325
-        foreach ($initial_address_fields as $address_field_name) {
326
-            $address_fields_value = $this->get($address_field_name);
327
-            if (! empty($address_fields_value)) {
328
-                $full_address_array[] = $address_fields_value;
329
-            }
330
-        }
331
-        // now handle state and country
332
-        $state_obj = $this->state_obj();
333
-        if ($state_obj instanceof EE_State) {
334
-            $full_address_array[] = $state_obj->name();
335
-        }
336
-        $country_obj = $this->country_obj();
337
-        if ($country_obj instanceof EE_Country) {
338
-            $full_address_array[] = $country_obj->name();
339
-        }
340
-        // lastly get the xip
341
-        $zip_value = $this->zip();
342
-        if (! empty($zip_value)) {
343
-            $full_address_array[] = $zip_value;
344
-        }
345
-        return $full_address_array;
346
-    }
347
-
348
-
349
-    /**
350
-     *        get Attendee Address
351
-     *
352
-     * @return string
353
-     * @throws EE_Error
354
-     */
355
-    public function address()
356
-    {
357
-        return $this->get('ATT_address');
358
-    }
359
-
360
-
361
-    /**
362
-     *        get Attendee Address2
363
-     *
364
-     * @return string
365
-     * @throws EE_Error
366
-     */
367
-    public function address2()
368
-    {
369
-        return $this->get('ATT_address2');
370
-    }
371
-
372
-
373
-    /**
374
-     *        get Attendee City
375
-     *
376
-     * @return string
377
-     * @throws EE_Error
378
-     */
379
-    public function city()
380
-    {
381
-        return $this->get('ATT_city');
382
-    }
383
-
384
-
385
-    /**
386
-     *        get Attendee State ID
387
-     *
388
-     * @return string
389
-     * @throws EE_Error
390
-     */
391
-    public function state_ID()
392
-    {
393
-        return $this->get('STA_ID');
394
-    }
395
-
396
-
397
-    /**
398
-     * @return string
399
-     * @throws EE_Error
400
-     */
401
-    public function state_abbrev()
402
-    {
403
-        return $this->state_obj() instanceof EE_State ? $this->state_obj()->abbrev() : '';
404
-    }
405
-
406
-
407
-    /**
408
-     * Gets the state set to this attendee
409
-     *
410
-     * @return EE_State
411
-     * @throws EE_Error
412
-     */
413
-    public function state_obj()
414
-    {
415
-        return $this->get_first_related('State');
416
-    }
417
-
418
-
419
-    /**
420
-     * Returns the state's name, otherwise 'Unknown'
421
-     *
422
-     * @return string
423
-     * @throws EE_Error
424
-     */
425
-    public function state_name()
426
-    {
427
-        if ($this->state_obj()) {
428
-            return $this->state_obj()->name();
429
-        } else {
430
-            return '';
431
-        }
432
-    }
433
-
434
-
435
-    /**
436
-     * either displays the state abbreviation or the state name, as determined
437
-     * by the "FHEE__EEI_Address__state__use_abbreviation" filter.
438
-     * defaults to abbreviation
439
-     *
440
-     * @return string
441
-     * @throws EE_Error
442
-     */
443
-    public function state()
444
-    {
445
-        if (apply_filters('FHEE__EEI_Address__state__use_abbreviation', true, $this->state_obj())) {
446
-            return $this->state_abbrev();
447
-        }
448
-        return $this->state_name();
449
-    }
450
-
451
-
452
-    /**
453
-     *    get Attendee Country ISO Code
454
-     *
455
-     * @return string
456
-     * @throws EE_Error
457
-     */
458
-    public function country_ID()
459
-    {
460
-        return $this->get('CNT_ISO');
461
-    }
462
-
463
-
464
-    /**
465
-     * Gets country set for this attendee
466
-     *
467
-     * @return EE_Country
468
-     * @throws EE_Error
469
-     */
470
-    public function country_obj()
471
-    {
472
-        return $this->get_first_related('Country');
473
-    }
474
-
475
-
476
-    /**
477
-     * Returns the country's name if known, otherwise 'Unknown'
478
-     *
479
-     * @return string
480
-     * @throws EE_Error
481
-     */
482
-    public function country_name()
483
-    {
484
-        if ($this->country_obj()) {
485
-            return $this->country_obj()->name();
486
-        }
487
-        return '';
488
-    }
489
-
490
-
491
-    /**
492
-     * either displays the country ISO2 code or the country name, as determined
493
-     * by the "FHEE__EEI_Address__country__use_abbreviation" filter.
494
-     * defaults to abbreviation
495
-     *
496
-     * @return string
497
-     * @throws EE_Error
498
-     */
499
-    public function country()
500
-    {
501
-        if (apply_filters('FHEE__EEI_Address__country__use_abbreviation', true, $this->country_obj())) {
502
-            return $this->country_ID();
503
-        }
504
-        return $this->country_name();
505
-    }
506
-
507
-
508
-    /**
509
-     *        get Attendee Zip/Postal Code
510
-     *
511
-     * @return string
512
-     * @throws EE_Error
513
-     */
514
-    public function zip()
515
-    {
516
-        return $this->get('ATT_zip');
517
-    }
518
-
519
-
520
-    /**
521
-     *        get Attendee Email Address
522
-     *
523
-     * @return string
524
-     * @throws EE_Error
525
-     */
526
-    public function email()
527
-    {
528
-        return $this->get('ATT_email');
529
-    }
530
-
531
-
532
-    /**
533
-     *        get Attendee Phone #
534
-     *
535
-     * @return string
536
-     * @throws EE_Error
537
-     */
538
-    public function phone()
539
-    {
540
-        return $this->get('ATT_phone');
541
-    }
542
-
543
-
544
-    /**
545
-     *    get deleted
546
-     *
547
-     * @return        bool
548
-     * @throws EE_Error
549
-     */
550
-    public function deleted()
551
-    {
552
-        return $this->get('ATT_deleted');
553
-    }
554
-
555
-
556
-    /**
557
-     * Gets registrations of this attendee
558
-     *
559
-     * @param array $query_params
560
-     * @return EE_Registration[]
561
-     * @throws EE_Error
562
-     */
563
-    public function get_registrations($query_params = array())
564
-    {
565
-        return $this->get_many_related('Registration', $query_params);
566
-    }
567
-
568
-
569
-    /**
570
-     * Gets the most recent registration of this attendee
571
-     *
572
-     * @return EE_Registration
573
-     * @throws EE_Error
574
-     */
575
-    public function get_most_recent_registration()
576
-    {
577
-        return $this->get_first_related(
578
-            'Registration',
579
-            array('order_by' => array('REG_date' => 'DESC'))
580
-        ); // null, 'REG_date', 'DESC', '=', 'OBJECT_K');
581
-    }
582
-
583
-
584
-    /**
585
-     * Gets the most recent registration for this attend at this event
586
-     *
587
-     * @param int $event_id
588
-     * @return EE_Registration
589
-     * @throws EE_Error
590
-     */
591
-    public function get_most_recent_registration_for_event($event_id)
592
-    {
593
-        return $this->get_first_related(
594
-            'Registration',
595
-            array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC'))
596
-        );
597
-    }
598
-
599
-
600
-    /**
601
-     * returns any events attached to this attendee ($_Event property);
602
-     *
603
-     * @return array
604
-     * @throws EE_Error
605
-     */
606
-    public function events()
607
-    {
608
-        return $this->get_many_related('Event');
609
-    }
610
-
611
-
612
-    /**
613
-     * Gets the billing info array where keys match espresso_reg_page_billing_inputs(),
614
-     * and keys are their cleaned values. @see EE_Attendee::save_and_clean_billing_info_for_payment_method() which was
615
-     * used to save the billing info
616
-     *
617
-     * @param EE_Payment_Method $payment_method the _gateway_name property on the gateway class
618
-     * @return EE_Form_Section_Proper|null
619
-     * @throws EE_Error
620
-     */
621
-    public function billing_info_for_payment_method($payment_method)
622
-    {
623
-        $pm_type = $payment_method->type_obj();
624
-        if (! $pm_type instanceof EE_PMT_Base) {
625
-            return null;
626
-        }
627
-        $billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
628
-        if (! $billing_info) {
629
-            return null;
630
-        }
631
-        $billing_form = $pm_type->billing_form();
632
-        // double-check the form isn't totally hidden, in which case pretend there is no form
633
-        $form_totally_hidden = true;
634
-        foreach ($billing_form->inputs_in_subsections() as $input) {
635
-            if (! $input->get_display_strategy() instanceof EE_Hidden_Display_Strategy) {
636
-                $form_totally_hidden = false;
637
-                break;
638
-            }
639
-        }
640
-        if ($form_totally_hidden) {
641
-            return null;
642
-        }
643
-        if ($billing_form instanceof EE_Form_Section_Proper) {
644
-            $billing_form->receive_form_submission(array($billing_form->name() => $billing_info), false);
645
-        }
646
-
647
-        return $billing_form;
648
-    }
649
-
650
-
651
-    /**
652
-     * Gets the postmeta key that holds this attendee's billing info for the
653
-     * specified payment method
654
-     *
655
-     * @param EE_Payment_Method $payment_method
656
-     * @return string
657
-     * @throws EE_Error
658
-     */
659
-    public function get_billing_info_postmeta_name($payment_method)
660
-    {
661
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
662
-            return 'billing_info_' . $payment_method->type_obj()->system_name();
663
-        }
664
-        return null;
665
-    }
666
-
667
-
668
-    /**
669
-     * Saves the billing info to the attendee. @see EE_Attendee::billing_info_for_payment_method() which is used to
670
-     * retrieve it
671
-     *
672
-     * @param EE_Billing_Attendee_Info_Form $billing_form
673
-     * @param EE_Payment_Method             $payment_method
674
-     * @return boolean
675
-     * @throws EE_Error
676
-     */
677
-    public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
678
-    {
679
-        if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
680
-            EE_Error::add_error(esc_html__('Cannot save billing info because there is none.', 'event_espresso'));
681
-            return false;
682
-        }
683
-        $billing_form->clean_sensitive_data();
684
-        return update_post_meta(
685
-            $this->ID(),
686
-            $this->get_billing_info_postmeta_name($payment_method),
687
-            $billing_form->input_values(true)
688
-        );
689
-    }
690
-
691
-
692
-    /**
693
-     * Return the link to the admin details for the object.
694
-     *
695
-     * @return string
696
-     * @throws EE_Error
697
-     * @throws InvalidArgumentException
698
-     * @throws InvalidDataTypeException
699
-     * @throws InvalidInterfaceException
700
-     * @throws ReflectionException
701
-     */
702
-    public function get_admin_details_link()
703
-    {
704
-        return $this->get_admin_edit_link();
705
-    }
706
-
707
-
708
-    /**
709
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
710
-     *
711
-     * @return string
712
-     * @throws EE_Error
713
-     * @throws InvalidArgumentException
714
-     * @throws ReflectionException
715
-     * @throws InvalidDataTypeException
716
-     * @throws InvalidInterfaceException
717
-     */
718
-    public function get_admin_edit_link()
719
-    {
720
-        EE_Registry::instance()->load_helper('URL');
721
-        return EEH_URL::add_query_args_and_nonce(
722
-            array(
723
-                'page'   => 'espresso_registrations',
724
-                'action' => 'edit_attendee',
725
-                'post'   => $this->ID(),
726
-            ),
727
-            admin_url('admin.php')
728
-        );
729
-    }
730
-
731
-
732
-    /**
733
-     * Returns the link to a settings page for the object.
734
-     *
735
-     * @return string
736
-     * @throws EE_Error
737
-     * @throws InvalidArgumentException
738
-     * @throws InvalidDataTypeException
739
-     * @throws InvalidInterfaceException
740
-     * @throws ReflectionException
741
-     */
742
-    public function get_admin_settings_link()
743
-    {
744
-        return $this->get_admin_edit_link();
745
-    }
746
-
747
-
748
-    /**
749
-     * Returns the link to the "overview" for the object (typically the "list table" view).
750
-     *
751
-     * @return string
752
-     * @throws EE_Error
753
-     * @throws InvalidArgumentException
754
-     * @throws ReflectionException
755
-     * @throws InvalidDataTypeException
756
-     * @throws InvalidInterfaceException
757
-     */
758
-    public function get_admin_overview_link()
759
-    {
760
-        EE_Registry::instance()->load_helper('URL');
761
-        return EEH_URL::add_query_args_and_nonce(
762
-            array(
763
-                'page'   => 'espresso_registrations',
764
-                'action' => 'contact_list',
765
-            ),
766
-            admin_url('admin.php')
767
-        );
768
-    }
27
+	/**
28
+	 * Sets some dynamic defaults
29
+	 *
30
+	 * @param array  $fieldValues
31
+	 * @param bool   $bydb
32
+	 * @param string $timezone
33
+	 * @param array  $date_formats
34
+	 * @throws EE_Error
35
+	 */
36
+	protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
37
+	{
38
+		if (! isset($fieldValues['ATT_full_name'])) {
39
+			$fname = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
40
+			$lname = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
41
+			$fieldValues['ATT_full_name'] = $fname . $lname;
42
+		}
43
+		if (! isset($fieldValues['ATT_slug'])) {
44
+			// $fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
45
+			$fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
46
+		}
47
+		if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
48
+			$fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
49
+		}
50
+		parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
51
+	}
52
+
53
+
54
+	/**
55
+	 * @param array  $props_n_values          incoming values
56
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
57
+	 *                                        used.)
58
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
59
+	 *                                        date_format and the second value is the time format
60
+	 * @return EE_Attendee
61
+	 * @throws EE_Error
62
+	 */
63
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
64
+	{
65
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
66
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
67
+	}
68
+
69
+
70
+	/**
71
+	 * @param array  $props_n_values  incoming values from the database
72
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
73
+	 *                                the website will be used.
74
+	 * @return EE_Attendee
75
+	 */
76
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
77
+	{
78
+		return new self($props_n_values, true, $timezone);
79
+	}
80
+
81
+
82
+	/**
83
+	 *        Set Attendee First Name
84
+	 *
85
+	 * @access        public
86
+	 * @param string $fname
87
+	 * @throws EE_Error
88
+	 */
89
+	public function set_fname($fname = '')
90
+	{
91
+		$this->set('ATT_fname', $fname);
92
+	}
93
+
94
+
95
+	/**
96
+	 *        Set Attendee Last Name
97
+	 *
98
+	 * @access        public
99
+	 * @param string $lname
100
+	 * @throws EE_Error
101
+	 */
102
+	public function set_lname($lname = '')
103
+	{
104
+		$this->set('ATT_lname', $lname);
105
+	}
106
+
107
+
108
+	/**
109
+	 *        Set Attendee Address
110
+	 *
111
+	 * @access        public
112
+	 * @param string $address
113
+	 * @throws EE_Error
114
+	 */
115
+	public function set_address($address = '')
116
+	{
117
+		$this->set('ATT_address', $address);
118
+	}
119
+
120
+
121
+	/**
122
+	 *        Set Attendee Address2
123
+	 *
124
+	 * @access        public
125
+	 * @param        string $address2
126
+	 * @throws EE_Error
127
+	 */
128
+	public function set_address2($address2 = '')
129
+	{
130
+		$this->set('ATT_address2', $address2);
131
+	}
132
+
133
+
134
+	/**
135
+	 *        Set Attendee City
136
+	 *
137
+	 * @access        public
138
+	 * @param        string $city
139
+	 * @throws EE_Error
140
+	 */
141
+	public function set_city($city = '')
142
+	{
143
+		$this->set('ATT_city', $city);
144
+	}
145
+
146
+
147
+	/**
148
+	 *        Set Attendee State ID
149
+	 *
150
+	 * @access        public
151
+	 * @param        int $STA_ID
152
+	 * @throws EE_Error
153
+	 */
154
+	public function set_state($STA_ID = 0)
155
+	{
156
+		$this->set('STA_ID', $STA_ID);
157
+	}
158
+
159
+
160
+	/**
161
+	 *        Set Attendee Country ISO Code
162
+	 *
163
+	 * @access        public
164
+	 * @param        string $CNT_ISO
165
+	 * @throws EE_Error
166
+	 */
167
+	public function set_country($CNT_ISO = '')
168
+	{
169
+		$this->set('CNT_ISO', $CNT_ISO);
170
+	}
171
+
172
+
173
+	/**
174
+	 *        Set Attendee Zip/Postal Code
175
+	 *
176
+	 * @access        public
177
+	 * @param        string $zip
178
+	 * @throws EE_Error
179
+	 */
180
+	public function set_zip($zip = '')
181
+	{
182
+		$this->set('ATT_zip', $zip);
183
+	}
184
+
185
+
186
+	/**
187
+	 *        Set Attendee Email Address
188
+	 *
189
+	 * @access        public
190
+	 * @param        string $email
191
+	 * @throws EE_Error
192
+	 */
193
+	public function set_email($email = '')
194
+	{
195
+		$this->set('ATT_email', $email);
196
+	}
197
+
198
+
199
+	/**
200
+	 *        Set Attendee Phone
201
+	 *
202
+	 * @access        public
203
+	 * @param        string $phone
204
+	 * @throws EE_Error
205
+	 */
206
+	public function set_phone($phone = '')
207
+	{
208
+		$this->set('ATT_phone', $phone);
209
+	}
210
+
211
+
212
+	/**
213
+	 *        set deleted
214
+	 *
215
+	 * @access        public
216
+	 * @param        bool $ATT_deleted
217
+	 * @throws EE_Error
218
+	 */
219
+	public function set_deleted($ATT_deleted = false)
220
+	{
221
+		$this->set('ATT_deleted', $ATT_deleted);
222
+	}
223
+
224
+
225
+	/**
226
+	 * Returns the value for the post_author id saved with the cpt
227
+	 *
228
+	 * @since 4.5.0
229
+	 * @return int
230
+	 * @throws EE_Error
231
+	 */
232
+	public function wp_user()
233
+	{
234
+		return $this->get('ATT_author');
235
+	}
236
+
237
+
238
+	/**
239
+	 *        get Attendee First Name
240
+	 *
241
+	 * @access        public
242
+	 * @return string
243
+	 * @throws EE_Error
244
+	 */
245
+	public function fname()
246
+	{
247
+		return $this->get('ATT_fname');
248
+	}
249
+
250
+
251
+	/**
252
+	 * echoes out the attendee's first name
253
+	 *
254
+	 * @return void
255
+	 * @throws EE_Error
256
+	 */
257
+	public function e_full_name()
258
+	{
259
+		echo esc_html($this->full_name());
260
+	}
261
+
262
+
263
+	/**
264
+	 * Returns the first and last name concatenated together with a space.
265
+	 *
266
+	 * @param bool $apply_html_entities
267
+	 * @return string
268
+	 * @throws EE_Error
269
+	 */
270
+	public function full_name($apply_html_entities = false)
271
+	{
272
+		$full_name = array(
273
+			$this->fname(),
274
+			$this->lname(),
275
+		);
276
+		$full_name = array_filter($full_name);
277
+		$full_name = implode(' ', $full_name);
278
+		return $apply_html_entities ? htmlentities($full_name, ENT_QUOTES, 'UTF-8') : $full_name;
279
+	}
280
+
281
+
282
+	/**
283
+	 * This returns the value of the `ATT_full_name` field which is usually equivalent to calling `full_name()` unless
284
+	 * the post_title field has been directly modified in the db for the post (espresso_attendees post type) for this
285
+	 * attendee.
286
+	 *
287
+	 * @param bool $apply_html_entities
288
+	 * @return string
289
+	 * @throws EE_Error
290
+	 */
291
+	public function ATT_full_name($apply_html_entities = false)
292
+	{
293
+		return $apply_html_entities
294
+			? htmlentities($this->get('ATT_full_name'), ENT_QUOTES, 'UTF-8')
295
+			: $this->get('ATT_full_name');
296
+	}
297
+
298
+
299
+	/**
300
+	 *        get Attendee Last Name
301
+	 *
302
+	 * @access        public
303
+	 * @return string
304
+	 * @throws EE_Error
305
+	 */
306
+	public function lname()
307
+	{
308
+		return $this->get('ATT_lname');
309
+	}
310
+
311
+
312
+	/**
313
+	 * Gets the attendee's full address as an array so client code can decide hwo to display it
314
+	 *
315
+	 * @return array numerically indexed, with each part of the address that is known.
316
+	 * Eg, if the user only responded to state and country,
317
+	 * it would be array(0=>'Alabama',1=>'USA')
318
+	 * @return array
319
+	 * @throws EE_Error
320
+	 */
321
+	public function full_address_as_array()
322
+	{
323
+		$full_address_array = array();
324
+		$initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
325
+		foreach ($initial_address_fields as $address_field_name) {
326
+			$address_fields_value = $this->get($address_field_name);
327
+			if (! empty($address_fields_value)) {
328
+				$full_address_array[] = $address_fields_value;
329
+			}
330
+		}
331
+		// now handle state and country
332
+		$state_obj = $this->state_obj();
333
+		if ($state_obj instanceof EE_State) {
334
+			$full_address_array[] = $state_obj->name();
335
+		}
336
+		$country_obj = $this->country_obj();
337
+		if ($country_obj instanceof EE_Country) {
338
+			$full_address_array[] = $country_obj->name();
339
+		}
340
+		// lastly get the xip
341
+		$zip_value = $this->zip();
342
+		if (! empty($zip_value)) {
343
+			$full_address_array[] = $zip_value;
344
+		}
345
+		return $full_address_array;
346
+	}
347
+
348
+
349
+	/**
350
+	 *        get Attendee Address
351
+	 *
352
+	 * @return string
353
+	 * @throws EE_Error
354
+	 */
355
+	public function address()
356
+	{
357
+		return $this->get('ATT_address');
358
+	}
359
+
360
+
361
+	/**
362
+	 *        get Attendee Address2
363
+	 *
364
+	 * @return string
365
+	 * @throws EE_Error
366
+	 */
367
+	public function address2()
368
+	{
369
+		return $this->get('ATT_address2');
370
+	}
371
+
372
+
373
+	/**
374
+	 *        get Attendee City
375
+	 *
376
+	 * @return string
377
+	 * @throws EE_Error
378
+	 */
379
+	public function city()
380
+	{
381
+		return $this->get('ATT_city');
382
+	}
383
+
384
+
385
+	/**
386
+	 *        get Attendee State ID
387
+	 *
388
+	 * @return string
389
+	 * @throws EE_Error
390
+	 */
391
+	public function state_ID()
392
+	{
393
+		return $this->get('STA_ID');
394
+	}
395
+
396
+
397
+	/**
398
+	 * @return string
399
+	 * @throws EE_Error
400
+	 */
401
+	public function state_abbrev()
402
+	{
403
+		return $this->state_obj() instanceof EE_State ? $this->state_obj()->abbrev() : '';
404
+	}
405
+
406
+
407
+	/**
408
+	 * Gets the state set to this attendee
409
+	 *
410
+	 * @return EE_State
411
+	 * @throws EE_Error
412
+	 */
413
+	public function state_obj()
414
+	{
415
+		return $this->get_first_related('State');
416
+	}
417
+
418
+
419
+	/**
420
+	 * Returns the state's name, otherwise 'Unknown'
421
+	 *
422
+	 * @return string
423
+	 * @throws EE_Error
424
+	 */
425
+	public function state_name()
426
+	{
427
+		if ($this->state_obj()) {
428
+			return $this->state_obj()->name();
429
+		} else {
430
+			return '';
431
+		}
432
+	}
433
+
434
+
435
+	/**
436
+	 * either displays the state abbreviation or the state name, as determined
437
+	 * by the "FHEE__EEI_Address__state__use_abbreviation" filter.
438
+	 * defaults to abbreviation
439
+	 *
440
+	 * @return string
441
+	 * @throws EE_Error
442
+	 */
443
+	public function state()
444
+	{
445
+		if (apply_filters('FHEE__EEI_Address__state__use_abbreviation', true, $this->state_obj())) {
446
+			return $this->state_abbrev();
447
+		}
448
+		return $this->state_name();
449
+	}
450
+
451
+
452
+	/**
453
+	 *    get Attendee Country ISO Code
454
+	 *
455
+	 * @return string
456
+	 * @throws EE_Error
457
+	 */
458
+	public function country_ID()
459
+	{
460
+		return $this->get('CNT_ISO');
461
+	}
462
+
463
+
464
+	/**
465
+	 * Gets country set for this attendee
466
+	 *
467
+	 * @return EE_Country
468
+	 * @throws EE_Error
469
+	 */
470
+	public function country_obj()
471
+	{
472
+		return $this->get_first_related('Country');
473
+	}
474
+
475
+
476
+	/**
477
+	 * Returns the country's name if known, otherwise 'Unknown'
478
+	 *
479
+	 * @return string
480
+	 * @throws EE_Error
481
+	 */
482
+	public function country_name()
483
+	{
484
+		if ($this->country_obj()) {
485
+			return $this->country_obj()->name();
486
+		}
487
+		return '';
488
+	}
489
+
490
+
491
+	/**
492
+	 * either displays the country ISO2 code or the country name, as determined
493
+	 * by the "FHEE__EEI_Address__country__use_abbreviation" filter.
494
+	 * defaults to abbreviation
495
+	 *
496
+	 * @return string
497
+	 * @throws EE_Error
498
+	 */
499
+	public function country()
500
+	{
501
+		if (apply_filters('FHEE__EEI_Address__country__use_abbreviation', true, $this->country_obj())) {
502
+			return $this->country_ID();
503
+		}
504
+		return $this->country_name();
505
+	}
506
+
507
+
508
+	/**
509
+	 *        get Attendee Zip/Postal Code
510
+	 *
511
+	 * @return string
512
+	 * @throws EE_Error
513
+	 */
514
+	public function zip()
515
+	{
516
+		return $this->get('ATT_zip');
517
+	}
518
+
519
+
520
+	/**
521
+	 *        get Attendee Email Address
522
+	 *
523
+	 * @return string
524
+	 * @throws EE_Error
525
+	 */
526
+	public function email()
527
+	{
528
+		return $this->get('ATT_email');
529
+	}
530
+
531
+
532
+	/**
533
+	 *        get Attendee Phone #
534
+	 *
535
+	 * @return string
536
+	 * @throws EE_Error
537
+	 */
538
+	public function phone()
539
+	{
540
+		return $this->get('ATT_phone');
541
+	}
542
+
543
+
544
+	/**
545
+	 *    get deleted
546
+	 *
547
+	 * @return        bool
548
+	 * @throws EE_Error
549
+	 */
550
+	public function deleted()
551
+	{
552
+		return $this->get('ATT_deleted');
553
+	}
554
+
555
+
556
+	/**
557
+	 * Gets registrations of this attendee
558
+	 *
559
+	 * @param array $query_params
560
+	 * @return EE_Registration[]
561
+	 * @throws EE_Error
562
+	 */
563
+	public function get_registrations($query_params = array())
564
+	{
565
+		return $this->get_many_related('Registration', $query_params);
566
+	}
567
+
568
+
569
+	/**
570
+	 * Gets the most recent registration of this attendee
571
+	 *
572
+	 * @return EE_Registration
573
+	 * @throws EE_Error
574
+	 */
575
+	public function get_most_recent_registration()
576
+	{
577
+		return $this->get_first_related(
578
+			'Registration',
579
+			array('order_by' => array('REG_date' => 'DESC'))
580
+		); // null, 'REG_date', 'DESC', '=', 'OBJECT_K');
581
+	}
582
+
583
+
584
+	/**
585
+	 * Gets the most recent registration for this attend at this event
586
+	 *
587
+	 * @param int $event_id
588
+	 * @return EE_Registration
589
+	 * @throws EE_Error
590
+	 */
591
+	public function get_most_recent_registration_for_event($event_id)
592
+	{
593
+		return $this->get_first_related(
594
+			'Registration',
595
+			array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC'))
596
+		);
597
+	}
598
+
599
+
600
+	/**
601
+	 * returns any events attached to this attendee ($_Event property);
602
+	 *
603
+	 * @return array
604
+	 * @throws EE_Error
605
+	 */
606
+	public function events()
607
+	{
608
+		return $this->get_many_related('Event');
609
+	}
610
+
611
+
612
+	/**
613
+	 * Gets the billing info array where keys match espresso_reg_page_billing_inputs(),
614
+	 * and keys are their cleaned values. @see EE_Attendee::save_and_clean_billing_info_for_payment_method() which was
615
+	 * used to save the billing info
616
+	 *
617
+	 * @param EE_Payment_Method $payment_method the _gateway_name property on the gateway class
618
+	 * @return EE_Form_Section_Proper|null
619
+	 * @throws EE_Error
620
+	 */
621
+	public function billing_info_for_payment_method($payment_method)
622
+	{
623
+		$pm_type = $payment_method->type_obj();
624
+		if (! $pm_type instanceof EE_PMT_Base) {
625
+			return null;
626
+		}
627
+		$billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
628
+		if (! $billing_info) {
629
+			return null;
630
+		}
631
+		$billing_form = $pm_type->billing_form();
632
+		// double-check the form isn't totally hidden, in which case pretend there is no form
633
+		$form_totally_hidden = true;
634
+		foreach ($billing_form->inputs_in_subsections() as $input) {
635
+			if (! $input->get_display_strategy() instanceof EE_Hidden_Display_Strategy) {
636
+				$form_totally_hidden = false;
637
+				break;
638
+			}
639
+		}
640
+		if ($form_totally_hidden) {
641
+			return null;
642
+		}
643
+		if ($billing_form instanceof EE_Form_Section_Proper) {
644
+			$billing_form->receive_form_submission(array($billing_form->name() => $billing_info), false);
645
+		}
646
+
647
+		return $billing_form;
648
+	}
649
+
650
+
651
+	/**
652
+	 * Gets the postmeta key that holds this attendee's billing info for the
653
+	 * specified payment method
654
+	 *
655
+	 * @param EE_Payment_Method $payment_method
656
+	 * @return string
657
+	 * @throws EE_Error
658
+	 */
659
+	public function get_billing_info_postmeta_name($payment_method)
660
+	{
661
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
662
+			return 'billing_info_' . $payment_method->type_obj()->system_name();
663
+		}
664
+		return null;
665
+	}
666
+
667
+
668
+	/**
669
+	 * Saves the billing info to the attendee. @see EE_Attendee::billing_info_for_payment_method() which is used to
670
+	 * retrieve it
671
+	 *
672
+	 * @param EE_Billing_Attendee_Info_Form $billing_form
673
+	 * @param EE_Payment_Method             $payment_method
674
+	 * @return boolean
675
+	 * @throws EE_Error
676
+	 */
677
+	public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
678
+	{
679
+		if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
680
+			EE_Error::add_error(esc_html__('Cannot save billing info because there is none.', 'event_espresso'));
681
+			return false;
682
+		}
683
+		$billing_form->clean_sensitive_data();
684
+		return update_post_meta(
685
+			$this->ID(),
686
+			$this->get_billing_info_postmeta_name($payment_method),
687
+			$billing_form->input_values(true)
688
+		);
689
+	}
690
+
691
+
692
+	/**
693
+	 * Return the link to the admin details for the object.
694
+	 *
695
+	 * @return string
696
+	 * @throws EE_Error
697
+	 * @throws InvalidArgumentException
698
+	 * @throws InvalidDataTypeException
699
+	 * @throws InvalidInterfaceException
700
+	 * @throws ReflectionException
701
+	 */
702
+	public function get_admin_details_link()
703
+	{
704
+		return $this->get_admin_edit_link();
705
+	}
706
+
707
+
708
+	/**
709
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
710
+	 *
711
+	 * @return string
712
+	 * @throws EE_Error
713
+	 * @throws InvalidArgumentException
714
+	 * @throws ReflectionException
715
+	 * @throws InvalidDataTypeException
716
+	 * @throws InvalidInterfaceException
717
+	 */
718
+	public function get_admin_edit_link()
719
+	{
720
+		EE_Registry::instance()->load_helper('URL');
721
+		return EEH_URL::add_query_args_and_nonce(
722
+			array(
723
+				'page'   => 'espresso_registrations',
724
+				'action' => 'edit_attendee',
725
+				'post'   => $this->ID(),
726
+			),
727
+			admin_url('admin.php')
728
+		);
729
+	}
730
+
731
+
732
+	/**
733
+	 * Returns the link to a settings page for the object.
734
+	 *
735
+	 * @return string
736
+	 * @throws EE_Error
737
+	 * @throws InvalidArgumentException
738
+	 * @throws InvalidDataTypeException
739
+	 * @throws InvalidInterfaceException
740
+	 * @throws ReflectionException
741
+	 */
742
+	public function get_admin_settings_link()
743
+	{
744
+		return $this->get_admin_edit_link();
745
+	}
746
+
747
+
748
+	/**
749
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
750
+	 *
751
+	 * @return string
752
+	 * @throws EE_Error
753
+	 * @throws InvalidArgumentException
754
+	 * @throws ReflectionException
755
+	 * @throws InvalidDataTypeException
756
+	 * @throws InvalidInterfaceException
757
+	 */
758
+	public function get_admin_overview_link()
759
+	{
760
+		EE_Registry::instance()->load_helper('URL');
761
+		return EEH_URL::add_query_args_and_nonce(
762
+			array(
763
+				'page'   => 'espresso_registrations',
764
+				'action' => 'contact_list',
765
+			),
766
+			admin_url('admin.php')
767
+		);
768
+	}
769 769
 }
Please login to merge, or discard this patch.
core/EE_Payment_Processor.core.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
     public static function instance()
34 34
     {
35 35
         // check if class object is instantiated
36
-        if (! self::$_instance instanceof EE_Payment_Processor) {
36
+        if ( ! self::$_instance instanceof EE_Payment_Processor) {
37 37
             self::$_instance = new self();
38 38
         }
39 39
         return self::$_instance;
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
         /** @type \EE_Transaction $transaction */
171 171
         $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
172 172
         $primary_reg = $transaction->primary_registration();
173
-        if (! $primary_reg instanceof EE_Registration) {
173
+        if ( ! $primary_reg instanceof EE_Registration) {
174 174
             throw new EE_Error(
175 175
                 sprintf(
176 176
                     esc_html__(
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
                         EEM_Change_Log::instance()->log(
266 266
                             EEM_Change_Log::type_gateway,
267 267
                             array(
268
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
268
+                                'message'     => 'IPN Exception: '.$e->getMessage(),
269 269
                                 'current_url' => EEH_URL::current_url(),
270 270
                                 'payment'     => $e->getPaymentProperties(),
271 271
                                 'IPN_data'    => $e->getIpnData(),
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
                         EEM_Change_Log::instance()->log(
310 310
                             EEM_Change_Log::type_gateway,
311 311
                             array(
312
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
312
+                                'message'     => 'IPN Exception: '.$e->getMessage(),
313 313
                                 'current_url' => EEH_URL::current_url(),
314 314
                                 'payment'     => $e->getPaymentProperties(),
315 315
                                 'IPN_data'    => $e->getIpnData(),
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
     {
381 381
         $return_data = array();
382 382
         foreach ($request_data as $key => $value) {
383
-            $return_data[ $this->_remove_unusable_characters($key) ] = $this->_remove_unusable_characters(
383
+            $return_data[$this->_remove_unusable_characters($key)] = $this->_remove_unusable_characters(
384 384
                 $value
385 385
             );
386 386
         }
Please login to merge, or discard this patch.
Indentation   +842 added lines, -842 removed lines patch added patch discarded remove patch
@@ -17,846 +17,846 @@
 block discarded – undo
17 17
  */
18 18
 class EE_Payment_Processor extends EE_Processor_Base implements ResettableInterface
19 19
 {
20
-    /**
21
-     * @var EE_Payment_Processor $_instance
22
-     * @access    private
23
-     */
24
-    private static $_instance;
25
-
26
-
27
-    /**
28
-     * @singleton method used to instantiate class object
29
-     * @access    public
30
-     * @return EE_Payment_Processor instance
31
-     */
32
-    public static function instance()
33
-    {
34
-        // check if class object is instantiated
35
-        if (! self::$_instance instanceof EE_Payment_Processor) {
36
-            self::$_instance = new self();
37
-        }
38
-        return self::$_instance;
39
-    }
40
-
41
-
42
-    /**
43
-     * @return EE_Payment_Processor
44
-     */
45
-    public static function reset()
46
-    {
47
-        self::$_instance = null;
48
-        return self::instance();
49
-    }
50
-
51
-
52
-    /**
53
-     *private constructor to prevent direct creation
54
-     *
55
-     * @Constructor
56
-     * @access private
57
-     */
58
-    private function __construct()
59
-    {
60
-        do_action('AHEE__EE_Payment_Processor__construct');
61
-        add_action('http_api_curl', array($this, '_curl_requests_to_paypal_use_tls'), 10, 3);
62
-    }
63
-
64
-
65
-    /**
66
-     * Using the selected gateway, processes the payment for that transaction, and updates the transaction
67
-     * appropriately. Saves the payment that is generated
68
-     *
69
-     * @param EE_Payment_Method    $payment_method
70
-     * @param EE_Transaction       $transaction
71
-     * @param float                $amount       if only part of the transaction is to be paid for, how much.
72
-     *                                           Leave null if payment is for the full amount owing
73
-     * @param EE_Billing_Info_Form $billing_form (or probably null, if it's an offline or offsite payment method).
74
-     *                                           Receive_form_submission() should have
75
-     *                                           already been called on the billing form
76
-     *                                           (ie, its inputs should have their normalized values set).
77
-     * @param string               $return_url   string used mostly by offsite gateways to specify
78
-     *                                           where to go AFTER the offsite gateway
79
-     * @param string               $method       like 'CART', indicates who the client who called this was
80
-     * @param bool                 $by_admin     TRUE if payment is being attempted from the admin
81
-     * @param boolean              $update_txn   whether or not to call
82
-     *                                           EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
83
-     * @param string               $cancel_url   URL to return to if off-site payments are cancelled
84
-     * @return EE_Payment
85
-     * @throws EE_Error
86
-     * @throws InvalidArgumentException
87
-     * @throws ReflectionException
88
-     * @throws RuntimeException
89
-     * @throws InvalidDataTypeException
90
-     * @throws InvalidInterfaceException
91
-     */
92
-    public function process_payment(
93
-        EE_Payment_Method $payment_method,
94
-        EE_Transaction $transaction,
95
-        $amount = null,
96
-        $billing_form = null,
97
-        $return_url = null,
98
-        $method = 'CART',
99
-        $by_admin = false,
100
-        $update_txn = true,
101
-        $cancel_url = ''
102
-    ) {
103
-        if ((float) $amount < 0) {
104
-            throw new EE_Error(
105
-                sprintf(
106
-                    esc_html__(
107
-                        'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
108
-                        'event_espresso'
109
-                    ),
110
-                    $amount,
111
-                    $transaction->ID()
112
-                )
113
-            );
114
-        }
115
-        // verify payment method
116
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
117
-            $payment_method,
118
-            true
119
-        );
120
-        // verify transaction
121
-        EEM_Transaction::instance()->ensure_is_obj($transaction);
122
-        $transaction->set_payment_method_ID($payment_method->ID());
123
-        // verify payment method type
124
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
125
-            $payment = $payment_method->type_obj()->process_payment(
126
-                $transaction,
127
-                min($amount, $transaction->remaining()), // make sure we don't overcharge
128
-                $billing_form,
129
-                $return_url,
130
-                add_query_arg(array('ee_cancel_payment' => true), $cancel_url),
131
-                $method,
132
-                $by_admin
133
-            );
134
-            // check if payment method uses an off-site gateway
135
-            if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
136
-                // don't process payments for off-site gateways yet because no payment has occurred yet
137
-                $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
138
-            }
139
-            return $payment;
140
-        }
141
-        EE_Error::add_error(
142
-            sprintf(
143
-                esc_html__(
144
-                    'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
145
-                    'event_espresso'
146
-                ),
147
-                '<br/>',
148
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
149
-            ),
150
-            __FILE__,
151
-            __FUNCTION__,
152
-            __LINE__
153
-        );
154
-        return null;
155
-    }
156
-
157
-
158
-    /**
159
-     * @param EE_Transaction|int $transaction
160
-     * @param EE_Payment_Method  $payment_method
161
-     * @return string
162
-     * @throws EE_Error
163
-     * @throws InvalidArgumentException
164
-     * @throws InvalidDataTypeException
165
-     * @throws InvalidInterfaceException
166
-     */
167
-    public function get_ipn_url_for_payment_method($transaction, $payment_method)
168
-    {
169
-        /** @type \EE_Transaction $transaction */
170
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
171
-        $primary_reg = $transaction->primary_registration();
172
-        if (! $primary_reg instanceof EE_Registration) {
173
-            throw new EE_Error(
174
-                sprintf(
175
-                    esc_html__(
176
-                        'Cannot get IPN URL for transaction with ID %d because it has no primary registration',
177
-                        'event_espresso'
178
-                    ),
179
-                    $transaction->ID()
180
-                )
181
-            );
182
-        }
183
-        $payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
184
-            $payment_method,
185
-            true
186
-        );
187
-        $url = add_query_arg(
188
-            array(
189
-                'e_reg_url_link'    => $primary_reg->reg_url_link(),
190
-                'ee_payment_method' => $payment_method->slug(),
191
-            ),
192
-            EE_Registry::instance()->CFG->core->txn_page_url()
193
-        );
194
-        return $url;
195
-    }
196
-
197
-
198
-    /**
199
-     * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
200
-     * we can easily find what registration the IPN is for and what payment method.
201
-     * However, if not, we'll give all payment methods a chance to claim it and process it.
202
-     * If a payment is found for the IPN info, it is saved.
203
-     *
204
-     * @param array              $_req_data            form post data
205
-     * @param EE_Transaction|int $transaction          optional (or a transactions id)
206
-     * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
207
-     * @param boolean            $update_txn           whether or not to call
208
-     *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
209
-     * @param bool               $separate_IPN_request whether the IPN uses a separate request (true, like PayPal)
210
-     *                                                 or is processed manually (false, like Authorize.net)
211
-     * @throws EE_Error
212
-     * @throws Exception
213
-     * @return EE_Payment
214
-     * @throws \RuntimeException
215
-     * @throws \ReflectionException
216
-     * @throws \InvalidArgumentException
217
-     * @throws InvalidInterfaceException
218
-     * @throws InvalidDataTypeException
219
-     */
220
-    public function process_ipn(
221
-        $_req_data,
222
-        $transaction = null,
223
-        $payment_method = null,
224
-        $update_txn = true,
225
-        $separate_IPN_request = true
226
-    ) {
227
-        EE_Registry::instance()->load_model('Change_Log');
228
-        $_req_data = $this->_remove_unusable_characters_from_array((array) $_req_data);
229
-        EE_Processor_Base::set_IPN($separate_IPN_request);
230
-        $obj_for_log = null;
231
-        if ($transaction instanceof EE_Transaction) {
232
-            $obj_for_log = $transaction;
233
-            if ($payment_method instanceof EE_Payment_Method) {
234
-                $obj_for_log = EEM_Payment::instance()->get_one(
235
-                    array(
236
-                        array('TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()),
237
-                        'order_by' => array('PAY_timestamp' => 'desc'),
238
-                    )
239
-                );
240
-            }
241
-        } elseif ($payment_method instanceof EE_Payment) {
242
-            $obj_for_log = $payment_method;
243
-        }
244
-        $log = EEM_Change_Log::instance()->log(
245
-            EEM_Change_Log::type_gateway,
246
-            array('IPN data received' => $_req_data),
247
-            $obj_for_log
248
-        );
249
-        try {
250
-            /**
251
-             * @var EE_Payment $payment
252
-             */
253
-            $payment = null;
254
-            if ($transaction && $payment_method) {
255
-                /** @type EE_Transaction $transaction */
256
-                $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
257
-                /** @type EE_Payment_Method $payment_method */
258
-                $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
259
-                if ($payment_method->type_obj() instanceof EE_PMT_Base) {
260
-                    try {
261
-                        $payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
262
-                        $log->set_object($payment);
263
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
264
-                        EEM_Change_Log::instance()->log(
265
-                            EEM_Change_Log::type_gateway,
266
-                            array(
267
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
268
-                                'current_url' => EEH_URL::current_url(),
269
-                                'payment'     => $e->getPaymentProperties(),
270
-                                'IPN_data'    => $e->getIpnData(),
271
-                            ),
272
-                            $obj_for_log
273
-                        );
274
-                        return $e->getPayment();
275
-                    }
276
-                } else {
277
-                    // not a payment
278
-                    EE_Error::add_error(
279
-                        sprintf(
280
-                            esc_html__(
281
-                                'A valid payment method could not be determined due to a technical issue.%sPlease refresh your browser and try again or contact %s for assistance.',
282
-                                'event_espresso'
283
-                            ),
284
-                            '<br/>',
285
-                            EE_Registry::instance()->CFG->organization->get_pretty('email')
286
-                        ),
287
-                        __FILE__,
288
-                        __FUNCTION__,
289
-                        __LINE__
290
-                    );
291
-                }
292
-            } else {
293
-                // that's actually pretty ok. The IPN just wasn't able
294
-                // to identify which transaction or payment method this was for
295
-                // give all active payment methods a chance to claim it
296
-                $active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
297
-                foreach ($active_payment_methods as $active_payment_method) {
298
-                    try {
299
-                        $payment = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
300
-                        $payment_method = $active_payment_method;
301
-                        EEM_Change_Log::instance()->log(
302
-                            EEM_Change_Log::type_gateway,
303
-                            array('IPN data' => $_req_data),
304
-                            $payment
305
-                        );
306
-                        break;
307
-                    } catch (EventEspresso\core\exceptions\IpnException $e) {
308
-                        EEM_Change_Log::instance()->log(
309
-                            EEM_Change_Log::type_gateway,
310
-                            array(
311
-                                'message'     => 'IPN Exception: ' . $e->getMessage(),
312
-                                'current_url' => EEH_URL::current_url(),
313
-                                'payment'     => $e->getPaymentProperties(),
314
-                                'IPN_data'    => $e->getIpnData(),
315
-                            ),
316
-                            $obj_for_log
317
-                        );
318
-                        return $e->getPayment();
319
-                    } catch (EE_Error $e) {
320
-                        // that's fine- it apparently couldn't handle the IPN
321
-                    }
322
-                }
323
-            }
324
-            // EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
325
-            if ($payment instanceof EE_Payment) {
326
-                $payment->save();
327
-                //  update the TXN
328
-                $this->update_txn_based_on_payment(
329
-                    $transaction,
330
-                    $payment,
331
-                    $update_txn,
332
-                    $separate_IPN_request
333
-                );
334
-            } else {
335
-                // we couldn't find the payment for this IPN... let's try and log at least SOMETHING
336
-                if ($payment_method) {
337
-                    EEM_Change_Log::instance()->log(
338
-                        EEM_Change_Log::type_gateway,
339
-                        array('IPN data' => $_req_data),
340
-                        $payment_method
341
-                    );
342
-                } elseif ($transaction) {
343
-                    EEM_Change_Log::instance()->log(
344
-                        EEM_Change_Log::type_gateway,
345
-                        array('IPN data' => $_req_data),
346
-                        $transaction
347
-                    );
348
-                }
349
-            }
350
-            return $payment;
351
-        } catch (EE_Error $e) {
352
-            do_action(
353
-                'AHEE__log',
354
-                __FILE__,
355
-                __FUNCTION__,
356
-                sprintf(
357
-                    esc_html__(
358
-                        'Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"',
359
-                        'event_espresso'
360
-                    ),
361
-                    print_r($transaction, true),
362
-                    print_r($_req_data, true),
363
-                    $e->getMessage()
364
-                )
365
-            );
366
-            throw $e;
367
-        }
368
-    }
369
-
370
-
371
-    /**
372
-     * Removes any non-printable illegal characters from the input,
373
-     * which might cause a raucous when trying to insert into the database
374
-     *
375
-     * @param  array $request_data
376
-     * @return array
377
-     */
378
-    protected function _remove_unusable_characters_from_array(array $request_data)
379
-    {
380
-        $return_data = array();
381
-        foreach ($request_data as $key => $value) {
382
-            $return_data[ $this->_remove_unusable_characters($key) ] = $this->_remove_unusable_characters(
383
-                $value
384
-            );
385
-        }
386
-        return $return_data;
387
-    }
388
-
389
-
390
-    /**
391
-     * Removes any non-printable illegal characters from the input,
392
-     * which might cause a raucous when trying to insert into the database
393
-     *
394
-     * @param string $request_data
395
-     * @return string
396
-     */
397
-    protected function _remove_unusable_characters($request_data)
398
-    {
399
-        return preg_replace('/[^[:print:]]/', '', $request_data);
400
-    }
401
-
402
-
403
-    /**
404
-     * Should be called just before displaying the payment attempt results to the user,
405
-     * when the payment attempt has finished. Some payment methods may have special
406
-     * logic to perform here. For example, if process_payment() happens on a special request
407
-     * and then the user is redirected to a page that displays the payment's status, this
408
-     * should be called while loading the page that displays the payment's status. If the user is
409
-     * sent to an offsite payment provider, this should be called upon returning from that offsite payment
410
-     * provider.
411
-     *
412
-     * @param EE_Transaction|int $transaction
413
-     * @param bool               $update_txn whether or not to call
414
-     *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
415
-     * @return EE_Payment
416
-     * @throws EE_Error
417
-     * @throws InvalidArgumentException
418
-     * @throws ReflectionException
419
-     * @throws RuntimeException
420
-     * @throws InvalidDataTypeException
421
-     * @throws InvalidInterfaceException
422
-     * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
423
-     *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
424
-     */
425
-    public function finalize_payment_for($transaction, $update_txn = true)
426
-    {
427
-        /** @var $transaction EE_Transaction */
428
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
429
-        $last_payment_method = $transaction->payment_method();
430
-        if ($last_payment_method instanceof EE_Payment_Method) {
431
-            $payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
432
-            $this->update_txn_based_on_payment($transaction, $payment, $update_txn);
433
-            return $payment;
434
-        }
435
-        return null;
436
-    }
437
-
438
-
439
-    /**
440
-     * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
441
-     *
442
-     * @param EE_Payment_Method $payment_method
443
-     * @param EE_Payment        $payment_to_refund
444
-     * @param array             $refund_info
445
-     * @return EE_Payment
446
-     * @throws EE_Error
447
-     * @throws InvalidArgumentException
448
-     * @throws ReflectionException
449
-     * @throws RuntimeException
450
-     * @throws InvalidDataTypeException
451
-     * @throws InvalidInterfaceException
452
-     */
453
-    public function process_refund(
454
-        EE_Payment_Method $payment_method,
455
-        EE_Payment $payment_to_refund,
456
-        array $refund_info = array()
457
-    ) {
458
-        if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
459
-            $payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
460
-            $this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
461
-        }
462
-        return $payment_to_refund;
463
-    }
464
-
465
-
466
-    /**
467
-     * This should be called each time there may have been an update to a
468
-     * payment on a transaction (ie, we asked for a payment to process a
469
-     * payment for a transaction, or we told a payment method about an IPN, or
470
-     * we told a payment method to
471
-     * "finalize_payment_for" (a transaction), or we told a payment method to
472
-     * process a refund. This should handle firing the correct hooks to
473
-     * indicate
474
-     * what exactly happened and updating the transaction appropriately). This
475
-     * could be integrated directly into EE_Transaction upon save, but we want
476
-     * this logic to be separate from 'normal' plain-jane saving and updating
477
-     * of transactions and payments, and to be tied to payment processing.
478
-     * Note: this method DOES NOT save the payment passed into it. It is the responsibility
479
-     * of previous code to decide whether or not to save (because the payment passed into
480
-     * this method might be a temporary, never-to-be-saved payment from an offline gateway,
481
-     * in which case we only want that payment object for some temporary usage during this request,
482
-     * but we don't want it to be saved).
483
-     *
484
-     * @param EE_Transaction|int $transaction
485
-     * @param EE_Payment         $payment
486
-     * @param boolean            $update_txn
487
-     *                        whether or not to call
488
-     *                        EE_Transaction_Processor::
489
-     *                        update_transaction_and_registrations_after_checkout_or_payment()
490
-     *                        (you can save 1 DB query if you know you're going
491
-     *                        to save it later instead)
492
-     * @param bool               $IPN
493
-     *                        if processing IPNs or other similar payment
494
-     *                        related activities that occur in alternate
495
-     *                        requests than the main one that is processing the
496
-     *                        TXN, then set this to true to check whether the
497
-     *                        TXN is locked before updating
498
-     * @throws EE_Error
499
-     * @throws InvalidArgumentException
500
-     * @throws ReflectionException
501
-     * @throws RuntimeException
502
-     * @throws InvalidDataTypeException
503
-     * @throws InvalidInterfaceException
504
-     */
505
-    public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
506
-    {
507
-        $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
508
-        /** @type EE_Transaction $transaction */
509
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
510
-        // can we freely update the TXN at this moment?
511
-        if ($IPN && $transaction->is_locked()) {
512
-            // don't update the transaction at this exact moment
513
-            // because the TXN is active in another request
514
-            EE_Cron_Tasks::schedule_update_transaction_with_payment(
515
-                time(),
516
-                $transaction->ID(),
517
-                $payment->ID()
518
-            );
519
-        } else {
520
-            // verify payment and that it has been saved
521
-            if ($payment instanceof EE_Payment && $payment->ID()) {
522
-                if (
523
-                    $payment->payment_method() instanceof EE_Payment_Method
524
-                    && $payment->payment_method()->type_obj() instanceof EE_PMT_Base
525
-                ) {
526
-                    $payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
527
-                    // update TXN registrations with payment info
528
-                    $this->process_registration_payments($transaction, $payment);
529
-                }
530
-                $do_action = $payment->just_approved()
531
-                    ? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
532
-                    : $do_action;
533
-            } else {
534
-                // send out notifications
535
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
536
-                $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
537
-            }
538
-            if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
539
-                /** @type EE_Transaction_Payments $transaction_payments */
540
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
541
-                // set new value for total paid
542
-                $transaction_payments->calculate_total_payments_and_update_status($transaction);
543
-                // call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
544
-                if ($update_txn) {
545
-                    $this->_post_payment_processing($transaction, $payment, $IPN);
546
-                }
547
-            }
548
-            // granular hook for others to use.
549
-            do_action($do_action, $transaction, $payment);
550
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
551
-            // global hook for others to use.
552
-            do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
553
-        }
554
-    }
555
-
556
-
557
-    /**
558
-     * update registrations REG_paid field after successful payment and link registrations with payment
559
-     *
560
-     * @param EE_Transaction    $transaction
561
-     * @param EE_Payment        $payment
562
-     * @param EE_Registration[] $registrations
563
-     * @throws EE_Error
564
-     * @throws InvalidArgumentException
565
-     * @throws RuntimeException
566
-     * @throws InvalidDataTypeException
567
-     * @throws InvalidInterfaceException
568
-     */
569
-    public function process_registration_payments(
570
-        EE_Transaction $transaction,
571
-        EE_Payment $payment,
572
-        array $registrations = array()
573
-    ) {
574
-        // only process if payment was successful
575
-        if ($payment->status() !== EEM_Payment::status_id_approved) {
576
-            return;
577
-        }
578
-        // EEM_Registration::instance()->show_next_x_db_queries();
579
-        if (empty($registrations)) {
580
-            // find registrations with monies owing that can receive a payment
581
-            $registrations = $transaction->registrations(
582
-                array(
583
-                    array(
584
-                        // only these reg statuses can receive payments
585
-                        'STS_ID'           => array('IN', EEM_Registration::reg_statuses_that_allow_payment()),
586
-                        'REG_final_price'  => array('!=', 0),
587
-                        'REG_final_price*' => array('!=', 'REG_paid', true),
588
-                    ),
589
-                )
590
-            );
591
-        }
592
-        // still nothing ??!??
593
-        if (empty($registrations)) {
594
-            return;
595
-        }
596
-        // todo: break out the following logic into a separate strategy class
597
-        // todo: named something like "Sequential_Reg_Payment_Strategy"
598
-        // todo: which would apply payments using the capitalist "first come first paid" approach
599
-        // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
600
-        // todo: which would be the socialist "everybody gets a piece of pie" approach,
601
-        // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
602
-        $refund = $payment->is_a_refund();
603
-        // how much is available to apply to registrations?
604
-        $available_payment_amount = abs($payment->amount());
605
-        foreach ($registrations as $registration) {
606
-            if ($registration instanceof EE_Registration) {
607
-                // nothing left?
608
-                if ($available_payment_amount <= 0) {
609
-                    break;
610
-                }
611
-                if ($refund) {
612
-                    $available_payment_amount = $this->process_registration_refund(
613
-                        $registration,
614
-                        $payment,
615
-                        $available_payment_amount
616
-                    );
617
-                } else {
618
-                    $available_payment_amount = $this->process_registration_payment(
619
-                        $registration,
620
-                        $payment,
621
-                        $available_payment_amount
622
-                    );
623
-                }
624
-            }
625
-        }
626
-        if (
627
-            $available_payment_amount > 0
628
-            && apply_filters(
629
-                'FHEE__EE_Payment_Processor__process_registration_payments__display_notifications',
630
-                false
631
-            )
632
-        ) {
633
-            EE_Error::add_attention(
634
-                sprintf(
635
-                    esc_html__(
636
-                        'A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
637
-                        'event_espresso'
638
-                    ),
639
-                    EEH_Template::format_currency($available_payment_amount),
640
-                    implode(', ', array_keys($registrations)),
641
-                    '<br/>',
642
-                    EEH_Template::format_currency($payment->amount())
643
-                ),
644
-                __FILE__,
645
-                __FUNCTION__,
646
-                __LINE__
647
-            );
648
-        }
649
-    }
650
-
651
-
652
-    /**
653
-     * update registration REG_paid field after successful payment and link registration with payment
654
-     *
655
-     * @param EE_Registration $registration
656
-     * @param EE_Payment      $payment
657
-     * @param float           $available_payment_amount
658
-     * @return float
659
-     * @throws EE_Error
660
-     * @throws InvalidArgumentException
661
-     * @throws RuntimeException
662
-     * @throws InvalidDataTypeException
663
-     * @throws InvalidInterfaceException
664
-     */
665
-    public function process_registration_payment(
666
-        EE_Registration $registration,
667
-        EE_Payment $payment,
668
-        $available_payment_amount = 0.00
669
-    ) {
670
-        $owing = $registration->final_price() - $registration->paid();
671
-        if ($owing > 0) {
672
-            // don't allow payment amount to exceed the available payment amount, OR the amount owing
673
-            $payment_amount = min($available_payment_amount, $owing);
674
-            // update $available_payment_amount
675
-            $available_payment_amount -= $payment_amount;
676
-            // calculate and set new REG_paid
677
-            $registration->set_paid($registration->paid() + $payment_amount);
678
-            // now save it
679
-            $this->_apply_registration_payment($registration, $payment, $payment_amount);
680
-        }
681
-        return $available_payment_amount;
682
-    }
683
-
684
-
685
-    /**
686
-     * update registration REG_paid field after successful payment and link registration with payment
687
-     *
688
-     * @param EE_Registration $registration
689
-     * @param EE_Payment      $payment
690
-     * @param float           $payment_amount
691
-     * @return void
692
-     * @throws EE_Error
693
-     * @throws InvalidArgumentException
694
-     * @throws InvalidDataTypeException
695
-     * @throws InvalidInterfaceException
696
-     */
697
-    protected function _apply_registration_payment(
698
-        EE_Registration $registration,
699
-        EE_Payment $payment,
700
-        $payment_amount = 0.00
701
-    ) {
702
-        // find any existing reg payment records for this registration and payment
703
-        $existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
704
-            array(array('REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()))
705
-        );
706
-        // if existing registration payment exists
707
-        if ($existing_reg_payment instanceof EE_Registration_Payment) {
708
-            // then update that record
709
-            $existing_reg_payment->set_amount($payment_amount);
710
-            $existing_reg_payment->save();
711
-        } else {
712
-            // or add new relation between registration and payment and set amount
713
-            $registration->_add_relation_to(
714
-                $payment,
715
-                'Payment',
716
-                array('RPY_amount' => $payment_amount)
717
-            );
718
-            // make it stick
719
-            $registration->save();
720
-        }
721
-    }
722
-
723
-
724
-    /**
725
-     * update registration REG_paid field after refund and link registration with payment
726
-     *
727
-     * @param EE_Registration $registration
728
-     * @param EE_Payment      $payment
729
-     * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
730
-     * @return float
731
-     * @throws EE_Error
732
-     * @throws InvalidArgumentException
733
-     * @throws RuntimeException
734
-     * @throws InvalidDataTypeException
735
-     * @throws InvalidInterfaceException
736
-     */
737
-    public function process_registration_refund(
738
-        EE_Registration $registration,
739
-        EE_Payment $payment,
740
-        $available_refund_amount = 0.00
741
-    ) {
742
-        // EEH_Debug_Tools::printr( $payment->amount(), '$payment->amount()', __FILE__, __LINE__ );
743
-        if ($registration->paid() > 0) {
744
-            // ensure $available_refund_amount is NOT negative
745
-            $available_refund_amount = (float) abs($available_refund_amount);
746
-            // don't allow refund amount to exceed the available payment amount, OR the amount paid
747
-            $refund_amount = min($available_refund_amount, (float) $registration->paid());
748
-            // update $available_payment_amount
749
-            $available_refund_amount -= $refund_amount;
750
-            // calculate and set new REG_paid
751
-            $registration->set_paid($registration->paid() - $refund_amount);
752
-            // convert payment amount back to a negative value for storage in the db
753
-            $refund_amount = (float) abs($refund_amount) * -1;
754
-            // now save it
755
-            $this->_apply_registration_payment($registration, $payment, $refund_amount);
756
-        }
757
-        return $available_refund_amount;
758
-    }
759
-
760
-
761
-    /**
762
-     * Process payments and transaction after payment process completed.
763
-     * ultimately this will send the TXN and payment details off so that notifications can be sent out.
764
-     * if this request happens to be processing an IPN,
765
-     * then we will also set the Payment Options Reg Step to completed,
766
-     * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
767
-     *
768
-     * @param EE_Transaction $transaction
769
-     * @param EE_Payment     $payment
770
-     * @param bool           $IPN
771
-     * @throws EE_Error
772
-     * @throws InvalidArgumentException
773
-     * @throws ReflectionException
774
-     * @throws RuntimeException
775
-     * @throws InvalidDataTypeException
776
-     * @throws InvalidInterfaceException
777
-     */
778
-    protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
779
-    {
780
-        /** @type EE_Transaction_Processor $transaction_processor */
781
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
782
-        // is the Payment Options Reg Step completed ?
783
-        $payment_options_step_completed = $transaction->reg_step_completed('payment_options');
784
-        // if the Payment Options Reg Step is completed...
785
-        $revisit = $payment_options_step_completed === true;
786
-        // then this is kinda sorta a revisit with regards to payments at least
787
-        $transaction_processor->set_revisit($revisit);
788
-        // if this is an IPN, let's consider the Payment Options Reg Step completed if not already
789
-        if (
790
-            $IPN
791
-            && $payment_options_step_completed !== true
792
-            && ($payment->is_approved() || $payment->is_pending())
793
-        ) {
794
-            $payment_options_step_completed = $transaction->set_reg_step_completed(
795
-                'payment_options'
796
-            );
797
-        }
798
-        // maybe update status, but don't save transaction just yet
799
-        $transaction->update_status_based_on_total_paid(false);
800
-        // check if 'finalize_registration' step has been completed...
801
-        $finalized = $transaction->reg_step_completed('finalize_registration');
802
-        //  if this is an IPN and the final step has not been initiated
803
-        if ($IPN && $payment_options_step_completed && $finalized === false) {
804
-            // and if it hasn't already been set as being started...
805
-            $finalized = $transaction->set_reg_step_initiated('finalize_registration');
806
-        }
807
-        $transaction->save();
808
-        // because the above will return false if the final step was not fully completed, we need to check again...
809
-        if ($IPN && $finalized !== false) {
810
-            // and if we are all good to go, then send out notifications
811
-            add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
812
-            // ok, now process the transaction according to the payment
813
-            $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
814
-                $transaction,
815
-                $payment
816
-            );
817
-        }
818
-        // DEBUG LOG
819
-        $payment_method = $payment->payment_method();
820
-        if ($payment_method instanceof EE_Payment_Method) {
821
-            $payment_method_type_obj = $payment_method->type_obj();
822
-            if ($payment_method_type_obj instanceof EE_PMT_Base) {
823
-                $gateway = $payment_method_type_obj->get_gateway();
824
-                if ($gateway instanceof EE_Gateway) {
825
-                    $gateway->log(
826
-                        array(
827
-                            'message'               => (string) esc_html__('Post Payment Transaction Details', 'event_espresso'),
828
-                            'transaction'           => $transaction->model_field_array(),
829
-                            'finalized'             => $finalized,
830
-                            'IPN'                   => $IPN,
831
-                            'deliver_notifications' => has_filter(
832
-                                'FHEE__EED_Messages___maybe_registration__deliver_notifications'
833
-                            ),
834
-                        ),
835
-                        $payment
836
-                    );
837
-                }
838
-            }
839
-        }
840
-    }
841
-
842
-
843
-    /**
844
-     * Force posts to PayPal to use TLS v1.2. See:
845
-     * https://core.trac.wordpress.org/ticket/36320
846
-     * https://core.trac.wordpress.org/ticket/34924#comment:15
847
-     * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
848
-     * This will affect PayPal standard, pro, express, and Payflow.
849
-     *
850
-     * @param $handle
851
-     * @param $r
852
-     * @param $url
853
-     */
854
-    public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
855
-    {
856
-        if (strpos($url, 'https://') !== false && strpos($url, '.paypal.com') !== false) {
857
-            // Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
858
-            // instead of the constant because it might not be defined
859
-            curl_setopt($handle, CURLOPT_SSLVERSION, 6);
860
-        }
861
-    }
20
+	/**
21
+	 * @var EE_Payment_Processor $_instance
22
+	 * @access    private
23
+	 */
24
+	private static $_instance;
25
+
26
+
27
+	/**
28
+	 * @singleton method used to instantiate class object
29
+	 * @access    public
30
+	 * @return EE_Payment_Processor instance
31
+	 */
32
+	public static function instance()
33
+	{
34
+		// check if class object is instantiated
35
+		if (! self::$_instance instanceof EE_Payment_Processor) {
36
+			self::$_instance = new self();
37
+		}
38
+		return self::$_instance;
39
+	}
40
+
41
+
42
+	/**
43
+	 * @return EE_Payment_Processor
44
+	 */
45
+	public static function reset()
46
+	{
47
+		self::$_instance = null;
48
+		return self::instance();
49
+	}
50
+
51
+
52
+	/**
53
+	 *private constructor to prevent direct creation
54
+	 *
55
+	 * @Constructor
56
+	 * @access private
57
+	 */
58
+	private function __construct()
59
+	{
60
+		do_action('AHEE__EE_Payment_Processor__construct');
61
+		add_action('http_api_curl', array($this, '_curl_requests_to_paypal_use_tls'), 10, 3);
62
+	}
63
+
64
+
65
+	/**
66
+	 * Using the selected gateway, processes the payment for that transaction, and updates the transaction
67
+	 * appropriately. Saves the payment that is generated
68
+	 *
69
+	 * @param EE_Payment_Method    $payment_method
70
+	 * @param EE_Transaction       $transaction
71
+	 * @param float                $amount       if only part of the transaction is to be paid for, how much.
72
+	 *                                           Leave null if payment is for the full amount owing
73
+	 * @param EE_Billing_Info_Form $billing_form (or probably null, if it's an offline or offsite payment method).
74
+	 *                                           Receive_form_submission() should have
75
+	 *                                           already been called on the billing form
76
+	 *                                           (ie, its inputs should have their normalized values set).
77
+	 * @param string               $return_url   string used mostly by offsite gateways to specify
78
+	 *                                           where to go AFTER the offsite gateway
79
+	 * @param string               $method       like 'CART', indicates who the client who called this was
80
+	 * @param bool                 $by_admin     TRUE if payment is being attempted from the admin
81
+	 * @param boolean              $update_txn   whether or not to call
82
+	 *                                           EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
83
+	 * @param string               $cancel_url   URL to return to if off-site payments are cancelled
84
+	 * @return EE_Payment
85
+	 * @throws EE_Error
86
+	 * @throws InvalidArgumentException
87
+	 * @throws ReflectionException
88
+	 * @throws RuntimeException
89
+	 * @throws InvalidDataTypeException
90
+	 * @throws InvalidInterfaceException
91
+	 */
92
+	public function process_payment(
93
+		EE_Payment_Method $payment_method,
94
+		EE_Transaction $transaction,
95
+		$amount = null,
96
+		$billing_form = null,
97
+		$return_url = null,
98
+		$method = 'CART',
99
+		$by_admin = false,
100
+		$update_txn = true,
101
+		$cancel_url = ''
102
+	) {
103
+		if ((float) $amount < 0) {
104
+			throw new EE_Error(
105
+				sprintf(
106
+					esc_html__(
107
+						'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
108
+						'event_espresso'
109
+					),
110
+					$amount,
111
+					$transaction->ID()
112
+				)
113
+			);
114
+		}
115
+		// verify payment method
116
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
117
+			$payment_method,
118
+			true
119
+		);
120
+		// verify transaction
121
+		EEM_Transaction::instance()->ensure_is_obj($transaction);
122
+		$transaction->set_payment_method_ID($payment_method->ID());
123
+		// verify payment method type
124
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
125
+			$payment = $payment_method->type_obj()->process_payment(
126
+				$transaction,
127
+				min($amount, $transaction->remaining()), // make sure we don't overcharge
128
+				$billing_form,
129
+				$return_url,
130
+				add_query_arg(array('ee_cancel_payment' => true), $cancel_url),
131
+				$method,
132
+				$by_admin
133
+			);
134
+			// check if payment method uses an off-site gateway
135
+			if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
136
+				// don't process payments for off-site gateways yet because no payment has occurred yet
137
+				$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
138
+			}
139
+			return $payment;
140
+		}
141
+		EE_Error::add_error(
142
+			sprintf(
143
+				esc_html__(
144
+					'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
145
+					'event_espresso'
146
+				),
147
+				'<br/>',
148
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
149
+			),
150
+			__FILE__,
151
+			__FUNCTION__,
152
+			__LINE__
153
+		);
154
+		return null;
155
+	}
156
+
157
+
158
+	/**
159
+	 * @param EE_Transaction|int $transaction
160
+	 * @param EE_Payment_Method  $payment_method
161
+	 * @return string
162
+	 * @throws EE_Error
163
+	 * @throws InvalidArgumentException
164
+	 * @throws InvalidDataTypeException
165
+	 * @throws InvalidInterfaceException
166
+	 */
167
+	public function get_ipn_url_for_payment_method($transaction, $payment_method)
168
+	{
169
+		/** @type \EE_Transaction $transaction */
170
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
171
+		$primary_reg = $transaction->primary_registration();
172
+		if (! $primary_reg instanceof EE_Registration) {
173
+			throw new EE_Error(
174
+				sprintf(
175
+					esc_html__(
176
+						'Cannot get IPN URL for transaction with ID %d because it has no primary registration',
177
+						'event_espresso'
178
+					),
179
+					$transaction->ID()
180
+				)
181
+			);
182
+		}
183
+		$payment_method = EEM_Payment_Method::instance()->ensure_is_obj(
184
+			$payment_method,
185
+			true
186
+		);
187
+		$url = add_query_arg(
188
+			array(
189
+				'e_reg_url_link'    => $primary_reg->reg_url_link(),
190
+				'ee_payment_method' => $payment_method->slug(),
191
+			),
192
+			EE_Registry::instance()->CFG->core->txn_page_url()
193
+		);
194
+		return $url;
195
+	}
196
+
197
+
198
+	/**
199
+	 * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
200
+	 * we can easily find what registration the IPN is for and what payment method.
201
+	 * However, if not, we'll give all payment methods a chance to claim it and process it.
202
+	 * If a payment is found for the IPN info, it is saved.
203
+	 *
204
+	 * @param array              $_req_data            form post data
205
+	 * @param EE_Transaction|int $transaction          optional (or a transactions id)
206
+	 * @param EE_Payment_Method  $payment_method       (or a slug or id of one)
207
+	 * @param boolean            $update_txn           whether or not to call
208
+	 *                                                 EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
209
+	 * @param bool               $separate_IPN_request whether the IPN uses a separate request (true, like PayPal)
210
+	 *                                                 or is processed manually (false, like Authorize.net)
211
+	 * @throws EE_Error
212
+	 * @throws Exception
213
+	 * @return EE_Payment
214
+	 * @throws \RuntimeException
215
+	 * @throws \ReflectionException
216
+	 * @throws \InvalidArgumentException
217
+	 * @throws InvalidInterfaceException
218
+	 * @throws InvalidDataTypeException
219
+	 */
220
+	public function process_ipn(
221
+		$_req_data,
222
+		$transaction = null,
223
+		$payment_method = null,
224
+		$update_txn = true,
225
+		$separate_IPN_request = true
226
+	) {
227
+		EE_Registry::instance()->load_model('Change_Log');
228
+		$_req_data = $this->_remove_unusable_characters_from_array((array) $_req_data);
229
+		EE_Processor_Base::set_IPN($separate_IPN_request);
230
+		$obj_for_log = null;
231
+		if ($transaction instanceof EE_Transaction) {
232
+			$obj_for_log = $transaction;
233
+			if ($payment_method instanceof EE_Payment_Method) {
234
+				$obj_for_log = EEM_Payment::instance()->get_one(
235
+					array(
236
+						array('TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()),
237
+						'order_by' => array('PAY_timestamp' => 'desc'),
238
+					)
239
+				);
240
+			}
241
+		} elseif ($payment_method instanceof EE_Payment) {
242
+			$obj_for_log = $payment_method;
243
+		}
244
+		$log = EEM_Change_Log::instance()->log(
245
+			EEM_Change_Log::type_gateway,
246
+			array('IPN data received' => $_req_data),
247
+			$obj_for_log
248
+		);
249
+		try {
250
+			/**
251
+			 * @var EE_Payment $payment
252
+			 */
253
+			$payment = null;
254
+			if ($transaction && $payment_method) {
255
+				/** @type EE_Transaction $transaction */
256
+				$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
257
+				/** @type EE_Payment_Method $payment_method */
258
+				$payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method);
259
+				if ($payment_method->type_obj() instanceof EE_PMT_Base) {
260
+					try {
261
+						$payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction);
262
+						$log->set_object($payment);
263
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
264
+						EEM_Change_Log::instance()->log(
265
+							EEM_Change_Log::type_gateway,
266
+							array(
267
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
268
+								'current_url' => EEH_URL::current_url(),
269
+								'payment'     => $e->getPaymentProperties(),
270
+								'IPN_data'    => $e->getIpnData(),
271
+							),
272
+							$obj_for_log
273
+						);
274
+						return $e->getPayment();
275
+					}
276
+				} else {
277
+					// not a payment
278
+					EE_Error::add_error(
279
+						sprintf(
280
+							esc_html__(
281
+								'A valid payment method could not be determined due to a technical issue.%sPlease refresh your browser and try again or contact %s for assistance.',
282
+								'event_espresso'
283
+							),
284
+							'<br/>',
285
+							EE_Registry::instance()->CFG->organization->get_pretty('email')
286
+						),
287
+						__FILE__,
288
+						__FUNCTION__,
289
+						__LINE__
290
+					);
291
+				}
292
+			} else {
293
+				// that's actually pretty ok. The IPN just wasn't able
294
+				// to identify which transaction or payment method this was for
295
+				// give all active payment methods a chance to claim it
296
+				$active_payment_methods = EEM_Payment_Method::instance()->get_all_active();
297
+				foreach ($active_payment_methods as $active_payment_method) {
298
+					try {
299
+						$payment = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data);
300
+						$payment_method = $active_payment_method;
301
+						EEM_Change_Log::instance()->log(
302
+							EEM_Change_Log::type_gateway,
303
+							array('IPN data' => $_req_data),
304
+							$payment
305
+						);
306
+						break;
307
+					} catch (EventEspresso\core\exceptions\IpnException $e) {
308
+						EEM_Change_Log::instance()->log(
309
+							EEM_Change_Log::type_gateway,
310
+							array(
311
+								'message'     => 'IPN Exception: ' . $e->getMessage(),
312
+								'current_url' => EEH_URL::current_url(),
313
+								'payment'     => $e->getPaymentProperties(),
314
+								'IPN_data'    => $e->getIpnData(),
315
+							),
316
+							$obj_for_log
317
+						);
318
+						return $e->getPayment();
319
+					} catch (EE_Error $e) {
320
+						// that's fine- it apparently couldn't handle the IPN
321
+					}
322
+				}
323
+			}
324
+			// EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method);
325
+			if ($payment instanceof EE_Payment) {
326
+				$payment->save();
327
+				//  update the TXN
328
+				$this->update_txn_based_on_payment(
329
+					$transaction,
330
+					$payment,
331
+					$update_txn,
332
+					$separate_IPN_request
333
+				);
334
+			} else {
335
+				// we couldn't find the payment for this IPN... let's try and log at least SOMETHING
336
+				if ($payment_method) {
337
+					EEM_Change_Log::instance()->log(
338
+						EEM_Change_Log::type_gateway,
339
+						array('IPN data' => $_req_data),
340
+						$payment_method
341
+					);
342
+				} elseif ($transaction) {
343
+					EEM_Change_Log::instance()->log(
344
+						EEM_Change_Log::type_gateway,
345
+						array('IPN data' => $_req_data),
346
+						$transaction
347
+					);
348
+				}
349
+			}
350
+			return $payment;
351
+		} catch (EE_Error $e) {
352
+			do_action(
353
+				'AHEE__log',
354
+				__FILE__,
355
+				__FUNCTION__,
356
+				sprintf(
357
+					esc_html__(
358
+						'Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"',
359
+						'event_espresso'
360
+					),
361
+					print_r($transaction, true),
362
+					print_r($_req_data, true),
363
+					$e->getMessage()
364
+				)
365
+			);
366
+			throw $e;
367
+		}
368
+	}
369
+
370
+
371
+	/**
372
+	 * Removes any non-printable illegal characters from the input,
373
+	 * which might cause a raucous when trying to insert into the database
374
+	 *
375
+	 * @param  array $request_data
376
+	 * @return array
377
+	 */
378
+	protected function _remove_unusable_characters_from_array(array $request_data)
379
+	{
380
+		$return_data = array();
381
+		foreach ($request_data as $key => $value) {
382
+			$return_data[ $this->_remove_unusable_characters($key) ] = $this->_remove_unusable_characters(
383
+				$value
384
+			);
385
+		}
386
+		return $return_data;
387
+	}
388
+
389
+
390
+	/**
391
+	 * Removes any non-printable illegal characters from the input,
392
+	 * which might cause a raucous when trying to insert into the database
393
+	 *
394
+	 * @param string $request_data
395
+	 * @return string
396
+	 */
397
+	protected function _remove_unusable_characters($request_data)
398
+	{
399
+		return preg_replace('/[^[:print:]]/', '', $request_data);
400
+	}
401
+
402
+
403
+	/**
404
+	 * Should be called just before displaying the payment attempt results to the user,
405
+	 * when the payment attempt has finished. Some payment methods may have special
406
+	 * logic to perform here. For example, if process_payment() happens on a special request
407
+	 * and then the user is redirected to a page that displays the payment's status, this
408
+	 * should be called while loading the page that displays the payment's status. If the user is
409
+	 * sent to an offsite payment provider, this should be called upon returning from that offsite payment
410
+	 * provider.
411
+	 *
412
+	 * @param EE_Transaction|int $transaction
413
+	 * @param bool               $update_txn whether or not to call
414
+	 *                                       EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
415
+	 * @return EE_Payment
416
+	 * @throws EE_Error
417
+	 * @throws InvalidArgumentException
418
+	 * @throws ReflectionException
419
+	 * @throws RuntimeException
420
+	 * @throws InvalidDataTypeException
421
+	 * @throws InvalidInterfaceException
422
+	 * @deprecated 4.6.24 method is no longer used. Instead it is up to client code, like SPCO,
423
+	 *                                       to call handle_ipn() for offsite gateways that don't receive separate IPNs
424
+	 */
425
+	public function finalize_payment_for($transaction, $update_txn = true)
426
+	{
427
+		/** @var $transaction EE_Transaction */
428
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
429
+		$last_payment_method = $transaction->payment_method();
430
+		if ($last_payment_method instanceof EE_Payment_Method) {
431
+			$payment = $last_payment_method->type_obj()->finalize_payment_for($transaction);
432
+			$this->update_txn_based_on_payment($transaction, $payment, $update_txn);
433
+			return $payment;
434
+		}
435
+		return null;
436
+	}
437
+
438
+
439
+	/**
440
+	 * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
441
+	 *
442
+	 * @param EE_Payment_Method $payment_method
443
+	 * @param EE_Payment        $payment_to_refund
444
+	 * @param array             $refund_info
445
+	 * @return EE_Payment
446
+	 * @throws EE_Error
447
+	 * @throws InvalidArgumentException
448
+	 * @throws ReflectionException
449
+	 * @throws RuntimeException
450
+	 * @throws InvalidDataTypeException
451
+	 * @throws InvalidInterfaceException
452
+	 */
453
+	public function process_refund(
454
+		EE_Payment_Method $payment_method,
455
+		EE_Payment $payment_to_refund,
456
+		array $refund_info = array()
457
+	) {
458
+		if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
459
+			$payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
460
+			$this->update_txn_based_on_payment($payment_to_refund->transaction(), $payment_to_refund);
461
+		}
462
+		return $payment_to_refund;
463
+	}
464
+
465
+
466
+	/**
467
+	 * This should be called each time there may have been an update to a
468
+	 * payment on a transaction (ie, we asked for a payment to process a
469
+	 * payment for a transaction, or we told a payment method about an IPN, or
470
+	 * we told a payment method to
471
+	 * "finalize_payment_for" (a transaction), or we told a payment method to
472
+	 * process a refund. This should handle firing the correct hooks to
473
+	 * indicate
474
+	 * what exactly happened and updating the transaction appropriately). This
475
+	 * could be integrated directly into EE_Transaction upon save, but we want
476
+	 * this logic to be separate from 'normal' plain-jane saving and updating
477
+	 * of transactions and payments, and to be tied to payment processing.
478
+	 * Note: this method DOES NOT save the payment passed into it. It is the responsibility
479
+	 * of previous code to decide whether or not to save (because the payment passed into
480
+	 * this method might be a temporary, never-to-be-saved payment from an offline gateway,
481
+	 * in which case we only want that payment object for some temporary usage during this request,
482
+	 * but we don't want it to be saved).
483
+	 *
484
+	 * @param EE_Transaction|int $transaction
485
+	 * @param EE_Payment         $payment
486
+	 * @param boolean            $update_txn
487
+	 *                        whether or not to call
488
+	 *                        EE_Transaction_Processor::
489
+	 *                        update_transaction_and_registrations_after_checkout_or_payment()
490
+	 *                        (you can save 1 DB query if you know you're going
491
+	 *                        to save it later instead)
492
+	 * @param bool               $IPN
493
+	 *                        if processing IPNs or other similar payment
494
+	 *                        related activities that occur in alternate
495
+	 *                        requests than the main one that is processing the
496
+	 *                        TXN, then set this to true to check whether the
497
+	 *                        TXN is locked before updating
498
+	 * @throws EE_Error
499
+	 * @throws InvalidArgumentException
500
+	 * @throws ReflectionException
501
+	 * @throws RuntimeException
502
+	 * @throws InvalidDataTypeException
503
+	 * @throws InvalidInterfaceException
504
+	 */
505
+	public function update_txn_based_on_payment($transaction, $payment, $update_txn = true, $IPN = false)
506
+	{
507
+		$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
508
+		/** @type EE_Transaction $transaction */
509
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
510
+		// can we freely update the TXN at this moment?
511
+		if ($IPN && $transaction->is_locked()) {
512
+			// don't update the transaction at this exact moment
513
+			// because the TXN is active in another request
514
+			EE_Cron_Tasks::schedule_update_transaction_with_payment(
515
+				time(),
516
+				$transaction->ID(),
517
+				$payment->ID()
518
+			);
519
+		} else {
520
+			// verify payment and that it has been saved
521
+			if ($payment instanceof EE_Payment && $payment->ID()) {
522
+				if (
523
+					$payment->payment_method() instanceof EE_Payment_Method
524
+					&& $payment->payment_method()->type_obj() instanceof EE_PMT_Base
525
+				) {
526
+					$payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
527
+					// update TXN registrations with payment info
528
+					$this->process_registration_payments($transaction, $payment);
529
+				}
530
+				$do_action = $payment->just_approved()
531
+					? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
532
+					: $do_action;
533
+			} else {
534
+				// send out notifications
535
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
536
+				$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
537
+			}
538
+			if ($payment instanceof EE_Payment && $payment->status() !== EEM_Payment::status_id_failed) {
539
+				/** @type EE_Transaction_Payments $transaction_payments */
540
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
541
+				// set new value for total paid
542
+				$transaction_payments->calculate_total_payments_and_update_status($transaction);
543
+				// call EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() ???
544
+				if ($update_txn) {
545
+					$this->_post_payment_processing($transaction, $payment, $IPN);
546
+				}
547
+			}
548
+			// granular hook for others to use.
549
+			do_action($do_action, $transaction, $payment);
550
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
551
+			// global hook for others to use.
552
+			do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
553
+		}
554
+	}
555
+
556
+
557
+	/**
558
+	 * update registrations REG_paid field after successful payment and link registrations with payment
559
+	 *
560
+	 * @param EE_Transaction    $transaction
561
+	 * @param EE_Payment        $payment
562
+	 * @param EE_Registration[] $registrations
563
+	 * @throws EE_Error
564
+	 * @throws InvalidArgumentException
565
+	 * @throws RuntimeException
566
+	 * @throws InvalidDataTypeException
567
+	 * @throws InvalidInterfaceException
568
+	 */
569
+	public function process_registration_payments(
570
+		EE_Transaction $transaction,
571
+		EE_Payment $payment,
572
+		array $registrations = array()
573
+	) {
574
+		// only process if payment was successful
575
+		if ($payment->status() !== EEM_Payment::status_id_approved) {
576
+			return;
577
+		}
578
+		// EEM_Registration::instance()->show_next_x_db_queries();
579
+		if (empty($registrations)) {
580
+			// find registrations with monies owing that can receive a payment
581
+			$registrations = $transaction->registrations(
582
+				array(
583
+					array(
584
+						// only these reg statuses can receive payments
585
+						'STS_ID'           => array('IN', EEM_Registration::reg_statuses_that_allow_payment()),
586
+						'REG_final_price'  => array('!=', 0),
587
+						'REG_final_price*' => array('!=', 'REG_paid', true),
588
+					),
589
+				)
590
+			);
591
+		}
592
+		// still nothing ??!??
593
+		if (empty($registrations)) {
594
+			return;
595
+		}
596
+		// todo: break out the following logic into a separate strategy class
597
+		// todo: named something like "Sequential_Reg_Payment_Strategy"
598
+		// todo: which would apply payments using the capitalist "first come first paid" approach
599
+		// todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
600
+		// todo: which would be the socialist "everybody gets a piece of pie" approach,
601
+		// todo: which would be better for deposits, where you want a bit of the payment applied to each registration
602
+		$refund = $payment->is_a_refund();
603
+		// how much is available to apply to registrations?
604
+		$available_payment_amount = abs($payment->amount());
605
+		foreach ($registrations as $registration) {
606
+			if ($registration instanceof EE_Registration) {
607
+				// nothing left?
608
+				if ($available_payment_amount <= 0) {
609
+					break;
610
+				}
611
+				if ($refund) {
612
+					$available_payment_amount = $this->process_registration_refund(
613
+						$registration,
614
+						$payment,
615
+						$available_payment_amount
616
+					);
617
+				} else {
618
+					$available_payment_amount = $this->process_registration_payment(
619
+						$registration,
620
+						$payment,
621
+						$available_payment_amount
622
+					);
623
+				}
624
+			}
625
+		}
626
+		if (
627
+			$available_payment_amount > 0
628
+			&& apply_filters(
629
+				'FHEE__EE_Payment_Processor__process_registration_payments__display_notifications',
630
+				false
631
+			)
632
+		) {
633
+			EE_Error::add_attention(
634
+				sprintf(
635
+					esc_html__(
636
+						'A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
637
+						'event_espresso'
638
+					),
639
+					EEH_Template::format_currency($available_payment_amount),
640
+					implode(', ', array_keys($registrations)),
641
+					'<br/>',
642
+					EEH_Template::format_currency($payment->amount())
643
+				),
644
+				__FILE__,
645
+				__FUNCTION__,
646
+				__LINE__
647
+			);
648
+		}
649
+	}
650
+
651
+
652
+	/**
653
+	 * update registration REG_paid field after successful payment and link registration with payment
654
+	 *
655
+	 * @param EE_Registration $registration
656
+	 * @param EE_Payment      $payment
657
+	 * @param float           $available_payment_amount
658
+	 * @return float
659
+	 * @throws EE_Error
660
+	 * @throws InvalidArgumentException
661
+	 * @throws RuntimeException
662
+	 * @throws InvalidDataTypeException
663
+	 * @throws InvalidInterfaceException
664
+	 */
665
+	public function process_registration_payment(
666
+		EE_Registration $registration,
667
+		EE_Payment $payment,
668
+		$available_payment_amount = 0.00
669
+	) {
670
+		$owing = $registration->final_price() - $registration->paid();
671
+		if ($owing > 0) {
672
+			// don't allow payment amount to exceed the available payment amount, OR the amount owing
673
+			$payment_amount = min($available_payment_amount, $owing);
674
+			// update $available_payment_amount
675
+			$available_payment_amount -= $payment_amount;
676
+			// calculate and set new REG_paid
677
+			$registration->set_paid($registration->paid() + $payment_amount);
678
+			// now save it
679
+			$this->_apply_registration_payment($registration, $payment, $payment_amount);
680
+		}
681
+		return $available_payment_amount;
682
+	}
683
+
684
+
685
+	/**
686
+	 * update registration REG_paid field after successful payment and link registration with payment
687
+	 *
688
+	 * @param EE_Registration $registration
689
+	 * @param EE_Payment      $payment
690
+	 * @param float           $payment_amount
691
+	 * @return void
692
+	 * @throws EE_Error
693
+	 * @throws InvalidArgumentException
694
+	 * @throws InvalidDataTypeException
695
+	 * @throws InvalidInterfaceException
696
+	 */
697
+	protected function _apply_registration_payment(
698
+		EE_Registration $registration,
699
+		EE_Payment $payment,
700
+		$payment_amount = 0.00
701
+	) {
702
+		// find any existing reg payment records for this registration and payment
703
+		$existing_reg_payment = EEM_Registration_Payment::instance()->get_one(
704
+			array(array('REG_ID' => $registration->ID(), 'PAY_ID' => $payment->ID()))
705
+		);
706
+		// if existing registration payment exists
707
+		if ($existing_reg_payment instanceof EE_Registration_Payment) {
708
+			// then update that record
709
+			$existing_reg_payment->set_amount($payment_amount);
710
+			$existing_reg_payment->save();
711
+		} else {
712
+			// or add new relation between registration and payment and set amount
713
+			$registration->_add_relation_to(
714
+				$payment,
715
+				'Payment',
716
+				array('RPY_amount' => $payment_amount)
717
+			);
718
+			// make it stick
719
+			$registration->save();
720
+		}
721
+	}
722
+
723
+
724
+	/**
725
+	 * update registration REG_paid field after refund and link registration with payment
726
+	 *
727
+	 * @param EE_Registration $registration
728
+	 * @param EE_Payment      $payment
729
+	 * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
730
+	 * @return float
731
+	 * @throws EE_Error
732
+	 * @throws InvalidArgumentException
733
+	 * @throws RuntimeException
734
+	 * @throws InvalidDataTypeException
735
+	 * @throws InvalidInterfaceException
736
+	 */
737
+	public function process_registration_refund(
738
+		EE_Registration $registration,
739
+		EE_Payment $payment,
740
+		$available_refund_amount = 0.00
741
+	) {
742
+		// EEH_Debug_Tools::printr( $payment->amount(), '$payment->amount()', __FILE__, __LINE__ );
743
+		if ($registration->paid() > 0) {
744
+			// ensure $available_refund_amount is NOT negative
745
+			$available_refund_amount = (float) abs($available_refund_amount);
746
+			// don't allow refund amount to exceed the available payment amount, OR the amount paid
747
+			$refund_amount = min($available_refund_amount, (float) $registration->paid());
748
+			// update $available_payment_amount
749
+			$available_refund_amount -= $refund_amount;
750
+			// calculate and set new REG_paid
751
+			$registration->set_paid($registration->paid() - $refund_amount);
752
+			// convert payment amount back to a negative value for storage in the db
753
+			$refund_amount = (float) abs($refund_amount) * -1;
754
+			// now save it
755
+			$this->_apply_registration_payment($registration, $payment, $refund_amount);
756
+		}
757
+		return $available_refund_amount;
758
+	}
759
+
760
+
761
+	/**
762
+	 * Process payments and transaction after payment process completed.
763
+	 * ultimately this will send the TXN and payment details off so that notifications can be sent out.
764
+	 * if this request happens to be processing an IPN,
765
+	 * then we will also set the Payment Options Reg Step to completed,
766
+	 * and attempt to completely finalize the TXN if all of the other Reg Steps are completed as well.
767
+	 *
768
+	 * @param EE_Transaction $transaction
769
+	 * @param EE_Payment     $payment
770
+	 * @param bool           $IPN
771
+	 * @throws EE_Error
772
+	 * @throws InvalidArgumentException
773
+	 * @throws ReflectionException
774
+	 * @throws RuntimeException
775
+	 * @throws InvalidDataTypeException
776
+	 * @throws InvalidInterfaceException
777
+	 */
778
+	protected function _post_payment_processing(EE_Transaction $transaction, EE_Payment $payment, $IPN = false)
779
+	{
780
+		/** @type EE_Transaction_Processor $transaction_processor */
781
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
782
+		// is the Payment Options Reg Step completed ?
783
+		$payment_options_step_completed = $transaction->reg_step_completed('payment_options');
784
+		// if the Payment Options Reg Step is completed...
785
+		$revisit = $payment_options_step_completed === true;
786
+		// then this is kinda sorta a revisit with regards to payments at least
787
+		$transaction_processor->set_revisit($revisit);
788
+		// if this is an IPN, let's consider the Payment Options Reg Step completed if not already
789
+		if (
790
+			$IPN
791
+			&& $payment_options_step_completed !== true
792
+			&& ($payment->is_approved() || $payment->is_pending())
793
+		) {
794
+			$payment_options_step_completed = $transaction->set_reg_step_completed(
795
+				'payment_options'
796
+			);
797
+		}
798
+		// maybe update status, but don't save transaction just yet
799
+		$transaction->update_status_based_on_total_paid(false);
800
+		// check if 'finalize_registration' step has been completed...
801
+		$finalized = $transaction->reg_step_completed('finalize_registration');
802
+		//  if this is an IPN and the final step has not been initiated
803
+		if ($IPN && $payment_options_step_completed && $finalized === false) {
804
+			// and if it hasn't already been set as being started...
805
+			$finalized = $transaction->set_reg_step_initiated('finalize_registration');
806
+		}
807
+		$transaction->save();
808
+		// because the above will return false if the final step was not fully completed, we need to check again...
809
+		if ($IPN && $finalized !== false) {
810
+			// and if we are all good to go, then send out notifications
811
+			add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
812
+			// ok, now process the transaction according to the payment
813
+			$transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
814
+				$transaction,
815
+				$payment
816
+			);
817
+		}
818
+		// DEBUG LOG
819
+		$payment_method = $payment->payment_method();
820
+		if ($payment_method instanceof EE_Payment_Method) {
821
+			$payment_method_type_obj = $payment_method->type_obj();
822
+			if ($payment_method_type_obj instanceof EE_PMT_Base) {
823
+				$gateway = $payment_method_type_obj->get_gateway();
824
+				if ($gateway instanceof EE_Gateway) {
825
+					$gateway->log(
826
+						array(
827
+							'message'               => (string) esc_html__('Post Payment Transaction Details', 'event_espresso'),
828
+							'transaction'           => $transaction->model_field_array(),
829
+							'finalized'             => $finalized,
830
+							'IPN'                   => $IPN,
831
+							'deliver_notifications' => has_filter(
832
+								'FHEE__EED_Messages___maybe_registration__deliver_notifications'
833
+							),
834
+						),
835
+						$payment
836
+					);
837
+				}
838
+			}
839
+		}
840
+	}
841
+
842
+
843
+	/**
844
+	 * Force posts to PayPal to use TLS v1.2. See:
845
+	 * https://core.trac.wordpress.org/ticket/36320
846
+	 * https://core.trac.wordpress.org/ticket/34924#comment:15
847
+	 * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
848
+	 * This will affect PayPal standard, pro, express, and Payflow.
849
+	 *
850
+	 * @param $handle
851
+	 * @param $r
852
+	 * @param $url
853
+	 */
854
+	public static function _curl_requests_to_paypal_use_tls($handle, $r, $url)
855
+	{
856
+		if (strpos($url, 'https://') !== false && strpos($url, '.paypal.com') !== false) {
857
+			// Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
858
+			// instead of the constant because it might not be defined
859
+			curl_setopt($handle, CURLOPT_SSLVERSION, 6);
860
+		}
861
+	}
862 862
 }
Please login to merge, or discard this patch.
core/services/container/CoffeeMaker.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
     public static function validateType($type)
69 69
     {
70 70
         $types = CoffeeMaker::getTypes();
71
-        if (! in_array($type, $types, true)) {
71
+        if ( ! in_array($type, $types, true)) {
72 72
             throw new InvalidIdentifierException(
73 73
                 is_object($type) ? get_class($type) : gettype($type),
74 74
                 esc_html__(
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
     protected function resolveClassAndFilepath(RecipeInterface $recipe)
152 152
     {
153 153
         $paths = $recipe->paths();
154
-        if (! empty($paths)) {
154
+        if ( ! empty($paths)) {
155 155
             foreach ($paths as $path) {
156 156
                 if (strpos($path, '*') === false && is_readable($path)) {
157 157
                     require_once($path);
Please login to merge, or discard this patch.
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -17,156 +17,156 @@
 block discarded – undo
17 17
  */
18 18
 abstract class CoffeeMaker implements CoffeeMakerInterface
19 19
 {
20
-    /**
21
-     * Indicates that CoffeeMaker should construct a NEW entity instance from the provided arguments (if given)
22
-     */
23
-    const BREW_NEW = 'new';
24
-
25
-    /**
26
-     * Indicates that CoffeeMaker should always return a SHARED instance
27
-     */
28
-    const BREW_SHARED = 'shared';
29
-
30
-    /**
31
-     * Indicates that CoffeeMaker should only load the file/class/interface but NOT instantiate
32
-     */
33
-    const BREW_LOAD_ONLY = 'load_only';
34
-
35
-
36
-    /**
37
-     * @var CoffeePotInterface $coffee_pot
38
-     */
39
-    private $coffee_pot;
40
-
41
-    /**
42
-     * @var DependencyInjector $injector
43
-     */
44
-    private $injector;
45
-
46
-
47
-    /**
48
-     * @return array
49
-     */
50
-    public static function getTypes()
51
-    {
52
-        return (array) apply_filters(
53
-            'FHEE__EventEspresso\core\services\container\CoffeeMaker__getTypes',
54
-            array(
55
-                CoffeeMaker::BREW_NEW,
56
-                CoffeeMaker::BREW_SHARED,
57
-                CoffeeMaker::BREW_LOAD_ONLY,
58
-            )
59
-        );
60
-    }
61
-
62
-
63
-    /**
64
-     * @param $type
65
-     * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
66
-     */
67
-    public static function validateType($type)
68
-    {
69
-        $types = CoffeeMaker::getTypes();
70
-        if (! in_array($type, $types, true)) {
71
-            throw new InvalidIdentifierException(
72
-                is_object($type) ? get_class($type) : gettype($type),
73
-                esc_html__(
74
-                    'recipe type (one of the class constants on \EventEspresso\core\services\container\CoffeeMaker)',
75
-                    'event_espresso'
76
-                )
77
-            );
78
-        }
79
-        return $type;
80
-    }
81
-
82
-
83
-    /**
84
-     * CoffeeMaker constructor.
85
-     *
86
-     * @param CoffeePotInterface $coffee_pot
87
-     * @param InjectorInterface  $injector
88
-     */
89
-    public function __construct(CoffeePotInterface $coffee_pot, InjectorInterface $injector)
90
-    {
91
-        $this->coffee_pot = $coffee_pot;
92
-        $this->injector = $injector;
93
-    }
94
-
95
-
96
-    /**
97
-     * @return \EventEspresso\core\services\container\CoffeePotInterface
98
-     */
99
-    protected function coffeePot()
100
-    {
101
-        return $this->coffee_pot;
102
-    }
103
-
104
-
105
-    /**
106
-     * @return \EventEspresso\core\services\container\DependencyInjector
107
-     */
108
-    protected function injector()
109
-    {
110
-        return $this->injector;
111
-    }
112
-
113
-
114
-    /**
115
-     * Examines the constructor to determine which method should be used for instantiation
116
-     *
117
-     * @param \ReflectionClass $reflector
118
-     * @return mixed
119
-     * @throws InstantiationException
120
-     */
121
-    protected function resolveInstantiationMethod(\ReflectionClass $reflector)
122
-    {
123
-        if ($reflector->getConstructor() === null) {
124
-            return 'NewInstance';
125
-        }
126
-        if ($reflector->isInstantiable()) {
127
-            return 'NewInstanceArgs';
128
-        }
129
-        if (method_exists($reflector->getName(), 'instance')) {
130
-            return 'instance';
131
-        }
132
-        if (method_exists($reflector->getName(), 'new_instance')) {
133
-            return 'new_instance';
134
-        }
135
-        if (method_exists($reflector->getName(), 'new_instance_from_db')) {
136
-            return 'new_instance_from_db';
137
-        }
138
-        throw new InstantiationException($reflector->getName());
139
-    }
140
-
141
-
142
-    /**
143
-     * Ensures files for classes that are not PSR-4 compatible are loaded
144
-     * and then verifies that classes exist where applicable
145
-     *
146
-     * @param RecipeInterface $recipe
147
-     * @return bool
148
-     * @throws InvalidClassException
149
-     */
150
-    protected function resolveClassAndFilepath(RecipeInterface $recipe)
151
-    {
152
-        $paths = $recipe->paths();
153
-        if (! empty($paths)) {
154
-            foreach ($paths as $path) {
155
-                if (strpos($path, '*') === false && is_readable($path)) {
156
-                    require_once($path);
157
-                }
158
-            }
159
-        }
160
-        // re: using "false" for class_exists() second param:
161
-        // if a class name is not already known to PHP, then class_exists() will run through
162
-        // all of the registered spl_autoload functions until it either finds the class,
163
-        // or gets to the end of the registered spl_autoload functions.
164
-        // When the second parameter is true, it will also attempt to load the class file,
165
-        // but it will also trigger an error if the class can not be loaded.
166
-        // We don't want that extra error in the mix, so we have set the second param to "false"
167
-        if ($recipe->type() !== CoffeeMaker::BREW_LOAD_ONLY && ! class_exists($recipe->fqcn(), false)) {
168
-            throw new InvalidClassException($recipe->identifier());
169
-        }
170
-        return true;
171
-    }
20
+	/**
21
+	 * Indicates that CoffeeMaker should construct a NEW entity instance from the provided arguments (if given)
22
+	 */
23
+	const BREW_NEW = 'new';
24
+
25
+	/**
26
+	 * Indicates that CoffeeMaker should always return a SHARED instance
27
+	 */
28
+	const BREW_SHARED = 'shared';
29
+
30
+	/**
31
+	 * Indicates that CoffeeMaker should only load the file/class/interface but NOT instantiate
32
+	 */
33
+	const BREW_LOAD_ONLY = 'load_only';
34
+
35
+
36
+	/**
37
+	 * @var CoffeePotInterface $coffee_pot
38
+	 */
39
+	private $coffee_pot;
40
+
41
+	/**
42
+	 * @var DependencyInjector $injector
43
+	 */
44
+	private $injector;
45
+
46
+
47
+	/**
48
+	 * @return array
49
+	 */
50
+	public static function getTypes()
51
+	{
52
+		return (array) apply_filters(
53
+			'FHEE__EventEspresso\core\services\container\CoffeeMaker__getTypes',
54
+			array(
55
+				CoffeeMaker::BREW_NEW,
56
+				CoffeeMaker::BREW_SHARED,
57
+				CoffeeMaker::BREW_LOAD_ONLY,
58
+			)
59
+		);
60
+	}
61
+
62
+
63
+	/**
64
+	 * @param $type
65
+	 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
66
+	 */
67
+	public static function validateType($type)
68
+	{
69
+		$types = CoffeeMaker::getTypes();
70
+		if (! in_array($type, $types, true)) {
71
+			throw new InvalidIdentifierException(
72
+				is_object($type) ? get_class($type) : gettype($type),
73
+				esc_html__(
74
+					'recipe type (one of the class constants on \EventEspresso\core\services\container\CoffeeMaker)',
75
+					'event_espresso'
76
+				)
77
+			);
78
+		}
79
+		return $type;
80
+	}
81
+
82
+
83
+	/**
84
+	 * CoffeeMaker constructor.
85
+	 *
86
+	 * @param CoffeePotInterface $coffee_pot
87
+	 * @param InjectorInterface  $injector
88
+	 */
89
+	public function __construct(CoffeePotInterface $coffee_pot, InjectorInterface $injector)
90
+	{
91
+		$this->coffee_pot = $coffee_pot;
92
+		$this->injector = $injector;
93
+	}
94
+
95
+
96
+	/**
97
+	 * @return \EventEspresso\core\services\container\CoffeePotInterface
98
+	 */
99
+	protected function coffeePot()
100
+	{
101
+		return $this->coffee_pot;
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return \EventEspresso\core\services\container\DependencyInjector
107
+	 */
108
+	protected function injector()
109
+	{
110
+		return $this->injector;
111
+	}
112
+
113
+
114
+	/**
115
+	 * Examines the constructor to determine which method should be used for instantiation
116
+	 *
117
+	 * @param \ReflectionClass $reflector
118
+	 * @return mixed
119
+	 * @throws InstantiationException
120
+	 */
121
+	protected function resolveInstantiationMethod(\ReflectionClass $reflector)
122
+	{
123
+		if ($reflector->getConstructor() === null) {
124
+			return 'NewInstance';
125
+		}
126
+		if ($reflector->isInstantiable()) {
127
+			return 'NewInstanceArgs';
128
+		}
129
+		if (method_exists($reflector->getName(), 'instance')) {
130
+			return 'instance';
131
+		}
132
+		if (method_exists($reflector->getName(), 'new_instance')) {
133
+			return 'new_instance';
134
+		}
135
+		if (method_exists($reflector->getName(), 'new_instance_from_db')) {
136
+			return 'new_instance_from_db';
137
+		}
138
+		throw new InstantiationException($reflector->getName());
139
+	}
140
+
141
+
142
+	/**
143
+	 * Ensures files for classes that are not PSR-4 compatible are loaded
144
+	 * and then verifies that classes exist where applicable
145
+	 *
146
+	 * @param RecipeInterface $recipe
147
+	 * @return bool
148
+	 * @throws InvalidClassException
149
+	 */
150
+	protected function resolveClassAndFilepath(RecipeInterface $recipe)
151
+	{
152
+		$paths = $recipe->paths();
153
+		if (! empty($paths)) {
154
+			foreach ($paths as $path) {
155
+				if (strpos($path, '*') === false && is_readable($path)) {
156
+					require_once($path);
157
+				}
158
+			}
159
+		}
160
+		// re: using "false" for class_exists() second param:
161
+		// if a class name is not already known to PHP, then class_exists() will run through
162
+		// all of the registered spl_autoload functions until it either finds the class,
163
+		// or gets to the end of the registered spl_autoload functions.
164
+		// When the second parameter is true, it will also attempt to load the class file,
165
+		// but it will also trigger an error if the class can not be loaded.
166
+		// We don't want that extra error in the mix, so we have set the second param to "false"
167
+		if ($recipe->type() !== CoffeeMaker::BREW_LOAD_ONLY && ! class_exists($recipe->fqcn(), false)) {
168
+			throw new InvalidClassException($recipe->identifier());
169
+		}
170
+		return true;
171
+	}
172 172
 }
Please login to merge, or discard this patch.
core/services/container/Recipe.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
      */
190 190
     public function setIdentifier($identifier)
191 191
     {
192
-        if (! is_string($identifier) || empty($identifier)) {
192
+        if ( ! is_string($identifier) || empty($identifier)) {
193 193
             throw new InvalidIdentifierException(
194 194
                 is_object($identifier) ? get_class($identifier) : gettype($identifier),
195 195
                 esc_html__('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso')
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
     public function setFqcn($fqcn)
217 217
     {
218 218
         $fqcn = ! empty($fqcn) ? $fqcn : $this->identifier;
219
-        if (! is_string($fqcn)) {
219
+        if ( ! is_string($fqcn)) {
220 220
             throw new InvalidDataTypeException(
221 221
                 '$fqcn',
222 222
                 is_object($fqcn) ? get_class($fqcn) : gettype($fqcn),
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
         if (empty($ingredients)) {
248 248
             return;
249 249
         }
250
-        if (! is_array($ingredients)) {
250
+        if ( ! is_array($ingredients)) {
251 251
             throw new InvalidDataTypeException(
252 252
                 '$ingredients',
253 253
                 is_object($ingredients) ? get_class($ingredients) : gettype($ingredients),
@@ -279,7 +279,7 @@  discard block
 block discarded – undo
279 279
         if (empty($filters)) {
280 280
             return;
281 281
         }
282
-        if (! is_array($filters)) {
282
+        if ( ! is_array($filters)) {
283 283
             throw new InvalidDataTypeException(
284 284
                 '$filters',
285 285
                 is_object($filters) ? get_class($filters) : gettype($filters),
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
         if (empty($paths)) {
307 307
             return;
308 308
         }
309
-        if (! (is_string($paths) || is_array($paths))) {
309
+        if ( ! (is_string($paths) || is_array($paths))) {
310 310
             throw new InvalidDataTypeException(
311 311
                 '$path',
312 312
                 is_object($paths) ? get_class($paths) : gettype($paths),
Please login to merge, or discard this patch.
Indentation   +307 added lines, -307 removed lines patch added patch discarded remove patch
@@ -18,311 +18,311 @@
 block discarded – undo
18 18
  */
19 19
 class Recipe implements RecipeInterface
20 20
 {
21
-    /**
22
-     * A default Recipe to use if none is specified for a class
23
-     */
24
-    const DEFAULT_ID = '*';
25
-
26
-    /**
27
-     * Identifier for the entity class to be constructed.
28
-     * Typically a Fully Qualified Class Name
29
-     *
30
-     * @var string $identifier
31
-     */
32
-    private $identifier;
33
-
34
-    /**
35
-     * Fully Qualified Class Name
36
-     *
37
-     * @var string $fqcn
38
-     */
39
-    private $fqcn;
40
-
41
-    /**
42
-     * a dependency class map array
43
-     * If a Recipe is for a single class (or group of classes that shares the EXACT SAME constructor arguments),
44
-     * and that class type hints for an interface, then this property allows you to configure what dependencies
45
-     * get used when instantiating the class.
46
-     * For example:
47
-     *  There's a class called Coffee, and one of its constructor arguments is BeanInterface
48
-     *  There are two implementations of BeanInterface: HonduranBean, and KenyanBean
49
-     *  We want one Coffee object to use HonduranBean for its BeanInterface,
50
-     *  and the 2nd Coffee object to use KenyanBean for its BeanInterface.
51
-     *  To do this, we need to create two Recipes:
52
-     *      one with an identifier of 'HonduranCoffee' using the following ingredients :
53
-     *          array('BeanInterface' => 'HonduranBean')
54
-     *      and the other with an identifier of 'KenyanCoffee' using the following ingredients :
55
-     *          array('BeanInterface' => 'KenyanBean')
56
-     *  Then, whenever the CoffeeShop brews an instance of HonduranCoffee,
57
-     *  an instance of HonduranBean will get injected for the BeanInterface dependency,
58
-     *  and whenever the CoffeeShop brews an instance of KenyanCoffee,
59
-     *  an instance of KenyanBean will get injected for the BeanInterface dependency
60
-     *
61
-     * @var array $ingredients
62
-     */
63
-    private $ingredients = array();
64
-
65
-    /**
66
-     * one of the class constants from CoffeeShop:
67
-     *  CoffeeMaker::BREW_NEW - creates a new instance
68
-     *  CoffeeMaker::BREW_SHARED - creates a shared instance
69
-     *  CoffeeMaker::BREW_LOAD_ONLY - loads but does not instantiate
70
-     *
71
-     * @var string $type
72
-     */
73
-    private $type;
74
-
75
-    /**
76
-     * class name aliases - typically a Fully Qualified Interface that the class implements
77
-     * identifiers passed to the CoffeeShop will be run through the filters to find the correct class name
78
-     *
79
-     * @var array $filters
80
-     */
81
-    private $filters = array();
82
-
83
-    /**
84
-     * array of full server filepaths to files that may contain the class
85
-     *
86
-     * @var array $paths
87
-     */
88
-    private $paths = array();
89
-
90
-
91
-    /**
92
-     * Recipe constructor.
93
-     *
94
-     * @param string $identifier    class identifier, can be an alias, or FQCN, or whatever
95
-     * @param string $fqcn          \Fully\Qualified\ClassName, optional if $identifier is FQCN
96
-     * @param array  $ingredients   array of dependencies that can not be resolved automatically,
97
-     *                              used for resolving concrete classes for type hinted interfaces
98
-     *                              for the dependencies of THIS class
99
-     * @param string $type          recipe type: one of the class constants on
100
-     *                              \EventEspresso\core\services\container\CoffeeMaker
101
-     * @param array  $filters       array of class aliases, or class interfaces
102
-     *                              this works somewhat opposite to the $ingredients array above,
103
-     *                              in that this array specifies interfaces or aliases
104
-     *                              that this Recipe can be used for when resolving OTHER class's dependencies
105
-     * @param array  $paths         if class can not be loaded via PSR-4 autoloading,
106
-     *                              then supply a filepath, or array of filepaths, so that it can be included
107
-     * @throws InvalidIdentifierException
108
-     * @throws RuntimeException
109
-     * @throws InvalidInterfaceException
110
-     * @throws InvalidClassException
111
-     * @throws InvalidDataTypeException
112
-     */
113
-    public function __construct(
114
-        $identifier,
115
-        $fqcn = '',
116
-        array $filters = array(),
117
-        array $ingredients = array(),
118
-        $type = CoffeeMaker::BREW_NEW,
119
-        array $paths = array()
120
-    ) {
121
-        $this->setIdentifier($identifier);
122
-        $this->setFilters($filters);
123
-        $this->setIngredients($ingredients);
124
-        $this->setType($type);
125
-        $this->setPaths($paths);
126
-        $this->setFqcn($fqcn);
127
-    }
128
-
129
-
130
-    /**
131
-     * @return string
132
-     */
133
-    public function identifier()
134
-    {
135
-        return $this->identifier;
136
-    }
137
-
138
-
139
-    /**
140
-     * @return string
141
-     */
142
-    public function fqcn()
143
-    {
144
-        return $this->fqcn;
145
-    }
146
-
147
-
148
-    /**
149
-     * @return array
150
-     */
151
-    public function filters()
152
-    {
153
-        return $this->filters;
154
-    }
155
-
156
-
157
-    /**
158
-     * @return array
159
-     */
160
-    public function ingredients()
161
-    {
162
-        return $this->ingredients;
163
-    }
164
-
165
-
166
-    /**
167
-     * @return string
168
-     */
169
-    public function type()
170
-    {
171
-        return $this->type;
172
-    }
173
-
174
-
175
-    /**
176
-     * @return array
177
-     */
178
-    public function paths()
179
-    {
180
-        return $this->paths;
181
-    }
182
-
183
-
184
-    /**
185
-     * @param  string $identifier Identifier for the entity class that the Recipe applies to
186
-     *                            Typically a Fully Qualified Class Name
187
-     * @throws InvalidIdentifierException
188
-     */
189
-    public function setIdentifier($identifier)
190
-    {
191
-        if (! is_string($identifier) || empty($identifier)) {
192
-            throw new InvalidIdentifierException(
193
-                is_object($identifier) ? get_class($identifier) : gettype($identifier),
194
-                esc_html__('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso')
195
-            );
196
-        }
197
-        $this->identifier = $identifier;
198
-    }
199
-
200
-
201
-    /**
202
-     * Ensures incoming string is a valid Fully Qualified Class Name,
203
-     * except if this is the default wildcard Recipe ( * ),
204
-     * or it's NOT an actual FQCN because the Recipe is using filepaths
205
-     * for classes that are not PSR-4 compatible
206
-     * PLZ NOTE:
207
-     *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
208
-     *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
209
-     *
210
-     * @param string $fqcn
211
-     * @throws InvalidDataTypeException
212
-     * @throws InvalidClassException
213
-     * @throws InvalidInterfaceException
214
-     */
215
-    public function setFqcn($fqcn)
216
-    {
217
-        $fqcn = ! empty($fqcn) ? $fqcn : $this->identifier;
218
-        if (! is_string($fqcn)) {
219
-            throw new InvalidDataTypeException(
220
-                '$fqcn',
221
-                is_object($fqcn) ? get_class($fqcn) : gettype($fqcn),
222
-                esc_html__('string (Fully\Qualified\ClassName)', 'event_espresso')
223
-            );
224
-        }
225
-        $fqcn = ltrim($fqcn, '\\');
226
-        if (
227
-            $fqcn !== Recipe::DEFAULT_ID
228
-            && ! empty($fqcn)
229
-            && empty($this->paths)
230
-            && ! (class_exists($fqcn) || interface_exists($fqcn))
231
-        ) {
232
-            throw new InvalidClassException($fqcn);
233
-        }
234
-        $this->fqcn = $fqcn;
235
-    }
236
-
237
-
238
-    /**
239
-     * @param array $ingredients    an array of dependencies where keys are the aliases and values are the FQCNs
240
-     *                              example:
241
-     *                              array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
242
-     * @throws InvalidDataTypeException
243
-     */
244
-    public function setIngredients(array $ingredients)
245
-    {
246
-        if (empty($ingredients)) {
247
-            return;
248
-        }
249
-        if (! is_array($ingredients)) {
250
-            throw new InvalidDataTypeException(
251
-                '$ingredients',
252
-                is_object($ingredients) ? get_class($ingredients) : gettype($ingredients),
253
-                esc_html__('array of class dependencies', 'event_espresso')
254
-            );
255
-        }
256
-        $this->ingredients = array_merge($this->ingredients, $ingredients);
257
-    }
258
-
259
-
260
-    /**
261
-     * @param string $type one of the class constants returned from CoffeeMaker::getTypes()
262
-     * @throws InvalidIdentifierException
263
-     */
264
-    public function setType($type = CoffeeMaker::BREW_NEW)
265
-    {
266
-        $this->type = CoffeeMaker::validateType($type);
267
-    }
268
-
269
-
270
-    /**
271
-     * @param array $filters    an array of filters where keys are the aliases and values are the FQCNs
272
-     *                          example:
273
-     *                          array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
274
-     * @throws InvalidDataTypeException
275
-     */
276
-    public function setFilters(array $filters)
277
-    {
278
-        if (empty($filters)) {
279
-            return;
280
-        }
281
-        if (! is_array($filters)) {
282
-            throw new InvalidDataTypeException(
283
-                '$filters',
284
-                is_object($filters) ? get_class($filters) : gettype($filters),
285
-                esc_html__('array of class aliases', 'event_espresso')
286
-            );
287
-        }
288
-        $this->filters = array_merge($this->filters, $filters);
289
-    }
290
-
291
-
292
-    /**
293
-     * Ensures incoming paths is a valid filepath, or array of valid filepaths,
294
-     * and merges them in with any existing filepaths
295
-     * PLZ NOTE:
296
-     *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
297
-     *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
298
-     *
299
-     * @param string|array $paths
300
-     * @throws RuntimeException
301
-     * @throws InvalidDataTypeException
302
-     */
303
-    public function setPaths($paths = array())
304
-    {
305
-        if (empty($paths)) {
306
-            return;
307
-        }
308
-        if (! (is_string($paths) || is_array($paths))) {
309
-            throw new InvalidDataTypeException(
310
-                '$path',
311
-                is_object($paths) ? get_class($paths) : gettype($paths),
312
-                esc_html__('string or array of strings (full server filepath(s))', 'event_espresso')
313
-            );
314
-        }
315
-        $paths = (array) $paths;
316
-        foreach ($paths as $path) {
317
-            if (strpos($path, '*') === false && ! is_readable($path)) {
318
-                throw new RuntimeException(
319
-                    sprintf(
320
-                        esc_html__('The following filepath is not readable: "%1$s"', 'event_espresso'),
321
-                        $path
322
-                    )
323
-                );
324
-            }
325
-        }
326
-        $this->paths = array_merge($this->paths, $paths);
327
-    }
21
+	/**
22
+	 * A default Recipe to use if none is specified for a class
23
+	 */
24
+	const DEFAULT_ID = '*';
25
+
26
+	/**
27
+	 * Identifier for the entity class to be constructed.
28
+	 * Typically a Fully Qualified Class Name
29
+	 *
30
+	 * @var string $identifier
31
+	 */
32
+	private $identifier;
33
+
34
+	/**
35
+	 * Fully Qualified Class Name
36
+	 *
37
+	 * @var string $fqcn
38
+	 */
39
+	private $fqcn;
40
+
41
+	/**
42
+	 * a dependency class map array
43
+	 * If a Recipe is for a single class (or group of classes that shares the EXACT SAME constructor arguments),
44
+	 * and that class type hints for an interface, then this property allows you to configure what dependencies
45
+	 * get used when instantiating the class.
46
+	 * For example:
47
+	 *  There's a class called Coffee, and one of its constructor arguments is BeanInterface
48
+	 *  There are two implementations of BeanInterface: HonduranBean, and KenyanBean
49
+	 *  We want one Coffee object to use HonduranBean for its BeanInterface,
50
+	 *  and the 2nd Coffee object to use KenyanBean for its BeanInterface.
51
+	 *  To do this, we need to create two Recipes:
52
+	 *      one with an identifier of 'HonduranCoffee' using the following ingredients :
53
+	 *          array('BeanInterface' => 'HonduranBean')
54
+	 *      and the other with an identifier of 'KenyanCoffee' using the following ingredients :
55
+	 *          array('BeanInterface' => 'KenyanBean')
56
+	 *  Then, whenever the CoffeeShop brews an instance of HonduranCoffee,
57
+	 *  an instance of HonduranBean will get injected for the BeanInterface dependency,
58
+	 *  and whenever the CoffeeShop brews an instance of KenyanCoffee,
59
+	 *  an instance of KenyanBean will get injected for the BeanInterface dependency
60
+	 *
61
+	 * @var array $ingredients
62
+	 */
63
+	private $ingredients = array();
64
+
65
+	/**
66
+	 * one of the class constants from CoffeeShop:
67
+	 *  CoffeeMaker::BREW_NEW - creates a new instance
68
+	 *  CoffeeMaker::BREW_SHARED - creates a shared instance
69
+	 *  CoffeeMaker::BREW_LOAD_ONLY - loads but does not instantiate
70
+	 *
71
+	 * @var string $type
72
+	 */
73
+	private $type;
74
+
75
+	/**
76
+	 * class name aliases - typically a Fully Qualified Interface that the class implements
77
+	 * identifiers passed to the CoffeeShop will be run through the filters to find the correct class name
78
+	 *
79
+	 * @var array $filters
80
+	 */
81
+	private $filters = array();
82
+
83
+	/**
84
+	 * array of full server filepaths to files that may contain the class
85
+	 *
86
+	 * @var array $paths
87
+	 */
88
+	private $paths = array();
89
+
90
+
91
+	/**
92
+	 * Recipe constructor.
93
+	 *
94
+	 * @param string $identifier    class identifier, can be an alias, or FQCN, or whatever
95
+	 * @param string $fqcn          \Fully\Qualified\ClassName, optional if $identifier is FQCN
96
+	 * @param array  $ingredients   array of dependencies that can not be resolved automatically,
97
+	 *                              used for resolving concrete classes for type hinted interfaces
98
+	 *                              for the dependencies of THIS class
99
+	 * @param string $type          recipe type: one of the class constants on
100
+	 *                              \EventEspresso\core\services\container\CoffeeMaker
101
+	 * @param array  $filters       array of class aliases, or class interfaces
102
+	 *                              this works somewhat opposite to the $ingredients array above,
103
+	 *                              in that this array specifies interfaces or aliases
104
+	 *                              that this Recipe can be used for when resolving OTHER class's dependencies
105
+	 * @param array  $paths         if class can not be loaded via PSR-4 autoloading,
106
+	 *                              then supply a filepath, or array of filepaths, so that it can be included
107
+	 * @throws InvalidIdentifierException
108
+	 * @throws RuntimeException
109
+	 * @throws InvalidInterfaceException
110
+	 * @throws InvalidClassException
111
+	 * @throws InvalidDataTypeException
112
+	 */
113
+	public function __construct(
114
+		$identifier,
115
+		$fqcn = '',
116
+		array $filters = array(),
117
+		array $ingredients = array(),
118
+		$type = CoffeeMaker::BREW_NEW,
119
+		array $paths = array()
120
+	) {
121
+		$this->setIdentifier($identifier);
122
+		$this->setFilters($filters);
123
+		$this->setIngredients($ingredients);
124
+		$this->setType($type);
125
+		$this->setPaths($paths);
126
+		$this->setFqcn($fqcn);
127
+	}
128
+
129
+
130
+	/**
131
+	 * @return string
132
+	 */
133
+	public function identifier()
134
+	{
135
+		return $this->identifier;
136
+	}
137
+
138
+
139
+	/**
140
+	 * @return string
141
+	 */
142
+	public function fqcn()
143
+	{
144
+		return $this->fqcn;
145
+	}
146
+
147
+
148
+	/**
149
+	 * @return array
150
+	 */
151
+	public function filters()
152
+	{
153
+		return $this->filters;
154
+	}
155
+
156
+
157
+	/**
158
+	 * @return array
159
+	 */
160
+	public function ingredients()
161
+	{
162
+		return $this->ingredients;
163
+	}
164
+
165
+
166
+	/**
167
+	 * @return string
168
+	 */
169
+	public function type()
170
+	{
171
+		return $this->type;
172
+	}
173
+
174
+
175
+	/**
176
+	 * @return array
177
+	 */
178
+	public function paths()
179
+	{
180
+		return $this->paths;
181
+	}
182
+
183
+
184
+	/**
185
+	 * @param  string $identifier Identifier for the entity class that the Recipe applies to
186
+	 *                            Typically a Fully Qualified Class Name
187
+	 * @throws InvalidIdentifierException
188
+	 */
189
+	public function setIdentifier($identifier)
190
+	{
191
+		if (! is_string($identifier) || empty($identifier)) {
192
+			throw new InvalidIdentifierException(
193
+				is_object($identifier) ? get_class($identifier) : gettype($identifier),
194
+				esc_html__('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso')
195
+			);
196
+		}
197
+		$this->identifier = $identifier;
198
+	}
199
+
200
+
201
+	/**
202
+	 * Ensures incoming string is a valid Fully Qualified Class Name,
203
+	 * except if this is the default wildcard Recipe ( * ),
204
+	 * or it's NOT an actual FQCN because the Recipe is using filepaths
205
+	 * for classes that are not PSR-4 compatible
206
+	 * PLZ NOTE:
207
+	 *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
208
+	 *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
209
+	 *
210
+	 * @param string $fqcn
211
+	 * @throws InvalidDataTypeException
212
+	 * @throws InvalidClassException
213
+	 * @throws InvalidInterfaceException
214
+	 */
215
+	public function setFqcn($fqcn)
216
+	{
217
+		$fqcn = ! empty($fqcn) ? $fqcn : $this->identifier;
218
+		if (! is_string($fqcn)) {
219
+			throw new InvalidDataTypeException(
220
+				'$fqcn',
221
+				is_object($fqcn) ? get_class($fqcn) : gettype($fqcn),
222
+				esc_html__('string (Fully\Qualified\ClassName)', 'event_espresso')
223
+			);
224
+		}
225
+		$fqcn = ltrim($fqcn, '\\');
226
+		if (
227
+			$fqcn !== Recipe::DEFAULT_ID
228
+			&& ! empty($fqcn)
229
+			&& empty($this->paths)
230
+			&& ! (class_exists($fqcn) || interface_exists($fqcn))
231
+		) {
232
+			throw new InvalidClassException($fqcn);
233
+		}
234
+		$this->fqcn = $fqcn;
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param array $ingredients    an array of dependencies where keys are the aliases and values are the FQCNs
240
+	 *                              example:
241
+	 *                              array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
242
+	 * @throws InvalidDataTypeException
243
+	 */
244
+	public function setIngredients(array $ingredients)
245
+	{
246
+		if (empty($ingredients)) {
247
+			return;
248
+		}
249
+		if (! is_array($ingredients)) {
250
+			throw new InvalidDataTypeException(
251
+				'$ingredients',
252
+				is_object($ingredients) ? get_class($ingredients) : gettype($ingredients),
253
+				esc_html__('array of class dependencies', 'event_espresso')
254
+			);
255
+		}
256
+		$this->ingredients = array_merge($this->ingredients, $ingredients);
257
+	}
258
+
259
+
260
+	/**
261
+	 * @param string $type one of the class constants returned from CoffeeMaker::getTypes()
262
+	 * @throws InvalidIdentifierException
263
+	 */
264
+	public function setType($type = CoffeeMaker::BREW_NEW)
265
+	{
266
+		$this->type = CoffeeMaker::validateType($type);
267
+	}
268
+
269
+
270
+	/**
271
+	 * @param array $filters    an array of filters where keys are the aliases and values are the FQCNs
272
+	 *                          example:
273
+	 *                          array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
274
+	 * @throws InvalidDataTypeException
275
+	 */
276
+	public function setFilters(array $filters)
277
+	{
278
+		if (empty($filters)) {
279
+			return;
280
+		}
281
+		if (! is_array($filters)) {
282
+			throw new InvalidDataTypeException(
283
+				'$filters',
284
+				is_object($filters) ? get_class($filters) : gettype($filters),
285
+				esc_html__('array of class aliases', 'event_espresso')
286
+			);
287
+		}
288
+		$this->filters = array_merge($this->filters, $filters);
289
+	}
290
+
291
+
292
+	/**
293
+	 * Ensures incoming paths is a valid filepath, or array of valid filepaths,
294
+	 * and merges them in with any existing filepaths
295
+	 * PLZ NOTE:
296
+	 *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
297
+	 *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
298
+	 *
299
+	 * @param string|array $paths
300
+	 * @throws RuntimeException
301
+	 * @throws InvalidDataTypeException
302
+	 */
303
+	public function setPaths($paths = array())
304
+	{
305
+		if (empty($paths)) {
306
+			return;
307
+		}
308
+		if (! (is_string($paths) || is_array($paths))) {
309
+			throw new InvalidDataTypeException(
310
+				'$path',
311
+				is_object($paths) ? get_class($paths) : gettype($paths),
312
+				esc_html__('string or array of strings (full server filepath(s))', 'event_espresso')
313
+			);
314
+		}
315
+		$paths = (array) $paths;
316
+		foreach ($paths as $path) {
317
+			if (strpos($path, '*') === false && ! is_readable($path)) {
318
+				throw new RuntimeException(
319
+					sprintf(
320
+						esc_html__('The following filepath is not readable: "%1$s"', 'event_espresso'),
321
+						$path
322
+					)
323
+				);
324
+			}
325
+		}
326
+		$this->paths = array_merge($this->paths, $paths);
327
+	}
328 328
 }
Please login to merge, or discard this patch.
core/services/container/CoffeeShop.php 2 patches
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
         }
160 160
         // if the reservoir doesn't have a closure already for the requested identifier,
161 161
         // then neither a shared service nor a closure for making entities has been built yet
162
-        if (! $this->reservoir->has($identifier)) {
162
+        if ( ! $this->reservoir->has($identifier)) {
163 163
             // so let's brew something up and add it to the proper collection
164 164
             $brewed = $this->makeCoffee($identifier, $arguments, $type);
165 165
         }
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
      */
285 285
     public function addClosure($identifier, $closure)
286 286
     {
287
-        if (! is_callable($closure)) {
287
+        if ( ! is_callable($closure)) {
288 288
             throw new InvalidDataTypeException('$closure', $closure, 'Closure');
289 289
         }
290 290
         $identifier = $this->processIdentifier($identifier);
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
             // is the wildcard recipe prefix in the identifier ?
394 394
             if (strpos($identifier, $wildcard) !== false) {
395 395
                 // track matches and use the number of wildcard characters matched for the key
396
-                $matches[ strlen($wildcard) ] = $default_recipe;
396
+                $matches[strlen($wildcard)] = $default_recipe;
397 397
             }
398 398
         }
399 399
         if (count($matches) > 0) {
@@ -433,7 +433,7 @@  discard block
 block discarded – undo
433 433
         }
434 434
         $identifier = $this->processIdentifier($identifier);
435 435
         foreach ((array) $aliases as $alias) {
436
-            $this->filters[ $this->processIdentifier($alias) ] = $identifier;
436
+            $this->filters[$this->processIdentifier($alias)] = $identifier;
437 437
         }
438 438
     }
439 439
 
@@ -475,8 +475,8 @@  discard block
 block discarded – undo
475 475
     private function filterIdentifier($identifier)
476 476
     {
477 477
         $identifier = $this->processIdentifier($identifier);
478
-        return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
479
-            ? $this->filters[ $identifier ]
478
+        return isset($this->filters[$identifier]) && ! empty($this->filters[$identifier])
479
+            ? $this->filters[$identifier]
480 480
             : $identifier;
481 481
     }
482 482
 
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
      */
492 492
     private function processIdentifier($identifier)
493 493
     {
494
-        if (! is_string($identifier)) {
494
+        if ( ! is_string($identifier)) {
495 495
             throw new InvalidIdentifierException(
496 496
                 is_object($identifier) ? get_class($identifier) : gettype($identifier),
497 497
                 '\Fully\Qualified\ClassName'
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
      */
511 511
     private function getCoffeeMaker($type)
512 512
     {
513
-        if (! $this->coffee_makers->has($type)) {
513
+        if ( ! $this->coffee_makers->has($type)) {
514 514
             throw new OutOfBoundsException(
515 515
                 esc_html__('The requested coffee maker is either missing or invalid.', 'event_espresso')
516 516
             );
@@ -537,7 +537,7 @@  discard block
 block discarded – undo
537 537
             // does this recipe use a wildcard ? (but is NOT the global default)
538 538
             if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
539 539
                 // strip the wildcard and use identifier as key
540
-                $default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
540
+                $default_recipes[str_replace('*', '', $identifier)] = $this->recipes->current();
541 541
             }
542 542
             $this->recipes->next();
543 543
         }
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
     private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
558 558
     {
559 559
         $recipe = clone $default_recipe;
560
-        if (! empty($type)) {
560
+        if ( ! empty($type)) {
561 561
             $recipe->setType($type);
562 562
         }
563 563
         // is this the base default recipe ?
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
      */
588 588
     private function validateService($identifier, $service)
589 589
     {
590
-        if (! is_object($service)) {
590
+        if ( ! is_object($service)) {
591 591
             throw new InvalidServiceException(
592 592
                 $identifier,
593 593
                 $service
Please login to merge, or discard this patch.
Indentation   +565 added lines, -565 removed lines patch added patch discarded remove patch
@@ -28,569 +28,569 @@
 block discarded – undo
28 28
  */
29 29
 class CoffeeShop implements CoffeePotInterface
30 30
 {
31
-    /**
32
-     * This was the best coffee related name I could think of to represent class name "aliases"
33
-     * So classes can be found via an alias identifier,
34
-     * that is revealed when it is run through... the filters... eh? get it?
35
-     *
36
-     * @var array $filters
37
-     */
38
-    private $filters;
39
-
40
-    /**
41
-     * These are the classes that will actually build the objects (to order of course)
42
-     *
43
-     * @var array $coffee_makers
44
-     */
45
-    private $coffee_makers;
46
-
47
-    /**
48
-     * where the instantiated "singleton" objects are stored
49
-     *
50
-     * @var CollectionInterface $carafe
51
-     */
52
-    private $carafe;
53
-
54
-    /**
55
-     * collection of Recipes that instruct us how to brew objects
56
-     *
57
-     * @var CollectionInterface $recipes
58
-     */
59
-    private $recipes;
60
-
61
-    /**
62
-     * collection of closures for brewing objects
63
-     *
64
-     * @var CollectionInterface $reservoir
65
-     */
66
-    private $reservoir;
67
-
68
-
69
-    /**
70
-     * CoffeeShop constructor
71
-     *
72
-     * @throws InvalidInterfaceException
73
-     */
74
-    public function __construct()
75
-    {
76
-        // array for storing class aliases
77
-        $this->filters = array();
78
-        // create collection for storing shared services
79
-        $this->carafe = new LooseCollection('');
80
-        // create collection for storing recipes that tell us how to build services and entities
81
-        $this->recipes = new Collection('EventEspresso\core\services\container\RecipeInterface');
82
-        // create collection for storing closures for constructing new entities
83
-        $this->reservoir = new Collection('Closure');
84
-        // create collection for storing the generators that build our services and entity closures
85
-        $this->coffee_makers = new Collection('EventEspresso\core\services\container\CoffeeMakerInterface');
86
-    }
87
-
88
-
89
-    /**
90
-     * Returns true if the container can return an entry for the given identifier.
91
-     * Returns false otherwise.
92
-     * `has($identifier)` returning true does not mean that `get($identifier)` will not throw an exception.
93
-     * It does however mean that `get($identifier)` will not throw a `ServiceNotFoundException`.
94
-     *
95
-     * @param string $identifier  Identifier of the entry to look for.
96
-     *                            Typically a Fully Qualified Class Name
97
-     * @return boolean
98
-     * @throws InvalidIdentifierException
99
-     */
100
-    public function has($identifier)
101
-    {
102
-        $identifier = $this->filterIdentifier($identifier);
103
-        return $this->carafe->has($identifier);
104
-    }
105
-
106
-
107
-    /**
108
-     * finds a previously brewed (SHARED) service and returns it
109
-     *
110
-     * @param  string $identifier Identifier for the entity class to be constructed.
111
-     *                            Typically a Fully Qualified Class Name
112
-     * @return mixed
113
-     * @throws InvalidIdentifierException
114
-     * @throws ServiceNotFoundException No service was found for this identifier.
115
-     */
116
-    public function get($identifier)
117
-    {
118
-        $identifier = $this->filterIdentifier($identifier);
119
-        if ($this->carafe->has($identifier)) {
120
-            return $this->carafe->get($identifier);
121
-        }
122
-        throw new ServiceNotFoundException($identifier);
123
-    }
124
-
125
-
126
-    /**
127
-     * returns an instance of the requested entity type using the supplied arguments.
128
-     * If a shared service is requested and an instance is already in the carafe, then it will be returned.
129
-     * If it is not already in the carafe, then the service will be constructed, added to the carafe, and returned
130
-     * If the request is for a new entity and a closure exists in the reservoir for creating it,
131
-     * then a new entity will be instantiated from the closure and returned.
132
-     * If a closure does not exist, then one will be built and added to the reservoir
133
-     * before instantiating the requested entity.
134
-     *
135
-     * @param  string $identifier Identifier for the entity class to be constructed.
136
-     *                            Typically a Fully Qualified Class Name
137
-     * @param array   $arguments  an array of arguments to be passed to the entity constructor
138
-     * @param string  $type
139
-     * @return mixed
140
-     * @throws OutOfBoundsException
141
-     * @throws InstantiationException
142
-     * @throws InvalidDataTypeException
143
-     * @throws InvalidClassException
144
-     * @throws InvalidIdentifierException
145
-     * @throws ServiceExistsException
146
-     * @throws ServiceNotFoundException No service was found for this identifier.
147
-     */
148
-    public function brew($identifier, $arguments = array(), $type = '')
149
-    {
150
-        // resolve any class aliases that may exist
151
-        $identifier = $this->filterIdentifier($identifier);
152
-        // is a shared service being requested and already exists in the carafe?
153
-        $brewed = $this->getShared($identifier, $type);
154
-        // then return whatever was found
155
-        if ($brewed !== false) {
156
-            return $brewed;
157
-        }
158
-        // if the reservoir doesn't have a closure already for the requested identifier,
159
-        // then neither a shared service nor a closure for making entities has been built yet
160
-        if (! $this->reservoir->has($identifier)) {
161
-            // so let's brew something up and add it to the proper collection
162
-            $brewed = $this->makeCoffee($identifier, $arguments, $type);
163
-        }
164
-        // did the requested class only require loading, and if so, was that successful?
165
-        if ($this->brewedLoadOnly($brewed, $identifier, $type) === true) {
166
-            return true;
167
-        }
168
-        // was the brewed item a callable factory function ?
169
-        if (is_callable($brewed)) {
170
-            // then instantiate a new entity from the cached closure
171
-            return $brewed($arguments);
172
-        }
173
-        if ($brewed) {
174
-            // requested object was a shared entity, so attempt to get it from the carafe again
175
-            // because if it wasn't there before, then it should have just been brewed and added,
176
-            // but if it still isn't there, then this time the thrown ServiceNotFoundException will not be caught
177
-            return $this->get($identifier);
178
-        }
179
-        // if identifier is for a non-shared entity,
180
-        // then either a cached closure already existed, or was just brewed
181
-        return $this->brewedClosure($identifier, $arguments);
182
-    }
183
-
184
-
185
-    /**
186
-     * @param string $identifier
187
-     * @param string $type
188
-     * @return bool|mixed
189
-     * @throws InvalidIdentifierException
190
-     */
191
-    protected function getShared($identifier, $type)
192
-    {
193
-        try {
194
-            if (empty($type) || $type === CoffeeMaker::BREW_SHARED) {
195
-                // if a shared service was requested and an instance is in the carafe, then return it
196
-                return $this->get($identifier);
197
-            }
198
-        } catch (ServiceNotFoundException $e) {
199
-            // if not then we'll just catch the ServiceNotFoundException but not do anything just yet,
200
-            // and instead, attempt to build whatever was requested
201
-        }
202
-        return false;
203
-    }
204
-
205
-
206
-    /**
207
-     * @param mixed  $brewed
208
-     * @param string $identifier
209
-     * @param string $type
210
-     * @return bool
211
-     * @throws InvalidClassException
212
-     * @throws InvalidDataTypeException
213
-     * @throws InvalidIdentifierException
214
-     * @throws OutOfBoundsException
215
-     * @throws ServiceExistsException
216
-     * @throws ServiceNotFoundException
217
-     */
218
-    protected function brewedLoadOnly($brewed, $identifier, $type)
219
-    {
220
-        if ($type === CoffeeMaker::BREW_LOAD_ONLY) {
221
-            if ($brewed !== true) {
222
-                throw new ServiceNotFoundException(
223
-                    sprintf(
224
-                        esc_html__(
225
-                            'The "%1$s" class could not be loaded.',
226
-                            'event_espresso'
227
-                        ),
228
-                        $identifier
229
-                    )
230
-                );
231
-            }
232
-            return true;
233
-        }
234
-        return false;
235
-    }
236
-
237
-
238
-    /**
239
-     * @param string $identifier
240
-     * @param array  $arguments
241
-     * @return mixed
242
-     * @throws InstantiationException
243
-     */
244
-    protected function brewedClosure($identifier, array $arguments)
245
-    {
246
-        $closure = $this->reservoir->get($identifier);
247
-        if (empty($closure)) {
248
-            throw new InstantiationException(
249
-                sprintf(
250
-                    esc_html__(
251
-                        'Could not brew an instance of "%1$s".',
252
-                        'event_espresso'
253
-                    ),
254
-                    $identifier
255
-                )
256
-            );
257
-        }
258
-        return $closure($arguments);
259
-    }
260
-
261
-
262
-    /**
263
-     * @param CoffeeMakerInterface $coffee_maker
264
-     * @param string               $type
265
-     * @return bool
266
-     * @throws InvalidIdentifierException
267
-     * @throws InvalidEntityException
268
-     */
269
-    public function addCoffeeMaker(CoffeeMakerInterface $coffee_maker, $type)
270
-    {
271
-        $type = CoffeeMaker::validateType($type);
272
-        return $this->coffee_makers->add($coffee_maker, $type);
273
-    }
274
-
275
-
276
-    /**
277
-     * @param string   $identifier
278
-     * @param callable $closure
279
-     * @return callable|null
280
-     * @throws InvalidIdentifierException
281
-     * @throws InvalidDataTypeException
282
-     */
283
-    public function addClosure($identifier, $closure)
284
-    {
285
-        if (! is_callable($closure)) {
286
-            throw new InvalidDataTypeException('$closure', $closure, 'Closure');
287
-        }
288
-        $identifier = $this->processIdentifier($identifier);
289
-        if ($this->reservoir->add($closure, $identifier)) {
290
-            return $closure;
291
-        }
292
-        return null;
293
-    }
294
-
295
-
296
-    /**
297
-     * @param string $identifier
298
-     * @return boolean
299
-     * @throws InvalidIdentifierException
300
-     */
301
-    public function removeClosure($identifier)
302
-    {
303
-        $identifier = $this->processIdentifier($identifier);
304
-        if ($this->reservoir->has($identifier)) {
305
-            return $this->reservoir->remove($this->reservoir->get($identifier));
306
-        }
307
-        return false;
308
-    }
309
-
310
-
311
-    /**
312
-     * @param  string $identifier Identifier for the entity class that the service applies to
313
-     *                            Typically a Fully Qualified Class Name
314
-     * @param mixed   $service
315
-     * @return bool
316
-     * @throws \EventEspresso\core\services\container\exceptions\InvalidServiceException
317
-     * @throws InvalidIdentifierException
318
-     */
319
-    public function addService($identifier, $service)
320
-    {
321
-        $identifier = $this->processIdentifier($identifier);
322
-        $service = $this->validateService($identifier, $service);
323
-        return $this->carafe->add($service, $identifier);
324
-    }
325
-
326
-
327
-    /**
328
-     * @param string $identifier
329
-     * @return boolean
330
-     * @throws InvalidIdentifierException
331
-     */
332
-    public function removeService($identifier)
333
-    {
334
-        $identifier = $this->processIdentifier($identifier);
335
-        if ($this->carafe->has($identifier)) {
336
-            return $this->carafe->remove($this->carafe->get($identifier));
337
-        }
338
-        return false;
339
-    }
340
-
341
-
342
-    /**
343
-     * Adds instructions on how to brew objects
344
-     *
345
-     * @param RecipeInterface $recipe
346
-     * @return mixed
347
-     * @throws InvalidIdentifierException
348
-     */
349
-    public function addRecipe(RecipeInterface $recipe)
350
-    {
351
-        $this->addAliases($recipe->identifier(), $recipe->filters());
352
-        $identifier = $this->processIdentifier($recipe->identifier());
353
-        return $this->recipes->add($recipe, $identifier);
354
-    }
355
-
356
-
357
-    /**
358
-     * @param string $identifier The Recipe's identifier
359
-     * @return boolean
360
-     * @throws InvalidIdentifierException
361
-     */
362
-    public function removeRecipe($identifier)
363
-    {
364
-        $identifier = $this->processIdentifier($identifier);
365
-        if ($this->recipes->has($identifier)) {
366
-            return $this->recipes->remove($this->recipes->get($identifier));
367
-        }
368
-        return false;
369
-    }
370
-
371
-
372
-    /**
373
-     * Get instructions on how to brew objects
374
-     *
375
-     * @param  string $identifier Identifier for the entity class that the recipe applies to
376
-     *                            Typically a Fully Qualified Class Name
377
-     * @param string  $type
378
-     * @return RecipeInterface
379
-     * @throws OutOfBoundsException
380
-     * @throws InvalidIdentifierException
381
-     */
382
-    public function getRecipe($identifier, $type = '')
383
-    {
384
-        $identifier = $this->processIdentifier($identifier);
385
-        if ($this->recipes->has($identifier)) {
386
-            return $this->recipes->get($identifier);
387
-        }
388
-        $default_recipes = $this->getDefaultRecipes();
389
-        $matches = array();
390
-        foreach ($default_recipes as $wildcard => $default_recipe) {
391
-            // is the wildcard recipe prefix in the identifier ?
392
-            if (strpos($identifier, $wildcard) !== false) {
393
-                // track matches and use the number of wildcard characters matched for the key
394
-                $matches[ strlen($wildcard) ] = $default_recipe;
395
-            }
396
-        }
397
-        if (count($matches) > 0) {
398
-            // sort our recipes by the number of wildcard characters matched
399
-            ksort($matches);
400
-            // then grab the last recipe form the list, since it had the most matching characters
401
-            $match = array_pop($matches);
402
-            // since we are using a default recipe, we need to set it's identifier and fqcn
403
-            return $this->copyDefaultRecipe($match, $identifier, $type);
404
-        }
405
-        if ($this->recipes->has(Recipe::DEFAULT_ID)) {
406
-            // since we are using a default recipe, we need to set it's identifier and fqcn
407
-            return $this->copyDefaultRecipe($this->recipes->get(Recipe::DEFAULT_ID), $identifier, $type);
408
-        }
409
-        throw new OutOfBoundsException(
410
-            sprintf(
411
-                esc_html__('Could not brew coffee because no recipes were found for class "%1$s".', 'event_espresso'),
412
-                $identifier
413
-            )
414
-        );
415
-    }
416
-
417
-
418
-    /**
419
-     * adds class name aliases to list of filters
420
-     *
421
-     * @param  string       $identifier Identifier for the entity class that the alias applies to
422
-     *                                  Typically a Fully Qualified Class Name
423
-     * @param  array|string $aliases
424
-     * @return void
425
-     * @throws InvalidIdentifierException
426
-     */
427
-    public function addAliases($identifier, $aliases)
428
-    {
429
-        if (empty($aliases)) {
430
-            return;
431
-        }
432
-        $identifier = $this->processIdentifier($identifier);
433
-        foreach ((array) $aliases as $alias) {
434
-            $this->filters[ $this->processIdentifier($alias) ] = $identifier;
435
-        }
436
-    }
437
-
438
-
439
-    /**
440
-     * Adds a service to one of the internal collections
441
-     *
442
-     * @param        $identifier
443
-     * @param array  $arguments
444
-     * @param string $type
445
-     * @return mixed
446
-     * @throws InvalidDataTypeException
447
-     * @throws InvalidClassException
448
-     * @throws OutOfBoundsException
449
-     * @throws InvalidIdentifierException
450
-     * @throws ServiceExistsException
451
-     */
452
-    private function makeCoffee($identifier, $arguments = array(), $type = '')
453
-    {
454
-        if ((empty($type) || $type === CoffeeMaker::BREW_SHARED) && $this->has($identifier)) {
455
-            throw new ServiceExistsException($identifier);
456
-        }
457
-        $identifier = $this->filterIdentifier($identifier);
458
-        $recipe = $this->getRecipe($identifier, $type);
459
-        $type = ! empty($type) ? $type : $recipe->type();
460
-        $coffee_maker = $this->getCoffeeMaker($type);
461
-        return $coffee_maker->brew($recipe, $arguments);
462
-    }
463
-
464
-
465
-    /**
466
-     * filters alias identifiers to find the real class name
467
-     *
468
-     * @param  string $identifier Identifier for the entity class that the filter applies to
469
-     *                            Typically a Fully Qualified Class Name
470
-     * @return string
471
-     * @throws InvalidIdentifierException
472
-     */
473
-    private function filterIdentifier($identifier)
474
-    {
475
-        $identifier = $this->processIdentifier($identifier);
476
-        return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
477
-            ? $this->filters[ $identifier ]
478
-            : $identifier;
479
-    }
480
-
481
-
482
-    /**
483
-     * verifies and standardizes identifiers
484
-     *
485
-     * @param  string $identifier Identifier for the entity class
486
-     *                            Typically a Fully Qualified Class Name
487
-     * @return string
488
-     * @throws InvalidIdentifierException
489
-     */
490
-    private function processIdentifier($identifier)
491
-    {
492
-        if (! is_string($identifier)) {
493
-            throw new InvalidIdentifierException(
494
-                is_object($identifier) ? get_class($identifier) : gettype($identifier),
495
-                '\Fully\Qualified\ClassName'
496
-            );
497
-        }
498
-        return ltrim($identifier, '\\');
499
-    }
500
-
501
-
502
-    /**
503
-     * @param string $type
504
-     * @return CoffeeMakerInterface
505
-     * @throws OutOfBoundsException
506
-     * @throws InvalidDataTypeException
507
-     * @throws InvalidClassException
508
-     */
509
-    private function getCoffeeMaker($type)
510
-    {
511
-        if (! $this->coffee_makers->has($type)) {
512
-            throw new OutOfBoundsException(
513
-                esc_html__('The requested coffee maker is either missing or invalid.', 'event_espresso')
514
-            );
515
-        }
516
-        return $this->coffee_makers->get($type);
517
-    }
518
-
519
-
520
-    /**
521
-     * Retrieves all recipes that use a wildcard "*" in their identifier
522
-     * This allows recipes to be set up for handling
523
-     * legacy classes that do not support PSR-4 autoloading.
524
-     * for example:
525
-     * using "EEM_*" for a recipe identifier would target all legacy models like EEM_Attendee
526
-     *
527
-     * @return array
528
-     */
529
-    private function getDefaultRecipes()
530
-    {
531
-        $default_recipes = array();
532
-        $this->recipes->rewind();
533
-        while ($this->recipes->valid()) {
534
-            $identifier = $this->recipes->getInfo();
535
-            // does this recipe use a wildcard ? (but is NOT the global default)
536
-            if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
537
-                // strip the wildcard and use identifier as key
538
-                $default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
539
-            }
540
-            $this->recipes->next();
541
-        }
542
-        return $default_recipes;
543
-    }
544
-
545
-
546
-    /**
547
-     * clones a default recipe and then copies details
548
-     * from the incoming request to it so that it can be used
549
-     *
550
-     * @param RecipeInterface $default_recipe
551
-     * @param string          $identifier
552
-     * @param string          $type
553
-     * @return RecipeInterface
554
-     */
555
-    private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
556
-    {
557
-        $recipe = clone $default_recipe;
558
-        if (! empty($type)) {
559
-            $recipe->setType($type);
560
-        }
561
-        // is this the base default recipe ?
562
-        if ($default_recipe->identifier() === Recipe::DEFAULT_ID) {
563
-            $recipe->setIdentifier($identifier);
564
-            $recipe->setFqcn($identifier);
565
-            return $recipe;
566
-        }
567
-        $recipe->setIdentifier($identifier);
568
-        foreach ($default_recipe->paths() as $path) {
569
-            $path = str_replace('*', $identifier, $path);
570
-            if (is_readable($path)) {
571
-                $recipe->setPaths($path);
572
-            }
573
-        }
574
-        $recipe->setFqcn($identifier);
575
-        return $recipe;
576
-    }
577
-
578
-
579
-    /**
580
-     * @param  string $identifier Identifier for the entity class that the service applies to
581
-     *                            Typically a Fully Qualified Class Name
582
-     * @param mixed   $service
583
-     * @return mixed
584
-     * @throws InvalidServiceException
585
-     */
586
-    private function validateService($identifier, $service)
587
-    {
588
-        if (! is_object($service)) {
589
-            throw new InvalidServiceException(
590
-                $identifier,
591
-                $service
592
-            );
593
-        }
594
-        return $service;
595
-    }
31
+	/**
32
+	 * This was the best coffee related name I could think of to represent class name "aliases"
33
+	 * So classes can be found via an alias identifier,
34
+	 * that is revealed when it is run through... the filters... eh? get it?
35
+	 *
36
+	 * @var array $filters
37
+	 */
38
+	private $filters;
39
+
40
+	/**
41
+	 * These are the classes that will actually build the objects (to order of course)
42
+	 *
43
+	 * @var array $coffee_makers
44
+	 */
45
+	private $coffee_makers;
46
+
47
+	/**
48
+	 * where the instantiated "singleton" objects are stored
49
+	 *
50
+	 * @var CollectionInterface $carafe
51
+	 */
52
+	private $carafe;
53
+
54
+	/**
55
+	 * collection of Recipes that instruct us how to brew objects
56
+	 *
57
+	 * @var CollectionInterface $recipes
58
+	 */
59
+	private $recipes;
60
+
61
+	/**
62
+	 * collection of closures for brewing objects
63
+	 *
64
+	 * @var CollectionInterface $reservoir
65
+	 */
66
+	private $reservoir;
67
+
68
+
69
+	/**
70
+	 * CoffeeShop constructor
71
+	 *
72
+	 * @throws InvalidInterfaceException
73
+	 */
74
+	public function __construct()
75
+	{
76
+		// array for storing class aliases
77
+		$this->filters = array();
78
+		// create collection for storing shared services
79
+		$this->carafe = new LooseCollection('');
80
+		// create collection for storing recipes that tell us how to build services and entities
81
+		$this->recipes = new Collection('EventEspresso\core\services\container\RecipeInterface');
82
+		// create collection for storing closures for constructing new entities
83
+		$this->reservoir = new Collection('Closure');
84
+		// create collection for storing the generators that build our services and entity closures
85
+		$this->coffee_makers = new Collection('EventEspresso\core\services\container\CoffeeMakerInterface');
86
+	}
87
+
88
+
89
+	/**
90
+	 * Returns true if the container can return an entry for the given identifier.
91
+	 * Returns false otherwise.
92
+	 * `has($identifier)` returning true does not mean that `get($identifier)` will not throw an exception.
93
+	 * It does however mean that `get($identifier)` will not throw a `ServiceNotFoundException`.
94
+	 *
95
+	 * @param string $identifier  Identifier of the entry to look for.
96
+	 *                            Typically a Fully Qualified Class Name
97
+	 * @return boolean
98
+	 * @throws InvalidIdentifierException
99
+	 */
100
+	public function has($identifier)
101
+	{
102
+		$identifier = $this->filterIdentifier($identifier);
103
+		return $this->carafe->has($identifier);
104
+	}
105
+
106
+
107
+	/**
108
+	 * finds a previously brewed (SHARED) service and returns it
109
+	 *
110
+	 * @param  string $identifier Identifier for the entity class to be constructed.
111
+	 *                            Typically a Fully Qualified Class Name
112
+	 * @return mixed
113
+	 * @throws InvalidIdentifierException
114
+	 * @throws ServiceNotFoundException No service was found for this identifier.
115
+	 */
116
+	public function get($identifier)
117
+	{
118
+		$identifier = $this->filterIdentifier($identifier);
119
+		if ($this->carafe->has($identifier)) {
120
+			return $this->carafe->get($identifier);
121
+		}
122
+		throw new ServiceNotFoundException($identifier);
123
+	}
124
+
125
+
126
+	/**
127
+	 * returns an instance of the requested entity type using the supplied arguments.
128
+	 * If a shared service is requested and an instance is already in the carafe, then it will be returned.
129
+	 * If it is not already in the carafe, then the service will be constructed, added to the carafe, and returned
130
+	 * If the request is for a new entity and a closure exists in the reservoir for creating it,
131
+	 * then a new entity will be instantiated from the closure and returned.
132
+	 * If a closure does not exist, then one will be built and added to the reservoir
133
+	 * before instantiating the requested entity.
134
+	 *
135
+	 * @param  string $identifier Identifier for the entity class to be constructed.
136
+	 *                            Typically a Fully Qualified Class Name
137
+	 * @param array   $arguments  an array of arguments to be passed to the entity constructor
138
+	 * @param string  $type
139
+	 * @return mixed
140
+	 * @throws OutOfBoundsException
141
+	 * @throws InstantiationException
142
+	 * @throws InvalidDataTypeException
143
+	 * @throws InvalidClassException
144
+	 * @throws InvalidIdentifierException
145
+	 * @throws ServiceExistsException
146
+	 * @throws ServiceNotFoundException No service was found for this identifier.
147
+	 */
148
+	public function brew($identifier, $arguments = array(), $type = '')
149
+	{
150
+		// resolve any class aliases that may exist
151
+		$identifier = $this->filterIdentifier($identifier);
152
+		// is a shared service being requested and already exists in the carafe?
153
+		$brewed = $this->getShared($identifier, $type);
154
+		// then return whatever was found
155
+		if ($brewed !== false) {
156
+			return $brewed;
157
+		}
158
+		// if the reservoir doesn't have a closure already for the requested identifier,
159
+		// then neither a shared service nor a closure for making entities has been built yet
160
+		if (! $this->reservoir->has($identifier)) {
161
+			// so let's brew something up and add it to the proper collection
162
+			$brewed = $this->makeCoffee($identifier, $arguments, $type);
163
+		}
164
+		// did the requested class only require loading, and if so, was that successful?
165
+		if ($this->brewedLoadOnly($brewed, $identifier, $type) === true) {
166
+			return true;
167
+		}
168
+		// was the brewed item a callable factory function ?
169
+		if (is_callable($brewed)) {
170
+			// then instantiate a new entity from the cached closure
171
+			return $brewed($arguments);
172
+		}
173
+		if ($brewed) {
174
+			// requested object was a shared entity, so attempt to get it from the carafe again
175
+			// because if it wasn't there before, then it should have just been brewed and added,
176
+			// but if it still isn't there, then this time the thrown ServiceNotFoundException will not be caught
177
+			return $this->get($identifier);
178
+		}
179
+		// if identifier is for a non-shared entity,
180
+		// then either a cached closure already existed, or was just brewed
181
+		return $this->brewedClosure($identifier, $arguments);
182
+	}
183
+
184
+
185
+	/**
186
+	 * @param string $identifier
187
+	 * @param string $type
188
+	 * @return bool|mixed
189
+	 * @throws InvalidIdentifierException
190
+	 */
191
+	protected function getShared($identifier, $type)
192
+	{
193
+		try {
194
+			if (empty($type) || $type === CoffeeMaker::BREW_SHARED) {
195
+				// if a shared service was requested and an instance is in the carafe, then return it
196
+				return $this->get($identifier);
197
+			}
198
+		} catch (ServiceNotFoundException $e) {
199
+			// if not then we'll just catch the ServiceNotFoundException but not do anything just yet,
200
+			// and instead, attempt to build whatever was requested
201
+		}
202
+		return false;
203
+	}
204
+
205
+
206
+	/**
207
+	 * @param mixed  $brewed
208
+	 * @param string $identifier
209
+	 * @param string $type
210
+	 * @return bool
211
+	 * @throws InvalidClassException
212
+	 * @throws InvalidDataTypeException
213
+	 * @throws InvalidIdentifierException
214
+	 * @throws OutOfBoundsException
215
+	 * @throws ServiceExistsException
216
+	 * @throws ServiceNotFoundException
217
+	 */
218
+	protected function brewedLoadOnly($brewed, $identifier, $type)
219
+	{
220
+		if ($type === CoffeeMaker::BREW_LOAD_ONLY) {
221
+			if ($brewed !== true) {
222
+				throw new ServiceNotFoundException(
223
+					sprintf(
224
+						esc_html__(
225
+							'The "%1$s" class could not be loaded.',
226
+							'event_espresso'
227
+						),
228
+						$identifier
229
+					)
230
+				);
231
+			}
232
+			return true;
233
+		}
234
+		return false;
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param string $identifier
240
+	 * @param array  $arguments
241
+	 * @return mixed
242
+	 * @throws InstantiationException
243
+	 */
244
+	protected function brewedClosure($identifier, array $arguments)
245
+	{
246
+		$closure = $this->reservoir->get($identifier);
247
+		if (empty($closure)) {
248
+			throw new InstantiationException(
249
+				sprintf(
250
+					esc_html__(
251
+						'Could not brew an instance of "%1$s".',
252
+						'event_espresso'
253
+					),
254
+					$identifier
255
+				)
256
+			);
257
+		}
258
+		return $closure($arguments);
259
+	}
260
+
261
+
262
+	/**
263
+	 * @param CoffeeMakerInterface $coffee_maker
264
+	 * @param string               $type
265
+	 * @return bool
266
+	 * @throws InvalidIdentifierException
267
+	 * @throws InvalidEntityException
268
+	 */
269
+	public function addCoffeeMaker(CoffeeMakerInterface $coffee_maker, $type)
270
+	{
271
+		$type = CoffeeMaker::validateType($type);
272
+		return $this->coffee_makers->add($coffee_maker, $type);
273
+	}
274
+
275
+
276
+	/**
277
+	 * @param string   $identifier
278
+	 * @param callable $closure
279
+	 * @return callable|null
280
+	 * @throws InvalidIdentifierException
281
+	 * @throws InvalidDataTypeException
282
+	 */
283
+	public function addClosure($identifier, $closure)
284
+	{
285
+		if (! is_callable($closure)) {
286
+			throw new InvalidDataTypeException('$closure', $closure, 'Closure');
287
+		}
288
+		$identifier = $this->processIdentifier($identifier);
289
+		if ($this->reservoir->add($closure, $identifier)) {
290
+			return $closure;
291
+		}
292
+		return null;
293
+	}
294
+
295
+
296
+	/**
297
+	 * @param string $identifier
298
+	 * @return boolean
299
+	 * @throws InvalidIdentifierException
300
+	 */
301
+	public function removeClosure($identifier)
302
+	{
303
+		$identifier = $this->processIdentifier($identifier);
304
+		if ($this->reservoir->has($identifier)) {
305
+			return $this->reservoir->remove($this->reservoir->get($identifier));
306
+		}
307
+		return false;
308
+	}
309
+
310
+
311
+	/**
312
+	 * @param  string $identifier Identifier for the entity class that the service applies to
313
+	 *                            Typically a Fully Qualified Class Name
314
+	 * @param mixed   $service
315
+	 * @return bool
316
+	 * @throws \EventEspresso\core\services\container\exceptions\InvalidServiceException
317
+	 * @throws InvalidIdentifierException
318
+	 */
319
+	public function addService($identifier, $service)
320
+	{
321
+		$identifier = $this->processIdentifier($identifier);
322
+		$service = $this->validateService($identifier, $service);
323
+		return $this->carafe->add($service, $identifier);
324
+	}
325
+
326
+
327
+	/**
328
+	 * @param string $identifier
329
+	 * @return boolean
330
+	 * @throws InvalidIdentifierException
331
+	 */
332
+	public function removeService($identifier)
333
+	{
334
+		$identifier = $this->processIdentifier($identifier);
335
+		if ($this->carafe->has($identifier)) {
336
+			return $this->carafe->remove($this->carafe->get($identifier));
337
+		}
338
+		return false;
339
+	}
340
+
341
+
342
+	/**
343
+	 * Adds instructions on how to brew objects
344
+	 *
345
+	 * @param RecipeInterface $recipe
346
+	 * @return mixed
347
+	 * @throws InvalidIdentifierException
348
+	 */
349
+	public function addRecipe(RecipeInterface $recipe)
350
+	{
351
+		$this->addAliases($recipe->identifier(), $recipe->filters());
352
+		$identifier = $this->processIdentifier($recipe->identifier());
353
+		return $this->recipes->add($recipe, $identifier);
354
+	}
355
+
356
+
357
+	/**
358
+	 * @param string $identifier The Recipe's identifier
359
+	 * @return boolean
360
+	 * @throws InvalidIdentifierException
361
+	 */
362
+	public function removeRecipe($identifier)
363
+	{
364
+		$identifier = $this->processIdentifier($identifier);
365
+		if ($this->recipes->has($identifier)) {
366
+			return $this->recipes->remove($this->recipes->get($identifier));
367
+		}
368
+		return false;
369
+	}
370
+
371
+
372
+	/**
373
+	 * Get instructions on how to brew objects
374
+	 *
375
+	 * @param  string $identifier Identifier for the entity class that the recipe applies to
376
+	 *                            Typically a Fully Qualified Class Name
377
+	 * @param string  $type
378
+	 * @return RecipeInterface
379
+	 * @throws OutOfBoundsException
380
+	 * @throws InvalidIdentifierException
381
+	 */
382
+	public function getRecipe($identifier, $type = '')
383
+	{
384
+		$identifier = $this->processIdentifier($identifier);
385
+		if ($this->recipes->has($identifier)) {
386
+			return $this->recipes->get($identifier);
387
+		}
388
+		$default_recipes = $this->getDefaultRecipes();
389
+		$matches = array();
390
+		foreach ($default_recipes as $wildcard => $default_recipe) {
391
+			// is the wildcard recipe prefix in the identifier ?
392
+			if (strpos($identifier, $wildcard) !== false) {
393
+				// track matches and use the number of wildcard characters matched for the key
394
+				$matches[ strlen($wildcard) ] = $default_recipe;
395
+			}
396
+		}
397
+		if (count($matches) > 0) {
398
+			// sort our recipes by the number of wildcard characters matched
399
+			ksort($matches);
400
+			// then grab the last recipe form the list, since it had the most matching characters
401
+			$match = array_pop($matches);
402
+			// since we are using a default recipe, we need to set it's identifier and fqcn
403
+			return $this->copyDefaultRecipe($match, $identifier, $type);
404
+		}
405
+		if ($this->recipes->has(Recipe::DEFAULT_ID)) {
406
+			// since we are using a default recipe, we need to set it's identifier and fqcn
407
+			return $this->copyDefaultRecipe($this->recipes->get(Recipe::DEFAULT_ID), $identifier, $type);
408
+		}
409
+		throw new OutOfBoundsException(
410
+			sprintf(
411
+				esc_html__('Could not brew coffee because no recipes were found for class "%1$s".', 'event_espresso'),
412
+				$identifier
413
+			)
414
+		);
415
+	}
416
+
417
+
418
+	/**
419
+	 * adds class name aliases to list of filters
420
+	 *
421
+	 * @param  string       $identifier Identifier for the entity class that the alias applies to
422
+	 *                                  Typically a Fully Qualified Class Name
423
+	 * @param  array|string $aliases
424
+	 * @return void
425
+	 * @throws InvalidIdentifierException
426
+	 */
427
+	public function addAliases($identifier, $aliases)
428
+	{
429
+		if (empty($aliases)) {
430
+			return;
431
+		}
432
+		$identifier = $this->processIdentifier($identifier);
433
+		foreach ((array) $aliases as $alias) {
434
+			$this->filters[ $this->processIdentifier($alias) ] = $identifier;
435
+		}
436
+	}
437
+
438
+
439
+	/**
440
+	 * Adds a service to one of the internal collections
441
+	 *
442
+	 * @param        $identifier
443
+	 * @param array  $arguments
444
+	 * @param string $type
445
+	 * @return mixed
446
+	 * @throws InvalidDataTypeException
447
+	 * @throws InvalidClassException
448
+	 * @throws OutOfBoundsException
449
+	 * @throws InvalidIdentifierException
450
+	 * @throws ServiceExistsException
451
+	 */
452
+	private function makeCoffee($identifier, $arguments = array(), $type = '')
453
+	{
454
+		if ((empty($type) || $type === CoffeeMaker::BREW_SHARED) && $this->has($identifier)) {
455
+			throw new ServiceExistsException($identifier);
456
+		}
457
+		$identifier = $this->filterIdentifier($identifier);
458
+		$recipe = $this->getRecipe($identifier, $type);
459
+		$type = ! empty($type) ? $type : $recipe->type();
460
+		$coffee_maker = $this->getCoffeeMaker($type);
461
+		return $coffee_maker->brew($recipe, $arguments);
462
+	}
463
+
464
+
465
+	/**
466
+	 * filters alias identifiers to find the real class name
467
+	 *
468
+	 * @param  string $identifier Identifier for the entity class that the filter applies to
469
+	 *                            Typically a Fully Qualified Class Name
470
+	 * @return string
471
+	 * @throws InvalidIdentifierException
472
+	 */
473
+	private function filterIdentifier($identifier)
474
+	{
475
+		$identifier = $this->processIdentifier($identifier);
476
+		return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
477
+			? $this->filters[ $identifier ]
478
+			: $identifier;
479
+	}
480
+
481
+
482
+	/**
483
+	 * verifies and standardizes identifiers
484
+	 *
485
+	 * @param  string $identifier Identifier for the entity class
486
+	 *                            Typically a Fully Qualified Class Name
487
+	 * @return string
488
+	 * @throws InvalidIdentifierException
489
+	 */
490
+	private function processIdentifier($identifier)
491
+	{
492
+		if (! is_string($identifier)) {
493
+			throw new InvalidIdentifierException(
494
+				is_object($identifier) ? get_class($identifier) : gettype($identifier),
495
+				'\Fully\Qualified\ClassName'
496
+			);
497
+		}
498
+		return ltrim($identifier, '\\');
499
+	}
500
+
501
+
502
+	/**
503
+	 * @param string $type
504
+	 * @return CoffeeMakerInterface
505
+	 * @throws OutOfBoundsException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws InvalidClassException
508
+	 */
509
+	private function getCoffeeMaker($type)
510
+	{
511
+		if (! $this->coffee_makers->has($type)) {
512
+			throw new OutOfBoundsException(
513
+				esc_html__('The requested coffee maker is either missing or invalid.', 'event_espresso')
514
+			);
515
+		}
516
+		return $this->coffee_makers->get($type);
517
+	}
518
+
519
+
520
+	/**
521
+	 * Retrieves all recipes that use a wildcard "*" in their identifier
522
+	 * This allows recipes to be set up for handling
523
+	 * legacy classes that do not support PSR-4 autoloading.
524
+	 * for example:
525
+	 * using "EEM_*" for a recipe identifier would target all legacy models like EEM_Attendee
526
+	 *
527
+	 * @return array
528
+	 */
529
+	private function getDefaultRecipes()
530
+	{
531
+		$default_recipes = array();
532
+		$this->recipes->rewind();
533
+		while ($this->recipes->valid()) {
534
+			$identifier = $this->recipes->getInfo();
535
+			// does this recipe use a wildcard ? (but is NOT the global default)
536
+			if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
537
+				// strip the wildcard and use identifier as key
538
+				$default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
539
+			}
540
+			$this->recipes->next();
541
+		}
542
+		return $default_recipes;
543
+	}
544
+
545
+
546
+	/**
547
+	 * clones a default recipe and then copies details
548
+	 * from the incoming request to it so that it can be used
549
+	 *
550
+	 * @param RecipeInterface $default_recipe
551
+	 * @param string          $identifier
552
+	 * @param string          $type
553
+	 * @return RecipeInterface
554
+	 */
555
+	private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
556
+	{
557
+		$recipe = clone $default_recipe;
558
+		if (! empty($type)) {
559
+			$recipe->setType($type);
560
+		}
561
+		// is this the base default recipe ?
562
+		if ($default_recipe->identifier() === Recipe::DEFAULT_ID) {
563
+			$recipe->setIdentifier($identifier);
564
+			$recipe->setFqcn($identifier);
565
+			return $recipe;
566
+		}
567
+		$recipe->setIdentifier($identifier);
568
+		foreach ($default_recipe->paths() as $path) {
569
+			$path = str_replace('*', $identifier, $path);
570
+			if (is_readable($path)) {
571
+				$recipe->setPaths($path);
572
+			}
573
+		}
574
+		$recipe->setFqcn($identifier);
575
+		return $recipe;
576
+	}
577
+
578
+
579
+	/**
580
+	 * @param  string $identifier Identifier for the entity class that the service applies to
581
+	 *                            Typically a Fully Qualified Class Name
582
+	 * @param mixed   $service
583
+	 * @return mixed
584
+	 * @throws InvalidServiceException
585
+	 */
586
+	private function validateService($identifier, $service)
587
+	{
588
+		if (! is_object($service)) {
589
+			throw new InvalidServiceException(
590
+				$identifier,
591
+				$service
592
+			);
593
+		}
594
+		return $service;
595
+	}
596 596
 }
Please login to merge, or discard this patch.
core/EE_Config.core.php 2 patches
Spacing   +117 added lines, -117 removed lines patch added patch discarded remove patch
@@ -147,7 +147,7 @@  discard block
 block discarded – undo
147 147
     public static function instance()
148 148
     {
149 149
         // check if class object is instantiated, and instantiated properly
150
-        if (! self::$_instance instanceof EE_Config) {
150
+        if ( ! self::$_instance instanceof EE_Config) {
151 151
             self::$_instance = new self();
152 152
         }
153 153
         return self::$_instance;
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
                 $this
286 286
             );
287 287
             if (is_object($settings) && property_exists($this, $config)) {
288
-                $this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__' . $config, $settings);
288
+                $this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__'.$config, $settings);
289 289
                 // call configs populate method to ensure any defaults are set for empty values.
290 290
                 if (method_exists($settings, 'populate')) {
291 291
                     $this->{$config}->populate();
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
                         break;
561 561
                     // TEST #2 : check that settings section exists
562 562
                     case 2:
563
-                        if (! isset($this->{$section})) {
563
+                        if ( ! isset($this->{$section})) {
564 564
                             if ($display_errors) {
565 565
                                 throw new EE_Error(
566 566
                                     sprintf(
@@ -621,7 +621,7 @@  discard block
 block discarded – undo
621 621
                         break;
622 622
                     // TEST #6 : verify config class is accessible
623 623
                     case 6:
624
-                        if (! class_exists($config_class)) {
624
+                        if ( ! class_exists($config_class)) {
625 625
                             if ($display_errors) {
626 626
                                 throw new EE_Error(
627 627
                                     sprintf(
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
                         break;
639 639
                     // TEST #7 : check that config has even been set
640 640
                     case 7:
641
-                        if (! isset($this->{$section}->{$name})) {
641
+                        if ( ! isset($this->{$section}->{$name})) {
642 642
                             if ($display_errors) {
643 643
                                 throw new EE_Error(
644 644
                                     sprintf(
@@ -656,7 +656,7 @@  discard block
 block discarded – undo
656 656
                         break;
657 657
                     // TEST #8 : check that config is the requested type
658 658
                     case 8:
659
-                        if (! $this->{$section}->{$name} instanceof $config_class) {
659
+                        if ( ! $this->{$section}->{$name} instanceof $config_class) {
660 660
                             if ($display_errors) {
661 661
                                 throw new EE_Error(
662 662
                                     sprintf(
@@ -675,7 +675,7 @@  discard block
 block discarded – undo
675 675
                         break;
676 676
                     // TEST #9 : verify config object
677 677
                     case 9:
678
-                        if (! $config_obj instanceof EE_Config_Base) {
678
+                        if ( ! $config_obj instanceof EE_Config_Base) {
679 679
                             if ($display_errors) {
680 680
                                 throw new EE_Error(
681 681
                                     sprintf(
@@ -707,7 +707,7 @@  discard block
 block discarded – undo
707 707
      */
708 708
     private function _generate_config_option_name($section = '', $name = '')
709 709
     {
710
-        return 'ee_config-' . strtolower($section . '-' . str_replace(array('EE_', 'EED_'), '', $name));
710
+        return 'ee_config-'.strtolower($section.'-'.str_replace(array('EE_', 'EED_'), '', $name));
711 711
     }
712 712
 
713 713
 
@@ -724,7 +724,7 @@  discard block
 block discarded – undo
724 724
     {
725 725
         return ! empty($config_class)
726 726
             ? $config_class
727
-            : str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))) . '_Config';
727
+            : str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))).'_Config';
728 728
     }
729 729
 
730 730
 
@@ -743,17 +743,17 @@  discard block
 block discarded – undo
743 743
         // ensure config class is set to something
744 744
         $config_class = $this->_set_config_class($config_class, $name);
745 745
         // run tests 1-4, 6, and 7 to verify all config params are set and valid
746
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
746
+        if ( ! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
747 747
             return null;
748 748
         }
749 749
         $config_option_name = $this->_generate_config_option_name($section, $name);
750 750
         // if the config option name hasn't been added yet to the list of option names we're tracking, then do so now
751
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
752
-            $this->_addon_option_names[ $config_option_name ] = $config_class;
751
+        if ( ! isset($this->_addon_option_names[$config_option_name])) {
752
+            $this->_addon_option_names[$config_option_name] = $config_class;
753 753
             $this->update_addon_option_names();
754 754
         }
755 755
         // verify the incoming config object but suppress errors
756
-        if (! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
756
+        if ( ! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
757 757
             $config_obj = new $config_class();
758 758
         }
759 759
         if (get_option($config_option_name)) {
@@ -815,7 +815,7 @@  discard block
 block discarded – undo
815 815
         }
816 816
         $config_option_name = $this->_generate_config_option_name($section, $name);
817 817
         // check if config object has been added to db by seeing if config option name is in $this->_addon_option_names array
818
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
818
+        if ( ! isset($this->_addon_option_names[$config_option_name])) {
819 819
             // save new config to db
820 820
             if ($this->set_config($section, $name, $config_class, $config_obj)) {
821 821
                 return true;
@@ -841,7 +841,7 @@  discard block
 block discarded – undo
841 841
                             'event_espresso'
842 842
                         ),
843 843
                         $config_class,
844
-                        'EE_Config->' . $section . '->' . $name
844
+                        'EE_Config->'.$section.'->'.$name
845 845
                     ),
846 846
                     __FILE__,
847 847
                     __FUNCTION__,
@@ -867,7 +867,7 @@  discard block
 block discarded – undo
867 867
         // ensure config class is set to something
868 868
         $config_class = $this->_set_config_class($config_class, $name);
869 869
         // run tests 1-4, 6 and 7 to verify that all params have been set
870
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
870
+        if ( ! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
871 871
             return null;
872 872
         }
873 873
         // now test if the requested config object exists, but suppress errors
@@ -912,7 +912,7 @@  discard block
 block discarded – undo
912 912
         // retrieve the wp-option for this config class.
913 913
         $config_option = maybe_unserialize(get_option($config_option_name, array()));
914 914
         if (empty($config_option)) {
915
-            EE_Config::log($config_option_name . '-NOT-FOUND');
915
+            EE_Config::log($config_option_name.'-NOT-FOUND');
916 916
         }
917 917
         return $config_option;
918 918
     }
@@ -929,7 +929,7 @@  discard block
 block discarded – undo
929 929
             $config_log = get_option(EE_Config::LOG_NAME, array());
930 930
             /** @var RequestParams $request */
931 931
             $request = LoaderFactory::getLoader()->getShared(RequestParams::class);
932
-            $config_log[ (string) microtime(true) ] = array(
932
+            $config_log[(string) microtime(true)] = array(
933 933
                 'config_name' => $config_option_name,
934 934
                 'request'     => $request->requestParams(),
935 935
             );
@@ -944,7 +944,7 @@  discard block
 block discarded – undo
944 944
      */
945 945
     public static function trim_log()
946 946
     {
947
-        if (! EE_Config::logging_enabled()) {
947
+        if ( ! EE_Config::logging_enabled()) {
948 948
             return;
949 949
         }
950 950
         $config_log = maybe_unserialize(get_option(EE_Config::LOG_NAME, array()));
@@ -968,7 +968,7 @@  discard block
 block discarded – undo
968 968
     public static function get_page_for_posts()
969 969
     {
970 970
         $page_for_posts = get_option('page_for_posts');
971
-        if (! $page_for_posts) {
971
+        if ( ! $page_for_posts) {
972 972
             return 'posts';
973 973
         }
974 974
         global $wpdb;
@@ -1025,13 +1025,13 @@  discard block
 block discarded – undo
1025 1025
             )
1026 1026
         ) {
1027 1027
             // grab list of installed widgets
1028
-            $widgets_to_register = glob(EE_WIDGETS . '*', GLOB_ONLYDIR);
1028
+            $widgets_to_register = glob(EE_WIDGETS.'*', GLOB_ONLYDIR);
1029 1029
             // filter list of modules to register
1030 1030
             $widgets_to_register = apply_filters(
1031 1031
                 'FHEE__EE_Config__register_widgets__widgets_to_register',
1032 1032
                 $widgets_to_register
1033 1033
             );
1034
-            if (! empty($widgets_to_register)) {
1034
+            if ( ! empty($widgets_to_register)) {
1035 1035
                 // cycle thru widget folders
1036 1036
                 foreach ($widgets_to_register as $widget_path) {
1037 1037
                     // add to list of installed widget modules
@@ -1081,31 +1081,31 @@  discard block
 block discarded – undo
1081 1081
         // create classname from widget directory name
1082 1082
         $widget = str_replace(' ', '_', ucwords(str_replace('_', ' ', $widget)));
1083 1083
         // add class prefix
1084
-        $widget_class = 'EEW_' . $widget;
1084
+        $widget_class = 'EEW_'.$widget;
1085 1085
         // does the widget exist ?
1086
-        if (! is_readable($widget_path . '/' . $widget_class . $widget_ext)) {
1086
+        if ( ! is_readable($widget_path.'/'.$widget_class.$widget_ext)) {
1087 1087
             $msg = sprintf(
1088 1088
                 esc_html__(
1089 1089
                     'The requested %s widget file could not be found or is not readable due to file permissions. Please ensure the following path is correct: %s',
1090 1090
                     'event_espresso'
1091 1091
                 ),
1092 1092
                 $widget_class,
1093
-                $widget_path . '/' . $widget_class . $widget_ext
1093
+                $widget_path.'/'.$widget_class.$widget_ext
1094 1094
             );
1095
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1095
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1096 1096
             return;
1097 1097
         }
1098 1098
         // load the widget class file
1099
-        require_once($widget_path . '/' . $widget_class . $widget_ext);
1099
+        require_once($widget_path.'/'.$widget_class.$widget_ext);
1100 1100
         // verify that class exists
1101
-        if (! class_exists($widget_class)) {
1101
+        if ( ! class_exists($widget_class)) {
1102 1102
             $msg = sprintf(esc_html__('The requested %s widget class does not exist.', 'event_espresso'), $widget_class);
1103
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1103
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1104 1104
             return;
1105 1105
         }
1106 1106
         register_widget($widget_class);
1107 1107
         // add to array of registered widgets
1108
-        EE_Registry::instance()->widgets->{$widget_class} = $widget_path . '/' . $widget_class . $widget_ext;
1108
+        EE_Registry::instance()->widgets->{$widget_class} = $widget_path.'/'.$widget_class.$widget_ext;
1109 1109
     }
1110 1110
 
1111 1111
 
@@ -1118,19 +1118,19 @@  discard block
 block discarded – undo
1118 1118
     private function _register_modules()
1119 1119
     {
1120 1120
         // grab list of installed modules
1121
-        $modules_to_register = glob(EE_MODULES . '*', GLOB_ONLYDIR);
1121
+        $modules_to_register = glob(EE_MODULES.'*', GLOB_ONLYDIR);
1122 1122
         // filter list of modules to register
1123 1123
         $modules_to_register = apply_filters(
1124 1124
             'FHEE__EE_Config__register_modules__modules_to_register',
1125 1125
             $modules_to_register
1126 1126
         );
1127
-        if (! empty($modules_to_register)) {
1127
+        if ( ! empty($modules_to_register)) {
1128 1128
             // loop through folders
1129 1129
             foreach ($modules_to_register as $module_path) {
1130 1130
                 /**TEMPORARILY EXCLUDE gateways from modules for time being**/
1131 1131
                 if (
1132
-                    $module_path !== EE_MODULES . 'zzz-copy-this-module-template'
1133
-                    && $module_path !== EE_MODULES . 'gateways'
1132
+                    $module_path !== EE_MODULES.'zzz-copy-this-module-template'
1133
+                    && $module_path !== EE_MODULES.'gateways'
1134 1134
                 ) {
1135 1135
                     // add to list of installed modules
1136 1136
                     EE_Config::register_module($module_path);
@@ -1167,25 +1167,25 @@  discard block
 block discarded – undo
1167 1167
             // remove last segment
1168 1168
             array_pop($module_path);
1169 1169
             // glue it back together
1170
-            $module_path = implode('/', $module_path) . '/';
1170
+            $module_path = implode('/', $module_path).'/';
1171 1171
             // take first segment from file name pieces and sanitize it
1172 1172
             $module = preg_replace('/[^a-zA-Z0-9_\-]/', '', $module_file[0]);
1173 1173
             // ensure class prefix is added
1174
-            $module_class = strpos($module, 'EED_') !== 0 ? 'EED_' . $module : $module;
1174
+            $module_class = strpos($module, 'EED_') !== 0 ? 'EED_'.$module : $module;
1175 1175
         } else {
1176 1176
             // we need to generate the filename based off of the folder name
1177 1177
             // grab and sanitize module name
1178 1178
             $module = strtolower(basename($module_path));
1179 1179
             $module = preg_replace('/[^a-z0-9_\-]/', '', $module);
1180 1180
             // like trailingslashit()
1181
-            $module_path = rtrim($module_path, '/') . '/';
1181
+            $module_path = rtrim($module_path, '/').'/';
1182 1182
             // create classname from module directory name
1183 1183
             $module = str_replace(' ', '_', ucwords(str_replace('_', ' ', $module)));
1184 1184
             // add class prefix
1185
-            $module_class = 'EED_' . $module;
1185
+            $module_class = 'EED_'.$module;
1186 1186
         }
1187 1187
         // does the module exist ?
1188
-        if (! is_readable($module_path . '/' . $module_class . $module_ext)) {
1188
+        if ( ! is_readable($module_path.'/'.$module_class.$module_ext)) {
1189 1189
             $msg = sprintf(
1190 1190
                 esc_html__(
1191 1191
                     'The requested %s module file could not be found or is not readable due to file permissions.',
@@ -1193,19 +1193,19 @@  discard block
 block discarded – undo
1193 1193
                 ),
1194 1194
                 $module
1195 1195
             );
1196
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1196
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1197 1197
             return false;
1198 1198
         }
1199 1199
         // load the module class file
1200
-        require_once($module_path . $module_class . $module_ext);
1200
+        require_once($module_path.$module_class.$module_ext);
1201 1201
         // verify that class exists
1202
-        if (! class_exists($module_class)) {
1202
+        if ( ! class_exists($module_class)) {
1203 1203
             $msg = sprintf(esc_html__('The requested %s module class does not exist.', 'event_espresso'), $module_class);
1204
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1204
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1205 1205
             return false;
1206 1206
         }
1207 1207
         // add to array of registered modules
1208
-        EE_Registry::instance()->modules->{$module_class} = $module_path . $module_class . $module_ext;
1208
+        EE_Registry::instance()->modules->{$module_class} = $module_path.$module_class.$module_ext;
1209 1209
         do_action(
1210 1210
             'AHEE__EE_Config__register_module__complete',
1211 1211
             $module_class,
@@ -1256,26 +1256,26 @@  discard block
 block discarded – undo
1256 1256
     {
1257 1257
         do_action('AHEE__EE_Config__register_route__begin', $route, $module, $method_name);
1258 1258
         $module = str_replace('EED_', '', $module);
1259
-        $module_class = 'EED_' . $module;
1260
-        if (! isset(EE_Registry::instance()->modules->{$module_class})) {
1259
+        $module_class = 'EED_'.$module;
1260
+        if ( ! isset(EE_Registry::instance()->modules->{$module_class})) {
1261 1261
             $msg = sprintf(esc_html__('The module %s has not been registered.', 'event_espresso'), $module);
1262
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1262
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1263 1263
             return false;
1264 1264
         }
1265 1265
         if (empty($route)) {
1266 1266
             $msg = sprintf(esc_html__('No route has been supplied.', 'event_espresso'), $route);
1267
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1267
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1268 1268
             return false;
1269 1269
         }
1270
-        if (! method_exists('EED_' . $module, $method_name)) {
1270
+        if ( ! method_exists('EED_'.$module, $method_name)) {
1271 1271
             $msg = sprintf(
1272 1272
                 esc_html__('A valid class method for the %s route has not been supplied.', 'event_espresso'),
1273 1273
                 $route
1274 1274
             );
1275
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1275
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1276 1276
             return false;
1277 1277
         }
1278
-        EE_Config::$_module_route_map[ (string) $key ][ (string) $route ] = array('EED_' . $module, $method_name);
1278
+        EE_Config::$_module_route_map[(string) $key][(string) $route] = array('EED_'.$module, $method_name);
1279 1279
         return true;
1280 1280
     }
1281 1281
 
@@ -1292,8 +1292,8 @@  discard block
 block discarded – undo
1292 1292
     {
1293 1293
         do_action('AHEE__EE_Config__get_route__begin', $route);
1294 1294
         $route = (string) apply_filters('FHEE__EE_Config__get_route', $route);
1295
-        if (isset(EE_Config::$_module_route_map[ $key ][ $route ])) {
1296
-            return EE_Config::$_module_route_map[ $key ][ $route ];
1295
+        if (isset(EE_Config::$_module_route_map[$key][$route])) {
1296
+            return EE_Config::$_module_route_map[$key][$route];
1297 1297
         }
1298 1298
         return null;
1299 1299
     }
@@ -1325,47 +1325,47 @@  discard block
 block discarded – undo
1325 1325
     public static function register_forward($route = null, $status = 0, $forward = null, $key = 'ee')
1326 1326
     {
1327 1327
         do_action('AHEE__EE_Config__register_forward', $route, $status, $forward);
1328
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1328
+        if ( ! isset(EE_Config::$_module_route_map[$key][$route]) || empty($route)) {
1329 1329
             $msg = sprintf(
1330 1330
                 esc_html__('The module route %s for this forward has not been registered.', 'event_espresso'),
1331 1331
                 $route
1332 1332
             );
1333
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1333
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1334 1334
             return false;
1335 1335
         }
1336 1336
         if (empty($forward)) {
1337 1337
             $msg = sprintf(esc_html__('No forwarding route has been supplied.', 'event_espresso'), $route);
1338
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1338
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1339 1339
             return false;
1340 1340
         }
1341 1341
         if (is_array($forward)) {
1342
-            if (! isset($forward[1])) {
1342
+            if ( ! isset($forward[1])) {
1343 1343
                 $msg = sprintf(
1344 1344
                     esc_html__('A class method for the %s forwarding route has not been supplied.', 'event_espresso'),
1345 1345
                     $route
1346 1346
                 );
1347
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1347
+                EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1348 1348
                 return false;
1349 1349
             }
1350
-            if (! method_exists($forward[0], $forward[1])) {
1350
+            if ( ! method_exists($forward[0], $forward[1])) {
1351 1351
                 $msg = sprintf(
1352 1352
                     esc_html__('The class method %s for the %s forwarding route is in invalid.', 'event_espresso'),
1353 1353
                     $forward[1],
1354 1354
                     $route
1355 1355
                 );
1356
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1356
+                EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1357 1357
                 return false;
1358 1358
             }
1359
-        } elseif (! function_exists($forward)) {
1359
+        } elseif ( ! function_exists($forward)) {
1360 1360
             $msg = sprintf(
1361 1361
                 esc_html__('The function %s for the %s forwarding route is in invalid.', 'event_espresso'),
1362 1362
                 $forward,
1363 1363
                 $route
1364 1364
             );
1365
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1365
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1366 1366
             return false;
1367 1367
         }
1368
-        EE_Config::$_module_forward_map[ $key ][ $route ][ absint($status) ] = $forward;
1368
+        EE_Config::$_module_forward_map[$key][$route][absint($status)] = $forward;
1369 1369
         return true;
1370 1370
     }
1371 1371
 
@@ -1383,10 +1383,10 @@  discard block
 block discarded – undo
1383 1383
     public static function get_forward($route = null, $status = 0, $key = 'ee')
1384 1384
     {
1385 1385
         do_action('AHEE__EE_Config__get_forward__begin', $route, $status);
1386
-        if (isset(EE_Config::$_module_forward_map[ $key ][ $route ][ $status ])) {
1386
+        if (isset(EE_Config::$_module_forward_map[$key][$route][$status])) {
1387 1387
             return apply_filters(
1388 1388
                 'FHEE__EE_Config__get_forward',
1389
-                EE_Config::$_module_forward_map[ $key ][ $route ][ $status ],
1389
+                EE_Config::$_module_forward_map[$key][$route][$status],
1390 1390
                 $route,
1391 1391
                 $status
1392 1392
             );
@@ -1410,15 +1410,15 @@  discard block
 block discarded – undo
1410 1410
     public static function register_view($route = null, $status = 0, $view = null, $key = 'ee')
1411 1411
     {
1412 1412
         do_action('AHEE__EE_Config__register_view__begin', $route, $status, $view);
1413
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1413
+        if ( ! isset(EE_Config::$_module_route_map[$key][$route]) || empty($route)) {
1414 1414
             $msg = sprintf(
1415 1415
                 esc_html__('The module route %s for this view has not been registered.', 'event_espresso'),
1416 1416
                 $route
1417 1417
             );
1418
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1418
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1419 1419
             return false;
1420 1420
         }
1421
-        if (! is_readable($view)) {
1421
+        if ( ! is_readable($view)) {
1422 1422
             $msg = sprintf(
1423 1423
                 esc_html__(
1424 1424
                     'The %s view file could not be found or is not readable due to file permissions.',
@@ -1426,10 +1426,10 @@  discard block
 block discarded – undo
1426 1426
                 ),
1427 1427
                 $view
1428 1428
             );
1429
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1429
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
1430 1430
             return false;
1431 1431
         }
1432
-        EE_Config::$_module_view_map[ $key ][ $route ][ absint($status) ] = $view;
1432
+        EE_Config::$_module_view_map[$key][$route][absint($status)] = $view;
1433 1433
         return true;
1434 1434
     }
1435 1435
 
@@ -1447,10 +1447,10 @@  discard block
 block discarded – undo
1447 1447
     public static function get_view($route = null, $status = 0, $key = 'ee')
1448 1448
     {
1449 1449
         do_action('AHEE__EE_Config__get_view__begin', $route, $status);
1450
-        if (isset(EE_Config::$_module_view_map[ $key ][ $route ][ $status ])) {
1450
+        if (isset(EE_Config::$_module_view_map[$key][$route][$status])) {
1451 1451
             return apply_filters(
1452 1452
                 'FHEE__EE_Config__get_view',
1453
-                EE_Config::$_module_view_map[ $key ][ $route ][ $status ],
1453
+                EE_Config::$_module_view_map[$key][$route][$status],
1454 1454
                 $route,
1455 1455
                 $status
1456 1456
             );
@@ -1476,7 +1476,7 @@  discard block
 block discarded – undo
1476 1476
      */
1477 1477
     public static function getLegacyShortcodesManager()
1478 1478
     {
1479
-        if (! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1479
+        if ( ! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1480 1480
             EE_Config::instance()->legacy_shortcodes_manager = LoaderFactory::getLoader()->getShared(
1481 1481
                 LegacyShortcodesManager::class
1482 1482
             );
@@ -1523,7 +1523,7 @@  discard block
 block discarded – undo
1523 1523
      */
1524 1524
     public function get_pretty($property)
1525 1525
     {
1526
-        if (! property_exists($this, $property)) {
1526
+        if ( ! property_exists($this, $property)) {
1527 1527
             throw new EE_Error(
1528 1528
                 sprintf(
1529 1529
                     esc_html__(
@@ -1752,11 +1752,11 @@  discard block
 block discarded – undo
1752 1752
      */
1753 1753
     public function reg_page_url()
1754 1754
     {
1755
-        if (! $this->reg_page_url) {
1755
+        if ( ! $this->reg_page_url) {
1756 1756
             $this->reg_page_url = add_query_arg(
1757 1757
                 array('uts' => time()),
1758 1758
                 get_permalink($this->reg_page_id)
1759
-            ) . '#checkout';
1759
+            ).'#checkout';
1760 1760
         }
1761 1761
         return $this->reg_page_url;
1762 1762
     }
@@ -1772,7 +1772,7 @@  discard block
 block discarded – undo
1772 1772
      */
1773 1773
     public function txn_page_url($query_args = array())
1774 1774
     {
1775
-        if (! $this->txn_page_url) {
1775
+        if ( ! $this->txn_page_url) {
1776 1776
             $this->txn_page_url = get_permalink($this->txn_page_id);
1777 1777
         }
1778 1778
         if ($query_args) {
@@ -1793,7 +1793,7 @@  discard block
 block discarded – undo
1793 1793
      */
1794 1794
     public function thank_you_page_url($query_args = array())
1795 1795
     {
1796
-        if (! $this->thank_you_page_url) {
1796
+        if ( ! $this->thank_you_page_url) {
1797 1797
             $this->thank_you_page_url = get_permalink($this->thank_you_page_id);
1798 1798
         }
1799 1799
         if ($query_args) {
@@ -1812,7 +1812,7 @@  discard block
 block discarded – undo
1812 1812
      */
1813 1813
     public function cancel_page_url()
1814 1814
     {
1815
-        if (! $this->cancel_page_url) {
1815
+        if ( ! $this->cancel_page_url) {
1816 1816
             $this->cancel_page_url = get_permalink($this->cancel_page_id);
1817 1817
         }
1818 1818
         return $this->cancel_page_url;
@@ -1855,13 +1855,13 @@  discard block
 block discarded – undo
1855 1855
         $current_main_site_id = ! empty($current_network_main_site) ? $current_network_main_site->blog_id : 1;
1856 1856
         $option = self::OPTION_NAME_UXIP;
1857 1857
         // set correct table for query
1858
-        $table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options';
1858
+        $table_name = $wpdb->get_blog_prefix($current_main_site_id).'options';
1859 1859
         // rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because
1860 1860
         // get_blog_option() does a switch_to_blog an that could cause infinite recursion because EE_Core_Config might be
1861 1861
         // re-constructed on the blog switch.  Note, we are still executing any core wp filters on this option retrieval.
1862 1862
         // this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog
1863 1863
         // for the purpose of caching.
1864
-        $pre = apply_filters('pre_option_' . $option, false, $option);
1864
+        $pre = apply_filters('pre_option_'.$option, false, $option);
1865 1865
         if (false !== $pre) {
1866 1866
             EE_Core_Config::$ee_ueip_option = $pre;
1867 1867
             return EE_Core_Config::$ee_ueip_option;
@@ -1875,10 +1875,10 @@  discard block
 block discarded – undo
1875 1875
         if (is_object($row)) {
1876 1876
             $value = $row->option_value;
1877 1877
         } else { // option does not exist so use default.
1878
-            EE_Core_Config::$ee_ueip_option =  apply_filters('default_option_' . $option, false, $option);
1878
+            EE_Core_Config::$ee_ueip_option = apply_filters('default_option_'.$option, false, $option);
1879 1879
             return EE_Core_Config::$ee_ueip_option;
1880 1880
         }
1881
-        EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option);
1881
+        EE_Core_Config::$ee_ueip_option = apply_filters('option_'.$option, maybe_unserialize($value), $option);
1882 1882
         return EE_Core_Config::$ee_ueip_option;
1883 1883
     }
1884 1884
 
@@ -2140,30 +2140,30 @@  discard block
 block discarded – undo
2140 2140
             // retrieve the country settings from the db, just in case they have been customized
2141 2141
             $country = EE_Registry::instance()->load_model('Country')->get_one_by_ID($CNT_ISO);
2142 2142
             if ($country instanceof EE_Country) {
2143
-                $this->code = $country->currency_code();    // currency code: USD, CAD, EUR
2144
-                $this->name = $country->currency_name_single();    // Dollar
2145
-                $this->plural = $country->currency_name_plural();    // Dollars
2146
-                $this->sign = $country->currency_sign();            // currency sign: $
2143
+                $this->code = $country->currency_code(); // currency code: USD, CAD, EUR
2144
+                $this->name = $country->currency_name_single(); // Dollar
2145
+                $this->plural = $country->currency_name_plural(); // Dollars
2146
+                $this->sign = $country->currency_sign(); // currency sign: $
2147 2147
                 $this->sign_b4 = $country->currency_sign_before(
2148
-                );        // currency sign before or after: $TRUE  or  FALSE$
2149
-                $this->dec_plc = $country->currency_decimal_places();    // decimal places: 2 = 0.00  3 = 0.000
2148
+                ); // currency sign before or after: $TRUE  or  FALSE$
2149
+                $this->dec_plc = $country->currency_decimal_places(); // decimal places: 2 = 0.00  3 = 0.000
2150 2150
                 $this->dec_mrk = $country->currency_decimal_mark(
2151
-                );    // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2151
+                ); // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2152 2152
                 $this->thsnds = $country->currency_thousands_separator(
2153
-                );    // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2153
+                ); // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2154 2154
             }
2155 2155
         }
2156 2156
         // fallback to hardcoded defaults, in case the above failed
2157 2157
         if (empty($this->code)) {
2158 2158
             // set default currency settings
2159
-            $this->code = 'USD';    // currency code: USD, CAD, EUR
2160
-            $this->name = esc_html__('Dollar', 'event_espresso');    // Dollar
2161
-            $this->plural = esc_html__('Dollars', 'event_espresso');    // Dollars
2162
-            $this->sign = '$';    // currency sign: $
2163
-            $this->sign_b4 = true;    // currency sign before or after: $TRUE  or  FALSE$
2164
-            $this->dec_plc = 2;    // decimal places: 2 = 0.00  3 = 0.000
2165
-            $this->dec_mrk = '.';    // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2166
-            $this->thsnds = ',';    // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2159
+            $this->code = 'USD'; // currency code: USD, CAD, EUR
2160
+            $this->name = esc_html__('Dollar', 'event_espresso'); // Dollar
2161
+            $this->plural = esc_html__('Dollars', 'event_espresso'); // Dollars
2162
+            $this->sign = '$'; // currency sign: $
2163
+            $this->sign_b4 = true; // currency sign before or after: $TRUE  or  FALSE$
2164
+            $this->dec_plc = 2; // decimal places: 2 = 0.00  3 = 0.000
2165
+            $this->dec_mrk = '.'; // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2166
+            $this->thsnds = ','; // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2167 2167
         }
2168 2168
     }
2169 2169
 }
@@ -2432,8 +2432,8 @@  discard block
 block discarded – undo
2432 2432
             $closing_a_tag = '';
2433 2433
             if (function_exists('get_privacy_policy_url')) {
2434 2434
                 $privacy_page_url = get_privacy_policy_url();
2435
-                if (! empty($privacy_page_url)) {
2436
-                    $opening_a_tag = '<a href="' . $privacy_page_url . '" target="_blank">';
2435
+                if ( ! empty($privacy_page_url)) {
2436
+                    $opening_a_tag = '<a href="'.$privacy_page_url.'" target="_blank">';
2437 2437
                     $closing_a_tag = '</a>';
2438 2438
                 }
2439 2439
             }
@@ -2662,7 +2662,7 @@  discard block
 block discarded – undo
2662 2662
     public function log_file_name($reset = false)
2663 2663
     {
2664 2664
         if (empty($this->log_file_name) || $reset) {
2665
-            $this->log_file_name = sanitize_key('espresso_log_' . md5(uniqid('', true))) . '.txt';
2665
+            $this->log_file_name = sanitize_key('espresso_log_'.md5(uniqid('', true))).'.txt';
2666 2666
             EE_Config::instance()->update_espresso_config(false, false);
2667 2667
         }
2668 2668
         return $this->log_file_name;
@@ -2676,7 +2676,7 @@  discard block
 block discarded – undo
2676 2676
     public function debug_file_name($reset = false)
2677 2677
     {
2678 2678
         if (empty($this->debug_file_name) || $reset) {
2679
-            $this->debug_file_name = sanitize_key('espresso_debug_' . md5(uniqid('', true))) . '.txt';
2679
+            $this->debug_file_name = sanitize_key('espresso_debug_'.md5(uniqid('', true))).'.txt';
2680 2680
             EE_Config::instance()->update_espresso_config(false, false);
2681 2681
         }
2682 2682
         return $this->debug_file_name;
@@ -2880,21 +2880,21 @@  discard block
 block discarded – undo
2880 2880
         $this->use_google_maps = true;
2881 2881
         $this->google_map_api_key = '';
2882 2882
         // for event details pages (reg page)
2883
-        $this->event_details_map_width = 585;            // ee_map_width_single
2884
-        $this->event_details_map_height = 362;            // ee_map_height_single
2885
-        $this->event_details_map_zoom = 14;            // ee_map_zoom_single
2886
-        $this->event_details_display_nav = true;            // ee_map_nav_display_single
2887
-        $this->event_details_nav_size = false;            // ee_map_nav_size_single
2888
-        $this->event_details_control_type = 'default';        // ee_map_type_control_single
2889
-        $this->event_details_map_align = 'center';            // ee_map_align_single
2883
+        $this->event_details_map_width = 585; // ee_map_width_single
2884
+        $this->event_details_map_height = 362; // ee_map_height_single
2885
+        $this->event_details_map_zoom = 14; // ee_map_zoom_single
2886
+        $this->event_details_display_nav = true; // ee_map_nav_display_single
2887
+        $this->event_details_nav_size = false; // ee_map_nav_size_single
2888
+        $this->event_details_control_type = 'default'; // ee_map_type_control_single
2889
+        $this->event_details_map_align = 'center'; // ee_map_align_single
2890 2890
         // for event list pages
2891
-        $this->event_list_map_width = 300;            // ee_map_width
2892
-        $this->event_list_map_height = 185;        // ee_map_height
2893
-        $this->event_list_map_zoom = 12;            // ee_map_zoom
2894
-        $this->event_list_display_nav = false;        // ee_map_nav_display
2895
-        $this->event_list_nav_size = true;            // ee_map_nav_size
2896
-        $this->event_list_control_type = 'dropdown';        // ee_map_type_control
2897
-        $this->event_list_map_align = 'center';            // ee_map_align
2891
+        $this->event_list_map_width = 300; // ee_map_width
2892
+        $this->event_list_map_height = 185; // ee_map_height
2893
+        $this->event_list_map_zoom = 12; // ee_map_zoom
2894
+        $this->event_list_display_nav = false; // ee_map_nav_display
2895
+        $this->event_list_nav_size = true; // ee_map_nav_size
2896
+        $this->event_list_control_type = 'dropdown'; // ee_map_type_control
2897
+        $this->event_list_map_align = 'center'; // ee_map_align
2898 2898
     }
2899 2899
 }
2900 2900
 
Please login to merge, or discard this patch.
Indentation   +3180 added lines, -3180 removed lines patch added patch discarded remove patch
@@ -18,2541 +18,2541 @@  discard block
 block discarded – undo
18 18
  */
19 19
 final class EE_Config implements ResettableInterface
20 20
 {
21
-    const OPTION_NAME = 'ee_config';
22
-
23
-    const LOG_NAME = 'ee_config_log';
24
-
25
-    const LOG_LENGTH = 100;
26
-
27
-    const ADDON_OPTION_NAMES = 'ee_config_option_names';
28
-
29
-    /**
30
-     *    instance of the EE_Config object
31
-     *
32
-     * @var    EE_Config $_instance
33
-     * @access    private
34
-     */
35
-    private static $_instance;
36
-
37
-    /**
38
-     * @var boolean $_logging_enabled
39
-     */
40
-    private static $_logging_enabled = false;
41
-
42
-    /**
43
-     * @var LegacyShortcodesManager $legacy_shortcodes_manager
44
-     */
45
-    private $legacy_shortcodes_manager;
46
-
47
-    /**
48
-     * An StdClass whose property names are addon slugs,
49
-     * and values are their config classes
50
-     *
51
-     * @var StdClass
52
-     */
53
-    public $addons;
54
-
55
-    /**
56
-     * @var EE_Admin_Config
57
-     */
58
-    public $admin;
59
-
60
-    /**
61
-     * @var EE_Core_Config
62
-     */
63
-    public $core;
64
-
65
-    /**
66
-     * @var EE_Currency_Config
67
-     */
68
-    public $currency;
69
-
70
-    /**
71
-     * @var EE_Organization_Config
72
-     */
73
-    public $organization;
74
-
75
-    /**
76
-     * @var EE_Registration_Config
77
-     */
78
-    public $registration;
79
-
80
-    /**
81
-     * @var EE_Template_Config
82
-     */
83
-    public $template_settings;
84
-
85
-    /**
86
-     * Holds EE environment values.
87
-     *
88
-     * @var EE_Environment_Config
89
-     */
90
-    public $environment;
91
-
92
-    /**
93
-     * settings pertaining to Google maps
94
-     *
95
-     * @var EE_Map_Config
96
-     */
97
-    public $map_settings;
98
-
99
-    /**
100
-     * settings pertaining to Taxes
101
-     *
102
-     * @var EE_Tax_Config
103
-     */
104
-    public $tax_settings;
105
-
106
-    /**
107
-     * Settings pertaining to global messages settings.
108
-     *
109
-     * @var EE_Messages_Config
110
-     */
111
-    public $messages;
112
-
113
-    /**
114
-     * @deprecated
115
-     * @var EE_Gateway_Config
116
-     */
117
-    public $gateway;
118
-
119
-    /**
120
-     * @var    array $_addon_option_names
121
-     * @access    private
122
-     */
123
-    private $_addon_option_names = array();
124
-
125
-    /**
126
-     * @var    array $_module_route_map
127
-     * @access    private
128
-     */
129
-    private static $_module_route_map = array();
130
-
131
-    /**
132
-     * @var    array $_module_forward_map
133
-     * @access    private
134
-     */
135
-    private static $_module_forward_map = array();
136
-
137
-    /**
138
-     * @var    array $_module_view_map
139
-     * @access    private
140
-     */
141
-    private static $_module_view_map = array();
142
-
143
-
144
-    /**
145
-     * @singleton method used to instantiate class object
146
-     * @access    public
147
-     * @return EE_Config instance
148
-     */
149
-    public static function instance()
150
-    {
151
-        // check if class object is instantiated, and instantiated properly
152
-        if (! self::$_instance instanceof EE_Config) {
153
-            self::$_instance = new self();
154
-        }
155
-        return self::$_instance;
156
-    }
157
-
158
-
159
-    /**
160
-     * Resets the config
161
-     *
162
-     * @param bool    $hard_reset    if TRUE, sets EE_CONFig back to its original settings in the database. If FALSE
163
-     *                               (default) leaves the database alone, and merely resets the EE_Config object to
164
-     *                               reflect its state in the database
165
-     * @param boolean $reinstantiate if TRUE (default) call instance() and return it. Otherwise, just leave
166
-     *                               $_instance as NULL. Useful in case you want to forget about the old instance on
167
-     *                               EE_Config, but might not be ready to instantiate EE_Config currently (eg if the
168
-     *                               site was put into maintenance mode)
169
-     * @return EE_Config
170
-     */
171
-    public static function reset($hard_reset = false, $reinstantiate = true)
172
-    {
173
-        if (self::$_instance instanceof EE_Config) {
174
-            if ($hard_reset) {
175
-                self::$_instance->legacy_shortcodes_manager = null;
176
-                self::$_instance->_addon_option_names = array();
177
-                self::$_instance->_initialize_config();
178
-                self::$_instance->update_espresso_config();
179
-            }
180
-            self::$_instance->update_addon_option_names();
181
-        }
182
-        self::$_instance = null;
183
-        // we don't need to reset the static properties imo because those should
184
-        // only change when a module is added or removed. Currently we don't
185
-        // support removing a module during a request when it previously existed
186
-        if ($reinstantiate) {
187
-            return self::instance();
188
-        } else {
189
-            return null;
190
-        }
191
-    }
192
-
193
-
194
-    /**
195
-     *    class constructor
196
-     *
197
-     * @access    private
198
-     */
199
-    private function __construct()
200
-    {
201
-        do_action('AHEE__EE_Config__construct__begin', $this);
202
-        EE_Config::$_logging_enabled = apply_filters('FHEE__EE_Config___construct__logging_enabled', false);
203
-        // setup empty config classes
204
-        $this->_initialize_config();
205
-        // load existing EE site settings
206
-        $this->_load_core_config();
207
-        // confirm everything loaded correctly and set filtered defaults if not
208
-        $this->_verify_config();
209
-        //  register shortcodes and modules
210
-        add_action(
211
-            'AHEE__EE_System__register_shortcodes_modules_and_widgets',
212
-            array($this, 'register_shortcodes_and_modules'),
213
-            999
214
-        );
215
-        //  initialize shortcodes and modules
216
-        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'initialize_shortcodes_and_modules'));
217
-        // register widgets
218
-        add_action('widgets_init', array($this, 'widgets_init'), 10);
219
-        // shutdown
220
-        add_action('shutdown', array($this, 'shutdown'), 10);
221
-        // construct__end hook
222
-        do_action('AHEE__EE_Config__construct__end', $this);
223
-        // hardcoded hack
224
-        $this->template_settings->current_espresso_theme = 'Espresso_Arabica_2014';
225
-    }
226
-
227
-
228
-    /**
229
-     * @return boolean
230
-     */
231
-    public static function logging_enabled()
232
-    {
233
-        return self::$_logging_enabled;
234
-    }
235
-
236
-
237
-    /**
238
-     * use to get the current theme if needed from static context
239
-     *
240
-     * @return string current theme set.
241
-     */
242
-    public static function get_current_theme()
243
-    {
244
-        return isset(self::$_instance->template_settings->current_espresso_theme)
245
-            ? self::$_instance->template_settings->current_espresso_theme : 'Espresso_Arabica_2014';
246
-    }
247
-
248
-
249
-    /**
250
-     *        _initialize_config
251
-     *
252
-     * @access private
253
-     * @return void
254
-     */
255
-    private function _initialize_config()
256
-    {
257
-        EE_Config::trim_log();
258
-        // set defaults
259
-        $this->_addon_option_names = get_option(EE_Config::ADDON_OPTION_NAMES, array());
260
-        $this->addons = new stdClass();
261
-        // set _module_route_map
262
-        EE_Config::$_module_route_map = array();
263
-        // set _module_forward_map
264
-        EE_Config::$_module_forward_map = array();
265
-        // set _module_view_map
266
-        EE_Config::$_module_view_map = array();
267
-    }
268
-
269
-
270
-    /**
271
-     *        load core plugin configuration
272
-     *
273
-     * @access private
274
-     * @return void
275
-     */
276
-    private function _load_core_config()
277
-    {
278
-        // load_core_config__start hook
279
-        do_action('AHEE__EE_Config___load_core_config__start', $this);
280
-        $espresso_config = $this->get_espresso_config();
281
-        foreach ($espresso_config as $config => $settings) {
282
-            // load_core_config__start hook
283
-            $settings = apply_filters(
284
-                'FHEE__EE_Config___load_core_config__config_settings',
285
-                $settings,
286
-                $config,
287
-                $this
288
-            );
289
-            if (is_object($settings) && property_exists($this, $config)) {
290
-                $this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__' . $config, $settings);
291
-                // call configs populate method to ensure any defaults are set for empty values.
292
-                if (method_exists($settings, 'populate')) {
293
-                    $this->{$config}->populate();
294
-                }
295
-                if (method_exists($settings, 'do_hooks')) {
296
-                    $this->{$config}->do_hooks();
297
-                }
298
-            }
299
-        }
300
-        if (apply_filters('FHEE__EE_Config___load_core_config__update_espresso_config', false)) {
301
-            $this->update_espresso_config();
302
-        }
303
-        // load_core_config__end hook
304
-        do_action('AHEE__EE_Config___load_core_config__end', $this);
305
-    }
306
-
307
-
308
-    /**
309
-     *    _verify_config
310
-     *
311
-     * @access    protected
312
-     * @return    void
313
-     */
314
-    protected function _verify_config()
315
-    {
316
-        $this->core = $this->core instanceof EE_Core_Config
317
-            ? $this->core
318
-            : new EE_Core_Config();
319
-        $this->core = apply_filters('FHEE__EE_Config___initialize_config__core', $this->core);
320
-        $this->organization = $this->organization instanceof EE_Organization_Config
321
-            ? $this->organization
322
-            : new EE_Organization_Config();
323
-        $this->organization = apply_filters(
324
-            'FHEE__EE_Config___initialize_config__organization',
325
-            $this->organization
326
-        );
327
-        $this->currency = $this->currency instanceof EE_Currency_Config
328
-            ? $this->currency
329
-            : new EE_Currency_Config();
330
-        $this->currency = apply_filters('FHEE__EE_Config___initialize_config__currency', $this->currency);
331
-        $this->registration = $this->registration instanceof EE_Registration_Config
332
-            ? $this->registration
333
-            : new EE_Registration_Config();
334
-        $this->registration = apply_filters(
335
-            'FHEE__EE_Config___initialize_config__registration',
336
-            $this->registration
337
-        );
338
-        $this->admin = $this->admin instanceof EE_Admin_Config
339
-            ? $this->admin
340
-            : new EE_Admin_Config();
341
-        $this->admin = apply_filters('FHEE__EE_Config___initialize_config__admin', $this->admin);
342
-        $this->template_settings = $this->template_settings instanceof EE_Template_Config
343
-            ? $this->template_settings
344
-            : new EE_Template_Config();
345
-        $this->template_settings = apply_filters(
346
-            'FHEE__EE_Config___initialize_config__template_settings',
347
-            $this->template_settings
348
-        );
349
-        $this->map_settings = $this->map_settings instanceof EE_Map_Config
350
-            ? $this->map_settings
351
-            : new EE_Map_Config();
352
-        $this->map_settings = apply_filters(
353
-            'FHEE__EE_Config___initialize_config__map_settings',
354
-            $this->map_settings
355
-        );
356
-        $this->environment = $this->environment instanceof EE_Environment_Config
357
-            ? $this->environment
358
-            : new EE_Environment_Config();
359
-        $this->environment = apply_filters(
360
-            'FHEE__EE_Config___initialize_config__environment',
361
-            $this->environment
362
-        );
363
-        $this->tax_settings = $this->tax_settings instanceof EE_Tax_Config
364
-            ? $this->tax_settings
365
-            : new EE_Tax_Config();
366
-        $this->tax_settings = apply_filters(
367
-            'FHEE__EE_Config___initialize_config__tax_settings',
368
-            $this->tax_settings
369
-        );
370
-        $this->messages = apply_filters('FHEE__EE_Config__initialize_config__messages', $this->messages);
371
-        $this->messages = $this->messages instanceof EE_Messages_Config
372
-            ? $this->messages
373
-            : new EE_Messages_Config();
374
-        $this->gateway = $this->gateway instanceof EE_Gateway_Config
375
-            ? $this->gateway
376
-            : new EE_Gateway_Config();
377
-        $this->gateway = apply_filters('FHEE__EE_Config___initialize_config__gateway', $this->gateway);
378
-        $this->legacy_shortcodes_manager = null;
379
-    }
380
-
381
-
382
-    /**
383
-     *    get_espresso_config
384
-     *
385
-     * @access    public
386
-     * @return    array of espresso config stuff
387
-     */
388
-    public function get_espresso_config()
389
-    {
390
-        // grab espresso configuration
391
-        return apply_filters(
392
-            'FHEE__EE_Config__get_espresso_config__CFG',
393
-            get_option(EE_Config::OPTION_NAME, array())
394
-        );
395
-    }
396
-
397
-
398
-    /**
399
-     *    double_check_config_comparison
400
-     *
401
-     * @access    public
402
-     * @param string $option
403
-     * @param        $old_value
404
-     * @param        $value
405
-     */
406
-    public function double_check_config_comparison($option, $old_value, $value)
407
-    {
408
-        // make sure we're checking the ee config
409
-        if ($option === EE_Config::OPTION_NAME) {
410
-            // run a loose comparison of the old value against the new value for type and properties,
411
-            // but NOT exact instance like WP update_option does (ie: NOT type safe comparison)
412
-            if ($value != $old_value) {
413
-                // if they are NOT the same, then remove the hook,
414
-                // which means the subsequent update results will be based solely on the update query results
415
-                // the reason we do this is because, as stated above,
416
-                // WP update_option performs an exact instance comparison (===) on any update values passed to it
417
-                // this happens PRIOR to serialization and any subsequent update.
418
-                // If values are found to match their previous old value,
419
-                // then WP bails before performing any update.
420
-                // Since we are passing the EE_Config object, it is comparing the EXACT instance of the saved version
421
-                // it just pulled from the db, with the one being passed to it (which will not match).
422
-                // HOWEVER, once the object is serialized and passed off to MySQL to update,
423
-                // MySQL MAY ALSO NOT perform the update because
424
-                // the string it sees in the db looks the same as the new one it has been passed!!!
425
-                // This results in the query returning an "affected rows" value of ZERO,
426
-                // which gets returned immediately by WP update_option and looks like an error.
427
-                remove_action('update_option', array($this, 'check_config_updated'));
428
-            }
429
-        }
430
-    }
431
-
432
-
433
-    /**
434
-     *    update_espresso_config
435
-     *
436
-     * @access   public
437
-     */
438
-    protected function _reset_espresso_addon_config()
439
-    {
440
-        $this->_addon_option_names = array();
441
-        foreach ($this->addons as $addon_name => $addon_config_obj) {
442
-            $addon_config_obj = maybe_unserialize($addon_config_obj);
443
-            if ($addon_config_obj instanceof EE_Config_Base) {
444
-                $this->update_config('addons', $addon_name, $addon_config_obj, false);
445
-            }
446
-            $this->addons->{$addon_name} = null;
447
-        }
448
-    }
449
-
450
-
451
-    /**
452
-     *    update_espresso_config
453
-     *
454
-     * @access   public
455
-     * @param   bool $add_success
456
-     * @param   bool $add_error
457
-     * @return   bool
458
-     */
459
-    public function update_espresso_config($add_success = false, $add_error = true)
460
-    {
461
-        // don't allow config updates during WP heartbeats
462
-        /** @var RequestInterface $request */
463
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
464
-        if ($request->isWordPressHeartbeat()) {
465
-            return false;
466
-        }
467
-        // commented out the following re: https://events.codebasehq.com/projects/event-espresso/tickets/8197
468
-        // $clone = clone( self::$_instance );
469
-        // self::$_instance = NULL;
470
-        do_action('AHEE__EE_Config__update_espresso_config__begin', $this);
471
-        $this->_reset_espresso_addon_config();
472
-        // hook into update_option because that happens AFTER the ( $value === $old_value ) conditional
473
-        // but BEFORE the actual update occurs
474
-        add_action('update_option', array($this, 'double_check_config_comparison'), 1, 3);
475
-        // don't want to persist legacy_shortcodes_manager, but don't want to lose it either
476
-        $legacy_shortcodes_manager = $this->legacy_shortcodes_manager;
477
-        $this->legacy_shortcodes_manager = null;
478
-        // now update "ee_config"
479
-        $saved = update_option(EE_Config::OPTION_NAME, $this);
480
-        $this->legacy_shortcodes_manager = $legacy_shortcodes_manager;
481
-        EE_Config::log(EE_Config::OPTION_NAME);
482
-        // if not saved... check if the hook we just added still exists;
483
-        // if it does, it means one of two things:
484
-        // that update_option bailed at the($value === $old_value) conditional,
485
-        // or...
486
-        // the db update query returned 0 rows affected
487
-        // (probably because the data  value was the same from it's perspective)
488
-        // so the existence of the hook means that a negative result from update_option is NOT an error,
489
-        // but just means no update occurred, so don't display an error to the user.
490
-        // BUT... if update_option returns FALSE, AND the hook is missing,
491
-        // then it means that something truly went wrong
492
-        $saved = ! $saved ? has_action('update_option', array($this, 'double_check_config_comparison')) : $saved;
493
-        // remove our action since we don't want it in the system anymore
494
-        remove_action('update_option', array($this, 'double_check_config_comparison'), 1);
495
-        do_action('AHEE__EE_Config__update_espresso_config__end', $this, $saved);
496
-        // self::$_instance = $clone;
497
-        // unset( $clone );
498
-        // if config remains the same or was updated successfully
499
-        if ($saved) {
500
-            if ($add_success) {
501
-                EE_Error::add_success(
502
-                    esc_html__('The Event Espresso Configuration Settings have been successfully updated.', 'event_espresso'),
503
-                    __FILE__,
504
-                    __FUNCTION__,
505
-                    __LINE__
506
-                );
507
-            }
508
-            return true;
509
-        } else {
510
-            if ($add_error) {
511
-                EE_Error::add_error(
512
-                    esc_html__('The Event Espresso Configuration Settings were not updated.', 'event_espresso'),
513
-                    __FILE__,
514
-                    __FUNCTION__,
515
-                    __LINE__
516
-                );
517
-            }
518
-            return false;
519
-        }
520
-    }
521
-
522
-
523
-    /**
524
-     *    _verify_config_params
525
-     *
526
-     * @access    private
527
-     * @param    string         $section
528
-     * @param    string         $name
529
-     * @param    string         $config_class
530
-     * @param    EE_Config_Base $config_obj
531
-     * @param    array          $tests_to_run
532
-     * @param    bool           $display_errors
533
-     * @return    bool    TRUE on success, FALSE on fail
534
-     */
535
-    private function _verify_config_params(
536
-        $section = '',
537
-        $name = '',
538
-        $config_class = '',
539
-        $config_obj = null,
540
-        $tests_to_run = array(1, 2, 3, 4, 5, 6, 7, 8),
541
-        $display_errors = true
542
-    ) {
543
-        try {
544
-            foreach ($tests_to_run as $test) {
545
-                switch ($test) {
546
-                    // TEST #1 : check that section was set
547
-                    case 1:
548
-                        if (empty($section)) {
549
-                            if ($display_errors) {
550
-                                throw new EE_Error(
551
-                                    sprintf(
552
-                                        esc_html__(
553
-                                            'No configuration section has been provided while attempting to save "%s".',
554
-                                            'event_espresso'
555
-                                        ),
556
-                                        $config_class
557
-                                    )
558
-                                );
559
-                            }
560
-                            return false;
561
-                        }
562
-                        break;
563
-                    // TEST #2 : check that settings section exists
564
-                    case 2:
565
-                        if (! isset($this->{$section})) {
566
-                            if ($display_errors) {
567
-                                throw new EE_Error(
568
-                                    sprintf(
569
-                                        esc_html__('The "%s" configuration section does not exist.', 'event_espresso'),
570
-                                        $section
571
-                                    )
572
-                                );
573
-                            }
574
-                            return false;
575
-                        }
576
-                        break;
577
-                    // TEST #3 : check that section is the proper format
578
-                    case 3:
579
-                        if (
580
-                            ! ($this->{$section} instanceof EE_Config_Base || $this->{$section} instanceof stdClass)
581
-                        ) {
582
-                            if ($display_errors) {
583
-                                throw new EE_Error(
584
-                                    sprintf(
585
-                                        esc_html__(
586
-                                            'The "%s" configuration settings have not been formatted correctly.',
587
-                                            'event_espresso'
588
-                                        ),
589
-                                        $section
590
-                                    )
591
-                                );
592
-                            }
593
-                            return false;
594
-                        }
595
-                        break;
596
-                    // TEST #4 : check that config section name has been set
597
-                    case 4:
598
-                        if (empty($name)) {
599
-                            if ($display_errors) {
600
-                                throw new EE_Error(
601
-                                    esc_html__(
602
-                                        'No name has been provided for the specific configuration section.',
603
-                                        'event_espresso'
604
-                                    )
605
-                                );
606
-                            }
607
-                            return false;
608
-                        }
609
-                        break;
610
-                    // TEST #5 : check that a config class name has been set
611
-                    case 5:
612
-                        if (empty($config_class)) {
613
-                            if ($display_errors) {
614
-                                throw new EE_Error(
615
-                                    esc_html__(
616
-                                        'No class name has been provided for the specific configuration section.',
617
-                                        'event_espresso'
618
-                                    )
619
-                                );
620
-                            }
621
-                            return false;
622
-                        }
623
-                        break;
624
-                    // TEST #6 : verify config class is accessible
625
-                    case 6:
626
-                        if (! class_exists($config_class)) {
627
-                            if ($display_errors) {
628
-                                throw new EE_Error(
629
-                                    sprintf(
630
-                                        esc_html__(
631
-                                            'The "%s" class does not exist. Please ensure that an autoloader has been set for it.',
632
-                                            'event_espresso'
633
-                                        ),
634
-                                        $config_class
635
-                                    )
636
-                                );
637
-                            }
638
-                            return false;
639
-                        }
640
-                        break;
641
-                    // TEST #7 : check that config has even been set
642
-                    case 7:
643
-                        if (! isset($this->{$section}->{$name})) {
644
-                            if ($display_errors) {
645
-                                throw new EE_Error(
646
-                                    sprintf(
647
-                                        esc_html__('No configuration has been set for "%1$s->%2$s".', 'event_espresso'),
648
-                                        $section,
649
-                                        $name
650
-                                    )
651
-                                );
652
-                            }
653
-                            return false;
654
-                        } else {
655
-                            // and make sure it's not serialized
656
-                            $this->{$section}->{$name} = maybe_unserialize($this->{$section}->{$name});
657
-                        }
658
-                        break;
659
-                    // TEST #8 : check that config is the requested type
660
-                    case 8:
661
-                        if (! $this->{$section}->{$name} instanceof $config_class) {
662
-                            if ($display_errors) {
663
-                                throw new EE_Error(
664
-                                    sprintf(
665
-                                        esc_html__(
666
-                                            'The configuration for "%1$s->%2$s" is not of the "%3$s" class.',
667
-                                            'event_espresso'
668
-                                        ),
669
-                                        $section,
670
-                                        $name,
671
-                                        $config_class
672
-                                    )
673
-                                );
674
-                            }
675
-                            return false;
676
-                        }
677
-                        break;
678
-                    // TEST #9 : verify config object
679
-                    case 9:
680
-                        if (! $config_obj instanceof EE_Config_Base) {
681
-                            if ($display_errors) {
682
-                                throw new EE_Error(
683
-                                    sprintf(
684
-                                        esc_html__('The "%s" class is not an instance of EE_Config_Base.', 'event_espresso'),
685
-                                        print_r($config_obj, true)
686
-                                    )
687
-                                );
688
-                            }
689
-                            return false;
690
-                        }
691
-                        break;
692
-                }
693
-            }
694
-        } catch (EE_Error $e) {
695
-            $e->get_error();
696
-        }
697
-        // you have successfully run the gauntlet
698
-        return true;
699
-    }
700
-
701
-
702
-    /**
703
-     *    _generate_config_option_name
704
-     *
705
-     * @access        protected
706
-     * @param        string $section
707
-     * @param        string $name
708
-     * @return        string
709
-     */
710
-    private function _generate_config_option_name($section = '', $name = '')
711
-    {
712
-        return 'ee_config-' . strtolower($section . '-' . str_replace(array('EE_', 'EED_'), '', $name));
713
-    }
714
-
715
-
716
-    /**
717
-     *    _set_config_class
718
-     * ensures that a config class is set, either from a passed config class or one generated from the config name
719
-     *
720
-     * @access    private
721
-     * @param    string $config_class
722
-     * @param    string $name
723
-     * @return    string
724
-     */
725
-    private function _set_config_class($config_class = '', $name = '')
726
-    {
727
-        return ! empty($config_class)
728
-            ? $config_class
729
-            : str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))) . '_Config';
730
-    }
731
-
732
-
733
-    /**
734
-     *    set_config
735
-     *
736
-     * @access    protected
737
-     * @param    string         $section
738
-     * @param    string         $name
739
-     * @param    string         $config_class
740
-     * @param    EE_Config_Base $config_obj
741
-     * @return    EE_Config_Base
742
-     */
743
-    public function set_config($section = '', $name = '', $config_class = '', EE_Config_Base $config_obj = null)
744
-    {
745
-        // ensure config class is set to something
746
-        $config_class = $this->_set_config_class($config_class, $name);
747
-        // run tests 1-4, 6, and 7 to verify all config params are set and valid
748
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
749
-            return null;
750
-        }
751
-        $config_option_name = $this->_generate_config_option_name($section, $name);
752
-        // if the config option name hasn't been added yet to the list of option names we're tracking, then do so now
753
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
754
-            $this->_addon_option_names[ $config_option_name ] = $config_class;
755
-            $this->update_addon_option_names();
756
-        }
757
-        // verify the incoming config object but suppress errors
758
-        if (! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
759
-            $config_obj = new $config_class();
760
-        }
761
-        if (get_option($config_option_name)) {
762
-            EE_Config::log($config_option_name);
763
-            update_option($config_option_name, $config_obj);
764
-            $this->{$section}->{$name} = $config_obj;
765
-            return $this->{$section}->{$name};
766
-        } else {
767
-            // create a wp-option for this config
768
-            if (add_option($config_option_name, $config_obj, '', 'no')) {
769
-                $this->{$section}->{$name} = maybe_unserialize($config_obj);
770
-                return $this->{$section}->{$name};
771
-            } else {
772
-                EE_Error::add_error(
773
-                    sprintf(esc_html__('The "%s" could not be saved to the database.', 'event_espresso'), $config_class),
774
-                    __FILE__,
775
-                    __FUNCTION__,
776
-                    __LINE__
777
-                );
778
-                return null;
779
-            }
780
-        }
781
-    }
782
-
783
-
784
-    /**
785
-     *    update_config
786
-     * Important: the config object must ALREADY be set, otherwise this will produce an error.
787
-     *
788
-     * @access    public
789
-     * @param    string                $section
790
-     * @param    string                $name
791
-     * @param    EE_Config_Base|string $config_obj
792
-     * @param    bool                  $throw_errors
793
-     * @return    bool
794
-     */
795
-    public function update_config($section = '', $name = '', $config_obj = '', $throw_errors = true)
796
-    {
797
-        // don't allow config updates during WP heartbeats
798
-        /** @var RequestInterface $request */
799
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
800
-        if ($request->isWordPressHeartbeat()) {
801
-            return false;
802
-        }
803
-        $config_obj = maybe_unserialize($config_obj);
804
-        // get class name of the incoming object
805
-        $config_class = get_class($config_obj);
806
-        // run tests 1-5 and 9 to verify config
807
-        if (
808
-            ! $this->_verify_config_params(
809
-                $section,
810
-                $name,
811
-                $config_class,
812
-                $config_obj,
813
-                array(1, 2, 3, 4, 7, 9)
814
-            )
815
-        ) {
816
-            return false;
817
-        }
818
-        $config_option_name = $this->_generate_config_option_name($section, $name);
819
-        // check if config object has been added to db by seeing if config option name is in $this->_addon_option_names array
820
-        if (! isset($this->_addon_option_names[ $config_option_name ])) {
821
-            // save new config to db
822
-            if ($this->set_config($section, $name, $config_class, $config_obj)) {
823
-                return true;
824
-            }
825
-        } else {
826
-            // first check if the record already exists
827
-            $existing_config = get_option($config_option_name);
828
-            $config_obj = serialize($config_obj);
829
-            // just return if db record is already up to date (NOT type safe comparison)
830
-            if ($existing_config == $config_obj) {
831
-                $this->{$section}->{$name} = $config_obj;
832
-                return true;
833
-            } elseif (update_option($config_option_name, $config_obj)) {
834
-                EE_Config::log($config_option_name);
835
-                // update wp-option for this config class
836
-                $this->{$section}->{$name} = $config_obj;
837
-                return true;
838
-            } elseif ($throw_errors) {
839
-                EE_Error::add_error(
840
-                    sprintf(
841
-                        esc_html__(
842
-                            'The "%1$s" object stored at"%2$s" was not successfully updated in the database.',
843
-                            'event_espresso'
844
-                        ),
845
-                        $config_class,
846
-                        'EE_Config->' . $section . '->' . $name
847
-                    ),
848
-                    __FILE__,
849
-                    __FUNCTION__,
850
-                    __LINE__
851
-                );
852
-            }
853
-        }
854
-        return false;
855
-    }
856
-
857
-
858
-    /**
859
-     *    get_config
860
-     *
861
-     * @access    public
862
-     * @param    string $section
863
-     * @param    string $name
864
-     * @param    string $config_class
865
-     * @return    mixed EE_Config_Base | NULL
866
-     */
867
-    public function get_config($section = '', $name = '', $config_class = '')
868
-    {
869
-        // ensure config class is set to something
870
-        $config_class = $this->_set_config_class($config_class, $name);
871
-        // run tests 1-4, 6 and 7 to verify that all params have been set
872
-        if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
873
-            return null;
874
-        }
875
-        // now test if the requested config object exists, but suppress errors
876
-        if ($this->_verify_config_params($section, $name, $config_class, null, array(7, 8), false)) {
877
-            // config already exists, so pass it back
878
-            return $this->{$section}->{$name};
879
-        }
880
-        // load config option from db if it exists
881
-        $config_obj = $this->get_config_option($this->_generate_config_option_name($section, $name));
882
-        // verify the newly retrieved config object, but suppress errors
883
-        if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
884
-            // config is good, so set it and pass it back
885
-            $this->{$section}->{$name} = $config_obj;
886
-            return $this->{$section}->{$name};
887
-        }
888
-        // oops! $config_obj is not already set and does not exist in the db, so create a new one
889
-        $config_obj = $this->set_config($section, $name, $config_class);
890
-        // verify the newly created config object
891
-        if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9))) {
892
-            return $this->{$section}->{$name};
893
-        } else {
894
-            EE_Error::add_error(
895
-                sprintf(esc_html__('The "%s" could not be retrieved from the database.', 'event_espresso'), $config_class),
896
-                __FILE__,
897
-                __FUNCTION__,
898
-                __LINE__
899
-            );
900
-        }
901
-        return null;
902
-    }
903
-
904
-
905
-    /**
906
-     *    get_config_option
907
-     *
908
-     * @access    public
909
-     * @param    string $config_option_name
910
-     * @return    mixed EE_Config_Base | FALSE
911
-     */
912
-    public function get_config_option($config_option_name = '')
913
-    {
914
-        // retrieve the wp-option for this config class.
915
-        $config_option = maybe_unserialize(get_option($config_option_name, array()));
916
-        if (empty($config_option)) {
917
-            EE_Config::log($config_option_name . '-NOT-FOUND');
918
-        }
919
-        return $config_option;
920
-    }
921
-
922
-
923
-    /**
924
-     * log
925
-     *
926
-     * @param string $config_option_name
927
-     */
928
-    public static function log($config_option_name = '')
929
-    {
930
-        if (EE_Config::logging_enabled() && ! empty($config_option_name)) {
931
-            $config_log = get_option(EE_Config::LOG_NAME, array());
932
-            /** @var RequestParams $request */
933
-            $request = LoaderFactory::getLoader()->getShared(RequestParams::class);
934
-            $config_log[ (string) microtime(true) ] = array(
935
-                'config_name' => $config_option_name,
936
-                'request'     => $request->requestParams(),
937
-            );
938
-            update_option(EE_Config::LOG_NAME, $config_log);
939
-        }
940
-    }
941
-
942
-
943
-    /**
944
-     * trim_log
945
-     * reduces the size of the config log to the length specified by EE_Config::LOG_LENGTH
946
-     */
947
-    public static function trim_log()
948
-    {
949
-        if (! EE_Config::logging_enabled()) {
950
-            return;
951
-        }
952
-        $config_log = maybe_unserialize(get_option(EE_Config::LOG_NAME, array()));
953
-        $log_length = count($config_log);
954
-        if ($log_length > EE_Config::LOG_LENGTH) {
955
-            ksort($config_log);
956
-            $config_log = array_slice($config_log, $log_length - EE_Config::LOG_LENGTH, null, true);
957
-            update_option(EE_Config::LOG_NAME, $config_log);
958
-        }
959
-    }
960
-
961
-
962
-    /**
963
-     *    get_page_for_posts
964
-     *    if the wp-option "show_on_front" is set to "page", then this is the post_name for the post set in the
965
-     *    wp-option "page_for_posts", or "posts" if no page is selected
966
-     *
967
-     * @access    public
968
-     * @return    string
969
-     */
970
-    public static function get_page_for_posts()
971
-    {
972
-        $page_for_posts = get_option('page_for_posts');
973
-        if (! $page_for_posts) {
974
-            return 'posts';
975
-        }
976
-        global $wpdb;
977
-        $SQL = "SELECT post_name from $wpdb->posts WHERE post_type='posts' OR post_type='page' AND post_status='publish' AND ID=%d";
978
-        return $wpdb->get_var($wpdb->prepare($SQL, $page_for_posts));
979
-    }
980
-
981
-
982
-    /**
983
-     *    register_shortcodes_and_modules.
984
-     *    At this point, it's too early to tell if we're maintenance mode or not.
985
-     *    In fact, this is where we give modules a chance to let core know they exist
986
-     *    so they can help trigger maintenance mode if it's needed
987
-     *
988
-     * @access    public
989
-     * @return    void
990
-     */
991
-    public function register_shortcodes_and_modules()
992
-    {
993
-        // allow modules to set hooks for the rest of the system
994
-        EE_Registry::instance()->modules = $this->_register_modules();
995
-    }
996
-
997
-
998
-    /**
999
-     *    initialize_shortcodes_and_modules
1000
-     *    meaning they can start adding their hooks to get stuff done
1001
-     *
1002
-     * @access    public
1003
-     * @return    void
1004
-     */
1005
-    public function initialize_shortcodes_and_modules()
1006
-    {
1007
-        // allow modules to set hooks for the rest of the system
1008
-        $this->_initialize_modules();
1009
-    }
1010
-
1011
-
1012
-    /**
1013
-     *    widgets_init
1014
-     *
1015
-     * @access private
1016
-     * @return void
1017
-     */
1018
-    public function widgets_init()
1019
-    {
1020
-        // only init widgets on admin pages when not in complete maintenance, and
1021
-        // on frontend when not in any maintenance mode
1022
-        if (
1023
-            ! EE_Maintenance_Mode::instance()->level()
1024
-            || (
1025
-                is_admin()
1026
-                && EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance
1027
-            )
1028
-        ) {
1029
-            // grab list of installed widgets
1030
-            $widgets_to_register = glob(EE_WIDGETS . '*', GLOB_ONLYDIR);
1031
-            // filter list of modules to register
1032
-            $widgets_to_register = apply_filters(
1033
-                'FHEE__EE_Config__register_widgets__widgets_to_register',
1034
-                $widgets_to_register
1035
-            );
1036
-            if (! empty($widgets_to_register)) {
1037
-                // cycle thru widget folders
1038
-                foreach ($widgets_to_register as $widget_path) {
1039
-                    // add to list of installed widget modules
1040
-                    EE_Config::register_ee_widget($widget_path);
1041
-                }
1042
-            }
1043
-            // filter list of installed modules
1044
-            EE_Registry::instance()->widgets = apply_filters(
1045
-                'FHEE__EE_Config__register_widgets__installed_widgets',
1046
-                EE_Registry::instance()->widgets
1047
-            );
1048
-        }
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     *    register_ee_widget - makes core aware of this widget
1054
-     *
1055
-     * @access    public
1056
-     * @param    string $widget_path - full path up to and including widget folder
1057
-     * @return    void
1058
-     */
1059
-    public static function register_ee_widget($widget_path = null)
1060
-    {
1061
-        do_action('AHEE__EE_Config__register_widget__begin', $widget_path);
1062
-        $widget_ext = '.widget.php';
1063
-        // make all separators match
1064
-        $widget_path = rtrim(str_replace('\\', DS, $widget_path), DS);
1065
-        // does the file path INCLUDE the actual file name as part of the path ?
1066
-        if (strpos($widget_path, $widget_ext) !== false) {
1067
-            // grab and shortcode file name from directory name and break apart at dots
1068
-            $file_name = explode('.', basename($widget_path));
1069
-            // take first segment from file name pieces and remove class prefix if it exists
1070
-            $widget = strpos($file_name[0], 'EEW_') === 0 ? substr($file_name[0], 4) : $file_name[0];
1071
-            // sanitize shortcode directory name
1072
-            $widget = sanitize_key($widget);
1073
-            // now we need to rebuild the shortcode path
1074
-            $widget_path = explode('/', $widget_path);
1075
-            // remove last segment
1076
-            array_pop($widget_path);
1077
-            // glue it back together
1078
-            $widget_path = implode(DS, $widget_path);
1079
-        } else {
1080
-            // grab and sanitize widget directory name
1081
-            $widget = sanitize_key(basename($widget_path));
1082
-        }
1083
-        // create classname from widget directory name
1084
-        $widget = str_replace(' ', '_', ucwords(str_replace('_', ' ', $widget)));
1085
-        // add class prefix
1086
-        $widget_class = 'EEW_' . $widget;
1087
-        // does the widget exist ?
1088
-        if (! is_readable($widget_path . '/' . $widget_class . $widget_ext)) {
1089
-            $msg = sprintf(
1090
-                esc_html__(
1091
-                    'The requested %s widget file could not be found or is not readable due to file permissions. Please ensure the following path is correct: %s',
1092
-                    'event_espresso'
1093
-                ),
1094
-                $widget_class,
1095
-                $widget_path . '/' . $widget_class . $widget_ext
1096
-            );
1097
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1098
-            return;
1099
-        }
1100
-        // load the widget class file
1101
-        require_once($widget_path . '/' . $widget_class . $widget_ext);
1102
-        // verify that class exists
1103
-        if (! class_exists($widget_class)) {
1104
-            $msg = sprintf(esc_html__('The requested %s widget class does not exist.', 'event_espresso'), $widget_class);
1105
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1106
-            return;
1107
-        }
1108
-        register_widget($widget_class);
1109
-        // add to array of registered widgets
1110
-        EE_Registry::instance()->widgets->{$widget_class} = $widget_path . '/' . $widget_class . $widget_ext;
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     *        _register_modules
1116
-     *
1117
-     * @access private
1118
-     * @return array
1119
-     */
1120
-    private function _register_modules()
1121
-    {
1122
-        // grab list of installed modules
1123
-        $modules_to_register = glob(EE_MODULES . '*', GLOB_ONLYDIR);
1124
-        // filter list of modules to register
1125
-        $modules_to_register = apply_filters(
1126
-            'FHEE__EE_Config__register_modules__modules_to_register',
1127
-            $modules_to_register
1128
-        );
1129
-        if (! empty($modules_to_register)) {
1130
-            // loop through folders
1131
-            foreach ($modules_to_register as $module_path) {
1132
-                /**TEMPORARILY EXCLUDE gateways from modules for time being**/
1133
-                if (
1134
-                    $module_path !== EE_MODULES . 'zzz-copy-this-module-template'
1135
-                    && $module_path !== EE_MODULES . 'gateways'
1136
-                ) {
1137
-                    // add to list of installed modules
1138
-                    EE_Config::register_module($module_path);
1139
-                }
1140
-            }
1141
-        }
1142
-        // filter list of installed modules
1143
-        return apply_filters(
1144
-            'FHEE__EE_Config___register_modules__installed_modules',
1145
-            EE_Registry::instance()->modules
1146
-        );
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     *    register_module - makes core aware of this module
1152
-     *
1153
-     * @access    public
1154
-     * @param    string $module_path - full path up to and including module folder
1155
-     * @return    bool
1156
-     */
1157
-    public static function register_module($module_path = null)
1158
-    {
1159
-        do_action('AHEE__EE_Config__register_module__begin', $module_path);
1160
-        $module_ext = '.module.php';
1161
-        // make all separators match
1162
-        $module_path = str_replace(array('\\', '/'), '/', $module_path);
1163
-        // does the file path INCLUDE the actual file name as part of the path ?
1164
-        if (strpos($module_path, $module_ext) !== false) {
1165
-            // grab and shortcode file name from directory name and break apart at dots
1166
-            $module_file = explode('.', basename($module_path));
1167
-            // now we need to rebuild the shortcode path
1168
-            $module_path = explode('/', $module_path);
1169
-            // remove last segment
1170
-            array_pop($module_path);
1171
-            // glue it back together
1172
-            $module_path = implode('/', $module_path) . '/';
1173
-            // take first segment from file name pieces and sanitize it
1174
-            $module = preg_replace('/[^a-zA-Z0-9_\-]/', '', $module_file[0]);
1175
-            // ensure class prefix is added
1176
-            $module_class = strpos($module, 'EED_') !== 0 ? 'EED_' . $module : $module;
1177
-        } else {
1178
-            // we need to generate the filename based off of the folder name
1179
-            // grab and sanitize module name
1180
-            $module = strtolower(basename($module_path));
1181
-            $module = preg_replace('/[^a-z0-9_\-]/', '', $module);
1182
-            // like trailingslashit()
1183
-            $module_path = rtrim($module_path, '/') . '/';
1184
-            // create classname from module directory name
1185
-            $module = str_replace(' ', '_', ucwords(str_replace('_', ' ', $module)));
1186
-            // add class prefix
1187
-            $module_class = 'EED_' . $module;
1188
-        }
1189
-        // does the module exist ?
1190
-        if (! is_readable($module_path . '/' . $module_class . $module_ext)) {
1191
-            $msg = sprintf(
1192
-                esc_html__(
1193
-                    'The requested %s module file could not be found or is not readable due to file permissions.',
1194
-                    'event_espresso'
1195
-                ),
1196
-                $module
1197
-            );
1198
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1199
-            return false;
1200
-        }
1201
-        // load the module class file
1202
-        require_once($module_path . $module_class . $module_ext);
1203
-        // verify that class exists
1204
-        if (! class_exists($module_class)) {
1205
-            $msg = sprintf(esc_html__('The requested %s module class does not exist.', 'event_espresso'), $module_class);
1206
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1207
-            return false;
1208
-        }
1209
-        // add to array of registered modules
1210
-        EE_Registry::instance()->modules->{$module_class} = $module_path . $module_class . $module_ext;
1211
-        do_action(
1212
-            'AHEE__EE_Config__register_module__complete',
1213
-            $module_class,
1214
-            EE_Registry::instance()->modules->{$module_class}
1215
-        );
1216
-        return true;
1217
-    }
1218
-
1219
-
1220
-    /**
1221
-     *    _initialize_modules
1222
-     *    allow modules to set hooks for the rest of the system
1223
-     *
1224
-     * @access private
1225
-     * @return void
1226
-     */
1227
-    private function _initialize_modules()
1228
-    {
1229
-        // cycle thru shortcode folders
1230
-        foreach (EE_Registry::instance()->modules as $module_class => $module_path) {
1231
-            // fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
1232
-            // which set hooks ?
1233
-            if (is_admin()) {
1234
-                // fire immediately
1235
-                call_user_func(array($module_class, 'set_hooks_admin'));
1236
-            } else {
1237
-                // delay until other systems are online
1238
-                add_action(
1239
-                    'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
1240
-                    array($module_class, 'set_hooks')
1241
-                );
1242
-            }
1243
-        }
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     *    register_route - adds module method routes to route_map
1249
-     *
1250
-     * @access    public
1251
-     * @param    string $route       - "pretty" public alias for module method
1252
-     * @param    string $module      - module name (classname without EED_ prefix)
1253
-     * @param    string $method_name - the actual module method to be routed to
1254
-     * @param    string $key         - url param key indicating a route is being called
1255
-     * @return    bool
1256
-     */
1257
-    public static function register_route($route = null, $module = null, $method_name = null, $key = 'ee')
1258
-    {
1259
-        do_action('AHEE__EE_Config__register_route__begin', $route, $module, $method_name);
1260
-        $module = str_replace('EED_', '', $module);
1261
-        $module_class = 'EED_' . $module;
1262
-        if (! isset(EE_Registry::instance()->modules->{$module_class})) {
1263
-            $msg = sprintf(esc_html__('The module %s has not been registered.', 'event_espresso'), $module);
1264
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1265
-            return false;
1266
-        }
1267
-        if (empty($route)) {
1268
-            $msg = sprintf(esc_html__('No route has been supplied.', 'event_espresso'), $route);
1269
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1270
-            return false;
1271
-        }
1272
-        if (! method_exists('EED_' . $module, $method_name)) {
1273
-            $msg = sprintf(
1274
-                esc_html__('A valid class method for the %s route has not been supplied.', 'event_espresso'),
1275
-                $route
1276
-            );
1277
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1278
-            return false;
1279
-        }
1280
-        EE_Config::$_module_route_map[ (string) $key ][ (string) $route ] = array('EED_' . $module, $method_name);
1281
-        return true;
1282
-    }
1283
-
1284
-
1285
-    /**
1286
-     *    get_route - get module method route
1287
-     *
1288
-     * @access    public
1289
-     * @param    string $route - "pretty" public alias for module method
1290
-     * @param    string $key   - url param key indicating a route is being called
1291
-     * @return    string
1292
-     */
1293
-    public static function get_route($route = null, $key = 'ee')
1294
-    {
1295
-        do_action('AHEE__EE_Config__get_route__begin', $route);
1296
-        $route = (string) apply_filters('FHEE__EE_Config__get_route', $route);
1297
-        if (isset(EE_Config::$_module_route_map[ $key ][ $route ])) {
1298
-            return EE_Config::$_module_route_map[ $key ][ $route ];
1299
-        }
1300
-        return null;
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     *    get_routes - get ALL module method routes
1306
-     *
1307
-     * @access    public
1308
-     * @return    array
1309
-     */
1310
-    public static function get_routes()
1311
-    {
1312
-        return EE_Config::$_module_route_map;
1313
-    }
1314
-
1315
-
1316
-    /**
1317
-     *    register_forward - allows modules to forward request to another module for further processing
1318
-     *
1319
-     * @access    public
1320
-     * @param    string       $route   - "pretty" public alias for module method
1321
-     * @param    integer      $status  - integer value corresponding  to status constant strings set in module parent
1322
-     *                                 class, allows different forwards to be served based on status
1323
-     * @param    array|string $forward - function name or array( class, method )
1324
-     * @param    string       $key     - url param key indicating a route is being called
1325
-     * @return    bool
1326
-     */
1327
-    public static function register_forward($route = null, $status = 0, $forward = null, $key = 'ee')
1328
-    {
1329
-        do_action('AHEE__EE_Config__register_forward', $route, $status, $forward);
1330
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1331
-            $msg = sprintf(
1332
-                esc_html__('The module route %s for this forward has not been registered.', 'event_espresso'),
1333
-                $route
1334
-            );
1335
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1336
-            return false;
1337
-        }
1338
-        if (empty($forward)) {
1339
-            $msg = sprintf(esc_html__('No forwarding route has been supplied.', 'event_espresso'), $route);
1340
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1341
-            return false;
1342
-        }
1343
-        if (is_array($forward)) {
1344
-            if (! isset($forward[1])) {
1345
-                $msg = sprintf(
1346
-                    esc_html__('A class method for the %s forwarding route has not been supplied.', 'event_espresso'),
1347
-                    $route
1348
-                );
1349
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1350
-                return false;
1351
-            }
1352
-            if (! method_exists($forward[0], $forward[1])) {
1353
-                $msg = sprintf(
1354
-                    esc_html__('The class method %s for the %s forwarding route is in invalid.', 'event_espresso'),
1355
-                    $forward[1],
1356
-                    $route
1357
-                );
1358
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1359
-                return false;
1360
-            }
1361
-        } elseif (! function_exists($forward)) {
1362
-            $msg = sprintf(
1363
-                esc_html__('The function %s for the %s forwarding route is in invalid.', 'event_espresso'),
1364
-                $forward,
1365
-                $route
1366
-            );
1367
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1368
-            return false;
1369
-        }
1370
-        EE_Config::$_module_forward_map[ $key ][ $route ][ absint($status) ] = $forward;
1371
-        return true;
1372
-    }
1373
-
1374
-
1375
-    /**
1376
-     *    get_forward - get forwarding route
1377
-     *
1378
-     * @access    public
1379
-     * @param    string  $route  - "pretty" public alias for module method
1380
-     * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1381
-     *                           allows different forwards to be served based on status
1382
-     * @param    string  $key    - url param key indicating a route is being called
1383
-     * @return    string
1384
-     */
1385
-    public static function get_forward($route = null, $status = 0, $key = 'ee')
1386
-    {
1387
-        do_action('AHEE__EE_Config__get_forward__begin', $route, $status);
1388
-        if (isset(EE_Config::$_module_forward_map[ $key ][ $route ][ $status ])) {
1389
-            return apply_filters(
1390
-                'FHEE__EE_Config__get_forward',
1391
-                EE_Config::$_module_forward_map[ $key ][ $route ][ $status ],
1392
-                $route,
1393
-                $status
1394
-            );
1395
-        }
1396
-        return null;
1397
-    }
1398
-
1399
-
1400
-    /**
1401
-     *    register_forward - allows modules to specify different view templates for different method routes and status
1402
-     *    results
1403
-     *
1404
-     * @access    public
1405
-     * @param    string  $route  - "pretty" public alias for module method
1406
-     * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1407
-     *                           allows different views to be served based on status
1408
-     * @param    string  $view
1409
-     * @param    string  $key    - url param key indicating a route is being called
1410
-     * @return    bool
1411
-     */
1412
-    public static function register_view($route = null, $status = 0, $view = null, $key = 'ee')
1413
-    {
1414
-        do_action('AHEE__EE_Config__register_view__begin', $route, $status, $view);
1415
-        if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1416
-            $msg = sprintf(
1417
-                esc_html__('The module route %s for this view has not been registered.', 'event_espresso'),
1418
-                $route
1419
-            );
1420
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1421
-            return false;
1422
-        }
1423
-        if (! is_readable($view)) {
1424
-            $msg = sprintf(
1425
-                esc_html__(
1426
-                    'The %s view file could not be found or is not readable due to file permissions.',
1427
-                    'event_espresso'
1428
-                ),
1429
-                $view
1430
-            );
1431
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1432
-            return false;
1433
-        }
1434
-        EE_Config::$_module_view_map[ $key ][ $route ][ absint($status) ] = $view;
1435
-        return true;
1436
-    }
1437
-
1438
-
1439
-    /**
1440
-     *    get_view - get view for route and status
1441
-     *
1442
-     * @access    public
1443
-     * @param    string  $route  - "pretty" public alias for module method
1444
-     * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1445
-     *                           allows different views to be served based on status
1446
-     * @param    string  $key    - url param key indicating a route is being called
1447
-     * @return    string
1448
-     */
1449
-    public static function get_view($route = null, $status = 0, $key = 'ee')
1450
-    {
1451
-        do_action('AHEE__EE_Config__get_view__begin', $route, $status);
1452
-        if (isset(EE_Config::$_module_view_map[ $key ][ $route ][ $status ])) {
1453
-            return apply_filters(
1454
-                'FHEE__EE_Config__get_view',
1455
-                EE_Config::$_module_view_map[ $key ][ $route ][ $status ],
1456
-                $route,
1457
-                $status
1458
-            );
1459
-        }
1460
-        return null;
1461
-    }
1462
-
1463
-
1464
-    public function update_addon_option_names()
1465
-    {
1466
-        update_option(EE_Config::ADDON_OPTION_NAMES, $this->_addon_option_names);
1467
-    }
1468
-
1469
-
1470
-    public function shutdown()
1471
-    {
1472
-        $this->update_addon_option_names();
1473
-    }
1474
-
1475
-
1476
-    /**
1477
-     * @return LegacyShortcodesManager
1478
-     */
1479
-    public static function getLegacyShortcodesManager()
1480
-    {
1481
-        if (! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1482
-            EE_Config::instance()->legacy_shortcodes_manager = LoaderFactory::getLoader()->getShared(
1483
-                LegacyShortcodesManager::class
1484
-            );
1485
-        }
1486
-        return EE_Config::instance()->legacy_shortcodes_manager;
1487
-    }
1488
-
1489
-
1490
-    /**
1491
-     * register_shortcode - makes core aware of this shortcode
1492
-     *
1493
-     * @deprecated 4.9.26
1494
-     * @param    string $shortcode_path - full path up to and including shortcode folder
1495
-     * @return    bool
1496
-     */
1497
-    public static function register_shortcode($shortcode_path = null)
1498
-    {
1499
-        EE_Error::doing_it_wrong(
1500
-            __METHOD__,
1501
-            esc_html__(
1502
-                'Usage is deprecated. Use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::registerShortcode() as direct replacement, or better yet, please see the new \EventEspresso\core\services\shortcodes\ShortcodesManager class.',
1503
-                'event_espresso'
1504
-            ),
1505
-            '4.9.26'
1506
-        );
1507
-        return EE_Config::instance()->getLegacyShortcodesManager()->registerShortcode($shortcode_path);
1508
-    }
1509
-}
1510
-
1511
-/**
1512
- * Base class used for config classes. These classes should generally not have
1513
- * magic functions in use, except we'll allow them to magically set and get stuff...
1514
- * basically, they should just be well-defined stdClasses
1515
- */
1516
-class EE_Config_Base
1517
-{
1518
-    /**
1519
-     * Utility function for escaping the value of a property and returning.
1520
-     *
1521
-     * @param string $property property name (checks to see if exists).
1522
-     * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1523
-     * @throws EE_Error
1524
-     */
1525
-    public function get_pretty($property)
1526
-    {
1527
-        if (! property_exists($this, $property)) {
1528
-            throw new EE_Error(
1529
-                sprintf(
1530
-                    esc_html__(
1531
-                        '%1$s::get_pretty() has been called with the property %2$s which does not exist on the %1$s config class.',
1532
-                        'event_espresso'
1533
-                    ),
1534
-                    get_class($this),
1535
-                    $property
1536
-                )
1537
-            );
1538
-        }
1539
-        // just handling escaping of strings for now.
1540
-        if (is_string($this->{$property})) {
1541
-            return stripslashes($this->{$property});
1542
-        }
1543
-        return $this->{$property};
1544
-    }
1545
-
1546
-
1547
-    public function populate()
1548
-    {
1549
-        // grab defaults via a new instance of this class.
1550
-        $class_name = get_class($this);
1551
-        $defaults = new $class_name();
1552
-        // loop through the properties for this class and see if they are set.  If they are NOT, then grab the
1553
-        // default from our $defaults object.
1554
-        foreach (get_object_vars($defaults) as $property => $value) {
1555
-            if ($this->{$property} === null) {
1556
-                $this->{$property} = $value;
1557
-            }
1558
-        }
1559
-        // cleanup
1560
-        unset($defaults);
1561
-    }
1562
-
1563
-
1564
-    /**
1565
-     *        __isset
1566
-     *
1567
-     * @param $a
1568
-     * @return bool
1569
-     */
1570
-    public function __isset($a)
1571
-    {
1572
-        return false;
1573
-    }
1574
-
1575
-
1576
-    /**
1577
-     *        __unset
1578
-     *
1579
-     * @param $a
1580
-     * @return bool
1581
-     */
1582
-    public function __unset($a)
1583
-    {
1584
-        return false;
1585
-    }
1586
-
1587
-
1588
-    /**
1589
-     *        __clone
1590
-     */
1591
-    public function __clone()
1592
-    {
1593
-    }
1594
-
1595
-
1596
-    /**
1597
-     *        __wakeup
1598
-     */
1599
-    public function __wakeup()
1600
-    {
1601
-    }
1602
-
1603
-
1604
-    /**
1605
-     *        __destruct
1606
-     */
1607
-    public function __destruct()
1608
-    {
1609
-    }
1610
-}
1611
-
1612
-/**
1613
- * Class for defining what's in the EE_Config relating to registration settings
1614
- */
1615
-class EE_Core_Config extends EE_Config_Base
1616
-{
1617
-    const OPTION_NAME_UXIP = 'ee_ueip_optin';
1618
-
1619
-
1620
-    public $current_blog_id;
1621
-
1622
-    public $ee_ueip_optin;
1623
-
1624
-    public $ee_ueip_has_notified;
1625
-
1626
-    /**
1627
-     * Not to be confused with the 4 critical page variables (See
1628
-     * get_critical_pages_array()), this is just an array of wp posts that have EE
1629
-     * shortcodes in them. Keys are slugs, values are arrays with only 1 element: where the key is the shortcode
1630
-     * in the page, and the value is the page's ID. The key 'posts' is basically a duplicate of this same array.
1631
-     *
1632
-     * @var array
1633
-     */
1634
-    public $post_shortcodes;
1635
-
1636
-    public $module_route_map;
1637
-
1638
-    public $module_forward_map;
1639
-
1640
-    public $module_view_map;
1641
-
1642
-    /**
1643
-     * The next 4 vars are the IDs of critical EE pages.
1644
-     *
1645
-     * @var int
1646
-     */
1647
-    public $reg_page_id;
1648
-
1649
-    public $txn_page_id;
1650
-
1651
-    public $thank_you_page_id;
1652
-
1653
-    public $cancel_page_id;
1654
-
1655
-    /**
1656
-     * The next 4 vars are the URLs of critical EE pages.
1657
-     *
1658
-     * @var int
1659
-     */
1660
-    public $reg_page_url;
1661
-
1662
-    public $txn_page_url;
1663
-
1664
-    public $thank_you_page_url;
1665
-
1666
-    public $cancel_page_url;
1667
-
1668
-    /**
1669
-     * The next vars relate to the custom slugs for EE CPT routes
1670
-     */
1671
-    public $event_cpt_slug;
1672
-
1673
-    /**
1674
-     * This caches the _ee_ueip_option in case this config is reset in the same
1675
-     * request across blog switches in a multisite context.
1676
-     * Avoids extra queries to the db for this option.
1677
-     *
1678
-     * @var bool
1679
-     */
1680
-    public static $ee_ueip_option;
1681
-
1682
-
1683
-    /**
1684
-     *    class constructor
1685
-     *
1686
-     * @access    public
1687
-     */
1688
-    public function __construct()
1689
-    {
1690
-        // set default organization settings
1691
-        $this->current_blog_id = get_current_blog_id();
1692
-        $this->current_blog_id = $this->current_blog_id === null ? 1 : $this->current_blog_id;
1693
-        $this->ee_ueip_optin = $this->_get_main_ee_ueip_optin();
1694
-        $this->ee_ueip_has_notified = is_main_site() ? get_option('ee_ueip_has_notified', false) : true;
1695
-        $this->post_shortcodes = array();
1696
-        $this->module_route_map = array();
1697
-        $this->module_forward_map = array();
1698
-        $this->module_view_map = array();
1699
-        // critical EE page IDs
1700
-        $this->reg_page_id = 0;
1701
-        $this->txn_page_id = 0;
1702
-        $this->thank_you_page_id = 0;
1703
-        $this->cancel_page_id = 0;
1704
-        // critical EE page URLs
1705
-        $this->reg_page_url = '';
1706
-        $this->txn_page_url = '';
1707
-        $this->thank_you_page_url = '';
1708
-        $this->cancel_page_url = '';
1709
-        // cpt slugs
1710
-        $this->event_cpt_slug = esc_html__('events', 'event_espresso');
1711
-        // ueip constant check
1712
-        if (defined('EE_DISABLE_UXIP') && EE_DISABLE_UXIP) {
1713
-            $this->ee_ueip_optin = false;
1714
-            $this->ee_ueip_has_notified = true;
1715
-        }
1716
-    }
1717
-
1718
-
1719
-    /**
1720
-     * @return array
1721
-     */
1722
-    public function get_critical_pages_array()
1723
-    {
1724
-        return array(
1725
-            $this->reg_page_id,
1726
-            $this->txn_page_id,
1727
-            $this->thank_you_page_id,
1728
-            $this->cancel_page_id,
1729
-        );
1730
-    }
1731
-
1732
-
1733
-    /**
1734
-     * @return array
1735
-     */
1736
-    public function get_critical_pages_shortcodes_array()
1737
-    {
1738
-        return array(
1739
-            $this->reg_page_id       => 'ESPRESSO_CHECKOUT',
1740
-            $this->txn_page_id       => 'ESPRESSO_TXN_PAGE',
1741
-            $this->thank_you_page_id => 'ESPRESSO_THANK_YOU',
1742
-            $this->cancel_page_id    => 'ESPRESSO_CANCELLED',
1743
-        );
1744
-    }
1745
-
1746
-
1747
-    /**
1748
-     *  gets/returns URL for EE reg_page
1749
-     *
1750
-     * @access    public
1751
-     * @return    string
1752
-     */
1753
-    public function reg_page_url()
1754
-    {
1755
-        if (! $this->reg_page_url) {
1756
-            $this->reg_page_url = add_query_arg(
1757
-                array('uts' => time()),
1758
-                get_permalink($this->reg_page_id)
1759
-            ) . '#checkout';
1760
-        }
1761
-        return $this->reg_page_url;
1762
-    }
1763
-
1764
-
1765
-    /**
1766
-     *  gets/returns URL for EE txn_page
1767
-     *
1768
-     * @param array $query_args like what gets passed to
1769
-     *                          add_query_arg() as the first argument
1770
-     * @access    public
1771
-     * @return    string
1772
-     */
1773
-    public function txn_page_url($query_args = array())
1774
-    {
1775
-        if (! $this->txn_page_url) {
1776
-            $this->txn_page_url = get_permalink($this->txn_page_id);
1777
-        }
1778
-        if ($query_args) {
1779
-            return add_query_arg($query_args, $this->txn_page_url);
1780
-        } else {
1781
-            return $this->txn_page_url;
1782
-        }
1783
-    }
1784
-
1785
-
1786
-    /**
1787
-     *  gets/returns URL for EE thank_you_page
1788
-     *
1789
-     * @param array $query_args like what gets passed to
1790
-     *                          add_query_arg() as the first argument
1791
-     * @access    public
1792
-     * @return    string
1793
-     */
1794
-    public function thank_you_page_url($query_args = array())
1795
-    {
1796
-        if (! $this->thank_you_page_url) {
1797
-            $this->thank_you_page_url = get_permalink($this->thank_you_page_id);
1798
-        }
1799
-        if ($query_args) {
1800
-            return add_query_arg($query_args, $this->thank_you_page_url);
1801
-        } else {
1802
-            return $this->thank_you_page_url;
1803
-        }
1804
-    }
1805
-
1806
-
1807
-    /**
1808
-     *  gets/returns URL for EE cancel_page
1809
-     *
1810
-     * @access    public
1811
-     * @return    string
1812
-     */
1813
-    public function cancel_page_url()
1814
-    {
1815
-        if (! $this->cancel_page_url) {
1816
-            $this->cancel_page_url = get_permalink($this->cancel_page_id);
1817
-        }
1818
-        return $this->cancel_page_url;
1819
-    }
1820
-
1821
-
1822
-    /**
1823
-     * Resets all critical page urls to their original state.  Used primarily by the __sleep() magic method currently.
1824
-     *
1825
-     * @since 4.7.5
1826
-     */
1827
-    protected function _reset_urls()
1828
-    {
1829
-        $this->reg_page_url = '';
1830
-        $this->txn_page_url = '';
1831
-        $this->cancel_page_url = '';
1832
-        $this->thank_you_page_url = '';
1833
-    }
1834
-
1835
-
1836
-    /**
1837
-     * Used to return what the optin value is set for the EE User Experience Program.
1838
-     * This accounts for multisite and this value being requested for a subsite.  In multisite, the value is set
1839
-     * on the main site only.
1840
-     *
1841
-     * @return bool
1842
-     */
1843
-    protected function _get_main_ee_ueip_optin()
1844
-    {
1845
-        // if this is the main site then we can just bypass our direct query.
1846
-        if (is_main_site()) {
1847
-            return get_option(self::OPTION_NAME_UXIP, false);
1848
-        }
1849
-        // is this already cached for this request?  If so use it.
1850
-        if (EE_Core_Config::$ee_ueip_option !== null) {
1851
-            return EE_Core_Config::$ee_ueip_option;
1852
-        }
1853
-        global $wpdb;
1854
-        $current_network_main_site = is_multisite() ? get_current_site() : null;
1855
-        $current_main_site_id = ! empty($current_network_main_site) ? $current_network_main_site->blog_id : 1;
1856
-        $option = self::OPTION_NAME_UXIP;
1857
-        // set correct table for query
1858
-        $table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options';
1859
-        // rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because
1860
-        // get_blog_option() does a switch_to_blog an that could cause infinite recursion because EE_Core_Config might be
1861
-        // re-constructed on the blog switch.  Note, we are still executing any core wp filters on this option retrieval.
1862
-        // this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog
1863
-        // for the purpose of caching.
1864
-        $pre = apply_filters('pre_option_' . $option, false, $option);
1865
-        if (false !== $pre) {
1866
-            EE_Core_Config::$ee_ueip_option = $pre;
1867
-            return EE_Core_Config::$ee_ueip_option;
1868
-        }
1869
-        $row = $wpdb->get_row(
1870
-            $wpdb->prepare(
1871
-                "SELECT option_value FROM $table_name WHERE option_name = %s LIMIT 1",
1872
-                $option
1873
-            )
1874
-        );
1875
-        if (is_object($row)) {
1876
-            $value = $row->option_value;
1877
-        } else { // option does not exist so use default.
1878
-            EE_Core_Config::$ee_ueip_option =  apply_filters('default_option_' . $option, false, $option);
1879
-            return EE_Core_Config::$ee_ueip_option;
1880
-        }
1881
-        EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option);
1882
-        return EE_Core_Config::$ee_ueip_option;
1883
-    }
1884
-
1885
-
1886
-    /**
1887
-     * Utility function for escaping the value of a property and returning.
1888
-     *
1889
-     * @param string $property property name (checks to see if exists).
1890
-     * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1891
-     * @throws EE_Error
1892
-     */
1893
-    public function get_pretty($property)
1894
-    {
1895
-        if ($property === self::OPTION_NAME_UXIP) {
1896
-            return $this->ee_ueip_optin ? 'yes' : 'no';
1897
-        }
1898
-        return parent::get_pretty($property);
1899
-    }
1900
-
1901
-
1902
-    /**
1903
-     * Currently used to ensure critical page urls have initial values saved to the db instead of any current set values
1904
-     * on the object.
1905
-     *
1906
-     * @return array
1907
-     */
1908
-    public function __sleep()
1909
-    {
1910
-        // reset all url properties
1911
-        $this->_reset_urls();
1912
-        // return what to save to db
1913
-        return array_keys(get_object_vars($this));
1914
-    }
1915
-}
1916
-
1917
-/**
1918
- * Config class for storing info on the Organization
1919
- */
1920
-class EE_Organization_Config extends EE_Config_Base
1921
-{
1922
-    /**
1923
-     * @var string $name
1924
-     * eg EE4.1
1925
-     */
1926
-    public $name;
1927
-
1928
-    /**
1929
-     * @var string $address_1
1930
-     * eg 123 Onna Road
1931
-     */
1932
-    public $address_1 = '';
1933
-
1934
-    /**
1935
-     * @var string $address_2
1936
-     * eg PO Box 123
1937
-     */
1938
-    public $address_2 = '';
1939
-
1940
-    /**
1941
-     * @var string $city
1942
-     * eg Inna City
1943
-     */
1944
-    public $city = '';
1945
-
1946
-    /**
1947
-     * @var int $STA_ID
1948
-     * eg 4
1949
-     */
1950
-    public $STA_ID = 0;
1951
-
1952
-    /**
1953
-     * @var string $CNT_ISO
1954
-     * eg US
1955
-     */
1956
-    public $CNT_ISO = '';
1957
-
1958
-    /**
1959
-     * @var string $zip
1960
-     * eg 12345  or V1A 2B3
1961
-     */
1962
-    public $zip = '';
1963
-
1964
-    /**
1965
-     * @var string $email
1966
-     * eg [email protected]
1967
-     */
1968
-    public $email;
1969
-
1970
-    /**
1971
-     * @var string $phone
1972
-     * eg. 111-111-1111
1973
-     */
1974
-    public $phone = '';
1975
-
1976
-    /**
1977
-     * @var string $vat
1978
-     * VAT/Tax Number
1979
-     */
1980
-    public $vat = '';
1981
-
1982
-    /**
1983
-     * @var string $logo_url
1984
-     * eg http://www.somedomain.com/wp-content/uploads/kittehs.jpg
1985
-     */
1986
-    public $logo_url = '';
1987
-
1988
-    /**
1989
-     * The below are all various properties for holding links to organization social network profiles
1990
-     *
1991
-     * @var string
1992
-     */
1993
-    /**
1994
-     * facebook (facebook.com/profile.name)
1995
-     *
1996
-     * @var string
1997
-     */
1998
-    public $facebook = '';
1999
-
2000
-    /**
2001
-     * twitter (twitter.com/twitter_handle)
2002
-     *
2003
-     * @var string
2004
-     */
2005
-    public $twitter = '';
2006
-
2007
-    /**
2008
-     * linkedin (linkedin.com/in/profile_name)
2009
-     *
2010
-     * @var string
2011
-     */
2012
-    public $linkedin = '';
2013
-
2014
-    /**
2015
-     * pinterest (www.pinterest.com/profile_name)
2016
-     *
2017
-     * @var string
2018
-     */
2019
-    public $pinterest = '';
2020
-
2021
-    /**
2022
-     * google+ (google.com/+profileName)
2023
-     *
2024
-     * @var string
2025
-     */
2026
-    public $google = '';
2027
-
2028
-    /**
2029
-     * instagram (instagram.com/handle)
2030
-     *
2031
-     * @var string
2032
-     */
2033
-    public $instagram = '';
2034
-
2035
-
2036
-    /**
2037
-     *    class constructor
2038
-     *
2039
-     * @access    public
2040
-     */
2041
-    public function __construct()
2042
-    {
2043
-        // set default organization settings
2044
-        // decode HTML entities from the WP blogname, because it's stored in the DB with HTML entities encoded
2045
-        $this->name = wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES);
2046
-        $this->email = get_bloginfo('admin_email');
2047
-    }
2048
-}
2049
-
2050
-/**
2051
- * Class for defining what's in the EE_Config relating to currency
2052
- */
2053
-class EE_Currency_Config extends EE_Config_Base
2054
-{
2055
-    /**
2056
-     * @var string $code
2057
-     * eg 'US'
2058
-     */
2059
-    public $code;
2060
-
2061
-    /**
2062
-     * @var string $name
2063
-     * eg 'Dollar'
2064
-     */
2065
-    public $name;
2066
-
2067
-    /**
2068
-     * plural name
2069
-     *
2070
-     * @var string $plural
2071
-     * eg 'Dollars'
2072
-     */
2073
-    public $plural;
2074
-
2075
-    /**
2076
-     * currency sign
2077
-     *
2078
-     * @var string $sign
2079
-     * eg '$'
2080
-     */
2081
-    public $sign;
2082
-
2083
-    /**
2084
-     * Whether the currency sign should come before the number or not
2085
-     *
2086
-     * @var boolean $sign_b4
2087
-     */
2088
-    public $sign_b4;
2089
-
2090
-    /**
2091
-     * How many digits should come after the decimal place
2092
-     *
2093
-     * @var int $dec_plc
2094
-     */
2095
-    public $dec_plc;
2096
-
2097
-    /**
2098
-     * Symbol to use for decimal mark
2099
-     *
2100
-     * @var string $dec_mrk
2101
-     * eg '.'
2102
-     */
2103
-    public $dec_mrk;
2104
-
2105
-    /**
2106
-     * Symbol to use for thousands
2107
-     *
2108
-     * @var string $thsnds
2109
-     * eg ','
2110
-     */
2111
-    public $thsnds;
2112
-
2113
-
2114
-    /**
2115
-     *    class constructor
2116
-     *
2117
-     * @access    public
2118
-     * @param string $CNT_ISO
2119
-     * @throws EE_Error
2120
-     * @throws ReflectionException
2121
-     */
2122
-    public function __construct($CNT_ISO = '')
2123
-    {
2124
-        /** @var TableAnalysis $table_analysis */
2125
-        $table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
2126
-        // get country code from organization settings or use default
2127
-        $ORG_CNT = isset(EE_Registry::instance()->CFG->organization)
2128
-                   && EE_Registry::instance()->CFG->organization instanceof EE_Organization_Config
2129
-            ? EE_Registry::instance()->CFG->organization->CNT_ISO
2130
-            : '';
2131
-        // but override if requested
2132
-        $CNT_ISO = ! empty($CNT_ISO) ? $CNT_ISO : $ORG_CNT;
2133
-        // so if that all went well, and we are not in M-Mode (cuz you can't query the db in M-Mode) and double-check the countries table exists
2134
-        if (
2135
-            ! empty($CNT_ISO)
2136
-            && EE_Maintenance_Mode::instance()->models_can_query()
2137
-            && $table_analysis->tableExists(EE_Registry::instance()->load_model('Country')->table())
2138
-        ) {
2139
-            // retrieve the country settings from the db, just in case they have been customized
2140
-            $country = EE_Registry::instance()->load_model('Country')->get_one_by_ID($CNT_ISO);
2141
-            if ($country instanceof EE_Country) {
2142
-                $this->code = $country->currency_code();    // currency code: USD, CAD, EUR
2143
-                $this->name = $country->currency_name_single();    // Dollar
2144
-                $this->plural = $country->currency_name_plural();    // Dollars
2145
-                $this->sign = $country->currency_sign();            // currency sign: $
2146
-                $this->sign_b4 = $country->currency_sign_before(
2147
-                );        // currency sign before or after: $TRUE  or  FALSE$
2148
-                $this->dec_plc = $country->currency_decimal_places();    // decimal places: 2 = 0.00  3 = 0.000
2149
-                $this->dec_mrk = $country->currency_decimal_mark(
2150
-                );    // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2151
-                $this->thsnds = $country->currency_thousands_separator(
2152
-                );    // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2153
-            }
2154
-        }
2155
-        // fallback to hardcoded defaults, in case the above failed
2156
-        if (empty($this->code)) {
2157
-            // set default currency settings
2158
-            $this->code = 'USD';    // currency code: USD, CAD, EUR
2159
-            $this->name = esc_html__('Dollar', 'event_espresso');    // Dollar
2160
-            $this->plural = esc_html__('Dollars', 'event_espresso');    // Dollars
2161
-            $this->sign = '$';    // currency sign: $
2162
-            $this->sign_b4 = true;    // currency sign before or after: $TRUE  or  FALSE$
2163
-            $this->dec_plc = 2;    // decimal places: 2 = 0.00  3 = 0.000
2164
-            $this->dec_mrk = '.';    // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2165
-            $this->thsnds = ',';    // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2166
-        }
2167
-    }
2168
-}
2169
-
2170
-/**
2171
- * Class for defining what's in the EE_Config relating to registration settings
2172
- */
2173
-class EE_Registration_Config extends EE_Config_Base
2174
-{
2175
-    /**
2176
-     * Default registration status
2177
-     *
2178
-     * @var string $default_STS_ID
2179
-     * eg 'RPP'
2180
-     */
2181
-    public $default_STS_ID;
2182
-
2183
-    /**
2184
-     * For new events, this will be the default value for the maximum number of tickets (equivalent to maximum number of
2185
-     * registrations)
2186
-     *
2187
-     * @var int
2188
-     */
2189
-    public $default_maximum_number_of_tickets;
2190
-
2191
-    /**
2192
-     * level of validation to apply to email addresses
2193
-     *
2194
-     * @var string $email_validation_level
2195
-     * options: 'basic', 'wp_default', 'i18n', 'i18n_dns'
2196
-     */
2197
-    public $email_validation_level;
2198
-
2199
-    /**
2200
-     *    whether or not to show alternate payment options during the reg process if payment status is pending
2201
-     *
2202
-     * @var boolean $show_pending_payment_options
2203
-     */
2204
-    public $show_pending_payment_options;
2205
-
2206
-    /**
2207
-     * Whether to skip the registration confirmation page
2208
-     *
2209
-     * @var boolean $skip_reg_confirmation
2210
-     */
2211
-    public $skip_reg_confirmation;
2212
-
2213
-    /**
2214
-     * an array of SPCO reg steps where:
2215
-     *        the keys denotes the reg step order
2216
-     *        each element consists of an array with the following elements:
2217
-     *            "file_path" => the file path to the EE_SPCO_Reg_Step class
2218
-     *            "class_name" => the specific EE_SPCO_Reg_Step child class name
2219
-     *            "slug" => the URL param used to trigger the reg step
2220
-     *
2221
-     * @var array $reg_steps
2222
-     */
2223
-    public $reg_steps;
2224
-
2225
-    /**
2226
-     * Whether registration confirmation should be the last page of SPCO
2227
-     *
2228
-     * @var boolean $reg_confirmation_last
2229
-     */
2230
-    public $reg_confirmation_last;
2231
-
2232
-    /**
2233
-     * Whether or not to enable the EE Bot Trap
2234
-     *
2235
-     * @var boolean $use_bot_trap
2236
-     */
2237
-    public $use_bot_trap;
2238
-
2239
-    /**
2240
-     * Whether or not to encrypt some data sent by the EE Bot Trap
2241
-     *
2242
-     * @var boolean $use_encryption
2243
-     */
2244
-    public $use_encryption;
2245
-
2246
-    /**
2247
-     * Whether or not to use ReCaptcha
2248
-     *
2249
-     * @var boolean $use_captcha
2250
-     */
2251
-    public $use_captcha;
2252
-
2253
-    /**
2254
-     * ReCaptcha Theme
2255
-     *
2256
-     * @var string $recaptcha_theme
2257
-     *    options: 'dark', 'light', 'invisible'
2258
-     */
2259
-    public $recaptcha_theme;
2260
-
2261
-    /**
2262
-     * ReCaptcha Badge - determines the position of the reCAPTCHA badge if using Invisible ReCaptcha.
2263
-     *
2264
-     * @var string $recaptcha_badge
2265
-     *    options: 'bottomright', 'bottomleft', 'inline'
2266
-     */
2267
-    public $recaptcha_badge;
2268
-
2269
-    /**
2270
-     * ReCaptcha Type
2271
-     *
2272
-     * @var string $recaptcha_type
2273
-     *    options: 'audio', 'image'
2274
-     */
2275
-    public $recaptcha_type;
2276
-
2277
-    /**
2278
-     * ReCaptcha language
2279
-     *
2280
-     * @var string $recaptcha_language
2281
-     * eg 'en'
2282
-     */
2283
-    public $recaptcha_language;
2284
-
2285
-    /**
2286
-     * ReCaptcha public key
2287
-     *
2288
-     * @var string $recaptcha_publickey
2289
-     */
2290
-    public $recaptcha_publickey;
2291
-
2292
-    /**
2293
-     * ReCaptcha private key
2294
-     *
2295
-     * @var string $recaptcha_privatekey
2296
-     */
2297
-    public $recaptcha_privatekey;
2298
-
2299
-    /**
2300
-     * array of form names protected by ReCaptcha
2301
-     *
2302
-     * @var array $recaptcha_protected_forms
2303
-     */
2304
-    public $recaptcha_protected_forms;
21
+	const OPTION_NAME = 'ee_config';
22
+
23
+	const LOG_NAME = 'ee_config_log';
24
+
25
+	const LOG_LENGTH = 100;
26
+
27
+	const ADDON_OPTION_NAMES = 'ee_config_option_names';
28
+
29
+	/**
30
+	 *    instance of the EE_Config object
31
+	 *
32
+	 * @var    EE_Config $_instance
33
+	 * @access    private
34
+	 */
35
+	private static $_instance;
36
+
37
+	/**
38
+	 * @var boolean $_logging_enabled
39
+	 */
40
+	private static $_logging_enabled = false;
41
+
42
+	/**
43
+	 * @var LegacyShortcodesManager $legacy_shortcodes_manager
44
+	 */
45
+	private $legacy_shortcodes_manager;
46
+
47
+	/**
48
+	 * An StdClass whose property names are addon slugs,
49
+	 * and values are their config classes
50
+	 *
51
+	 * @var StdClass
52
+	 */
53
+	public $addons;
54
+
55
+	/**
56
+	 * @var EE_Admin_Config
57
+	 */
58
+	public $admin;
59
+
60
+	/**
61
+	 * @var EE_Core_Config
62
+	 */
63
+	public $core;
64
+
65
+	/**
66
+	 * @var EE_Currency_Config
67
+	 */
68
+	public $currency;
69
+
70
+	/**
71
+	 * @var EE_Organization_Config
72
+	 */
73
+	public $organization;
74
+
75
+	/**
76
+	 * @var EE_Registration_Config
77
+	 */
78
+	public $registration;
79
+
80
+	/**
81
+	 * @var EE_Template_Config
82
+	 */
83
+	public $template_settings;
84
+
85
+	/**
86
+	 * Holds EE environment values.
87
+	 *
88
+	 * @var EE_Environment_Config
89
+	 */
90
+	public $environment;
91
+
92
+	/**
93
+	 * settings pertaining to Google maps
94
+	 *
95
+	 * @var EE_Map_Config
96
+	 */
97
+	public $map_settings;
98
+
99
+	/**
100
+	 * settings pertaining to Taxes
101
+	 *
102
+	 * @var EE_Tax_Config
103
+	 */
104
+	public $tax_settings;
105
+
106
+	/**
107
+	 * Settings pertaining to global messages settings.
108
+	 *
109
+	 * @var EE_Messages_Config
110
+	 */
111
+	public $messages;
112
+
113
+	/**
114
+	 * @deprecated
115
+	 * @var EE_Gateway_Config
116
+	 */
117
+	public $gateway;
118
+
119
+	/**
120
+	 * @var    array $_addon_option_names
121
+	 * @access    private
122
+	 */
123
+	private $_addon_option_names = array();
124
+
125
+	/**
126
+	 * @var    array $_module_route_map
127
+	 * @access    private
128
+	 */
129
+	private static $_module_route_map = array();
130
+
131
+	/**
132
+	 * @var    array $_module_forward_map
133
+	 * @access    private
134
+	 */
135
+	private static $_module_forward_map = array();
136
+
137
+	/**
138
+	 * @var    array $_module_view_map
139
+	 * @access    private
140
+	 */
141
+	private static $_module_view_map = array();
142
+
143
+
144
+	/**
145
+	 * @singleton method used to instantiate class object
146
+	 * @access    public
147
+	 * @return EE_Config instance
148
+	 */
149
+	public static function instance()
150
+	{
151
+		// check if class object is instantiated, and instantiated properly
152
+		if (! self::$_instance instanceof EE_Config) {
153
+			self::$_instance = new self();
154
+		}
155
+		return self::$_instance;
156
+	}
157
+
158
+
159
+	/**
160
+	 * Resets the config
161
+	 *
162
+	 * @param bool    $hard_reset    if TRUE, sets EE_CONFig back to its original settings in the database. If FALSE
163
+	 *                               (default) leaves the database alone, and merely resets the EE_Config object to
164
+	 *                               reflect its state in the database
165
+	 * @param boolean $reinstantiate if TRUE (default) call instance() and return it. Otherwise, just leave
166
+	 *                               $_instance as NULL. Useful in case you want to forget about the old instance on
167
+	 *                               EE_Config, but might not be ready to instantiate EE_Config currently (eg if the
168
+	 *                               site was put into maintenance mode)
169
+	 * @return EE_Config
170
+	 */
171
+	public static function reset($hard_reset = false, $reinstantiate = true)
172
+	{
173
+		if (self::$_instance instanceof EE_Config) {
174
+			if ($hard_reset) {
175
+				self::$_instance->legacy_shortcodes_manager = null;
176
+				self::$_instance->_addon_option_names = array();
177
+				self::$_instance->_initialize_config();
178
+				self::$_instance->update_espresso_config();
179
+			}
180
+			self::$_instance->update_addon_option_names();
181
+		}
182
+		self::$_instance = null;
183
+		// we don't need to reset the static properties imo because those should
184
+		// only change when a module is added or removed. Currently we don't
185
+		// support removing a module during a request when it previously existed
186
+		if ($reinstantiate) {
187
+			return self::instance();
188
+		} else {
189
+			return null;
190
+		}
191
+	}
192
+
193
+
194
+	/**
195
+	 *    class constructor
196
+	 *
197
+	 * @access    private
198
+	 */
199
+	private function __construct()
200
+	{
201
+		do_action('AHEE__EE_Config__construct__begin', $this);
202
+		EE_Config::$_logging_enabled = apply_filters('FHEE__EE_Config___construct__logging_enabled', false);
203
+		// setup empty config classes
204
+		$this->_initialize_config();
205
+		// load existing EE site settings
206
+		$this->_load_core_config();
207
+		// confirm everything loaded correctly and set filtered defaults if not
208
+		$this->_verify_config();
209
+		//  register shortcodes and modules
210
+		add_action(
211
+			'AHEE__EE_System__register_shortcodes_modules_and_widgets',
212
+			array($this, 'register_shortcodes_and_modules'),
213
+			999
214
+		);
215
+		//  initialize shortcodes and modules
216
+		add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'initialize_shortcodes_and_modules'));
217
+		// register widgets
218
+		add_action('widgets_init', array($this, 'widgets_init'), 10);
219
+		// shutdown
220
+		add_action('shutdown', array($this, 'shutdown'), 10);
221
+		// construct__end hook
222
+		do_action('AHEE__EE_Config__construct__end', $this);
223
+		// hardcoded hack
224
+		$this->template_settings->current_espresso_theme = 'Espresso_Arabica_2014';
225
+	}
226
+
227
+
228
+	/**
229
+	 * @return boolean
230
+	 */
231
+	public static function logging_enabled()
232
+	{
233
+		return self::$_logging_enabled;
234
+	}
235
+
236
+
237
+	/**
238
+	 * use to get the current theme if needed from static context
239
+	 *
240
+	 * @return string current theme set.
241
+	 */
242
+	public static function get_current_theme()
243
+	{
244
+		return isset(self::$_instance->template_settings->current_espresso_theme)
245
+			? self::$_instance->template_settings->current_espresso_theme : 'Espresso_Arabica_2014';
246
+	}
247
+
248
+
249
+	/**
250
+	 *        _initialize_config
251
+	 *
252
+	 * @access private
253
+	 * @return void
254
+	 */
255
+	private function _initialize_config()
256
+	{
257
+		EE_Config::trim_log();
258
+		// set defaults
259
+		$this->_addon_option_names = get_option(EE_Config::ADDON_OPTION_NAMES, array());
260
+		$this->addons = new stdClass();
261
+		// set _module_route_map
262
+		EE_Config::$_module_route_map = array();
263
+		// set _module_forward_map
264
+		EE_Config::$_module_forward_map = array();
265
+		// set _module_view_map
266
+		EE_Config::$_module_view_map = array();
267
+	}
268
+
269
+
270
+	/**
271
+	 *        load core plugin configuration
272
+	 *
273
+	 * @access private
274
+	 * @return void
275
+	 */
276
+	private function _load_core_config()
277
+	{
278
+		// load_core_config__start hook
279
+		do_action('AHEE__EE_Config___load_core_config__start', $this);
280
+		$espresso_config = $this->get_espresso_config();
281
+		foreach ($espresso_config as $config => $settings) {
282
+			// load_core_config__start hook
283
+			$settings = apply_filters(
284
+				'FHEE__EE_Config___load_core_config__config_settings',
285
+				$settings,
286
+				$config,
287
+				$this
288
+			);
289
+			if (is_object($settings) && property_exists($this, $config)) {
290
+				$this->{$config} = apply_filters('FHEE__EE_Config___load_core_config__' . $config, $settings);
291
+				// call configs populate method to ensure any defaults are set for empty values.
292
+				if (method_exists($settings, 'populate')) {
293
+					$this->{$config}->populate();
294
+				}
295
+				if (method_exists($settings, 'do_hooks')) {
296
+					$this->{$config}->do_hooks();
297
+				}
298
+			}
299
+		}
300
+		if (apply_filters('FHEE__EE_Config___load_core_config__update_espresso_config', false)) {
301
+			$this->update_espresso_config();
302
+		}
303
+		// load_core_config__end hook
304
+		do_action('AHEE__EE_Config___load_core_config__end', $this);
305
+	}
306
+
307
+
308
+	/**
309
+	 *    _verify_config
310
+	 *
311
+	 * @access    protected
312
+	 * @return    void
313
+	 */
314
+	protected function _verify_config()
315
+	{
316
+		$this->core = $this->core instanceof EE_Core_Config
317
+			? $this->core
318
+			: new EE_Core_Config();
319
+		$this->core = apply_filters('FHEE__EE_Config___initialize_config__core', $this->core);
320
+		$this->organization = $this->organization instanceof EE_Organization_Config
321
+			? $this->organization
322
+			: new EE_Organization_Config();
323
+		$this->organization = apply_filters(
324
+			'FHEE__EE_Config___initialize_config__organization',
325
+			$this->organization
326
+		);
327
+		$this->currency = $this->currency instanceof EE_Currency_Config
328
+			? $this->currency
329
+			: new EE_Currency_Config();
330
+		$this->currency = apply_filters('FHEE__EE_Config___initialize_config__currency', $this->currency);
331
+		$this->registration = $this->registration instanceof EE_Registration_Config
332
+			? $this->registration
333
+			: new EE_Registration_Config();
334
+		$this->registration = apply_filters(
335
+			'FHEE__EE_Config___initialize_config__registration',
336
+			$this->registration
337
+		);
338
+		$this->admin = $this->admin instanceof EE_Admin_Config
339
+			? $this->admin
340
+			: new EE_Admin_Config();
341
+		$this->admin = apply_filters('FHEE__EE_Config___initialize_config__admin', $this->admin);
342
+		$this->template_settings = $this->template_settings instanceof EE_Template_Config
343
+			? $this->template_settings
344
+			: new EE_Template_Config();
345
+		$this->template_settings = apply_filters(
346
+			'FHEE__EE_Config___initialize_config__template_settings',
347
+			$this->template_settings
348
+		);
349
+		$this->map_settings = $this->map_settings instanceof EE_Map_Config
350
+			? $this->map_settings
351
+			: new EE_Map_Config();
352
+		$this->map_settings = apply_filters(
353
+			'FHEE__EE_Config___initialize_config__map_settings',
354
+			$this->map_settings
355
+		);
356
+		$this->environment = $this->environment instanceof EE_Environment_Config
357
+			? $this->environment
358
+			: new EE_Environment_Config();
359
+		$this->environment = apply_filters(
360
+			'FHEE__EE_Config___initialize_config__environment',
361
+			$this->environment
362
+		);
363
+		$this->tax_settings = $this->tax_settings instanceof EE_Tax_Config
364
+			? $this->tax_settings
365
+			: new EE_Tax_Config();
366
+		$this->tax_settings = apply_filters(
367
+			'FHEE__EE_Config___initialize_config__tax_settings',
368
+			$this->tax_settings
369
+		);
370
+		$this->messages = apply_filters('FHEE__EE_Config__initialize_config__messages', $this->messages);
371
+		$this->messages = $this->messages instanceof EE_Messages_Config
372
+			? $this->messages
373
+			: new EE_Messages_Config();
374
+		$this->gateway = $this->gateway instanceof EE_Gateway_Config
375
+			? $this->gateway
376
+			: new EE_Gateway_Config();
377
+		$this->gateway = apply_filters('FHEE__EE_Config___initialize_config__gateway', $this->gateway);
378
+		$this->legacy_shortcodes_manager = null;
379
+	}
380
+
381
+
382
+	/**
383
+	 *    get_espresso_config
384
+	 *
385
+	 * @access    public
386
+	 * @return    array of espresso config stuff
387
+	 */
388
+	public function get_espresso_config()
389
+	{
390
+		// grab espresso configuration
391
+		return apply_filters(
392
+			'FHEE__EE_Config__get_espresso_config__CFG',
393
+			get_option(EE_Config::OPTION_NAME, array())
394
+		);
395
+	}
396
+
397
+
398
+	/**
399
+	 *    double_check_config_comparison
400
+	 *
401
+	 * @access    public
402
+	 * @param string $option
403
+	 * @param        $old_value
404
+	 * @param        $value
405
+	 */
406
+	public function double_check_config_comparison($option, $old_value, $value)
407
+	{
408
+		// make sure we're checking the ee config
409
+		if ($option === EE_Config::OPTION_NAME) {
410
+			// run a loose comparison of the old value against the new value for type and properties,
411
+			// but NOT exact instance like WP update_option does (ie: NOT type safe comparison)
412
+			if ($value != $old_value) {
413
+				// if they are NOT the same, then remove the hook,
414
+				// which means the subsequent update results will be based solely on the update query results
415
+				// the reason we do this is because, as stated above,
416
+				// WP update_option performs an exact instance comparison (===) on any update values passed to it
417
+				// this happens PRIOR to serialization and any subsequent update.
418
+				// If values are found to match their previous old value,
419
+				// then WP bails before performing any update.
420
+				// Since we are passing the EE_Config object, it is comparing the EXACT instance of the saved version
421
+				// it just pulled from the db, with the one being passed to it (which will not match).
422
+				// HOWEVER, once the object is serialized and passed off to MySQL to update,
423
+				// MySQL MAY ALSO NOT perform the update because
424
+				// the string it sees in the db looks the same as the new one it has been passed!!!
425
+				// This results in the query returning an "affected rows" value of ZERO,
426
+				// which gets returned immediately by WP update_option and looks like an error.
427
+				remove_action('update_option', array($this, 'check_config_updated'));
428
+			}
429
+		}
430
+	}
431
+
432
+
433
+	/**
434
+	 *    update_espresso_config
435
+	 *
436
+	 * @access   public
437
+	 */
438
+	protected function _reset_espresso_addon_config()
439
+	{
440
+		$this->_addon_option_names = array();
441
+		foreach ($this->addons as $addon_name => $addon_config_obj) {
442
+			$addon_config_obj = maybe_unserialize($addon_config_obj);
443
+			if ($addon_config_obj instanceof EE_Config_Base) {
444
+				$this->update_config('addons', $addon_name, $addon_config_obj, false);
445
+			}
446
+			$this->addons->{$addon_name} = null;
447
+		}
448
+	}
449
+
450
+
451
+	/**
452
+	 *    update_espresso_config
453
+	 *
454
+	 * @access   public
455
+	 * @param   bool $add_success
456
+	 * @param   bool $add_error
457
+	 * @return   bool
458
+	 */
459
+	public function update_espresso_config($add_success = false, $add_error = true)
460
+	{
461
+		// don't allow config updates during WP heartbeats
462
+		/** @var RequestInterface $request */
463
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
464
+		if ($request->isWordPressHeartbeat()) {
465
+			return false;
466
+		}
467
+		// commented out the following re: https://events.codebasehq.com/projects/event-espresso/tickets/8197
468
+		// $clone = clone( self::$_instance );
469
+		// self::$_instance = NULL;
470
+		do_action('AHEE__EE_Config__update_espresso_config__begin', $this);
471
+		$this->_reset_espresso_addon_config();
472
+		// hook into update_option because that happens AFTER the ( $value === $old_value ) conditional
473
+		// but BEFORE the actual update occurs
474
+		add_action('update_option', array($this, 'double_check_config_comparison'), 1, 3);
475
+		// don't want to persist legacy_shortcodes_manager, but don't want to lose it either
476
+		$legacy_shortcodes_manager = $this->legacy_shortcodes_manager;
477
+		$this->legacy_shortcodes_manager = null;
478
+		// now update "ee_config"
479
+		$saved = update_option(EE_Config::OPTION_NAME, $this);
480
+		$this->legacy_shortcodes_manager = $legacy_shortcodes_manager;
481
+		EE_Config::log(EE_Config::OPTION_NAME);
482
+		// if not saved... check if the hook we just added still exists;
483
+		// if it does, it means one of two things:
484
+		// that update_option bailed at the($value === $old_value) conditional,
485
+		// or...
486
+		// the db update query returned 0 rows affected
487
+		// (probably because the data  value was the same from it's perspective)
488
+		// so the existence of the hook means that a negative result from update_option is NOT an error,
489
+		// but just means no update occurred, so don't display an error to the user.
490
+		// BUT... if update_option returns FALSE, AND the hook is missing,
491
+		// then it means that something truly went wrong
492
+		$saved = ! $saved ? has_action('update_option', array($this, 'double_check_config_comparison')) : $saved;
493
+		// remove our action since we don't want it in the system anymore
494
+		remove_action('update_option', array($this, 'double_check_config_comparison'), 1);
495
+		do_action('AHEE__EE_Config__update_espresso_config__end', $this, $saved);
496
+		// self::$_instance = $clone;
497
+		// unset( $clone );
498
+		// if config remains the same or was updated successfully
499
+		if ($saved) {
500
+			if ($add_success) {
501
+				EE_Error::add_success(
502
+					esc_html__('The Event Espresso Configuration Settings have been successfully updated.', 'event_espresso'),
503
+					__FILE__,
504
+					__FUNCTION__,
505
+					__LINE__
506
+				);
507
+			}
508
+			return true;
509
+		} else {
510
+			if ($add_error) {
511
+				EE_Error::add_error(
512
+					esc_html__('The Event Espresso Configuration Settings were not updated.', 'event_espresso'),
513
+					__FILE__,
514
+					__FUNCTION__,
515
+					__LINE__
516
+				);
517
+			}
518
+			return false;
519
+		}
520
+	}
521
+
522
+
523
+	/**
524
+	 *    _verify_config_params
525
+	 *
526
+	 * @access    private
527
+	 * @param    string         $section
528
+	 * @param    string         $name
529
+	 * @param    string         $config_class
530
+	 * @param    EE_Config_Base $config_obj
531
+	 * @param    array          $tests_to_run
532
+	 * @param    bool           $display_errors
533
+	 * @return    bool    TRUE on success, FALSE on fail
534
+	 */
535
+	private function _verify_config_params(
536
+		$section = '',
537
+		$name = '',
538
+		$config_class = '',
539
+		$config_obj = null,
540
+		$tests_to_run = array(1, 2, 3, 4, 5, 6, 7, 8),
541
+		$display_errors = true
542
+	) {
543
+		try {
544
+			foreach ($tests_to_run as $test) {
545
+				switch ($test) {
546
+					// TEST #1 : check that section was set
547
+					case 1:
548
+						if (empty($section)) {
549
+							if ($display_errors) {
550
+								throw new EE_Error(
551
+									sprintf(
552
+										esc_html__(
553
+											'No configuration section has been provided while attempting to save "%s".',
554
+											'event_espresso'
555
+										),
556
+										$config_class
557
+									)
558
+								);
559
+							}
560
+							return false;
561
+						}
562
+						break;
563
+					// TEST #2 : check that settings section exists
564
+					case 2:
565
+						if (! isset($this->{$section})) {
566
+							if ($display_errors) {
567
+								throw new EE_Error(
568
+									sprintf(
569
+										esc_html__('The "%s" configuration section does not exist.', 'event_espresso'),
570
+										$section
571
+									)
572
+								);
573
+							}
574
+							return false;
575
+						}
576
+						break;
577
+					// TEST #3 : check that section is the proper format
578
+					case 3:
579
+						if (
580
+							! ($this->{$section} instanceof EE_Config_Base || $this->{$section} instanceof stdClass)
581
+						) {
582
+							if ($display_errors) {
583
+								throw new EE_Error(
584
+									sprintf(
585
+										esc_html__(
586
+											'The "%s" configuration settings have not been formatted correctly.',
587
+											'event_espresso'
588
+										),
589
+										$section
590
+									)
591
+								);
592
+							}
593
+							return false;
594
+						}
595
+						break;
596
+					// TEST #4 : check that config section name has been set
597
+					case 4:
598
+						if (empty($name)) {
599
+							if ($display_errors) {
600
+								throw new EE_Error(
601
+									esc_html__(
602
+										'No name has been provided for the specific configuration section.',
603
+										'event_espresso'
604
+									)
605
+								);
606
+							}
607
+							return false;
608
+						}
609
+						break;
610
+					// TEST #5 : check that a config class name has been set
611
+					case 5:
612
+						if (empty($config_class)) {
613
+							if ($display_errors) {
614
+								throw new EE_Error(
615
+									esc_html__(
616
+										'No class name has been provided for the specific configuration section.',
617
+										'event_espresso'
618
+									)
619
+								);
620
+							}
621
+							return false;
622
+						}
623
+						break;
624
+					// TEST #6 : verify config class is accessible
625
+					case 6:
626
+						if (! class_exists($config_class)) {
627
+							if ($display_errors) {
628
+								throw new EE_Error(
629
+									sprintf(
630
+										esc_html__(
631
+											'The "%s" class does not exist. Please ensure that an autoloader has been set for it.',
632
+											'event_espresso'
633
+										),
634
+										$config_class
635
+									)
636
+								);
637
+							}
638
+							return false;
639
+						}
640
+						break;
641
+					// TEST #7 : check that config has even been set
642
+					case 7:
643
+						if (! isset($this->{$section}->{$name})) {
644
+							if ($display_errors) {
645
+								throw new EE_Error(
646
+									sprintf(
647
+										esc_html__('No configuration has been set for "%1$s->%2$s".', 'event_espresso'),
648
+										$section,
649
+										$name
650
+									)
651
+								);
652
+							}
653
+							return false;
654
+						} else {
655
+							// and make sure it's not serialized
656
+							$this->{$section}->{$name} = maybe_unserialize($this->{$section}->{$name});
657
+						}
658
+						break;
659
+					// TEST #8 : check that config is the requested type
660
+					case 8:
661
+						if (! $this->{$section}->{$name} instanceof $config_class) {
662
+							if ($display_errors) {
663
+								throw new EE_Error(
664
+									sprintf(
665
+										esc_html__(
666
+											'The configuration for "%1$s->%2$s" is not of the "%3$s" class.',
667
+											'event_espresso'
668
+										),
669
+										$section,
670
+										$name,
671
+										$config_class
672
+									)
673
+								);
674
+							}
675
+							return false;
676
+						}
677
+						break;
678
+					// TEST #9 : verify config object
679
+					case 9:
680
+						if (! $config_obj instanceof EE_Config_Base) {
681
+							if ($display_errors) {
682
+								throw new EE_Error(
683
+									sprintf(
684
+										esc_html__('The "%s" class is not an instance of EE_Config_Base.', 'event_espresso'),
685
+										print_r($config_obj, true)
686
+									)
687
+								);
688
+							}
689
+							return false;
690
+						}
691
+						break;
692
+				}
693
+			}
694
+		} catch (EE_Error $e) {
695
+			$e->get_error();
696
+		}
697
+		// you have successfully run the gauntlet
698
+		return true;
699
+	}
700
+
701
+
702
+	/**
703
+	 *    _generate_config_option_name
704
+	 *
705
+	 * @access        protected
706
+	 * @param        string $section
707
+	 * @param        string $name
708
+	 * @return        string
709
+	 */
710
+	private function _generate_config_option_name($section = '', $name = '')
711
+	{
712
+		return 'ee_config-' . strtolower($section . '-' . str_replace(array('EE_', 'EED_'), '', $name));
713
+	}
714
+
715
+
716
+	/**
717
+	 *    _set_config_class
718
+	 * ensures that a config class is set, either from a passed config class or one generated from the config name
719
+	 *
720
+	 * @access    private
721
+	 * @param    string $config_class
722
+	 * @param    string $name
723
+	 * @return    string
724
+	 */
725
+	private function _set_config_class($config_class = '', $name = '')
726
+	{
727
+		return ! empty($config_class)
728
+			? $config_class
729
+			: str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))) . '_Config';
730
+	}
731
+
732
+
733
+	/**
734
+	 *    set_config
735
+	 *
736
+	 * @access    protected
737
+	 * @param    string         $section
738
+	 * @param    string         $name
739
+	 * @param    string         $config_class
740
+	 * @param    EE_Config_Base $config_obj
741
+	 * @return    EE_Config_Base
742
+	 */
743
+	public function set_config($section = '', $name = '', $config_class = '', EE_Config_Base $config_obj = null)
744
+	{
745
+		// ensure config class is set to something
746
+		$config_class = $this->_set_config_class($config_class, $name);
747
+		// run tests 1-4, 6, and 7 to verify all config params are set and valid
748
+		if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
749
+			return null;
750
+		}
751
+		$config_option_name = $this->_generate_config_option_name($section, $name);
752
+		// if the config option name hasn't been added yet to the list of option names we're tracking, then do so now
753
+		if (! isset($this->_addon_option_names[ $config_option_name ])) {
754
+			$this->_addon_option_names[ $config_option_name ] = $config_class;
755
+			$this->update_addon_option_names();
756
+		}
757
+		// verify the incoming config object but suppress errors
758
+		if (! $this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
759
+			$config_obj = new $config_class();
760
+		}
761
+		if (get_option($config_option_name)) {
762
+			EE_Config::log($config_option_name);
763
+			update_option($config_option_name, $config_obj);
764
+			$this->{$section}->{$name} = $config_obj;
765
+			return $this->{$section}->{$name};
766
+		} else {
767
+			// create a wp-option for this config
768
+			if (add_option($config_option_name, $config_obj, '', 'no')) {
769
+				$this->{$section}->{$name} = maybe_unserialize($config_obj);
770
+				return $this->{$section}->{$name};
771
+			} else {
772
+				EE_Error::add_error(
773
+					sprintf(esc_html__('The "%s" could not be saved to the database.', 'event_espresso'), $config_class),
774
+					__FILE__,
775
+					__FUNCTION__,
776
+					__LINE__
777
+				);
778
+				return null;
779
+			}
780
+		}
781
+	}
782
+
783
+
784
+	/**
785
+	 *    update_config
786
+	 * Important: the config object must ALREADY be set, otherwise this will produce an error.
787
+	 *
788
+	 * @access    public
789
+	 * @param    string                $section
790
+	 * @param    string                $name
791
+	 * @param    EE_Config_Base|string $config_obj
792
+	 * @param    bool                  $throw_errors
793
+	 * @return    bool
794
+	 */
795
+	public function update_config($section = '', $name = '', $config_obj = '', $throw_errors = true)
796
+	{
797
+		// don't allow config updates during WP heartbeats
798
+		/** @var RequestInterface $request */
799
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
800
+		if ($request->isWordPressHeartbeat()) {
801
+			return false;
802
+		}
803
+		$config_obj = maybe_unserialize($config_obj);
804
+		// get class name of the incoming object
805
+		$config_class = get_class($config_obj);
806
+		// run tests 1-5 and 9 to verify config
807
+		if (
808
+			! $this->_verify_config_params(
809
+				$section,
810
+				$name,
811
+				$config_class,
812
+				$config_obj,
813
+				array(1, 2, 3, 4, 7, 9)
814
+			)
815
+		) {
816
+			return false;
817
+		}
818
+		$config_option_name = $this->_generate_config_option_name($section, $name);
819
+		// check if config object has been added to db by seeing if config option name is in $this->_addon_option_names array
820
+		if (! isset($this->_addon_option_names[ $config_option_name ])) {
821
+			// save new config to db
822
+			if ($this->set_config($section, $name, $config_class, $config_obj)) {
823
+				return true;
824
+			}
825
+		} else {
826
+			// first check if the record already exists
827
+			$existing_config = get_option($config_option_name);
828
+			$config_obj = serialize($config_obj);
829
+			// just return if db record is already up to date (NOT type safe comparison)
830
+			if ($existing_config == $config_obj) {
831
+				$this->{$section}->{$name} = $config_obj;
832
+				return true;
833
+			} elseif (update_option($config_option_name, $config_obj)) {
834
+				EE_Config::log($config_option_name);
835
+				// update wp-option for this config class
836
+				$this->{$section}->{$name} = $config_obj;
837
+				return true;
838
+			} elseif ($throw_errors) {
839
+				EE_Error::add_error(
840
+					sprintf(
841
+						esc_html__(
842
+							'The "%1$s" object stored at"%2$s" was not successfully updated in the database.',
843
+							'event_espresso'
844
+						),
845
+						$config_class,
846
+						'EE_Config->' . $section . '->' . $name
847
+					),
848
+					__FILE__,
849
+					__FUNCTION__,
850
+					__LINE__
851
+				);
852
+			}
853
+		}
854
+		return false;
855
+	}
856
+
857
+
858
+	/**
859
+	 *    get_config
860
+	 *
861
+	 * @access    public
862
+	 * @param    string $section
863
+	 * @param    string $name
864
+	 * @param    string $config_class
865
+	 * @return    mixed EE_Config_Base | NULL
866
+	 */
867
+	public function get_config($section = '', $name = '', $config_class = '')
868
+	{
869
+		// ensure config class is set to something
870
+		$config_class = $this->_set_config_class($config_class, $name);
871
+		// run tests 1-4, 6 and 7 to verify that all params have been set
872
+		if (! $this->_verify_config_params($section, $name, $config_class, null, array(1, 2, 3, 4, 5, 6))) {
873
+			return null;
874
+		}
875
+		// now test if the requested config object exists, but suppress errors
876
+		if ($this->_verify_config_params($section, $name, $config_class, null, array(7, 8), false)) {
877
+			// config already exists, so pass it back
878
+			return $this->{$section}->{$name};
879
+		}
880
+		// load config option from db if it exists
881
+		$config_obj = $this->get_config_option($this->_generate_config_option_name($section, $name));
882
+		// verify the newly retrieved config object, but suppress errors
883
+		if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9), false)) {
884
+			// config is good, so set it and pass it back
885
+			$this->{$section}->{$name} = $config_obj;
886
+			return $this->{$section}->{$name};
887
+		}
888
+		// oops! $config_obj is not already set and does not exist in the db, so create a new one
889
+		$config_obj = $this->set_config($section, $name, $config_class);
890
+		// verify the newly created config object
891
+		if ($this->_verify_config_params($section, $name, $config_class, $config_obj, array(9))) {
892
+			return $this->{$section}->{$name};
893
+		} else {
894
+			EE_Error::add_error(
895
+				sprintf(esc_html__('The "%s" could not be retrieved from the database.', 'event_espresso'), $config_class),
896
+				__FILE__,
897
+				__FUNCTION__,
898
+				__LINE__
899
+			);
900
+		}
901
+		return null;
902
+	}
903
+
904
+
905
+	/**
906
+	 *    get_config_option
907
+	 *
908
+	 * @access    public
909
+	 * @param    string $config_option_name
910
+	 * @return    mixed EE_Config_Base | FALSE
911
+	 */
912
+	public function get_config_option($config_option_name = '')
913
+	{
914
+		// retrieve the wp-option for this config class.
915
+		$config_option = maybe_unserialize(get_option($config_option_name, array()));
916
+		if (empty($config_option)) {
917
+			EE_Config::log($config_option_name . '-NOT-FOUND');
918
+		}
919
+		return $config_option;
920
+	}
921
+
922
+
923
+	/**
924
+	 * log
925
+	 *
926
+	 * @param string $config_option_name
927
+	 */
928
+	public static function log($config_option_name = '')
929
+	{
930
+		if (EE_Config::logging_enabled() && ! empty($config_option_name)) {
931
+			$config_log = get_option(EE_Config::LOG_NAME, array());
932
+			/** @var RequestParams $request */
933
+			$request = LoaderFactory::getLoader()->getShared(RequestParams::class);
934
+			$config_log[ (string) microtime(true) ] = array(
935
+				'config_name' => $config_option_name,
936
+				'request'     => $request->requestParams(),
937
+			);
938
+			update_option(EE_Config::LOG_NAME, $config_log);
939
+		}
940
+	}
941
+
942
+
943
+	/**
944
+	 * trim_log
945
+	 * reduces the size of the config log to the length specified by EE_Config::LOG_LENGTH
946
+	 */
947
+	public static function trim_log()
948
+	{
949
+		if (! EE_Config::logging_enabled()) {
950
+			return;
951
+		}
952
+		$config_log = maybe_unserialize(get_option(EE_Config::LOG_NAME, array()));
953
+		$log_length = count($config_log);
954
+		if ($log_length > EE_Config::LOG_LENGTH) {
955
+			ksort($config_log);
956
+			$config_log = array_slice($config_log, $log_length - EE_Config::LOG_LENGTH, null, true);
957
+			update_option(EE_Config::LOG_NAME, $config_log);
958
+		}
959
+	}
960
+
961
+
962
+	/**
963
+	 *    get_page_for_posts
964
+	 *    if the wp-option "show_on_front" is set to "page", then this is the post_name for the post set in the
965
+	 *    wp-option "page_for_posts", or "posts" if no page is selected
966
+	 *
967
+	 * @access    public
968
+	 * @return    string
969
+	 */
970
+	public static function get_page_for_posts()
971
+	{
972
+		$page_for_posts = get_option('page_for_posts');
973
+		if (! $page_for_posts) {
974
+			return 'posts';
975
+		}
976
+		global $wpdb;
977
+		$SQL = "SELECT post_name from $wpdb->posts WHERE post_type='posts' OR post_type='page' AND post_status='publish' AND ID=%d";
978
+		return $wpdb->get_var($wpdb->prepare($SQL, $page_for_posts));
979
+	}
980
+
981
+
982
+	/**
983
+	 *    register_shortcodes_and_modules.
984
+	 *    At this point, it's too early to tell if we're maintenance mode or not.
985
+	 *    In fact, this is where we give modules a chance to let core know they exist
986
+	 *    so they can help trigger maintenance mode if it's needed
987
+	 *
988
+	 * @access    public
989
+	 * @return    void
990
+	 */
991
+	public function register_shortcodes_and_modules()
992
+	{
993
+		// allow modules to set hooks for the rest of the system
994
+		EE_Registry::instance()->modules = $this->_register_modules();
995
+	}
996
+
997
+
998
+	/**
999
+	 *    initialize_shortcodes_and_modules
1000
+	 *    meaning they can start adding their hooks to get stuff done
1001
+	 *
1002
+	 * @access    public
1003
+	 * @return    void
1004
+	 */
1005
+	public function initialize_shortcodes_and_modules()
1006
+	{
1007
+		// allow modules to set hooks for the rest of the system
1008
+		$this->_initialize_modules();
1009
+	}
1010
+
1011
+
1012
+	/**
1013
+	 *    widgets_init
1014
+	 *
1015
+	 * @access private
1016
+	 * @return void
1017
+	 */
1018
+	public function widgets_init()
1019
+	{
1020
+		// only init widgets on admin pages when not in complete maintenance, and
1021
+		// on frontend when not in any maintenance mode
1022
+		if (
1023
+			! EE_Maintenance_Mode::instance()->level()
1024
+			|| (
1025
+				is_admin()
1026
+				&& EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance
1027
+			)
1028
+		) {
1029
+			// grab list of installed widgets
1030
+			$widgets_to_register = glob(EE_WIDGETS . '*', GLOB_ONLYDIR);
1031
+			// filter list of modules to register
1032
+			$widgets_to_register = apply_filters(
1033
+				'FHEE__EE_Config__register_widgets__widgets_to_register',
1034
+				$widgets_to_register
1035
+			);
1036
+			if (! empty($widgets_to_register)) {
1037
+				// cycle thru widget folders
1038
+				foreach ($widgets_to_register as $widget_path) {
1039
+					// add to list of installed widget modules
1040
+					EE_Config::register_ee_widget($widget_path);
1041
+				}
1042
+			}
1043
+			// filter list of installed modules
1044
+			EE_Registry::instance()->widgets = apply_filters(
1045
+				'FHEE__EE_Config__register_widgets__installed_widgets',
1046
+				EE_Registry::instance()->widgets
1047
+			);
1048
+		}
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 *    register_ee_widget - makes core aware of this widget
1054
+	 *
1055
+	 * @access    public
1056
+	 * @param    string $widget_path - full path up to and including widget folder
1057
+	 * @return    void
1058
+	 */
1059
+	public static function register_ee_widget($widget_path = null)
1060
+	{
1061
+		do_action('AHEE__EE_Config__register_widget__begin', $widget_path);
1062
+		$widget_ext = '.widget.php';
1063
+		// make all separators match
1064
+		$widget_path = rtrim(str_replace('\\', DS, $widget_path), DS);
1065
+		// does the file path INCLUDE the actual file name as part of the path ?
1066
+		if (strpos($widget_path, $widget_ext) !== false) {
1067
+			// grab and shortcode file name from directory name and break apart at dots
1068
+			$file_name = explode('.', basename($widget_path));
1069
+			// take first segment from file name pieces and remove class prefix if it exists
1070
+			$widget = strpos($file_name[0], 'EEW_') === 0 ? substr($file_name[0], 4) : $file_name[0];
1071
+			// sanitize shortcode directory name
1072
+			$widget = sanitize_key($widget);
1073
+			// now we need to rebuild the shortcode path
1074
+			$widget_path = explode('/', $widget_path);
1075
+			// remove last segment
1076
+			array_pop($widget_path);
1077
+			// glue it back together
1078
+			$widget_path = implode(DS, $widget_path);
1079
+		} else {
1080
+			// grab and sanitize widget directory name
1081
+			$widget = sanitize_key(basename($widget_path));
1082
+		}
1083
+		// create classname from widget directory name
1084
+		$widget = str_replace(' ', '_', ucwords(str_replace('_', ' ', $widget)));
1085
+		// add class prefix
1086
+		$widget_class = 'EEW_' . $widget;
1087
+		// does the widget exist ?
1088
+		if (! is_readable($widget_path . '/' . $widget_class . $widget_ext)) {
1089
+			$msg = sprintf(
1090
+				esc_html__(
1091
+					'The requested %s widget file could not be found or is not readable due to file permissions. Please ensure the following path is correct: %s',
1092
+					'event_espresso'
1093
+				),
1094
+				$widget_class,
1095
+				$widget_path . '/' . $widget_class . $widget_ext
1096
+			);
1097
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1098
+			return;
1099
+		}
1100
+		// load the widget class file
1101
+		require_once($widget_path . '/' . $widget_class . $widget_ext);
1102
+		// verify that class exists
1103
+		if (! class_exists($widget_class)) {
1104
+			$msg = sprintf(esc_html__('The requested %s widget class does not exist.', 'event_espresso'), $widget_class);
1105
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1106
+			return;
1107
+		}
1108
+		register_widget($widget_class);
1109
+		// add to array of registered widgets
1110
+		EE_Registry::instance()->widgets->{$widget_class} = $widget_path . '/' . $widget_class . $widget_ext;
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 *        _register_modules
1116
+	 *
1117
+	 * @access private
1118
+	 * @return array
1119
+	 */
1120
+	private function _register_modules()
1121
+	{
1122
+		// grab list of installed modules
1123
+		$modules_to_register = glob(EE_MODULES . '*', GLOB_ONLYDIR);
1124
+		// filter list of modules to register
1125
+		$modules_to_register = apply_filters(
1126
+			'FHEE__EE_Config__register_modules__modules_to_register',
1127
+			$modules_to_register
1128
+		);
1129
+		if (! empty($modules_to_register)) {
1130
+			// loop through folders
1131
+			foreach ($modules_to_register as $module_path) {
1132
+				/**TEMPORARILY EXCLUDE gateways from modules for time being**/
1133
+				if (
1134
+					$module_path !== EE_MODULES . 'zzz-copy-this-module-template'
1135
+					&& $module_path !== EE_MODULES . 'gateways'
1136
+				) {
1137
+					// add to list of installed modules
1138
+					EE_Config::register_module($module_path);
1139
+				}
1140
+			}
1141
+		}
1142
+		// filter list of installed modules
1143
+		return apply_filters(
1144
+			'FHEE__EE_Config___register_modules__installed_modules',
1145
+			EE_Registry::instance()->modules
1146
+		);
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 *    register_module - makes core aware of this module
1152
+	 *
1153
+	 * @access    public
1154
+	 * @param    string $module_path - full path up to and including module folder
1155
+	 * @return    bool
1156
+	 */
1157
+	public static function register_module($module_path = null)
1158
+	{
1159
+		do_action('AHEE__EE_Config__register_module__begin', $module_path);
1160
+		$module_ext = '.module.php';
1161
+		// make all separators match
1162
+		$module_path = str_replace(array('\\', '/'), '/', $module_path);
1163
+		// does the file path INCLUDE the actual file name as part of the path ?
1164
+		if (strpos($module_path, $module_ext) !== false) {
1165
+			// grab and shortcode file name from directory name and break apart at dots
1166
+			$module_file = explode('.', basename($module_path));
1167
+			// now we need to rebuild the shortcode path
1168
+			$module_path = explode('/', $module_path);
1169
+			// remove last segment
1170
+			array_pop($module_path);
1171
+			// glue it back together
1172
+			$module_path = implode('/', $module_path) . '/';
1173
+			// take first segment from file name pieces and sanitize it
1174
+			$module = preg_replace('/[^a-zA-Z0-9_\-]/', '', $module_file[0]);
1175
+			// ensure class prefix is added
1176
+			$module_class = strpos($module, 'EED_') !== 0 ? 'EED_' . $module : $module;
1177
+		} else {
1178
+			// we need to generate the filename based off of the folder name
1179
+			// grab and sanitize module name
1180
+			$module = strtolower(basename($module_path));
1181
+			$module = preg_replace('/[^a-z0-9_\-]/', '', $module);
1182
+			// like trailingslashit()
1183
+			$module_path = rtrim($module_path, '/') . '/';
1184
+			// create classname from module directory name
1185
+			$module = str_replace(' ', '_', ucwords(str_replace('_', ' ', $module)));
1186
+			// add class prefix
1187
+			$module_class = 'EED_' . $module;
1188
+		}
1189
+		// does the module exist ?
1190
+		if (! is_readable($module_path . '/' . $module_class . $module_ext)) {
1191
+			$msg = sprintf(
1192
+				esc_html__(
1193
+					'The requested %s module file could not be found or is not readable due to file permissions.',
1194
+					'event_espresso'
1195
+				),
1196
+				$module
1197
+			);
1198
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1199
+			return false;
1200
+		}
1201
+		// load the module class file
1202
+		require_once($module_path . $module_class . $module_ext);
1203
+		// verify that class exists
1204
+		if (! class_exists($module_class)) {
1205
+			$msg = sprintf(esc_html__('The requested %s module class does not exist.', 'event_espresso'), $module_class);
1206
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1207
+			return false;
1208
+		}
1209
+		// add to array of registered modules
1210
+		EE_Registry::instance()->modules->{$module_class} = $module_path . $module_class . $module_ext;
1211
+		do_action(
1212
+			'AHEE__EE_Config__register_module__complete',
1213
+			$module_class,
1214
+			EE_Registry::instance()->modules->{$module_class}
1215
+		);
1216
+		return true;
1217
+	}
1218
+
1219
+
1220
+	/**
1221
+	 *    _initialize_modules
1222
+	 *    allow modules to set hooks for the rest of the system
1223
+	 *
1224
+	 * @access private
1225
+	 * @return void
1226
+	 */
1227
+	private function _initialize_modules()
1228
+	{
1229
+		// cycle thru shortcode folders
1230
+		foreach (EE_Registry::instance()->modules as $module_class => $module_path) {
1231
+			// fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
1232
+			// which set hooks ?
1233
+			if (is_admin()) {
1234
+				// fire immediately
1235
+				call_user_func(array($module_class, 'set_hooks_admin'));
1236
+			} else {
1237
+				// delay until other systems are online
1238
+				add_action(
1239
+					'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
1240
+					array($module_class, 'set_hooks')
1241
+				);
1242
+			}
1243
+		}
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 *    register_route - adds module method routes to route_map
1249
+	 *
1250
+	 * @access    public
1251
+	 * @param    string $route       - "pretty" public alias for module method
1252
+	 * @param    string $module      - module name (classname without EED_ prefix)
1253
+	 * @param    string $method_name - the actual module method to be routed to
1254
+	 * @param    string $key         - url param key indicating a route is being called
1255
+	 * @return    bool
1256
+	 */
1257
+	public static function register_route($route = null, $module = null, $method_name = null, $key = 'ee')
1258
+	{
1259
+		do_action('AHEE__EE_Config__register_route__begin', $route, $module, $method_name);
1260
+		$module = str_replace('EED_', '', $module);
1261
+		$module_class = 'EED_' . $module;
1262
+		if (! isset(EE_Registry::instance()->modules->{$module_class})) {
1263
+			$msg = sprintf(esc_html__('The module %s has not been registered.', 'event_espresso'), $module);
1264
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1265
+			return false;
1266
+		}
1267
+		if (empty($route)) {
1268
+			$msg = sprintf(esc_html__('No route has been supplied.', 'event_espresso'), $route);
1269
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1270
+			return false;
1271
+		}
1272
+		if (! method_exists('EED_' . $module, $method_name)) {
1273
+			$msg = sprintf(
1274
+				esc_html__('A valid class method for the %s route has not been supplied.', 'event_espresso'),
1275
+				$route
1276
+			);
1277
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1278
+			return false;
1279
+		}
1280
+		EE_Config::$_module_route_map[ (string) $key ][ (string) $route ] = array('EED_' . $module, $method_name);
1281
+		return true;
1282
+	}
1283
+
1284
+
1285
+	/**
1286
+	 *    get_route - get module method route
1287
+	 *
1288
+	 * @access    public
1289
+	 * @param    string $route - "pretty" public alias for module method
1290
+	 * @param    string $key   - url param key indicating a route is being called
1291
+	 * @return    string
1292
+	 */
1293
+	public static function get_route($route = null, $key = 'ee')
1294
+	{
1295
+		do_action('AHEE__EE_Config__get_route__begin', $route);
1296
+		$route = (string) apply_filters('FHEE__EE_Config__get_route', $route);
1297
+		if (isset(EE_Config::$_module_route_map[ $key ][ $route ])) {
1298
+			return EE_Config::$_module_route_map[ $key ][ $route ];
1299
+		}
1300
+		return null;
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 *    get_routes - get ALL module method routes
1306
+	 *
1307
+	 * @access    public
1308
+	 * @return    array
1309
+	 */
1310
+	public static function get_routes()
1311
+	{
1312
+		return EE_Config::$_module_route_map;
1313
+	}
1314
+
1315
+
1316
+	/**
1317
+	 *    register_forward - allows modules to forward request to another module for further processing
1318
+	 *
1319
+	 * @access    public
1320
+	 * @param    string       $route   - "pretty" public alias for module method
1321
+	 * @param    integer      $status  - integer value corresponding  to status constant strings set in module parent
1322
+	 *                                 class, allows different forwards to be served based on status
1323
+	 * @param    array|string $forward - function name or array( class, method )
1324
+	 * @param    string       $key     - url param key indicating a route is being called
1325
+	 * @return    bool
1326
+	 */
1327
+	public static function register_forward($route = null, $status = 0, $forward = null, $key = 'ee')
1328
+	{
1329
+		do_action('AHEE__EE_Config__register_forward', $route, $status, $forward);
1330
+		if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1331
+			$msg = sprintf(
1332
+				esc_html__('The module route %s for this forward has not been registered.', 'event_espresso'),
1333
+				$route
1334
+			);
1335
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1336
+			return false;
1337
+		}
1338
+		if (empty($forward)) {
1339
+			$msg = sprintf(esc_html__('No forwarding route has been supplied.', 'event_espresso'), $route);
1340
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1341
+			return false;
1342
+		}
1343
+		if (is_array($forward)) {
1344
+			if (! isset($forward[1])) {
1345
+				$msg = sprintf(
1346
+					esc_html__('A class method for the %s forwarding route has not been supplied.', 'event_espresso'),
1347
+					$route
1348
+				);
1349
+				EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1350
+				return false;
1351
+			}
1352
+			if (! method_exists($forward[0], $forward[1])) {
1353
+				$msg = sprintf(
1354
+					esc_html__('The class method %s for the %s forwarding route is in invalid.', 'event_espresso'),
1355
+					$forward[1],
1356
+					$route
1357
+				);
1358
+				EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1359
+				return false;
1360
+			}
1361
+		} elseif (! function_exists($forward)) {
1362
+			$msg = sprintf(
1363
+				esc_html__('The function %s for the %s forwarding route is in invalid.', 'event_espresso'),
1364
+				$forward,
1365
+				$route
1366
+			);
1367
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1368
+			return false;
1369
+		}
1370
+		EE_Config::$_module_forward_map[ $key ][ $route ][ absint($status) ] = $forward;
1371
+		return true;
1372
+	}
1373
+
1374
+
1375
+	/**
1376
+	 *    get_forward - get forwarding route
1377
+	 *
1378
+	 * @access    public
1379
+	 * @param    string  $route  - "pretty" public alias for module method
1380
+	 * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1381
+	 *                           allows different forwards to be served based on status
1382
+	 * @param    string  $key    - url param key indicating a route is being called
1383
+	 * @return    string
1384
+	 */
1385
+	public static function get_forward($route = null, $status = 0, $key = 'ee')
1386
+	{
1387
+		do_action('AHEE__EE_Config__get_forward__begin', $route, $status);
1388
+		if (isset(EE_Config::$_module_forward_map[ $key ][ $route ][ $status ])) {
1389
+			return apply_filters(
1390
+				'FHEE__EE_Config__get_forward',
1391
+				EE_Config::$_module_forward_map[ $key ][ $route ][ $status ],
1392
+				$route,
1393
+				$status
1394
+			);
1395
+		}
1396
+		return null;
1397
+	}
1398
+
1399
+
1400
+	/**
1401
+	 *    register_forward - allows modules to specify different view templates for different method routes and status
1402
+	 *    results
1403
+	 *
1404
+	 * @access    public
1405
+	 * @param    string  $route  - "pretty" public alias for module method
1406
+	 * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1407
+	 *                           allows different views to be served based on status
1408
+	 * @param    string  $view
1409
+	 * @param    string  $key    - url param key indicating a route is being called
1410
+	 * @return    bool
1411
+	 */
1412
+	public static function register_view($route = null, $status = 0, $view = null, $key = 'ee')
1413
+	{
1414
+		do_action('AHEE__EE_Config__register_view__begin', $route, $status, $view);
1415
+		if (! isset(EE_Config::$_module_route_map[ $key ][ $route ]) || empty($route)) {
1416
+			$msg = sprintf(
1417
+				esc_html__('The module route %s for this view has not been registered.', 'event_espresso'),
1418
+				$route
1419
+			);
1420
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1421
+			return false;
1422
+		}
1423
+		if (! is_readable($view)) {
1424
+			$msg = sprintf(
1425
+				esc_html__(
1426
+					'The %s view file could not be found or is not readable due to file permissions.',
1427
+					'event_espresso'
1428
+				),
1429
+				$view
1430
+			);
1431
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
1432
+			return false;
1433
+		}
1434
+		EE_Config::$_module_view_map[ $key ][ $route ][ absint($status) ] = $view;
1435
+		return true;
1436
+	}
1437
+
1438
+
1439
+	/**
1440
+	 *    get_view - get view for route and status
1441
+	 *
1442
+	 * @access    public
1443
+	 * @param    string  $route  - "pretty" public alias for module method
1444
+	 * @param    integer $status - integer value corresponding  to status constant strings set in module parent class,
1445
+	 *                           allows different views to be served based on status
1446
+	 * @param    string  $key    - url param key indicating a route is being called
1447
+	 * @return    string
1448
+	 */
1449
+	public static function get_view($route = null, $status = 0, $key = 'ee')
1450
+	{
1451
+		do_action('AHEE__EE_Config__get_view__begin', $route, $status);
1452
+		if (isset(EE_Config::$_module_view_map[ $key ][ $route ][ $status ])) {
1453
+			return apply_filters(
1454
+				'FHEE__EE_Config__get_view',
1455
+				EE_Config::$_module_view_map[ $key ][ $route ][ $status ],
1456
+				$route,
1457
+				$status
1458
+			);
1459
+		}
1460
+		return null;
1461
+	}
1462
+
1463
+
1464
+	public function update_addon_option_names()
1465
+	{
1466
+		update_option(EE_Config::ADDON_OPTION_NAMES, $this->_addon_option_names);
1467
+	}
1468
+
1469
+
1470
+	public function shutdown()
1471
+	{
1472
+		$this->update_addon_option_names();
1473
+	}
1474
+
1475
+
1476
+	/**
1477
+	 * @return LegacyShortcodesManager
1478
+	 */
1479
+	public static function getLegacyShortcodesManager()
1480
+	{
1481
+		if (! EE_Config::instance()->legacy_shortcodes_manager instanceof LegacyShortcodesManager) {
1482
+			EE_Config::instance()->legacy_shortcodes_manager = LoaderFactory::getLoader()->getShared(
1483
+				LegacyShortcodesManager::class
1484
+			);
1485
+		}
1486
+		return EE_Config::instance()->legacy_shortcodes_manager;
1487
+	}
1488
+
1489
+
1490
+	/**
1491
+	 * register_shortcode - makes core aware of this shortcode
1492
+	 *
1493
+	 * @deprecated 4.9.26
1494
+	 * @param    string $shortcode_path - full path up to and including shortcode folder
1495
+	 * @return    bool
1496
+	 */
1497
+	public static function register_shortcode($shortcode_path = null)
1498
+	{
1499
+		EE_Error::doing_it_wrong(
1500
+			__METHOD__,
1501
+			esc_html__(
1502
+				'Usage is deprecated. Use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::registerShortcode() as direct replacement, or better yet, please see the new \EventEspresso\core\services\shortcodes\ShortcodesManager class.',
1503
+				'event_espresso'
1504
+			),
1505
+			'4.9.26'
1506
+		);
1507
+		return EE_Config::instance()->getLegacyShortcodesManager()->registerShortcode($shortcode_path);
1508
+	}
1509
+}
2305 1510
 
2306
-    /**
2307
-     * ReCaptcha width
2308
-     *
2309
-     * @var int $recaptcha_width
2310
-     * @deprecated
2311
-     */
2312
-    public $recaptcha_width;
1511
+/**
1512
+ * Base class used for config classes. These classes should generally not have
1513
+ * magic functions in use, except we'll allow them to magically set and get stuff...
1514
+ * basically, they should just be well-defined stdClasses
1515
+ */
1516
+class EE_Config_Base
1517
+{
1518
+	/**
1519
+	 * Utility function for escaping the value of a property and returning.
1520
+	 *
1521
+	 * @param string $property property name (checks to see if exists).
1522
+	 * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1523
+	 * @throws EE_Error
1524
+	 */
1525
+	public function get_pretty($property)
1526
+	{
1527
+		if (! property_exists($this, $property)) {
1528
+			throw new EE_Error(
1529
+				sprintf(
1530
+					esc_html__(
1531
+						'%1$s::get_pretty() has been called with the property %2$s which does not exist on the %1$s config class.',
1532
+						'event_espresso'
1533
+					),
1534
+					get_class($this),
1535
+					$property
1536
+				)
1537
+			);
1538
+		}
1539
+		// just handling escaping of strings for now.
1540
+		if (is_string($this->{$property})) {
1541
+			return stripslashes($this->{$property});
1542
+		}
1543
+		return $this->{$property};
1544
+	}
1545
+
1546
+
1547
+	public function populate()
1548
+	{
1549
+		// grab defaults via a new instance of this class.
1550
+		$class_name = get_class($this);
1551
+		$defaults = new $class_name();
1552
+		// loop through the properties for this class and see if they are set.  If they are NOT, then grab the
1553
+		// default from our $defaults object.
1554
+		foreach (get_object_vars($defaults) as $property => $value) {
1555
+			if ($this->{$property} === null) {
1556
+				$this->{$property} = $value;
1557
+			}
1558
+		}
1559
+		// cleanup
1560
+		unset($defaults);
1561
+	}
1562
+
1563
+
1564
+	/**
1565
+	 *        __isset
1566
+	 *
1567
+	 * @param $a
1568
+	 * @return bool
1569
+	 */
1570
+	public function __isset($a)
1571
+	{
1572
+		return false;
1573
+	}
1574
+
1575
+
1576
+	/**
1577
+	 *        __unset
1578
+	 *
1579
+	 * @param $a
1580
+	 * @return bool
1581
+	 */
1582
+	public function __unset($a)
1583
+	{
1584
+		return false;
1585
+	}
1586
+
1587
+
1588
+	/**
1589
+	 *        __clone
1590
+	 */
1591
+	public function __clone()
1592
+	{
1593
+	}
1594
+
1595
+
1596
+	/**
1597
+	 *        __wakeup
1598
+	 */
1599
+	public function __wakeup()
1600
+	{
1601
+	}
1602
+
1603
+
1604
+	/**
1605
+	 *        __destruct
1606
+	 */
1607
+	public function __destruct()
1608
+	{
1609
+	}
1610
+}
2313 1611
 
2314
-    /**
2315
-     * Whether or not invalid attempts to directly access the registration checkout page should be tracked.
2316
-     *
2317
-     * @var boolean $track_invalid_checkout_access
2318
-     */
2319
-    protected $track_invalid_checkout_access = true;
1612
+/**
1613
+ * Class for defining what's in the EE_Config relating to registration settings
1614
+ */
1615
+class EE_Core_Config extends EE_Config_Base
1616
+{
1617
+	const OPTION_NAME_UXIP = 'ee_ueip_optin';
1618
+
1619
+
1620
+	public $current_blog_id;
1621
+
1622
+	public $ee_ueip_optin;
1623
+
1624
+	public $ee_ueip_has_notified;
1625
+
1626
+	/**
1627
+	 * Not to be confused with the 4 critical page variables (See
1628
+	 * get_critical_pages_array()), this is just an array of wp posts that have EE
1629
+	 * shortcodes in them. Keys are slugs, values are arrays with only 1 element: where the key is the shortcode
1630
+	 * in the page, and the value is the page's ID. The key 'posts' is basically a duplicate of this same array.
1631
+	 *
1632
+	 * @var array
1633
+	 */
1634
+	public $post_shortcodes;
1635
+
1636
+	public $module_route_map;
1637
+
1638
+	public $module_forward_map;
1639
+
1640
+	public $module_view_map;
1641
+
1642
+	/**
1643
+	 * The next 4 vars are the IDs of critical EE pages.
1644
+	 *
1645
+	 * @var int
1646
+	 */
1647
+	public $reg_page_id;
1648
+
1649
+	public $txn_page_id;
1650
+
1651
+	public $thank_you_page_id;
1652
+
1653
+	public $cancel_page_id;
1654
+
1655
+	/**
1656
+	 * The next 4 vars are the URLs of critical EE pages.
1657
+	 *
1658
+	 * @var int
1659
+	 */
1660
+	public $reg_page_url;
1661
+
1662
+	public $txn_page_url;
1663
+
1664
+	public $thank_you_page_url;
1665
+
1666
+	public $cancel_page_url;
1667
+
1668
+	/**
1669
+	 * The next vars relate to the custom slugs for EE CPT routes
1670
+	 */
1671
+	public $event_cpt_slug;
1672
+
1673
+	/**
1674
+	 * This caches the _ee_ueip_option in case this config is reset in the same
1675
+	 * request across blog switches in a multisite context.
1676
+	 * Avoids extra queries to the db for this option.
1677
+	 *
1678
+	 * @var bool
1679
+	 */
1680
+	public static $ee_ueip_option;
1681
+
1682
+
1683
+	/**
1684
+	 *    class constructor
1685
+	 *
1686
+	 * @access    public
1687
+	 */
1688
+	public function __construct()
1689
+	{
1690
+		// set default organization settings
1691
+		$this->current_blog_id = get_current_blog_id();
1692
+		$this->current_blog_id = $this->current_blog_id === null ? 1 : $this->current_blog_id;
1693
+		$this->ee_ueip_optin = $this->_get_main_ee_ueip_optin();
1694
+		$this->ee_ueip_has_notified = is_main_site() ? get_option('ee_ueip_has_notified', false) : true;
1695
+		$this->post_shortcodes = array();
1696
+		$this->module_route_map = array();
1697
+		$this->module_forward_map = array();
1698
+		$this->module_view_map = array();
1699
+		// critical EE page IDs
1700
+		$this->reg_page_id = 0;
1701
+		$this->txn_page_id = 0;
1702
+		$this->thank_you_page_id = 0;
1703
+		$this->cancel_page_id = 0;
1704
+		// critical EE page URLs
1705
+		$this->reg_page_url = '';
1706
+		$this->txn_page_url = '';
1707
+		$this->thank_you_page_url = '';
1708
+		$this->cancel_page_url = '';
1709
+		// cpt slugs
1710
+		$this->event_cpt_slug = esc_html__('events', 'event_espresso');
1711
+		// ueip constant check
1712
+		if (defined('EE_DISABLE_UXIP') && EE_DISABLE_UXIP) {
1713
+			$this->ee_ueip_optin = false;
1714
+			$this->ee_ueip_has_notified = true;
1715
+		}
1716
+	}
1717
+
1718
+
1719
+	/**
1720
+	 * @return array
1721
+	 */
1722
+	public function get_critical_pages_array()
1723
+	{
1724
+		return array(
1725
+			$this->reg_page_id,
1726
+			$this->txn_page_id,
1727
+			$this->thank_you_page_id,
1728
+			$this->cancel_page_id,
1729
+		);
1730
+	}
1731
+
1732
+
1733
+	/**
1734
+	 * @return array
1735
+	 */
1736
+	public function get_critical_pages_shortcodes_array()
1737
+	{
1738
+		return array(
1739
+			$this->reg_page_id       => 'ESPRESSO_CHECKOUT',
1740
+			$this->txn_page_id       => 'ESPRESSO_TXN_PAGE',
1741
+			$this->thank_you_page_id => 'ESPRESSO_THANK_YOU',
1742
+			$this->cancel_page_id    => 'ESPRESSO_CANCELLED',
1743
+		);
1744
+	}
1745
+
1746
+
1747
+	/**
1748
+	 *  gets/returns URL for EE reg_page
1749
+	 *
1750
+	 * @access    public
1751
+	 * @return    string
1752
+	 */
1753
+	public function reg_page_url()
1754
+	{
1755
+		if (! $this->reg_page_url) {
1756
+			$this->reg_page_url = add_query_arg(
1757
+				array('uts' => time()),
1758
+				get_permalink($this->reg_page_id)
1759
+			) . '#checkout';
1760
+		}
1761
+		return $this->reg_page_url;
1762
+	}
1763
+
1764
+
1765
+	/**
1766
+	 *  gets/returns URL for EE txn_page
1767
+	 *
1768
+	 * @param array $query_args like what gets passed to
1769
+	 *                          add_query_arg() as the first argument
1770
+	 * @access    public
1771
+	 * @return    string
1772
+	 */
1773
+	public function txn_page_url($query_args = array())
1774
+	{
1775
+		if (! $this->txn_page_url) {
1776
+			$this->txn_page_url = get_permalink($this->txn_page_id);
1777
+		}
1778
+		if ($query_args) {
1779
+			return add_query_arg($query_args, $this->txn_page_url);
1780
+		} else {
1781
+			return $this->txn_page_url;
1782
+		}
1783
+	}
1784
+
1785
+
1786
+	/**
1787
+	 *  gets/returns URL for EE thank_you_page
1788
+	 *
1789
+	 * @param array $query_args like what gets passed to
1790
+	 *                          add_query_arg() as the first argument
1791
+	 * @access    public
1792
+	 * @return    string
1793
+	 */
1794
+	public function thank_you_page_url($query_args = array())
1795
+	{
1796
+		if (! $this->thank_you_page_url) {
1797
+			$this->thank_you_page_url = get_permalink($this->thank_you_page_id);
1798
+		}
1799
+		if ($query_args) {
1800
+			return add_query_arg($query_args, $this->thank_you_page_url);
1801
+		} else {
1802
+			return $this->thank_you_page_url;
1803
+		}
1804
+	}
1805
+
1806
+
1807
+	/**
1808
+	 *  gets/returns URL for EE cancel_page
1809
+	 *
1810
+	 * @access    public
1811
+	 * @return    string
1812
+	 */
1813
+	public function cancel_page_url()
1814
+	{
1815
+		if (! $this->cancel_page_url) {
1816
+			$this->cancel_page_url = get_permalink($this->cancel_page_id);
1817
+		}
1818
+		return $this->cancel_page_url;
1819
+	}
1820
+
1821
+
1822
+	/**
1823
+	 * Resets all critical page urls to their original state.  Used primarily by the __sleep() magic method currently.
1824
+	 *
1825
+	 * @since 4.7.5
1826
+	 */
1827
+	protected function _reset_urls()
1828
+	{
1829
+		$this->reg_page_url = '';
1830
+		$this->txn_page_url = '';
1831
+		$this->cancel_page_url = '';
1832
+		$this->thank_you_page_url = '';
1833
+	}
1834
+
1835
+
1836
+	/**
1837
+	 * Used to return what the optin value is set for the EE User Experience Program.
1838
+	 * This accounts for multisite and this value being requested for a subsite.  In multisite, the value is set
1839
+	 * on the main site only.
1840
+	 *
1841
+	 * @return bool
1842
+	 */
1843
+	protected function _get_main_ee_ueip_optin()
1844
+	{
1845
+		// if this is the main site then we can just bypass our direct query.
1846
+		if (is_main_site()) {
1847
+			return get_option(self::OPTION_NAME_UXIP, false);
1848
+		}
1849
+		// is this already cached for this request?  If so use it.
1850
+		if (EE_Core_Config::$ee_ueip_option !== null) {
1851
+			return EE_Core_Config::$ee_ueip_option;
1852
+		}
1853
+		global $wpdb;
1854
+		$current_network_main_site = is_multisite() ? get_current_site() : null;
1855
+		$current_main_site_id = ! empty($current_network_main_site) ? $current_network_main_site->blog_id : 1;
1856
+		$option = self::OPTION_NAME_UXIP;
1857
+		// set correct table for query
1858
+		$table_name = $wpdb->get_blog_prefix($current_main_site_id) . 'options';
1859
+		// rather than getting blog option for the $current_main_site_id, we do a direct $wpdb query because
1860
+		// get_blog_option() does a switch_to_blog an that could cause infinite recursion because EE_Core_Config might be
1861
+		// re-constructed on the blog switch.  Note, we are still executing any core wp filters on this option retrieval.
1862
+		// this bit of code is basically a direct copy of get_option without any caching because we are NOT switched to the blog
1863
+		// for the purpose of caching.
1864
+		$pre = apply_filters('pre_option_' . $option, false, $option);
1865
+		if (false !== $pre) {
1866
+			EE_Core_Config::$ee_ueip_option = $pre;
1867
+			return EE_Core_Config::$ee_ueip_option;
1868
+		}
1869
+		$row = $wpdb->get_row(
1870
+			$wpdb->prepare(
1871
+				"SELECT option_value FROM $table_name WHERE option_name = %s LIMIT 1",
1872
+				$option
1873
+			)
1874
+		);
1875
+		if (is_object($row)) {
1876
+			$value = $row->option_value;
1877
+		} else { // option does not exist so use default.
1878
+			EE_Core_Config::$ee_ueip_option =  apply_filters('default_option_' . $option, false, $option);
1879
+			return EE_Core_Config::$ee_ueip_option;
1880
+		}
1881
+		EE_Core_Config::$ee_ueip_option = apply_filters('option_' . $option, maybe_unserialize($value), $option);
1882
+		return EE_Core_Config::$ee_ueip_option;
1883
+	}
1884
+
1885
+
1886
+	/**
1887
+	 * Utility function for escaping the value of a property and returning.
1888
+	 *
1889
+	 * @param string $property property name (checks to see if exists).
1890
+	 * @return mixed if a detected type found return the escaped value, otherwise just the raw value is returned.
1891
+	 * @throws EE_Error
1892
+	 */
1893
+	public function get_pretty($property)
1894
+	{
1895
+		if ($property === self::OPTION_NAME_UXIP) {
1896
+			return $this->ee_ueip_optin ? 'yes' : 'no';
1897
+		}
1898
+		return parent::get_pretty($property);
1899
+	}
1900
+
1901
+
1902
+	/**
1903
+	 * Currently used to ensure critical page urls have initial values saved to the db instead of any current set values
1904
+	 * on the object.
1905
+	 *
1906
+	 * @return array
1907
+	 */
1908
+	public function __sleep()
1909
+	{
1910
+		// reset all url properties
1911
+		$this->_reset_urls();
1912
+		// return what to save to db
1913
+		return array_keys(get_object_vars($this));
1914
+	}
1915
+}
2320 1916
 
2321
-    /**
2322
-     * Whether or not to show the privacy policy consent checkbox
2323
-     *
2324
-     * @var bool
2325
-     */
2326
-    public $consent_checkbox_enabled;
1917
+/**
1918
+ * Config class for storing info on the Organization
1919
+ */
1920
+class EE_Organization_Config extends EE_Config_Base
1921
+{
1922
+	/**
1923
+	 * @var string $name
1924
+	 * eg EE4.1
1925
+	 */
1926
+	public $name;
1927
+
1928
+	/**
1929
+	 * @var string $address_1
1930
+	 * eg 123 Onna Road
1931
+	 */
1932
+	public $address_1 = '';
1933
+
1934
+	/**
1935
+	 * @var string $address_2
1936
+	 * eg PO Box 123
1937
+	 */
1938
+	public $address_2 = '';
1939
+
1940
+	/**
1941
+	 * @var string $city
1942
+	 * eg Inna City
1943
+	 */
1944
+	public $city = '';
1945
+
1946
+	/**
1947
+	 * @var int $STA_ID
1948
+	 * eg 4
1949
+	 */
1950
+	public $STA_ID = 0;
1951
+
1952
+	/**
1953
+	 * @var string $CNT_ISO
1954
+	 * eg US
1955
+	 */
1956
+	public $CNT_ISO = '';
1957
+
1958
+	/**
1959
+	 * @var string $zip
1960
+	 * eg 12345  or V1A 2B3
1961
+	 */
1962
+	public $zip = '';
1963
+
1964
+	/**
1965
+	 * @var string $email
1966
+	 * eg [email protected]
1967
+	 */
1968
+	public $email;
1969
+
1970
+	/**
1971
+	 * @var string $phone
1972
+	 * eg. 111-111-1111
1973
+	 */
1974
+	public $phone = '';
1975
+
1976
+	/**
1977
+	 * @var string $vat
1978
+	 * VAT/Tax Number
1979
+	 */
1980
+	public $vat = '';
1981
+
1982
+	/**
1983
+	 * @var string $logo_url
1984
+	 * eg http://www.somedomain.com/wp-content/uploads/kittehs.jpg
1985
+	 */
1986
+	public $logo_url = '';
1987
+
1988
+	/**
1989
+	 * The below are all various properties for holding links to organization social network profiles
1990
+	 *
1991
+	 * @var string
1992
+	 */
1993
+	/**
1994
+	 * facebook (facebook.com/profile.name)
1995
+	 *
1996
+	 * @var string
1997
+	 */
1998
+	public $facebook = '';
1999
+
2000
+	/**
2001
+	 * twitter (twitter.com/twitter_handle)
2002
+	 *
2003
+	 * @var string
2004
+	 */
2005
+	public $twitter = '';
2006
+
2007
+	/**
2008
+	 * linkedin (linkedin.com/in/profile_name)
2009
+	 *
2010
+	 * @var string
2011
+	 */
2012
+	public $linkedin = '';
2013
+
2014
+	/**
2015
+	 * pinterest (www.pinterest.com/profile_name)
2016
+	 *
2017
+	 * @var string
2018
+	 */
2019
+	public $pinterest = '';
2020
+
2021
+	/**
2022
+	 * google+ (google.com/+profileName)
2023
+	 *
2024
+	 * @var string
2025
+	 */
2026
+	public $google = '';
2027
+
2028
+	/**
2029
+	 * instagram (instagram.com/handle)
2030
+	 *
2031
+	 * @var string
2032
+	 */
2033
+	public $instagram = '';
2034
+
2035
+
2036
+	/**
2037
+	 *    class constructor
2038
+	 *
2039
+	 * @access    public
2040
+	 */
2041
+	public function __construct()
2042
+	{
2043
+		// set default organization settings
2044
+		// decode HTML entities from the WP blogname, because it's stored in the DB with HTML entities encoded
2045
+		$this->name = wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES);
2046
+		$this->email = get_bloginfo('admin_email');
2047
+	}
2048
+}
2327 2049
 
2328
-    /**
2329
-     * Label text to show on the checkbox
2330
-     *
2331
-     * @var string
2332
-     */
2333
-    public $consent_checkbox_label_text;
2050
+/**
2051
+ * Class for defining what's in the EE_Config relating to currency
2052
+ */
2053
+class EE_Currency_Config extends EE_Config_Base
2054
+{
2055
+	/**
2056
+	 * @var string $code
2057
+	 * eg 'US'
2058
+	 */
2059
+	public $code;
2060
+
2061
+	/**
2062
+	 * @var string $name
2063
+	 * eg 'Dollar'
2064
+	 */
2065
+	public $name;
2066
+
2067
+	/**
2068
+	 * plural name
2069
+	 *
2070
+	 * @var string $plural
2071
+	 * eg 'Dollars'
2072
+	 */
2073
+	public $plural;
2074
+
2075
+	/**
2076
+	 * currency sign
2077
+	 *
2078
+	 * @var string $sign
2079
+	 * eg '$'
2080
+	 */
2081
+	public $sign;
2082
+
2083
+	/**
2084
+	 * Whether the currency sign should come before the number or not
2085
+	 *
2086
+	 * @var boolean $sign_b4
2087
+	 */
2088
+	public $sign_b4;
2089
+
2090
+	/**
2091
+	 * How many digits should come after the decimal place
2092
+	 *
2093
+	 * @var int $dec_plc
2094
+	 */
2095
+	public $dec_plc;
2096
+
2097
+	/**
2098
+	 * Symbol to use for decimal mark
2099
+	 *
2100
+	 * @var string $dec_mrk
2101
+	 * eg '.'
2102
+	 */
2103
+	public $dec_mrk;
2104
+
2105
+	/**
2106
+	 * Symbol to use for thousands
2107
+	 *
2108
+	 * @var string $thsnds
2109
+	 * eg ','
2110
+	 */
2111
+	public $thsnds;
2112
+
2113
+
2114
+	/**
2115
+	 *    class constructor
2116
+	 *
2117
+	 * @access    public
2118
+	 * @param string $CNT_ISO
2119
+	 * @throws EE_Error
2120
+	 * @throws ReflectionException
2121
+	 */
2122
+	public function __construct($CNT_ISO = '')
2123
+	{
2124
+		/** @var TableAnalysis $table_analysis */
2125
+		$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
2126
+		// get country code from organization settings or use default
2127
+		$ORG_CNT = isset(EE_Registry::instance()->CFG->organization)
2128
+				   && EE_Registry::instance()->CFG->organization instanceof EE_Organization_Config
2129
+			? EE_Registry::instance()->CFG->organization->CNT_ISO
2130
+			: '';
2131
+		// but override if requested
2132
+		$CNT_ISO = ! empty($CNT_ISO) ? $CNT_ISO : $ORG_CNT;
2133
+		// so if that all went well, and we are not in M-Mode (cuz you can't query the db in M-Mode) and double-check the countries table exists
2134
+		if (
2135
+			! empty($CNT_ISO)
2136
+			&& EE_Maintenance_Mode::instance()->models_can_query()
2137
+			&& $table_analysis->tableExists(EE_Registry::instance()->load_model('Country')->table())
2138
+		) {
2139
+			// retrieve the country settings from the db, just in case they have been customized
2140
+			$country = EE_Registry::instance()->load_model('Country')->get_one_by_ID($CNT_ISO);
2141
+			if ($country instanceof EE_Country) {
2142
+				$this->code = $country->currency_code();    // currency code: USD, CAD, EUR
2143
+				$this->name = $country->currency_name_single();    // Dollar
2144
+				$this->plural = $country->currency_name_plural();    // Dollars
2145
+				$this->sign = $country->currency_sign();            // currency sign: $
2146
+				$this->sign_b4 = $country->currency_sign_before(
2147
+				);        // currency sign before or after: $TRUE  or  FALSE$
2148
+				$this->dec_plc = $country->currency_decimal_places();    // decimal places: 2 = 0.00  3 = 0.000
2149
+				$this->dec_mrk = $country->currency_decimal_mark(
2150
+				);    // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2151
+				$this->thsnds = $country->currency_thousands_separator(
2152
+				);    // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2153
+			}
2154
+		}
2155
+		// fallback to hardcoded defaults, in case the above failed
2156
+		if (empty($this->code)) {
2157
+			// set default currency settings
2158
+			$this->code = 'USD';    // currency code: USD, CAD, EUR
2159
+			$this->name = esc_html__('Dollar', 'event_espresso');    // Dollar
2160
+			$this->plural = esc_html__('Dollars', 'event_espresso');    // Dollars
2161
+			$this->sign = '$';    // currency sign: $
2162
+			$this->sign_b4 = true;    // currency sign before or after: $TRUE  or  FALSE$
2163
+			$this->dec_plc = 2;    // decimal places: 2 = 0.00  3 = 0.000
2164
+			$this->dec_mrk = '.';    // decimal mark: (comma) ',' = 0,01   or (decimal) '.' = 0.01
2165
+			$this->thsnds = ',';    // thousands separator: (comma) ',' = 1,000   or (decimal) '.' = 1.000
2166
+		}
2167
+	}
2168
+}
2334 2169
 
2335
-    /*
2170
+/**
2171
+ * Class for defining what's in the EE_Config relating to registration settings
2172
+ */
2173
+class EE_Registration_Config extends EE_Config_Base
2174
+{
2175
+	/**
2176
+	 * Default registration status
2177
+	 *
2178
+	 * @var string $default_STS_ID
2179
+	 * eg 'RPP'
2180
+	 */
2181
+	public $default_STS_ID;
2182
+
2183
+	/**
2184
+	 * For new events, this will be the default value for the maximum number of tickets (equivalent to maximum number of
2185
+	 * registrations)
2186
+	 *
2187
+	 * @var int
2188
+	 */
2189
+	public $default_maximum_number_of_tickets;
2190
+
2191
+	/**
2192
+	 * level of validation to apply to email addresses
2193
+	 *
2194
+	 * @var string $email_validation_level
2195
+	 * options: 'basic', 'wp_default', 'i18n', 'i18n_dns'
2196
+	 */
2197
+	public $email_validation_level;
2198
+
2199
+	/**
2200
+	 *    whether or not to show alternate payment options during the reg process if payment status is pending
2201
+	 *
2202
+	 * @var boolean $show_pending_payment_options
2203
+	 */
2204
+	public $show_pending_payment_options;
2205
+
2206
+	/**
2207
+	 * Whether to skip the registration confirmation page
2208
+	 *
2209
+	 * @var boolean $skip_reg_confirmation
2210
+	 */
2211
+	public $skip_reg_confirmation;
2212
+
2213
+	/**
2214
+	 * an array of SPCO reg steps where:
2215
+	 *        the keys denotes the reg step order
2216
+	 *        each element consists of an array with the following elements:
2217
+	 *            "file_path" => the file path to the EE_SPCO_Reg_Step class
2218
+	 *            "class_name" => the specific EE_SPCO_Reg_Step child class name
2219
+	 *            "slug" => the URL param used to trigger the reg step
2220
+	 *
2221
+	 * @var array $reg_steps
2222
+	 */
2223
+	public $reg_steps;
2224
+
2225
+	/**
2226
+	 * Whether registration confirmation should be the last page of SPCO
2227
+	 *
2228
+	 * @var boolean $reg_confirmation_last
2229
+	 */
2230
+	public $reg_confirmation_last;
2231
+
2232
+	/**
2233
+	 * Whether or not to enable the EE Bot Trap
2234
+	 *
2235
+	 * @var boolean $use_bot_trap
2236
+	 */
2237
+	public $use_bot_trap;
2238
+
2239
+	/**
2240
+	 * Whether or not to encrypt some data sent by the EE Bot Trap
2241
+	 *
2242
+	 * @var boolean $use_encryption
2243
+	 */
2244
+	public $use_encryption;
2245
+
2246
+	/**
2247
+	 * Whether or not to use ReCaptcha
2248
+	 *
2249
+	 * @var boolean $use_captcha
2250
+	 */
2251
+	public $use_captcha;
2252
+
2253
+	/**
2254
+	 * ReCaptcha Theme
2255
+	 *
2256
+	 * @var string $recaptcha_theme
2257
+	 *    options: 'dark', 'light', 'invisible'
2258
+	 */
2259
+	public $recaptcha_theme;
2260
+
2261
+	/**
2262
+	 * ReCaptcha Badge - determines the position of the reCAPTCHA badge if using Invisible ReCaptcha.
2263
+	 *
2264
+	 * @var string $recaptcha_badge
2265
+	 *    options: 'bottomright', 'bottomleft', 'inline'
2266
+	 */
2267
+	public $recaptcha_badge;
2268
+
2269
+	/**
2270
+	 * ReCaptcha Type
2271
+	 *
2272
+	 * @var string $recaptcha_type
2273
+	 *    options: 'audio', 'image'
2274
+	 */
2275
+	public $recaptcha_type;
2276
+
2277
+	/**
2278
+	 * ReCaptcha language
2279
+	 *
2280
+	 * @var string $recaptcha_language
2281
+	 * eg 'en'
2282
+	 */
2283
+	public $recaptcha_language;
2284
+
2285
+	/**
2286
+	 * ReCaptcha public key
2287
+	 *
2288
+	 * @var string $recaptcha_publickey
2289
+	 */
2290
+	public $recaptcha_publickey;
2291
+
2292
+	/**
2293
+	 * ReCaptcha private key
2294
+	 *
2295
+	 * @var string $recaptcha_privatekey
2296
+	 */
2297
+	public $recaptcha_privatekey;
2298
+
2299
+	/**
2300
+	 * array of form names protected by ReCaptcha
2301
+	 *
2302
+	 * @var array $recaptcha_protected_forms
2303
+	 */
2304
+	public $recaptcha_protected_forms;
2305
+
2306
+	/**
2307
+	 * ReCaptcha width
2308
+	 *
2309
+	 * @var int $recaptcha_width
2310
+	 * @deprecated
2311
+	 */
2312
+	public $recaptcha_width;
2313
+
2314
+	/**
2315
+	 * Whether or not invalid attempts to directly access the registration checkout page should be tracked.
2316
+	 *
2317
+	 * @var boolean $track_invalid_checkout_access
2318
+	 */
2319
+	protected $track_invalid_checkout_access = true;
2320
+
2321
+	/**
2322
+	 * Whether or not to show the privacy policy consent checkbox
2323
+	 *
2324
+	 * @var bool
2325
+	 */
2326
+	public $consent_checkbox_enabled;
2327
+
2328
+	/**
2329
+	 * Label text to show on the checkbox
2330
+	 *
2331
+	 * @var string
2332
+	 */
2333
+	public $consent_checkbox_label_text;
2334
+
2335
+	/*
2336 2336
      * String describing how long to keep payment logs. Passed into DateTime constructor
2337 2337
      * @var string
2338 2338
      */
2339
-    public $gateway_log_lifespan = '1 week';
2340
-
2341
-    /**
2342
-     * Enable copy attendee info at form
2343
-     *
2344
-     * @var boolean $enable_copy_attendee
2345
-     */
2346
-    protected $copy_attendee_info = true;
2347
-
2348
-
2349
-    /**
2350
-     *    class constructor
2351
-     *
2352
-     * @access    public
2353
-     */
2354
-    public function __construct()
2355
-    {
2356
-        // set default registration settings
2357
-        $this->default_STS_ID = EEM_Registration::status_id_pending_payment;
2358
-        $this->email_validation_level = 'wp_default';
2359
-        $this->show_pending_payment_options = true;
2360
-        $this->skip_reg_confirmation = true;
2361
-        $this->reg_steps = array();
2362
-        $this->reg_confirmation_last = false;
2363
-        $this->use_bot_trap = true;
2364
-        $this->use_encryption = true;
2365
-        $this->use_captcha = false;
2366
-        $this->recaptcha_theme = 'light';
2367
-        $this->recaptcha_badge = 'bottomleft';
2368
-        $this->recaptcha_type = 'image';
2369
-        $this->recaptcha_language = 'en';
2370
-        $this->recaptcha_publickey = null;
2371
-        $this->recaptcha_privatekey = null;
2372
-        $this->recaptcha_protected_forms = array();
2373
-        $this->recaptcha_width = 500;
2374
-        $this->default_maximum_number_of_tickets = 10;
2375
-        $this->consent_checkbox_enabled = false;
2376
-        $this->consent_checkbox_label_text = '';
2377
-        $this->gateway_log_lifespan = '7 days';
2378
-        $this->copy_attendee_info = true;
2379
-    }
2380
-
2381
-
2382
-    /**
2383
-     * This is called by the config loader and hooks are initialized AFTER the config has been populated.
2384
-     *
2385
-     * @since 4.8.8.rc.019
2386
-     */
2387
-    public function do_hooks()
2388
-    {
2389
-        add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_reg_status_on_EEM_Event'));
2390
-        add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_max_ticket_on_EEM_Event'));
2391
-        add_action('setup_theme', array($this, 'setDefaultCheckboxLabelText'));
2392
-    }
2393
-
2394
-
2395
-    /**
2396
-     * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the
2397
-     * EVT_default_registration_status field matches the config setting for default_STS_ID.
2398
-     */
2399
-    public function set_default_reg_status_on_EEM_Event()
2400
-    {
2401
-        EEM_Event::set_default_reg_status($this->default_STS_ID);
2402
-    }
2403
-
2404
-
2405
-    /**
2406
-     * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the EVT_additional_limit field
2407
-     * for Events matches the config setting for default_maximum_number_of_tickets
2408
-     */
2409
-    public function set_default_max_ticket_on_EEM_Event()
2410
-    {
2411
-        EEM_Event::set_default_additional_limit($this->default_maximum_number_of_tickets);
2412
-    }
2413
-
2414
-
2415
-    /**
2416
-     * Sets the default consent checkbox text. This needs to be done a bit later than when EE_Registration_Config is
2417
-     * constructed because that happens before we can get the privacy policy page's permalink.
2418
-     *
2419
-     * @throws InvalidArgumentException
2420
-     * @throws InvalidDataTypeException
2421
-     * @throws InvalidInterfaceException
2422
-     */
2423
-    public function setDefaultCheckboxLabelText()
2424
-    {
2425
-        if (
2426
-            $this->getConsentCheckboxLabelText() === null
2427
-            || $this->getConsentCheckboxLabelText() === ''
2428
-        ) {
2429
-            $opening_a_tag = '';
2430
-            $closing_a_tag = '';
2431
-            if (function_exists('get_privacy_policy_url')) {
2432
-                $privacy_page_url = get_privacy_policy_url();
2433
-                if (! empty($privacy_page_url)) {
2434
-                    $opening_a_tag = '<a href="' . $privacy_page_url . '" target="_blank">';
2435
-                    $closing_a_tag = '</a>';
2436
-                }
2437
-            }
2438
-            $loader = LoaderFactory::getLoader();
2439
-            $org_config = $loader->getShared('EE_Organization_Config');
2440
-            /**
2441
-             * @var $org_config EE_Organization_Config
2442
-             */
2443
-
2444
-            $this->setConsentCheckboxLabelText(
2445
-                sprintf(
2446
-                    esc_html__(
2447
-                        'I consent to %1$s storing and using my personal information, according to their %2$sprivacy policy%3$s.',
2448
-                        'event_espresso'
2449
-                    ),
2450
-                    $org_config->name,
2451
-                    $opening_a_tag,
2452
-                    $closing_a_tag
2453
-                )
2454
-            );
2455
-        }
2456
-    }
2457
-
2458
-
2459
-    /**
2460
-     * @return boolean
2461
-     */
2462
-    public function track_invalid_checkout_access()
2463
-    {
2464
-        return $this->track_invalid_checkout_access;
2465
-    }
2466
-
2467
-
2468
-    /**
2469
-     * @param boolean $track_invalid_checkout_access
2470
-     */
2471
-    public function set_track_invalid_checkout_access($track_invalid_checkout_access)
2472
-    {
2473
-        $this->track_invalid_checkout_access = filter_var(
2474
-            $track_invalid_checkout_access,
2475
-            FILTER_VALIDATE_BOOLEAN
2476
-        );
2477
-    }
2478
-
2479
-    /**
2480
-     * @return boolean
2481
-     */
2482
-    public function copyAttendeeInfo()
2483
-    {
2484
-        return $this->copy_attendee_info;
2485
-    }
2486
-
2487
-
2488
-    /**
2489
-     * @param boolean $copy_attendee_info
2490
-     */
2491
-    public function setCopyAttendeeInfo($copy_attendee_info)
2492
-    {
2493
-        $this->copy_attendee_info = filter_var(
2494
-            $copy_attendee_info,
2495
-            FILTER_VALIDATE_BOOLEAN
2496
-        );
2497
-    }
2498
-
2499
-
2500
-    /**
2501
-     * Gets the options to make availalbe for the gateway log lifespan
2502
-     * @return array
2503
-     */
2504
-    public function gatewayLogLifespanOptions()
2505
-    {
2506
-        return (array) apply_filters(
2507
-            'FHEE_EE_Admin_Config__gatewayLogLifespanOptions',
2508
-            array(
2509
-                '1 second' => esc_html__('Don\'t Log At All', 'event_espresso'),
2510
-                '1 day' => esc_html__('1 Day', 'event_espresso'),
2511
-                '7 days' => esc_html__('7 Days', 'event_espresso'),
2512
-                '14 days' => esc_html__('14 Days', 'event_espresso'),
2513
-                '30 days' => esc_html__('30 Days', 'event_espresso')
2514
-            )
2515
-        );
2516
-    }
2517
-
2518
-
2519
-    /**
2520
-     * @return bool
2521
-     */
2522
-    public function isConsentCheckboxEnabled()
2523
-    {
2524
-        return $this->consent_checkbox_enabled;
2525
-    }
2526
-
2527
-
2528
-    /**
2529
-     * @param bool $consent_checkbox_enabled
2530
-     */
2531
-    public function setConsentCheckboxEnabled($consent_checkbox_enabled)
2532
-    {
2533
-        $this->consent_checkbox_enabled = filter_var(
2534
-            $consent_checkbox_enabled,
2535
-            FILTER_VALIDATE_BOOLEAN
2536
-        );
2537
-    }
2538
-
2539
-
2540
-    /**
2541
-     * @return string
2542
-     */
2543
-    public function getConsentCheckboxLabelText()
2544
-    {
2545
-        return $this->consent_checkbox_label_text;
2546
-    }
2547
-
2548
-
2549
-    /**
2550
-     * @param string $consent_checkbox_label_text
2551
-     */
2552
-    public function setConsentCheckboxLabelText($consent_checkbox_label_text)
2553
-    {
2554
-        $this->consent_checkbox_label_text = (string) $consent_checkbox_label_text;
2555
-    }
2339
+	public $gateway_log_lifespan = '1 week';
2340
+
2341
+	/**
2342
+	 * Enable copy attendee info at form
2343
+	 *
2344
+	 * @var boolean $enable_copy_attendee
2345
+	 */
2346
+	protected $copy_attendee_info = true;
2347
+
2348
+
2349
+	/**
2350
+	 *    class constructor
2351
+	 *
2352
+	 * @access    public
2353
+	 */
2354
+	public function __construct()
2355
+	{
2356
+		// set default registration settings
2357
+		$this->default_STS_ID = EEM_Registration::status_id_pending_payment;
2358
+		$this->email_validation_level = 'wp_default';
2359
+		$this->show_pending_payment_options = true;
2360
+		$this->skip_reg_confirmation = true;
2361
+		$this->reg_steps = array();
2362
+		$this->reg_confirmation_last = false;
2363
+		$this->use_bot_trap = true;
2364
+		$this->use_encryption = true;
2365
+		$this->use_captcha = false;
2366
+		$this->recaptcha_theme = 'light';
2367
+		$this->recaptcha_badge = 'bottomleft';
2368
+		$this->recaptcha_type = 'image';
2369
+		$this->recaptcha_language = 'en';
2370
+		$this->recaptcha_publickey = null;
2371
+		$this->recaptcha_privatekey = null;
2372
+		$this->recaptcha_protected_forms = array();
2373
+		$this->recaptcha_width = 500;
2374
+		$this->default_maximum_number_of_tickets = 10;
2375
+		$this->consent_checkbox_enabled = false;
2376
+		$this->consent_checkbox_label_text = '';
2377
+		$this->gateway_log_lifespan = '7 days';
2378
+		$this->copy_attendee_info = true;
2379
+	}
2380
+
2381
+
2382
+	/**
2383
+	 * This is called by the config loader and hooks are initialized AFTER the config has been populated.
2384
+	 *
2385
+	 * @since 4.8.8.rc.019
2386
+	 */
2387
+	public function do_hooks()
2388
+	{
2389
+		add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_reg_status_on_EEM_Event'));
2390
+		add_action('AHEE__EE_Config___load_core_config__end', array($this, 'set_default_max_ticket_on_EEM_Event'));
2391
+		add_action('setup_theme', array($this, 'setDefaultCheckboxLabelText'));
2392
+	}
2393
+
2394
+
2395
+	/**
2396
+	 * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the
2397
+	 * EVT_default_registration_status field matches the config setting for default_STS_ID.
2398
+	 */
2399
+	public function set_default_reg_status_on_EEM_Event()
2400
+	{
2401
+		EEM_Event::set_default_reg_status($this->default_STS_ID);
2402
+	}
2403
+
2404
+
2405
+	/**
2406
+	 * Hooked into `AHEE__EE_Config___load_core_config__end` to ensure the default for the EVT_additional_limit field
2407
+	 * for Events matches the config setting for default_maximum_number_of_tickets
2408
+	 */
2409
+	public function set_default_max_ticket_on_EEM_Event()
2410
+	{
2411
+		EEM_Event::set_default_additional_limit($this->default_maximum_number_of_tickets);
2412
+	}
2413
+
2414
+
2415
+	/**
2416
+	 * Sets the default consent checkbox text. This needs to be done a bit later than when EE_Registration_Config is
2417
+	 * constructed because that happens before we can get the privacy policy page's permalink.
2418
+	 *
2419
+	 * @throws InvalidArgumentException
2420
+	 * @throws InvalidDataTypeException
2421
+	 * @throws InvalidInterfaceException
2422
+	 */
2423
+	public function setDefaultCheckboxLabelText()
2424
+	{
2425
+		if (
2426
+			$this->getConsentCheckboxLabelText() === null
2427
+			|| $this->getConsentCheckboxLabelText() === ''
2428
+		) {
2429
+			$opening_a_tag = '';
2430
+			$closing_a_tag = '';
2431
+			if (function_exists('get_privacy_policy_url')) {
2432
+				$privacy_page_url = get_privacy_policy_url();
2433
+				if (! empty($privacy_page_url)) {
2434
+					$opening_a_tag = '<a href="' . $privacy_page_url . '" target="_blank">';
2435
+					$closing_a_tag = '</a>';
2436
+				}
2437
+			}
2438
+			$loader = LoaderFactory::getLoader();
2439
+			$org_config = $loader->getShared('EE_Organization_Config');
2440
+			/**
2441
+			 * @var $org_config EE_Organization_Config
2442
+			 */
2443
+
2444
+			$this->setConsentCheckboxLabelText(
2445
+				sprintf(
2446
+					esc_html__(
2447
+						'I consent to %1$s storing and using my personal information, according to their %2$sprivacy policy%3$s.',
2448
+						'event_espresso'
2449
+					),
2450
+					$org_config->name,
2451
+					$opening_a_tag,
2452
+					$closing_a_tag
2453
+				)
2454
+			);
2455
+		}
2456
+	}
2457
+
2458
+
2459
+	/**
2460
+	 * @return boolean
2461
+	 */
2462
+	public function track_invalid_checkout_access()
2463
+	{
2464
+		return $this->track_invalid_checkout_access;
2465
+	}
2466
+
2467
+
2468
+	/**
2469
+	 * @param boolean $track_invalid_checkout_access
2470
+	 */
2471
+	public function set_track_invalid_checkout_access($track_invalid_checkout_access)
2472
+	{
2473
+		$this->track_invalid_checkout_access = filter_var(
2474
+			$track_invalid_checkout_access,
2475
+			FILTER_VALIDATE_BOOLEAN
2476
+		);
2477
+	}
2478
+
2479
+	/**
2480
+	 * @return boolean
2481
+	 */
2482
+	public function copyAttendeeInfo()
2483
+	{
2484
+		return $this->copy_attendee_info;
2485
+	}
2486
+
2487
+
2488
+	/**
2489
+	 * @param boolean $copy_attendee_info
2490
+	 */
2491
+	public function setCopyAttendeeInfo($copy_attendee_info)
2492
+	{
2493
+		$this->copy_attendee_info = filter_var(
2494
+			$copy_attendee_info,
2495
+			FILTER_VALIDATE_BOOLEAN
2496
+		);
2497
+	}
2498
+
2499
+
2500
+	/**
2501
+	 * Gets the options to make availalbe for the gateway log lifespan
2502
+	 * @return array
2503
+	 */
2504
+	public function gatewayLogLifespanOptions()
2505
+	{
2506
+		return (array) apply_filters(
2507
+			'FHEE_EE_Admin_Config__gatewayLogLifespanOptions',
2508
+			array(
2509
+				'1 second' => esc_html__('Don\'t Log At All', 'event_espresso'),
2510
+				'1 day' => esc_html__('1 Day', 'event_espresso'),
2511
+				'7 days' => esc_html__('7 Days', 'event_espresso'),
2512
+				'14 days' => esc_html__('14 Days', 'event_espresso'),
2513
+				'30 days' => esc_html__('30 Days', 'event_espresso')
2514
+			)
2515
+		);
2516
+	}
2517
+
2518
+
2519
+	/**
2520
+	 * @return bool
2521
+	 */
2522
+	public function isConsentCheckboxEnabled()
2523
+	{
2524
+		return $this->consent_checkbox_enabled;
2525
+	}
2526
+
2527
+
2528
+	/**
2529
+	 * @param bool $consent_checkbox_enabled
2530
+	 */
2531
+	public function setConsentCheckboxEnabled($consent_checkbox_enabled)
2532
+	{
2533
+		$this->consent_checkbox_enabled = filter_var(
2534
+			$consent_checkbox_enabled,
2535
+			FILTER_VALIDATE_BOOLEAN
2536
+		);
2537
+	}
2538
+
2539
+
2540
+	/**
2541
+	 * @return string
2542
+	 */
2543
+	public function getConsentCheckboxLabelText()
2544
+	{
2545
+		return $this->consent_checkbox_label_text;
2546
+	}
2547
+
2548
+
2549
+	/**
2550
+	 * @param string $consent_checkbox_label_text
2551
+	 */
2552
+	public function setConsentCheckboxLabelText($consent_checkbox_label_text)
2553
+	{
2554
+		$this->consent_checkbox_label_text = (string) $consent_checkbox_label_text;
2555
+	}
2556 2556
 }
2557 2557
 
2558 2558
 /**
@@ -2560,143 +2560,143 @@  discard block
 block discarded – undo
2560 2560
  */
2561 2561
 class EE_Admin_Config extends EE_Config_Base
2562 2562
 {
2563
-    /**
2564
-     * @var boolean $use_personnel_manager
2565
-     */
2566
-    public $use_personnel_manager;
2567
-
2568
-    /**
2569
-     * @var boolean $use_dashboard_widget
2570
-     */
2571
-    public $use_dashboard_widget;
2572
-
2573
-    /**
2574
-     * @var int $events_in_dashboard
2575
-     */
2576
-    public $events_in_dashboard;
2577
-
2578
-    /**
2579
-     * @var boolean $use_event_timezones
2580
-     */
2581
-    public $use_event_timezones;
2582
-
2583
-    /**
2584
-     * @var string $log_file_name
2585
-     */
2586
-    public $log_file_name;
2587
-
2588
-    /**
2589
-     * @var string $debug_file_name
2590
-     */
2591
-    public $debug_file_name;
2592
-
2593
-    /**
2594
-     * @var boolean $use_remote_logging
2595
-     */
2596
-    public $use_remote_logging;
2597
-
2598
-    /**
2599
-     * @var string $remote_logging_url
2600
-     */
2601
-    public $remote_logging_url;
2602
-
2603
-    /**
2604
-     * @var boolean $show_reg_footer
2605
-     */
2606
-    public $show_reg_footer;
2607
-
2608
-    /**
2609
-     * @var string $affiliate_id
2610
-     */
2611
-    public $affiliate_id;
2612
-
2613
-    /**
2614
-     * adds extra layer of encoding to session data to prevent serialization errors
2615
-     * but is incompatible with some server configuration errors
2616
-     * if you get "500 internal server errors" during registration, try turning this on
2617
-     * if you get PHP fatal errors regarding base 64 methods not defined, then turn this off
2618
-     *
2619
-     * @var boolean $encode_session_data
2620
-     */
2621
-    private $encode_session_data = false;
2622
-
2623
-
2624
-    /**
2625
-     *    class constructor
2626
-     *
2627
-     * @access    public
2628
-     */
2629
-    public function __construct()
2630
-    {
2631
-        // set default general admin settings
2632
-        $this->use_personnel_manager = true;
2633
-        $this->use_dashboard_widget = true;
2634
-        $this->events_in_dashboard = 30;
2635
-        $this->use_event_timezones = false;
2636
-        $this->use_remote_logging = false;
2637
-        $this->remote_logging_url = null;
2638
-        $this->show_reg_footer = apply_filters(
2639
-            'FHEE__EE_Admin_Config__show_reg_footer__default',
2640
-            false
2641
-        );
2642
-        $this->affiliate_id = 'default';
2643
-        $this->encode_session_data = false;
2644
-    }
2645
-
2646
-
2647
-    /**
2648
-     * @param bool $reset
2649
-     * @return string
2650
-     */
2651
-    public function log_file_name($reset = false)
2652
-    {
2653
-        if (empty($this->log_file_name) || $reset) {
2654
-            $this->log_file_name = sanitize_key('espresso_log_' . md5(uniqid('', true))) . '.txt';
2655
-            EE_Config::instance()->update_espresso_config(false, false);
2656
-        }
2657
-        return $this->log_file_name;
2658
-    }
2659
-
2660
-
2661
-    /**
2662
-     * @param bool $reset
2663
-     * @return string
2664
-     */
2665
-    public function debug_file_name($reset = false)
2666
-    {
2667
-        if (empty($this->debug_file_name) || $reset) {
2668
-            $this->debug_file_name = sanitize_key('espresso_debug_' . md5(uniqid('', true))) . '.txt';
2669
-            EE_Config::instance()->update_espresso_config(false, false);
2670
-        }
2671
-        return $this->debug_file_name;
2672
-    }
2673
-
2674
-
2675
-    /**
2676
-     * @return string
2677
-     */
2678
-    public function affiliate_id()
2679
-    {
2680
-        return ! empty($this->affiliate_id) ? $this->affiliate_id : 'default';
2681
-    }
2682
-
2683
-
2684
-    /**
2685
-     * @return boolean
2686
-     */
2687
-    public function encode_session_data()
2688
-    {
2689
-        return filter_var($this->encode_session_data, FILTER_VALIDATE_BOOLEAN);
2690
-    }
2691
-
2692
-
2693
-    /**
2694
-     * @param boolean $encode_session_data
2695
-     */
2696
-    public function set_encode_session_data($encode_session_data)
2697
-    {
2698
-        $this->encode_session_data = filter_var($encode_session_data, FILTER_VALIDATE_BOOLEAN);
2699
-    }
2563
+	/**
2564
+	 * @var boolean $use_personnel_manager
2565
+	 */
2566
+	public $use_personnel_manager;
2567
+
2568
+	/**
2569
+	 * @var boolean $use_dashboard_widget
2570
+	 */
2571
+	public $use_dashboard_widget;
2572
+
2573
+	/**
2574
+	 * @var int $events_in_dashboard
2575
+	 */
2576
+	public $events_in_dashboard;
2577
+
2578
+	/**
2579
+	 * @var boolean $use_event_timezones
2580
+	 */
2581
+	public $use_event_timezones;
2582
+
2583
+	/**
2584
+	 * @var string $log_file_name
2585
+	 */
2586
+	public $log_file_name;
2587
+
2588
+	/**
2589
+	 * @var string $debug_file_name
2590
+	 */
2591
+	public $debug_file_name;
2592
+
2593
+	/**
2594
+	 * @var boolean $use_remote_logging
2595
+	 */
2596
+	public $use_remote_logging;
2597
+
2598
+	/**
2599
+	 * @var string $remote_logging_url
2600
+	 */
2601
+	public $remote_logging_url;
2602
+
2603
+	/**
2604
+	 * @var boolean $show_reg_footer
2605
+	 */
2606
+	public $show_reg_footer;
2607
+
2608
+	/**
2609
+	 * @var string $affiliate_id
2610
+	 */
2611
+	public $affiliate_id;
2612
+
2613
+	/**
2614
+	 * adds extra layer of encoding to session data to prevent serialization errors
2615
+	 * but is incompatible with some server configuration errors
2616
+	 * if you get "500 internal server errors" during registration, try turning this on
2617
+	 * if you get PHP fatal errors regarding base 64 methods not defined, then turn this off
2618
+	 *
2619
+	 * @var boolean $encode_session_data
2620
+	 */
2621
+	private $encode_session_data = false;
2622
+
2623
+
2624
+	/**
2625
+	 *    class constructor
2626
+	 *
2627
+	 * @access    public
2628
+	 */
2629
+	public function __construct()
2630
+	{
2631
+		// set default general admin settings
2632
+		$this->use_personnel_manager = true;
2633
+		$this->use_dashboard_widget = true;
2634
+		$this->events_in_dashboard = 30;
2635
+		$this->use_event_timezones = false;
2636
+		$this->use_remote_logging = false;
2637
+		$this->remote_logging_url = null;
2638
+		$this->show_reg_footer = apply_filters(
2639
+			'FHEE__EE_Admin_Config__show_reg_footer__default',
2640
+			false
2641
+		);
2642
+		$this->affiliate_id = 'default';
2643
+		$this->encode_session_data = false;
2644
+	}
2645
+
2646
+
2647
+	/**
2648
+	 * @param bool $reset
2649
+	 * @return string
2650
+	 */
2651
+	public function log_file_name($reset = false)
2652
+	{
2653
+		if (empty($this->log_file_name) || $reset) {
2654
+			$this->log_file_name = sanitize_key('espresso_log_' . md5(uniqid('', true))) . '.txt';
2655
+			EE_Config::instance()->update_espresso_config(false, false);
2656
+		}
2657
+		return $this->log_file_name;
2658
+	}
2659
+
2660
+
2661
+	/**
2662
+	 * @param bool $reset
2663
+	 * @return string
2664
+	 */
2665
+	public function debug_file_name($reset = false)
2666
+	{
2667
+		if (empty($this->debug_file_name) || $reset) {
2668
+			$this->debug_file_name = sanitize_key('espresso_debug_' . md5(uniqid('', true))) . '.txt';
2669
+			EE_Config::instance()->update_espresso_config(false, false);
2670
+		}
2671
+		return $this->debug_file_name;
2672
+	}
2673
+
2674
+
2675
+	/**
2676
+	 * @return string
2677
+	 */
2678
+	public function affiliate_id()
2679
+	{
2680
+		return ! empty($this->affiliate_id) ? $this->affiliate_id : 'default';
2681
+	}
2682
+
2683
+
2684
+	/**
2685
+	 * @return boolean
2686
+	 */
2687
+	public function encode_session_data()
2688
+	{
2689
+		return filter_var($this->encode_session_data, FILTER_VALIDATE_BOOLEAN);
2690
+	}
2691
+
2692
+
2693
+	/**
2694
+	 * @param boolean $encode_session_data
2695
+	 */
2696
+	public function set_encode_session_data($encode_session_data)
2697
+	{
2698
+		$this->encode_session_data = filter_var($encode_session_data, FILTER_VALIDATE_BOOLEAN);
2699
+	}
2700 2700
 }
2701 2701
 
2702 2702
 /**
@@ -2704,70 +2704,70 @@  discard block
 block discarded – undo
2704 2704
  */
2705 2705
 class EE_Template_Config extends EE_Config_Base
2706 2706
 {
2707
-    /**
2708
-     * @var boolean $enable_default_style
2709
-     */
2710
-    public $enable_default_style;
2711
-
2712
-    /**
2713
-     * @var string $custom_style_sheet
2714
-     */
2715
-    public $custom_style_sheet;
2716
-
2717
-    /**
2718
-     * @var boolean $display_address_in_regform
2719
-     */
2720
-    public $display_address_in_regform;
2721
-
2722
-    /**
2723
-     * @var int $display_description_on_multi_reg_page
2724
-     */
2725
-    public $display_description_on_multi_reg_page;
2726
-
2727
-    /**
2728
-     * @var boolean $use_custom_templates
2729
-     */
2730
-    public $use_custom_templates;
2731
-
2732
-    /**
2733
-     * @var string $current_espresso_theme
2734
-     */
2735
-    public $current_espresso_theme;
2736
-
2737
-    /**
2738
-     * @var EE_Ticket_Selector_Config $EED_Ticket_Selector
2739
-     */
2740
-    public $EED_Ticket_Selector;
2741
-
2742
-    /**
2743
-     * @var EE_Event_Single_Config $EED_Event_Single
2744
-     */
2745
-    public $EED_Event_Single;
2746
-
2747
-    /**
2748
-     * @var EE_Events_Archive_Config $EED_Events_Archive
2749
-     */
2750
-    public $EED_Events_Archive;
2751
-
2752
-
2753
-    /**
2754
-     *    class constructor
2755
-     *
2756
-     * @access    public
2757
-     */
2758
-    public function __construct()
2759
-    {
2760
-        // set default template settings
2761
-        $this->enable_default_style = true;
2762
-        $this->custom_style_sheet = null;
2763
-        $this->display_address_in_regform = true;
2764
-        $this->display_description_on_multi_reg_page = false;
2765
-        $this->use_custom_templates = false;
2766
-        $this->current_espresso_theme = 'Espresso_Arabica_2014';
2767
-        $this->EED_Event_Single = null;
2768
-        $this->EED_Events_Archive = null;
2769
-        $this->EED_Ticket_Selector = null;
2770
-    }
2707
+	/**
2708
+	 * @var boolean $enable_default_style
2709
+	 */
2710
+	public $enable_default_style;
2711
+
2712
+	/**
2713
+	 * @var string $custom_style_sheet
2714
+	 */
2715
+	public $custom_style_sheet;
2716
+
2717
+	/**
2718
+	 * @var boolean $display_address_in_regform
2719
+	 */
2720
+	public $display_address_in_regform;
2721
+
2722
+	/**
2723
+	 * @var int $display_description_on_multi_reg_page
2724
+	 */
2725
+	public $display_description_on_multi_reg_page;
2726
+
2727
+	/**
2728
+	 * @var boolean $use_custom_templates
2729
+	 */
2730
+	public $use_custom_templates;
2731
+
2732
+	/**
2733
+	 * @var string $current_espresso_theme
2734
+	 */
2735
+	public $current_espresso_theme;
2736
+
2737
+	/**
2738
+	 * @var EE_Ticket_Selector_Config $EED_Ticket_Selector
2739
+	 */
2740
+	public $EED_Ticket_Selector;
2741
+
2742
+	/**
2743
+	 * @var EE_Event_Single_Config $EED_Event_Single
2744
+	 */
2745
+	public $EED_Event_Single;
2746
+
2747
+	/**
2748
+	 * @var EE_Events_Archive_Config $EED_Events_Archive
2749
+	 */
2750
+	public $EED_Events_Archive;
2751
+
2752
+
2753
+	/**
2754
+	 *    class constructor
2755
+	 *
2756
+	 * @access    public
2757
+	 */
2758
+	public function __construct()
2759
+	{
2760
+		// set default template settings
2761
+		$this->enable_default_style = true;
2762
+		$this->custom_style_sheet = null;
2763
+		$this->display_address_in_regform = true;
2764
+		$this->display_description_on_multi_reg_page = false;
2765
+		$this->use_custom_templates = false;
2766
+		$this->current_espresso_theme = 'Espresso_Arabica_2014';
2767
+		$this->EED_Event_Single = null;
2768
+		$this->EED_Events_Archive = null;
2769
+		$this->EED_Ticket_Selector = null;
2770
+	}
2771 2771
 }
2772 2772
 
2773 2773
 /**
@@ -2775,114 +2775,114 @@  discard block
 block discarded – undo
2775 2775
  */
2776 2776
 class EE_Map_Config extends EE_Config_Base
2777 2777
 {
2778
-    /**
2779
-     * @var boolean $use_google_maps
2780
-     */
2781
-    public $use_google_maps;
2782
-
2783
-    /**
2784
-     * @var string $api_key
2785
-     */
2786
-    public $google_map_api_key;
2787
-
2788
-    /**
2789
-     * @var int $event_details_map_width
2790
-     */
2791
-    public $event_details_map_width;
2792
-
2793
-    /**
2794
-     * @var int $event_details_map_height
2795
-     */
2796
-    public $event_details_map_height;
2797
-
2798
-    /**
2799
-     * @var int $event_details_map_zoom
2800
-     */
2801
-    public $event_details_map_zoom;
2802
-
2803
-    /**
2804
-     * @var boolean $event_details_display_nav
2805
-     */
2806
-    public $event_details_display_nav;
2807
-
2808
-    /**
2809
-     * @var boolean $event_details_nav_size
2810
-     */
2811
-    public $event_details_nav_size;
2812
-
2813
-    /**
2814
-     * @var string $event_details_control_type
2815
-     */
2816
-    public $event_details_control_type;
2817
-
2818
-    /**
2819
-     * @var string $event_details_map_align
2820
-     */
2821
-    public $event_details_map_align;
2822
-
2823
-    /**
2824
-     * @var int $event_list_map_width
2825
-     */
2826
-    public $event_list_map_width;
2827
-
2828
-    /**
2829
-     * @var int $event_list_map_height
2830
-     */
2831
-    public $event_list_map_height;
2832
-
2833
-    /**
2834
-     * @var int $event_list_map_zoom
2835
-     */
2836
-    public $event_list_map_zoom;
2837
-
2838
-    /**
2839
-     * @var boolean $event_list_display_nav
2840
-     */
2841
-    public $event_list_display_nav;
2842
-
2843
-    /**
2844
-     * @var boolean $event_list_nav_size
2845
-     */
2846
-    public $event_list_nav_size;
2847
-
2848
-    /**
2849
-     * @var string $event_list_control_type
2850
-     */
2851
-    public $event_list_control_type;
2852
-
2853
-    /**
2854
-     * @var string $event_list_map_align
2855
-     */
2856
-    public $event_list_map_align;
2857
-
2858
-
2859
-    /**
2860
-     *    class constructor
2861
-     *
2862
-     * @access    public
2863
-     */
2864
-    public function __construct()
2865
-    {
2866
-        // set default map settings
2867
-        $this->use_google_maps = true;
2868
-        $this->google_map_api_key = '';
2869
-        // for event details pages (reg page)
2870
-        $this->event_details_map_width = 585;            // ee_map_width_single
2871
-        $this->event_details_map_height = 362;            // ee_map_height_single
2872
-        $this->event_details_map_zoom = 14;            // ee_map_zoom_single
2873
-        $this->event_details_display_nav = true;            // ee_map_nav_display_single
2874
-        $this->event_details_nav_size = false;            // ee_map_nav_size_single
2875
-        $this->event_details_control_type = 'default';        // ee_map_type_control_single
2876
-        $this->event_details_map_align = 'center';            // ee_map_align_single
2877
-        // for event list pages
2878
-        $this->event_list_map_width = 300;            // ee_map_width
2879
-        $this->event_list_map_height = 185;        // ee_map_height
2880
-        $this->event_list_map_zoom = 12;            // ee_map_zoom
2881
-        $this->event_list_display_nav = false;        // ee_map_nav_display
2882
-        $this->event_list_nav_size = true;            // ee_map_nav_size
2883
-        $this->event_list_control_type = 'dropdown';        // ee_map_type_control
2884
-        $this->event_list_map_align = 'center';            // ee_map_align
2885
-    }
2778
+	/**
2779
+	 * @var boolean $use_google_maps
2780
+	 */
2781
+	public $use_google_maps;
2782
+
2783
+	/**
2784
+	 * @var string $api_key
2785
+	 */
2786
+	public $google_map_api_key;
2787
+
2788
+	/**
2789
+	 * @var int $event_details_map_width
2790
+	 */
2791
+	public $event_details_map_width;
2792
+
2793
+	/**
2794
+	 * @var int $event_details_map_height
2795
+	 */
2796
+	public $event_details_map_height;
2797
+
2798
+	/**
2799
+	 * @var int $event_details_map_zoom
2800
+	 */
2801
+	public $event_details_map_zoom;
2802
+
2803
+	/**
2804
+	 * @var boolean $event_details_display_nav
2805
+	 */
2806
+	public $event_details_display_nav;
2807
+
2808
+	/**
2809
+	 * @var boolean $event_details_nav_size
2810
+	 */
2811
+	public $event_details_nav_size;
2812
+
2813
+	/**
2814
+	 * @var string $event_details_control_type
2815
+	 */
2816
+	public $event_details_control_type;
2817
+
2818
+	/**
2819
+	 * @var string $event_details_map_align
2820
+	 */
2821
+	public $event_details_map_align;
2822
+
2823
+	/**
2824
+	 * @var int $event_list_map_width
2825
+	 */
2826
+	public $event_list_map_width;
2827
+
2828
+	/**
2829
+	 * @var int $event_list_map_height
2830
+	 */
2831
+	public $event_list_map_height;
2832
+
2833
+	/**
2834
+	 * @var int $event_list_map_zoom
2835
+	 */
2836
+	public $event_list_map_zoom;
2837
+
2838
+	/**
2839
+	 * @var boolean $event_list_display_nav
2840
+	 */
2841
+	public $event_list_display_nav;
2842
+
2843
+	/**
2844
+	 * @var boolean $event_list_nav_size
2845
+	 */
2846
+	public $event_list_nav_size;
2847
+
2848
+	/**
2849
+	 * @var string $event_list_control_type
2850
+	 */
2851
+	public $event_list_control_type;
2852
+
2853
+	/**
2854
+	 * @var string $event_list_map_align
2855
+	 */
2856
+	public $event_list_map_align;
2857
+
2858
+
2859
+	/**
2860
+	 *    class constructor
2861
+	 *
2862
+	 * @access    public
2863
+	 */
2864
+	public function __construct()
2865
+	{
2866
+		// set default map settings
2867
+		$this->use_google_maps = true;
2868
+		$this->google_map_api_key = '';
2869
+		// for event details pages (reg page)
2870
+		$this->event_details_map_width = 585;            // ee_map_width_single
2871
+		$this->event_details_map_height = 362;            // ee_map_height_single
2872
+		$this->event_details_map_zoom = 14;            // ee_map_zoom_single
2873
+		$this->event_details_display_nav = true;            // ee_map_nav_display_single
2874
+		$this->event_details_nav_size = false;            // ee_map_nav_size_single
2875
+		$this->event_details_control_type = 'default';        // ee_map_type_control_single
2876
+		$this->event_details_map_align = 'center';            // ee_map_align_single
2877
+		// for event list pages
2878
+		$this->event_list_map_width = 300;            // ee_map_width
2879
+		$this->event_list_map_height = 185;        // ee_map_height
2880
+		$this->event_list_map_zoom = 12;            // ee_map_zoom
2881
+		$this->event_list_display_nav = false;        // ee_map_nav_display
2882
+		$this->event_list_nav_size = true;            // ee_map_nav_size
2883
+		$this->event_list_control_type = 'dropdown';        // ee_map_type_control
2884
+		$this->event_list_map_align = 'center';            // ee_map_align
2885
+	}
2886 2886
 }
2887 2887
 
2888 2888
 /**
@@ -2890,46 +2890,46 @@  discard block
 block discarded – undo
2890 2890
  */
2891 2891
 class EE_Events_Archive_Config extends EE_Config_Base
2892 2892
 {
2893
-    public $display_status_banner;
2893
+	public $display_status_banner;
2894 2894
 
2895
-    public $display_description;
2895
+	public $display_description;
2896 2896
 
2897
-    public $display_ticket_selector;
2897
+	public $display_ticket_selector;
2898 2898
 
2899
-    public $display_datetimes;
2899
+	public $display_datetimes;
2900 2900
 
2901
-    public $display_venue;
2901
+	public $display_venue;
2902 2902
 
2903
-    public $display_expired_events;
2903
+	public $display_expired_events;
2904 2904
 
2905
-    public $use_sortable_display_order;
2905
+	public $use_sortable_display_order;
2906 2906
 
2907
-    public $display_order_tickets;
2907
+	public $display_order_tickets;
2908 2908
 
2909
-    public $display_order_datetimes;
2909
+	public $display_order_datetimes;
2910 2910
 
2911
-    public $display_order_event;
2911
+	public $display_order_event;
2912 2912
 
2913
-    public $display_order_venue;
2913
+	public $display_order_venue;
2914 2914
 
2915 2915
 
2916
-    /**
2917
-     *    class constructor
2918
-     */
2919
-    public function __construct()
2920
-    {
2921
-        $this->display_status_banner = 0;
2922
-        $this->display_description = 1;
2923
-        $this->display_ticket_selector = 0;
2924
-        $this->display_datetimes = 1;
2925
-        $this->display_venue = 0;
2926
-        $this->display_expired_events = 0;
2927
-        $this->use_sortable_display_order = false;
2928
-        $this->display_order_tickets = 100;
2929
-        $this->display_order_datetimes = 110;
2930
-        $this->display_order_event = 120;
2931
-        $this->display_order_venue = 130;
2932
-    }
2916
+	/**
2917
+	 *    class constructor
2918
+	 */
2919
+	public function __construct()
2920
+	{
2921
+		$this->display_status_banner = 0;
2922
+		$this->display_description = 1;
2923
+		$this->display_ticket_selector = 0;
2924
+		$this->display_datetimes = 1;
2925
+		$this->display_venue = 0;
2926
+		$this->display_expired_events = 0;
2927
+		$this->use_sortable_display_order = false;
2928
+		$this->display_order_tickets = 100;
2929
+		$this->display_order_datetimes = 110;
2930
+		$this->display_order_event = 120;
2931
+		$this->display_order_venue = 130;
2932
+	}
2933 2933
 }
2934 2934
 
2935 2935
 /**
@@ -2937,34 +2937,34 @@  discard block
 block discarded – undo
2937 2937
  */
2938 2938
 class EE_Event_Single_Config extends EE_Config_Base
2939 2939
 {
2940
-    public $display_status_banner_single;
2940
+	public $display_status_banner_single;
2941 2941
 
2942
-    public $display_venue;
2942
+	public $display_venue;
2943 2943
 
2944
-    public $use_sortable_display_order;
2944
+	public $use_sortable_display_order;
2945 2945
 
2946
-    public $display_order_tickets;
2946
+	public $display_order_tickets;
2947 2947
 
2948
-    public $display_order_datetimes;
2948
+	public $display_order_datetimes;
2949 2949
 
2950
-    public $display_order_event;
2950
+	public $display_order_event;
2951 2951
 
2952
-    public $display_order_venue;
2952
+	public $display_order_venue;
2953 2953
 
2954 2954
 
2955
-    /**
2956
-     *    class constructor
2957
-     */
2958
-    public function __construct()
2959
-    {
2960
-        $this->display_status_banner_single = 0;
2961
-        $this->display_venue = 1;
2962
-        $this->use_sortable_display_order = false;
2963
-        $this->display_order_tickets = 100;
2964
-        $this->display_order_datetimes = 110;
2965
-        $this->display_order_event = 120;
2966
-        $this->display_order_venue = 130;
2967
-    }
2955
+	/**
2956
+	 *    class constructor
2957
+	 */
2958
+	public function __construct()
2959
+	{
2960
+		$this->display_status_banner_single = 0;
2961
+		$this->display_venue = 1;
2962
+		$this->use_sortable_display_order = false;
2963
+		$this->display_order_tickets = 100;
2964
+		$this->display_order_datetimes = 110;
2965
+		$this->display_order_event = 120;
2966
+		$this->display_order_venue = 130;
2967
+	}
2968 2968
 }
2969 2969
 
2970 2970
 /**
@@ -2972,172 +2972,172 @@  discard block
 block discarded – undo
2972 2972
  */
2973 2973
 class EE_Ticket_Selector_Config extends EE_Config_Base
2974 2974
 {
2975
-    /**
2976
-     * constant to indicate that a datetime selector should NEVER be shown for ticket selectors
2977
-     */
2978
-    const DO_NOT_SHOW_DATETIME_SELECTOR = 'no_datetime_selector';
2979
-
2980
-    /**
2981
-     * constant to indicate that a datetime selector should only be shown for ticket selectors
2982
-     * when the number of datetimes for the event matches the value set for $datetime_selector_threshold
2983
-     */
2984
-    const MAYBE_SHOW_DATETIME_SELECTOR = 'maybe_datetime_selector';
2985
-
2986
-    /**
2987
-     * @var boolean $show_ticket_sale_columns
2988
-     */
2989
-    public $show_ticket_sale_columns;
2990
-
2991
-    /**
2992
-     * @var boolean $show_ticket_details
2993
-     */
2994
-    public $show_ticket_details;
2995
-
2996
-    /**
2997
-     * @var boolean $show_expired_tickets
2998
-     */
2999
-    public $show_expired_tickets;
3000
-
3001
-    /**
3002
-     * whether or not to display a dropdown box populated with event datetimes
3003
-     * that toggles which tickets are displayed for a ticket selector.
3004
-     * uses one of the *_DATETIME_SELECTOR constants defined above
3005
-     *
3006
-     * @var string $show_datetime_selector
3007
-     */
3008
-    private $show_datetime_selector = 'no_datetime_selector';
3009
-
3010
-    /**
3011
-     * the number of datetimes an event has to have before conditionally displaying a datetime selector
3012
-     *
3013
-     * @var int $datetime_selector_threshold
3014
-     */
3015
-    private $datetime_selector_threshold = 3;
3016
-
3017
-    /**
3018
-     * determines the maximum number of "checked" dates in the date and time filter
3019
-     *
3020
-     * @var int $datetime_selector_checked
3021
-     */
3022
-    private $datetime_selector_max_checked = 10;
3023
-
3024
-
3025
-    /**
3026
-     *    class constructor
3027
-     */
3028
-    public function __construct()
3029
-    {
3030
-        $this->show_ticket_sale_columns = true;
3031
-        $this->show_ticket_details = true;
3032
-        $this->show_expired_tickets = true;
3033
-        $this->show_datetime_selector = EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3034
-        $this->datetime_selector_threshold = 3;
3035
-        $this->datetime_selector_max_checked = 10;
3036
-    }
3037
-
3038
-
3039
-    /**
3040
-     * returns true if a datetime selector should be displayed
3041
-     *
3042
-     * @param array $datetimes
3043
-     * @return bool
3044
-     */
3045
-    public function showDatetimeSelector(array $datetimes)
3046
-    {
3047
-        // if the settings are NOT: don't show OR below threshold, THEN active = true
3048
-        return ! (
3049
-            $this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR
3050
-            || (
3051
-                $this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR
3052
-                && count($datetimes) < $this->getDatetimeSelectorThreshold()
3053
-            )
3054
-        );
3055
-    }
3056
-
3057
-
3058
-    /**
3059
-     * @return string
3060
-     */
3061
-    public function getShowDatetimeSelector()
3062
-    {
3063
-        return $this->show_datetime_selector;
3064
-    }
3065
-
3066
-
3067
-    /**
3068
-     * @param bool $keys_only
3069
-     * @return array
3070
-     */
3071
-    public function getShowDatetimeSelectorOptions($keys_only = true)
3072
-    {
3073
-        return $keys_only
3074
-            ? array(
3075
-                EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR,
3076
-                EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR,
3077
-            )
3078
-            : array(
3079
-                EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR => esc_html__(
3080
-                    'Do not show date & time filter',
3081
-                    'event_espresso'
3082
-                ),
3083
-                EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR  => esc_html__(
3084
-                    'Maybe show date & time filter',
3085
-                    'event_espresso'
3086
-                ),
3087
-            );
3088
-    }
3089
-
3090
-
3091
-    /**
3092
-     * @param string $show_datetime_selector
3093
-     */
3094
-    public function setShowDatetimeSelector($show_datetime_selector)
3095
-    {
3096
-        $this->show_datetime_selector = in_array(
3097
-            $show_datetime_selector,
3098
-            $this->getShowDatetimeSelectorOptions(),
3099
-            true
3100
-        )
3101
-            ? $show_datetime_selector
3102
-            : EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3103
-    }
3104
-
3105
-
3106
-    /**
3107
-     * @return int
3108
-     */
3109
-    public function getDatetimeSelectorThreshold()
3110
-    {
3111
-        return $this->datetime_selector_threshold;
3112
-    }
3113
-
3114
-
3115
-    /**
3116
-     * @param int $datetime_selector_threshold
3117
-     */
3118
-    public function setDatetimeSelectorThreshold($datetime_selector_threshold)
3119
-    {
3120
-        $datetime_selector_threshold = absint($datetime_selector_threshold);
3121
-        $this->datetime_selector_threshold = $datetime_selector_threshold ? $datetime_selector_threshold : 3;
3122
-    }
3123
-
3124
-
3125
-    /**
3126
-     * @return int
3127
-     */
3128
-    public function getDatetimeSelectorMaxChecked()
3129
-    {
3130
-        return $this->datetime_selector_max_checked;
3131
-    }
3132
-
3133
-
3134
-    /**
3135
-     * @param int $datetime_selector_max_checked
3136
-     */
3137
-    public function setDatetimeSelectorMaxChecked($datetime_selector_max_checked)
3138
-    {
3139
-        $this->datetime_selector_max_checked = absint($datetime_selector_max_checked);
3140
-    }
2975
+	/**
2976
+	 * constant to indicate that a datetime selector should NEVER be shown for ticket selectors
2977
+	 */
2978
+	const DO_NOT_SHOW_DATETIME_SELECTOR = 'no_datetime_selector';
2979
+
2980
+	/**
2981
+	 * constant to indicate that a datetime selector should only be shown for ticket selectors
2982
+	 * when the number of datetimes for the event matches the value set for $datetime_selector_threshold
2983
+	 */
2984
+	const MAYBE_SHOW_DATETIME_SELECTOR = 'maybe_datetime_selector';
2985
+
2986
+	/**
2987
+	 * @var boolean $show_ticket_sale_columns
2988
+	 */
2989
+	public $show_ticket_sale_columns;
2990
+
2991
+	/**
2992
+	 * @var boolean $show_ticket_details
2993
+	 */
2994
+	public $show_ticket_details;
2995
+
2996
+	/**
2997
+	 * @var boolean $show_expired_tickets
2998
+	 */
2999
+	public $show_expired_tickets;
3000
+
3001
+	/**
3002
+	 * whether or not to display a dropdown box populated with event datetimes
3003
+	 * that toggles which tickets are displayed for a ticket selector.
3004
+	 * uses one of the *_DATETIME_SELECTOR constants defined above
3005
+	 *
3006
+	 * @var string $show_datetime_selector
3007
+	 */
3008
+	private $show_datetime_selector = 'no_datetime_selector';
3009
+
3010
+	/**
3011
+	 * the number of datetimes an event has to have before conditionally displaying a datetime selector
3012
+	 *
3013
+	 * @var int $datetime_selector_threshold
3014
+	 */
3015
+	private $datetime_selector_threshold = 3;
3016
+
3017
+	/**
3018
+	 * determines the maximum number of "checked" dates in the date and time filter
3019
+	 *
3020
+	 * @var int $datetime_selector_checked
3021
+	 */
3022
+	private $datetime_selector_max_checked = 10;
3023
+
3024
+
3025
+	/**
3026
+	 *    class constructor
3027
+	 */
3028
+	public function __construct()
3029
+	{
3030
+		$this->show_ticket_sale_columns = true;
3031
+		$this->show_ticket_details = true;
3032
+		$this->show_expired_tickets = true;
3033
+		$this->show_datetime_selector = EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3034
+		$this->datetime_selector_threshold = 3;
3035
+		$this->datetime_selector_max_checked = 10;
3036
+	}
3037
+
3038
+
3039
+	/**
3040
+	 * returns true if a datetime selector should be displayed
3041
+	 *
3042
+	 * @param array $datetimes
3043
+	 * @return bool
3044
+	 */
3045
+	public function showDatetimeSelector(array $datetimes)
3046
+	{
3047
+		// if the settings are NOT: don't show OR below threshold, THEN active = true
3048
+		return ! (
3049
+			$this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR
3050
+			|| (
3051
+				$this->getShowDatetimeSelector() === EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR
3052
+				&& count($datetimes) < $this->getDatetimeSelectorThreshold()
3053
+			)
3054
+		);
3055
+	}
3056
+
3057
+
3058
+	/**
3059
+	 * @return string
3060
+	 */
3061
+	public function getShowDatetimeSelector()
3062
+	{
3063
+		return $this->show_datetime_selector;
3064
+	}
3065
+
3066
+
3067
+	/**
3068
+	 * @param bool $keys_only
3069
+	 * @return array
3070
+	 */
3071
+	public function getShowDatetimeSelectorOptions($keys_only = true)
3072
+	{
3073
+		return $keys_only
3074
+			? array(
3075
+				EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR,
3076
+				EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR,
3077
+			)
3078
+			: array(
3079
+				EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR => esc_html__(
3080
+					'Do not show date & time filter',
3081
+					'event_espresso'
3082
+				),
3083
+				EE_Ticket_Selector_Config::MAYBE_SHOW_DATETIME_SELECTOR  => esc_html__(
3084
+					'Maybe show date & time filter',
3085
+					'event_espresso'
3086
+				),
3087
+			);
3088
+	}
3089
+
3090
+
3091
+	/**
3092
+	 * @param string $show_datetime_selector
3093
+	 */
3094
+	public function setShowDatetimeSelector($show_datetime_selector)
3095
+	{
3096
+		$this->show_datetime_selector = in_array(
3097
+			$show_datetime_selector,
3098
+			$this->getShowDatetimeSelectorOptions(),
3099
+			true
3100
+		)
3101
+			? $show_datetime_selector
3102
+			: EE_Ticket_Selector_Config::DO_NOT_SHOW_DATETIME_SELECTOR;
3103
+	}
3104
+
3105
+
3106
+	/**
3107
+	 * @return int
3108
+	 */
3109
+	public function getDatetimeSelectorThreshold()
3110
+	{
3111
+		return $this->datetime_selector_threshold;
3112
+	}
3113
+
3114
+
3115
+	/**
3116
+	 * @param int $datetime_selector_threshold
3117
+	 */
3118
+	public function setDatetimeSelectorThreshold($datetime_selector_threshold)
3119
+	{
3120
+		$datetime_selector_threshold = absint($datetime_selector_threshold);
3121
+		$this->datetime_selector_threshold = $datetime_selector_threshold ? $datetime_selector_threshold : 3;
3122
+	}
3123
+
3124
+
3125
+	/**
3126
+	 * @return int
3127
+	 */
3128
+	public function getDatetimeSelectorMaxChecked()
3129
+	{
3130
+		return $this->datetime_selector_max_checked;
3131
+	}
3132
+
3133
+
3134
+	/**
3135
+	 * @param int $datetime_selector_max_checked
3136
+	 */
3137
+	public function setDatetimeSelectorMaxChecked($datetime_selector_max_checked)
3138
+	{
3139
+		$this->datetime_selector_max_checked = absint($datetime_selector_max_checked);
3140
+	}
3141 3141
 }
3142 3142
 
3143 3143
 /**
@@ -3149,87 +3149,87 @@  discard block
 block discarded – undo
3149 3149
  */
3150 3150
 class EE_Environment_Config extends EE_Config_Base
3151 3151
 {
3152
-    /**
3153
-     * Hold any php environment variables that we want to track.
3154
-     *
3155
-     * @var stdClass;
3156
-     */
3157
-    public $php;
3158
-
3159
-
3160
-    /**
3161
-     *    constructor
3162
-     */
3163
-    public function __construct()
3164
-    {
3165
-        $this->php = new stdClass();
3166
-        $this->_set_php_values();
3167
-    }
3168
-
3169
-
3170
-    /**
3171
-     * This sets the php environment variables.
3172
-     *
3173
-     * @since 4.4.0
3174
-     * @return void
3175
-     */
3176
-    protected function _set_php_values()
3177
-    {
3178
-        $this->php->max_input_vars = ini_get('max_input_vars');
3179
-        $this->php->version = phpversion();
3180
-    }
3181
-
3182
-
3183
-    /**
3184
-     * helper method for determining whether input_count is
3185
-     * reaching the potential maximum the server can handle
3186
-     * according to max_input_vars
3187
-     *
3188
-     * @param int   $input_count the count of input vars.
3189
-     * @return array {
3190
-     *                           An array that represents whether available space and if no available space the error
3191
-     *                           message.
3192
-     * @type bool   $has_space   whether more inputs can be added.
3193
-     * @type string $msg         Any message to be displayed.
3194
-     *                           }
3195
-     */
3196
-    public function max_input_vars_limit_check($input_count = 0)
3197
-    {
3198
-        if (
3199
-            ! empty($this->php->max_input_vars)
3200
-            && ($input_count >= $this->php->max_input_vars)
3201
-        ) {
3202
-            // check the server setting because the config value could be stale
3203
-            $max_input_vars = ini_get('max_input_vars');
3204
-            if ($input_count >= $max_input_vars) {
3205
-                return sprintf(
3206
-                    esc_html__(
3207
-                        'The maximum number of inputs on this page has been exceeded. You cannot make edits to this page because of your server\'s PHP "max_input_vars" setting.%1$sThere are %2$d inputs and the maximum amount currently allowed by your server is %3$d.%1$sPlease contact your web host and ask them to raise the "max_input_vars" limit.',
3208
-                        'event_espresso'
3209
-                    ),
3210
-                    '<br>',
3211
-                    $input_count,
3212
-                    $max_input_vars
3213
-                );
3214
-            } else {
3215
-                return '';
3216
-            }
3217
-        } else {
3218
-            return '';
3219
-        }
3220
-    }
3221
-
3222
-
3223
-    /**
3224
-     * The purpose of this method is just to force rechecking php values so if they've changed, they get updated.
3225
-     *
3226
-     * @since 4.4.1
3227
-     * @return void
3228
-     */
3229
-    public function recheck_values()
3230
-    {
3231
-        $this->_set_php_values();
3232
-    }
3152
+	/**
3153
+	 * Hold any php environment variables that we want to track.
3154
+	 *
3155
+	 * @var stdClass;
3156
+	 */
3157
+	public $php;
3158
+
3159
+
3160
+	/**
3161
+	 *    constructor
3162
+	 */
3163
+	public function __construct()
3164
+	{
3165
+		$this->php = new stdClass();
3166
+		$this->_set_php_values();
3167
+	}
3168
+
3169
+
3170
+	/**
3171
+	 * This sets the php environment variables.
3172
+	 *
3173
+	 * @since 4.4.0
3174
+	 * @return void
3175
+	 */
3176
+	protected function _set_php_values()
3177
+	{
3178
+		$this->php->max_input_vars = ini_get('max_input_vars');
3179
+		$this->php->version = phpversion();
3180
+	}
3181
+
3182
+
3183
+	/**
3184
+	 * helper method for determining whether input_count is
3185
+	 * reaching the potential maximum the server can handle
3186
+	 * according to max_input_vars
3187
+	 *
3188
+	 * @param int   $input_count the count of input vars.
3189
+	 * @return array {
3190
+	 *                           An array that represents whether available space and if no available space the error
3191
+	 *                           message.
3192
+	 * @type bool   $has_space   whether more inputs can be added.
3193
+	 * @type string $msg         Any message to be displayed.
3194
+	 *                           }
3195
+	 */
3196
+	public function max_input_vars_limit_check($input_count = 0)
3197
+	{
3198
+		if (
3199
+			! empty($this->php->max_input_vars)
3200
+			&& ($input_count >= $this->php->max_input_vars)
3201
+		) {
3202
+			// check the server setting because the config value could be stale
3203
+			$max_input_vars = ini_get('max_input_vars');
3204
+			if ($input_count >= $max_input_vars) {
3205
+				return sprintf(
3206
+					esc_html__(
3207
+						'The maximum number of inputs on this page has been exceeded. You cannot make edits to this page because of your server\'s PHP "max_input_vars" setting.%1$sThere are %2$d inputs and the maximum amount currently allowed by your server is %3$d.%1$sPlease contact your web host and ask them to raise the "max_input_vars" limit.',
3208
+						'event_espresso'
3209
+					),
3210
+					'<br>',
3211
+					$input_count,
3212
+					$max_input_vars
3213
+				);
3214
+			} else {
3215
+				return '';
3216
+			}
3217
+		} else {
3218
+			return '';
3219
+		}
3220
+	}
3221
+
3222
+
3223
+	/**
3224
+	 * The purpose of this method is just to force rechecking php values so if they've changed, they get updated.
3225
+	 *
3226
+	 * @since 4.4.1
3227
+	 * @return void
3228
+	 */
3229
+	public function recheck_values()
3230
+	{
3231
+		$this->_set_php_values();
3232
+	}
3233 3233
 }
3234 3234
 
3235 3235
 /**
@@ -3241,21 +3241,21 @@  discard block
 block discarded – undo
3241 3241
  */
3242 3242
 class EE_Tax_Config extends EE_Config_Base
3243 3243
 {
3244
-    /*
3244
+	/*
3245 3245
      * flag to indicate whether or not to display ticket prices with the taxes included
3246 3246
      *
3247 3247
      * @var boolean $prices_displayed_including_taxes
3248 3248
      */
3249
-    public $prices_displayed_including_taxes;
3249
+	public $prices_displayed_including_taxes;
3250 3250
 
3251 3251
 
3252
-    /**
3253
-     *    class constructor
3254
-     */
3255
-    public function __construct()
3256
-    {
3257
-        $this->prices_displayed_including_taxes = true;
3258
-    }
3252
+	/**
3253
+	 *    class constructor
3254
+	 */
3255
+	public function __construct()
3256
+	{
3257
+		$this->prices_displayed_including_taxes = true;
3258
+	}
3259 3259
 }
3260 3260
 
3261 3261
 /**
@@ -3268,19 +3268,19 @@  discard block
 block discarded – undo
3268 3268
  */
3269 3269
 class EE_Messages_Config extends EE_Config_Base
3270 3270
 {
3271
-    /**
3272
-     * This is an integer representing the deletion threshold in months for when old messages will get deleted.
3273
-     * A value of 0 represents never deleting.  Default is 0.
3274
-     *
3275
-     * @var integer
3276
-     */
3277
-    public $delete_threshold;
3278
-
3279
-
3280
-    public function __construct()
3281
-    {
3282
-        $this->delete_threshold = 0;
3283
-    }
3271
+	/**
3272
+	 * This is an integer representing the deletion threshold in months for when old messages will get deleted.
3273
+	 * A value of 0 represents never deleting.  Default is 0.
3274
+	 *
3275
+	 * @var integer
3276
+	 */
3277
+	public $delete_threshold;
3278
+
3279
+
3280
+	public function __construct()
3281
+	{
3282
+		$this->delete_threshold = 0;
3283
+	}
3284 3284
 }
3285 3285
 
3286 3286
 /**
@@ -3290,31 +3290,31 @@  discard block
 block discarded – undo
3290 3290
  */
3291 3291
 class EE_Gateway_Config extends EE_Config_Base
3292 3292
 {
3293
-    /**
3294
-     * Array with keys that are payment gateways slugs, and values are arrays
3295
-     * with any config info the gateway wants to store
3296
-     *
3297
-     * @var array
3298
-     */
3299
-    public $payment_settings;
3300
-
3301
-    /**
3302
-     * Where keys are gateway slugs, and values are booleans indicating whether or not
3303
-     * the gateway is stored in the uploads directory
3304
-     *
3305
-     * @var array
3306
-     */
3307
-    public $active_gateways;
3308
-
3309
-
3310
-    /**
3311
-     *    class constructor
3312
-     *
3313
-     * @deprecated
3314
-     */
3315
-    public function __construct()
3316
-    {
3317
-        $this->payment_settings = array();
3318
-        $this->active_gateways = array('Invoice' => false);
3319
-    }
3293
+	/**
3294
+	 * Array with keys that are payment gateways slugs, and values are arrays
3295
+	 * with any config info the gateway wants to store
3296
+	 *
3297
+	 * @var array
3298
+	 */
3299
+	public $payment_settings;
3300
+
3301
+	/**
3302
+	 * Where keys are gateway slugs, and values are booleans indicating whether or not
3303
+	 * the gateway is stored in the uploads directory
3304
+	 *
3305
+	 * @var array
3306
+	 */
3307
+	public $active_gateways;
3308
+
3309
+
3310
+	/**
3311
+	 *    class constructor
3312
+	 *
3313
+	 * @deprecated
3314
+	 */
3315
+	public function __construct()
3316
+	{
3317
+		$this->payment_settings = array();
3318
+		$this->active_gateways = array('Invoice' => false);
3319
+	}
3320 3320
 }
Please login to merge, or discard this patch.
core/CPTs/CptQueryModifier.php 2 patches
Indentation   +578 added lines, -578 removed lines patch added patch discarded remove patch
@@ -30,582 +30,582 @@
 block discarded – undo
30 30
  */
31 31
 class CptQueryModifier
32 32
 {
33
-    /**
34
-     * @var CurrentPage $current_page
35
-     */
36
-    protected $current_page;
37
-
38
-    /**
39
-     * @var string $post_type
40
-     */
41
-    protected $post_type = '';
42
-
43
-    /**
44
-     * CPT details from CustomPostTypeDefinitions for specific post type
45
-     *
46
-     * @var array $cpt_details
47
-     */
48
-    protected $cpt_details = array();
49
-
50
-    /**
51
-     * @var EE_Table_Base[] $model_tables
52
-     */
53
-    protected $model_tables = array();
54
-
55
-    /**
56
-     * @var array $taxonomies
57
-     */
58
-    protected $taxonomies = array();
59
-
60
-    /**
61
-     * meta table for the related CPT
62
-     *
63
-     * @var EE_Secondary_Table $meta_table
64
-     */
65
-    protected $meta_table;
66
-
67
-    /**
68
-     * EEM_CPT_Base model for the related CPT
69
-     *
70
-     * @var EEM_CPT_Base $model
71
-     */
72
-    protected $model;
73
-
74
-    /**
75
-     * @var EE_Request_Handler $request_handler
76
-     */
77
-    protected $request_handler;
78
-
79
-    /**
80
-     * @var WP_Query $wp_query
81
-     */
82
-    protected $wp_query;
83
-
84
-    /**
85
-     * @var LoaderInterface $loader
86
-     */
87
-    protected $loader;
88
-
89
-    /**
90
-     * @var RequestInterface $request
91
-     */
92
-    protected $request;
93
-
94
-
95
-    /**
96
-     * CptQueryModifier constructor
97
-     *
98
-     * @param string             $post_type
99
-     * @param array              $cpt_details
100
-     * @param WP_Query           $WP_Query
101
-     * @param CurrentPage $current_page
102
-     * @param RequestInterface   $request
103
-     * @param LoaderInterface    $loader
104
-     * @throws EE_Error
105
-     */
106
-    public function __construct(
107
-        $post_type,
108
-        array $cpt_details,
109
-        WP_Query $WP_Query,
110
-        CurrentPage $current_page,
111
-        RequestInterface $request,
112
-        LoaderInterface $loader
113
-    ) {
114
-        $this->loader = $loader;
115
-        $this->request = $request;
116
-        $this->current_page = $current_page;
117
-        $this->setWpQuery($WP_Query);
118
-        $this->setPostType($post_type);
119
-        $this->setCptDetails($cpt_details);
120
-        $this->init();
121
-    }
122
-
123
-
124
-    /**
125
-     * @return string
126
-     */
127
-    public function postType()
128
-    {
129
-        return $this->post_type;
130
-    }
131
-
132
-
133
-    /**
134
-     * @param string $post_type
135
-     */
136
-    protected function setPostType($post_type)
137
-    {
138
-        $this->post_type = $post_type;
139
-    }
140
-
141
-
142
-    /**
143
-     * @return array
144
-     */
145
-    public function cptDetails()
146
-    {
147
-        return $this->cpt_details;
148
-    }
149
-
150
-
151
-    /**
152
-     * @param array $cpt_details
153
-     */
154
-    protected function setCptDetails($cpt_details)
155
-    {
156
-        $this->cpt_details = $cpt_details;
157
-    }
158
-
159
-
160
-    /**
161
-     * @return EE_Table_Base[]
162
-     */
163
-    public function modelTables()
164
-    {
165
-        return $this->model_tables;
166
-    }
167
-
168
-
169
-    /**
170
-     * @param EE_Table_Base[] $model_tables
171
-     */
172
-    protected function setModelTables($model_tables)
173
-    {
174
-        $this->model_tables = $model_tables;
175
-    }
176
-
177
-
178
-    /**
179
-     * @return array
180
-     * @throws InvalidArgumentException
181
-     * @throws InvalidDataTypeException
182
-     * @throws InvalidInterfaceException
183
-     */
184
-    public function taxonomies()
185
-    {
186
-        if (empty($this->taxonomies)) {
187
-            $this->initializeTaxonomies();
188
-        }
189
-        return $this->taxonomies;
190
-    }
191
-
192
-
193
-    /**
194
-     * @param array $taxonomies
195
-     */
196
-    protected function setTaxonomies(array $taxonomies)
197
-    {
198
-        $this->taxonomies = $taxonomies;
199
-    }
200
-
201
-
202
-    /**
203
-     * @return EE_Secondary_Table
204
-     */
205
-    public function metaTable()
206
-    {
207
-        return $this->meta_table;
208
-    }
209
-
210
-
211
-    /**
212
-     * @param EE_Secondary_Table $meta_table
213
-     */
214
-    public function setMetaTable(EE_Secondary_Table $meta_table)
215
-    {
216
-        $this->meta_table = $meta_table;
217
-    }
218
-
219
-
220
-    /**
221
-     * @return EEM_Base
222
-     */
223
-    public function model()
224
-    {
225
-        return $this->model;
226
-    }
227
-
228
-
229
-    /**
230
-     * @param EEM_Base $CPT_model
231
-     */
232
-    protected function setModel(EEM_Base $CPT_model)
233
-    {
234
-        $this->model = $CPT_model;
235
-    }
236
-
237
-
238
-    /**
239
-     * @deprecated 4.9.63.p
240
-     * @return EE_Request_Handler
241
-     */
242
-    public function request()
243
-    {
244
-        if (! $this->request_handler instanceof EE_Request_Handler) {
245
-            $this->request_handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
246
-        }
247
-        return $this->request_handler;
248
-    }
249
-
250
-
251
-
252
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
253
-
254
-
255
-    /**
256
-     * @return WP_Query
257
-     */
258
-    public function WpQuery()
259
-    {
260
-        return $this->wp_query;
261
-    }
262
-    // phpcs:enable
263
-
264
-
265
-    /**
266
-     * @param WP_Query $wp_query
267
-     */
268
-    public function setWpQuery(WP_Query $wp_query)
269
-    {
270
-        $this->wp_query = $wp_query;
271
-    }
272
-
273
-
274
-    /**
275
-     * @return void
276
-     * @throws InvalidDataTypeException
277
-     * @throws InvalidInterfaceException
278
-     * @throws InvalidArgumentException
279
-     */
280
-    protected function initializeTaxonomies()
281
-    {
282
-        // check if taxonomies have already been set and that this CPT has taxonomies registered for it
283
-        if (
284
-            empty($this->taxonomies)
285
-            && isset($this->cpt_details['args']['taxonomies'])
286
-        ) {
287
-            // if so then grab them, but we want the taxonomy name as the key
288
-            $taxonomies = array_flip($this->cpt_details['args']['taxonomies']);
289
-            // then grab the list of ALL taxonomies
290
-            /** @var CustomTaxonomyDefinitions
291
-             * $taxonomy_definitions
292
-             */
293
-            $taxonomy_definitions = $this->loader->getShared(
294
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions'
295
-            );
296
-            $all_taxonomies = $taxonomy_definitions->getCustomTaxonomyDefinitions();
297
-            foreach ($taxonomies as $taxonomy => &$details) {
298
-                // add details to our taxonomies if they exist
299
-                $details = isset($all_taxonomies[ $taxonomy ])
300
-                    ? $all_taxonomies[ $taxonomy ]
301
-                    : array();
302
-            }
303
-            // ALWAYS unset() variables that were passed by reference
304
-            unset($details);
305
-            $this->setTaxonomies($taxonomies);
306
-        }
307
-    }
308
-
309
-
310
-    /**
311
-     * @since 4.9.63.p
312
-     * @throws EE_Error
313
-     */
314
-    protected function init()
315
-    {
316
-        $this->setAdditionalCptDetails();
317
-        $this->setRequestVarsIfCpt();
318
-        // convert post_type to model name
319
-        $model_name = str_replace('EE_', '', $this->cpt_details['class_name']);
320
-        // load all tables related to CPT
321
-        $this->setupModelsAndTables($model_name);
322
-        // load and instantiate CPT_*_Strategy
323
-        $CPT_Strategy = $this->cptStrategyClass($model_name);
324
-        // !!!!!!!!!!  IMPORTANT !!!!!!!!!!!!
325
-        // here's the list of available filters in the WP_Query object
326
-        // 'posts_where_paged'
327
-        // 'posts_groupby'
328
-        // 'posts_join_paged'
329
-        // 'posts_orderby'
330
-        // 'posts_distinct'
331
-        // 'post_limits'
332
-        // 'posts_fields'
333
-        // 'posts_join'
334
-        add_filter('posts_fields', array($this, 'postsFields'));
335
-        add_filter('posts_join', array($this, 'postsJoin'));
336
-        add_filter(
337
-            'get_' . $this->post_type . '_metadata',
338
-            array($CPT_Strategy, 'get_EE_post_type_metadata'),
339
-            1,
340
-            4
341
-        );
342
-        add_filter('the_posts', array($this, 'thePosts'), 1, 1);
343
-        if ($this->wp_query->is_main_query()) {
344
-            add_filter('get_edit_post_link', array($this, 'getEditPostLink'), 10, 2);
345
-            $this->addTemplateFilters();
346
-        }
347
-    }
348
-
349
-
350
-    /**
351
-     * sets some basic query vars that pertain to the CPT
352
-     *
353
-     * @access protected
354
-     * @return void
355
-     */
356
-    protected function setAdditionalCptDetails()
357
-    {
358
-        // the post or category or term that is triggering EE
359
-        $this->cpt_details['espresso_page'] = $this->current_page->isEspressoPage();
360
-        // requested post name
361
-        $this->cpt_details['post_name'] = $this->request->getRequestParam('post_name');
362
-        // add support for viewing 'private', 'draft', or 'pending' posts
363
-        if (
364
-            isset($this->wp_query->query_vars['p'])
365
-            && $this->wp_query->query_vars['p'] !== 0
366
-            && is_user_logged_in()
367
-            && current_user_can('edit_post', $this->wp_query->query_vars['p'])
368
-        ) {
369
-            // we can just inject directly into the WP_Query object
370
-            $this->wp_query->query['post_status'] = array('publish', 'private', 'draft', 'pending');
371
-            // now set the main 'ee' request var so that the appropriate module can load the appropriate template(s)
372
-            $this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
373
-        }
374
-    }
375
-
376
-
377
-    /**
378
-     * Checks if we're on a EE-CPT archive-or-single page, and if we've never set the EE request var.
379
-     * If so, sets the 'ee' request variable
380
-     * so other parts of EE can know what CPT is getting queried.
381
-     * To Mike's knowledge, this must be called from during or after the pre_get_posts hook
382
-     * in order for is_archive() and is_single() methods to work properly.
383
-     *
384
-     * @return void
385
-     */
386
-    public function setRequestVarsIfCpt()
387
-    {
388
-        // check if ee action var has been set
389
-        if (! $this->request->requestParamIsSet('ee')) {
390
-            // check that route exists for CPT archive slug
391
-            if (is_archive() && EE_Config::get_route($this->cpt_details['plural_slug'])) {
392
-                // ie: set "ee" to "events"
393
-                $this->request->setRequestParam('ee', $this->cpt_details['plural_slug']);
394
-                // or does it match a single page CPT like /event/
395
-            } elseif (is_single() && EE_Config::get_route($this->cpt_details['singular_slug'])) {
396
-                // ie: set "ee" to "event"
397
-                $this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
398
-            }
399
-        }
400
-    }
401
-
402
-
403
-    /**
404
-     * setupModelsAndTables
405
-     *
406
-     * @access protected
407
-     * @param string $model_name
408
-     * @throws EE_Error
409
-     */
410
-    protected function setupModelsAndTables($model_name)
411
-    {
412
-        // get CPT table data via CPT Model
413
-        $full_model_name = strpos($model_name, 'EEM_') !== 0
414
-            ? 'EEM_' . $model_name
415
-            : $model_name;
416
-        $model = $this->loader->getShared($full_model_name);
417
-        if (! $model instanceof EEM_Base) {
418
-            throw new EE_Error(
419
-                sprintf(
420
-                    esc_html__(
421
-                        'The "%1$s" model could not be loaded.',
422
-                        'event_espresso'
423
-                    ),
424
-                    $full_model_name
425
-                )
426
-            );
427
-        }
428
-        $this->setModel($model);
429
-        $this->setModelTables($this->model->get_tables());
430
-        $meta_model = $model_name . '_Meta';
431
-        // is there a Meta Table for this CPT?
432
-        if (
433
-            isset($this->cpt_details['tables'][ $meta_model ])
434
-            && $this->cpt_details['tables'][ $meta_model ] instanceof EE_Secondary_Table
435
-        ) {
436
-            $this->setMetaTable($this->cpt_details['tables'][ $meta_model ]);
437
-        }
438
-    }
439
-
440
-
441
-    /**
442
-     * cptStrategyClass
443
-     *
444
-     * @access protected
445
-     * @param  string $model_name
446
-     * @return string
447
-     */
448
-    protected function cptStrategyClass($model_name)
449
-    {
450
-        // creates classname like:  CPT_Event_Strategy
451
-        $CPT_Strategy_class_name = 'EE_CPT_' . $model_name . '_Strategy';
452
-        // load and instantiate
453
-        $CPT_Strategy = $this->loader->getShared(
454
-            $CPT_Strategy_class_name,
455
-            array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
456
-        );
457
-        if ($CPT_Strategy === null) {
458
-            $CPT_Strategy = $this->loader->getShared(
459
-                'EE_CPT_Default_Strategy',
460
-                array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
461
-            );
462
-        }
463
-        return $CPT_Strategy;
464
-    }
465
-
466
-
467
-    /**
468
-     * postsFields
469
-     *
470
-     * @access public
471
-     * @param  $SQL
472
-     * @return string
473
-     */
474
-    public function postsFields($SQL)
475
-    {
476
-        // does this CPT have a meta table ?
477
-        if ($this->meta_table instanceof EE_Secondary_Table) {
478
-            // adds something like ", wp_esp_event_meta.* " to WP Query SELECT statement
479
-            $SQL .= ', ' . $this->meta_table->get_table_name() . '.* ';
480
-        }
481
-        remove_filter('posts_fields', array($this, 'postsFields'));
482
-        return $SQL;
483
-    }
484
-
485
-
486
-    /**
487
-     * postsJoin
488
-     *
489
-     * @access public
490
-     * @param  $SQL
491
-     * @return string
492
-     */
493
-    public function postsJoin($SQL)
494
-    {
495
-        // does this CPT have a meta table ?
496
-        if ($this->meta_table instanceof EE_Secondary_Table) {
497
-            global $wpdb;
498
-            // adds something like " LEFT JOIN wp_esp_event_meta ON ( wp_esp_event_meta.EVT_ID = wp_posts.ID ) " to WP Query JOIN statement
499
-            $SQL .= ' LEFT JOIN '
500
-                    . $this->meta_table->get_table_name()
501
-                    . ' ON ( '
502
-                    . $this->meta_table->get_table_name()
503
-                    . '.'
504
-                    . $this->meta_table->get_fk_on_table()
505
-                    . ' = '
506
-                    . $wpdb->posts
507
-                    . '.ID ) ';
508
-        }
509
-        remove_filter('posts_join', array($this, 'postsJoin'));
510
-        return $SQL;
511
-    }
512
-
513
-
514
-    /**
515
-     * thePosts
516
-     *
517
-     * @access public
518
-     * @param  WP_Post[] $posts
519
-     * @return WP_Post[]
520
-     */
521
-    public function thePosts($posts)
522
-    {
523
-        $CPT_class = $this->cpt_details['class_name'];
524
-        // loop thru posts
525
-        if (is_array($posts) && $this->model instanceof EEM_CPT_Base) {
526
-            foreach ($posts as $post) {
527
-                if ($post->post_type === $this->post_type) {
528
-                    $post->{$CPT_class} = $this->model->instantiate_class_from_post_object($post);
529
-                }
530
-            }
531
-        }
532
-        remove_filter('the_posts', array($this, 'thePosts'), 1);
533
-        return $posts;
534
-    }
535
-
536
-
537
-    /**
538
-     * @param $url
539
-     * @param $ID
540
-     * @return string
541
-     */
542
-    public function getEditPostLink($url, $ID)
543
-    {
544
-        // need to make sure we only edit links if our cpt
545
-        global $post;
546
-        // notice if the cpt is registered with `show_ee_ui` set to false, we take that to mean that the WordPress core ui
547
-        // for interacting with the CPT is desired and there is no EE UI for interacting with the CPT in the admin.
548
-        if (
549
-            ! $post instanceof WP_Post
550
-            || $post->post_type !== $this->post_type
551
-            || (
552
-                isset($this->cpt_details['args']['show_ee_ui'])
553
-                && ! $this->cpt_details['args']['show_ee_ui']
554
-            )
555
-        ) {
556
-            return $url;
557
-        }
558
-        // k made it here so all is good.
559
-        return wp_nonce_url(
560
-            add_query_arg(
561
-                array('page' => $this->post_type, 'post' => $ID, 'action' => 'edit'),
562
-                admin_url('admin.php')
563
-            ),
564
-            'edit',
565
-            'edit_nonce'
566
-        );
567
-    }
568
-
569
-
570
-    /**
571
-     * Execute any template filters.
572
-     * This method is only called if in main query.
573
-     *
574
-     * @return void
575
-     */
576
-    public function addTemplateFilters()
577
-    {
578
-        // if requested cpt supports page_templates and it's the main query
579
-        if (! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
580
-            // then let's hook into the appropriate query_template hook
581
-            add_filter('single_template', array($this, 'singleCptTemplate'));
582
-        }
583
-    }
584
-
585
-
586
-    /**
587
-     * Callback for single_template wp filter.
588
-     * This is used to load the set page_template for a single ee cpt if its set.  If "default" then we load the normal
589
-     * hierarchy.
590
-     *
591
-     * @access public
592
-     * @param string $current_template Existing default template path derived for this page call.
593
-     * @return string the path to the full template file.
594
-     */
595
-    public function singleCptTemplate($current_template)
596
-    {
597
-        $object = get_queried_object();
598
-        // does this called object HAVE a page template set that is something other than the default.
599
-        $template = get_post_meta($object->ID, '_wp_page_template', true);
600
-        // exit early if default or not set or invalid path (accounts for theme changes)
601
-        if (
602
-            $template === 'default'
603
-            || empty($template)
604
-            || ! is_readable(get_stylesheet_directory() . '/' . $template)
605
-        ) {
606
-            return $current_template;
607
-        }
608
-        // made it here so we SHOULD be able to just locate the template and then return it.
609
-        return locate_template(array($template));
610
-    }
33
+	/**
34
+	 * @var CurrentPage $current_page
35
+	 */
36
+	protected $current_page;
37
+
38
+	/**
39
+	 * @var string $post_type
40
+	 */
41
+	protected $post_type = '';
42
+
43
+	/**
44
+	 * CPT details from CustomPostTypeDefinitions for specific post type
45
+	 *
46
+	 * @var array $cpt_details
47
+	 */
48
+	protected $cpt_details = array();
49
+
50
+	/**
51
+	 * @var EE_Table_Base[] $model_tables
52
+	 */
53
+	protected $model_tables = array();
54
+
55
+	/**
56
+	 * @var array $taxonomies
57
+	 */
58
+	protected $taxonomies = array();
59
+
60
+	/**
61
+	 * meta table for the related CPT
62
+	 *
63
+	 * @var EE_Secondary_Table $meta_table
64
+	 */
65
+	protected $meta_table;
66
+
67
+	/**
68
+	 * EEM_CPT_Base model for the related CPT
69
+	 *
70
+	 * @var EEM_CPT_Base $model
71
+	 */
72
+	protected $model;
73
+
74
+	/**
75
+	 * @var EE_Request_Handler $request_handler
76
+	 */
77
+	protected $request_handler;
78
+
79
+	/**
80
+	 * @var WP_Query $wp_query
81
+	 */
82
+	protected $wp_query;
83
+
84
+	/**
85
+	 * @var LoaderInterface $loader
86
+	 */
87
+	protected $loader;
88
+
89
+	/**
90
+	 * @var RequestInterface $request
91
+	 */
92
+	protected $request;
93
+
94
+
95
+	/**
96
+	 * CptQueryModifier constructor
97
+	 *
98
+	 * @param string             $post_type
99
+	 * @param array              $cpt_details
100
+	 * @param WP_Query           $WP_Query
101
+	 * @param CurrentPage $current_page
102
+	 * @param RequestInterface   $request
103
+	 * @param LoaderInterface    $loader
104
+	 * @throws EE_Error
105
+	 */
106
+	public function __construct(
107
+		$post_type,
108
+		array $cpt_details,
109
+		WP_Query $WP_Query,
110
+		CurrentPage $current_page,
111
+		RequestInterface $request,
112
+		LoaderInterface $loader
113
+	) {
114
+		$this->loader = $loader;
115
+		$this->request = $request;
116
+		$this->current_page = $current_page;
117
+		$this->setWpQuery($WP_Query);
118
+		$this->setPostType($post_type);
119
+		$this->setCptDetails($cpt_details);
120
+		$this->init();
121
+	}
122
+
123
+
124
+	/**
125
+	 * @return string
126
+	 */
127
+	public function postType()
128
+	{
129
+		return $this->post_type;
130
+	}
131
+
132
+
133
+	/**
134
+	 * @param string $post_type
135
+	 */
136
+	protected function setPostType($post_type)
137
+	{
138
+		$this->post_type = $post_type;
139
+	}
140
+
141
+
142
+	/**
143
+	 * @return array
144
+	 */
145
+	public function cptDetails()
146
+	{
147
+		return $this->cpt_details;
148
+	}
149
+
150
+
151
+	/**
152
+	 * @param array $cpt_details
153
+	 */
154
+	protected function setCptDetails($cpt_details)
155
+	{
156
+		$this->cpt_details = $cpt_details;
157
+	}
158
+
159
+
160
+	/**
161
+	 * @return EE_Table_Base[]
162
+	 */
163
+	public function modelTables()
164
+	{
165
+		return $this->model_tables;
166
+	}
167
+
168
+
169
+	/**
170
+	 * @param EE_Table_Base[] $model_tables
171
+	 */
172
+	protected function setModelTables($model_tables)
173
+	{
174
+		$this->model_tables = $model_tables;
175
+	}
176
+
177
+
178
+	/**
179
+	 * @return array
180
+	 * @throws InvalidArgumentException
181
+	 * @throws InvalidDataTypeException
182
+	 * @throws InvalidInterfaceException
183
+	 */
184
+	public function taxonomies()
185
+	{
186
+		if (empty($this->taxonomies)) {
187
+			$this->initializeTaxonomies();
188
+		}
189
+		return $this->taxonomies;
190
+	}
191
+
192
+
193
+	/**
194
+	 * @param array $taxonomies
195
+	 */
196
+	protected function setTaxonomies(array $taxonomies)
197
+	{
198
+		$this->taxonomies = $taxonomies;
199
+	}
200
+
201
+
202
+	/**
203
+	 * @return EE_Secondary_Table
204
+	 */
205
+	public function metaTable()
206
+	{
207
+		return $this->meta_table;
208
+	}
209
+
210
+
211
+	/**
212
+	 * @param EE_Secondary_Table $meta_table
213
+	 */
214
+	public function setMetaTable(EE_Secondary_Table $meta_table)
215
+	{
216
+		$this->meta_table = $meta_table;
217
+	}
218
+
219
+
220
+	/**
221
+	 * @return EEM_Base
222
+	 */
223
+	public function model()
224
+	{
225
+		return $this->model;
226
+	}
227
+
228
+
229
+	/**
230
+	 * @param EEM_Base $CPT_model
231
+	 */
232
+	protected function setModel(EEM_Base $CPT_model)
233
+	{
234
+		$this->model = $CPT_model;
235
+	}
236
+
237
+
238
+	/**
239
+	 * @deprecated 4.9.63.p
240
+	 * @return EE_Request_Handler
241
+	 */
242
+	public function request()
243
+	{
244
+		if (! $this->request_handler instanceof EE_Request_Handler) {
245
+			$this->request_handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
246
+		}
247
+		return $this->request_handler;
248
+	}
249
+
250
+
251
+
252
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
253
+
254
+
255
+	/**
256
+	 * @return WP_Query
257
+	 */
258
+	public function WpQuery()
259
+	{
260
+		return $this->wp_query;
261
+	}
262
+	// phpcs:enable
263
+
264
+
265
+	/**
266
+	 * @param WP_Query $wp_query
267
+	 */
268
+	public function setWpQuery(WP_Query $wp_query)
269
+	{
270
+		$this->wp_query = $wp_query;
271
+	}
272
+
273
+
274
+	/**
275
+	 * @return void
276
+	 * @throws InvalidDataTypeException
277
+	 * @throws InvalidInterfaceException
278
+	 * @throws InvalidArgumentException
279
+	 */
280
+	protected function initializeTaxonomies()
281
+	{
282
+		// check if taxonomies have already been set and that this CPT has taxonomies registered for it
283
+		if (
284
+			empty($this->taxonomies)
285
+			&& isset($this->cpt_details['args']['taxonomies'])
286
+		) {
287
+			// if so then grab them, but we want the taxonomy name as the key
288
+			$taxonomies = array_flip($this->cpt_details['args']['taxonomies']);
289
+			// then grab the list of ALL taxonomies
290
+			/** @var CustomTaxonomyDefinitions
291
+			 * $taxonomy_definitions
292
+			 */
293
+			$taxonomy_definitions = $this->loader->getShared(
294
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions'
295
+			);
296
+			$all_taxonomies = $taxonomy_definitions->getCustomTaxonomyDefinitions();
297
+			foreach ($taxonomies as $taxonomy => &$details) {
298
+				// add details to our taxonomies if they exist
299
+				$details = isset($all_taxonomies[ $taxonomy ])
300
+					? $all_taxonomies[ $taxonomy ]
301
+					: array();
302
+			}
303
+			// ALWAYS unset() variables that were passed by reference
304
+			unset($details);
305
+			$this->setTaxonomies($taxonomies);
306
+		}
307
+	}
308
+
309
+
310
+	/**
311
+	 * @since 4.9.63.p
312
+	 * @throws EE_Error
313
+	 */
314
+	protected function init()
315
+	{
316
+		$this->setAdditionalCptDetails();
317
+		$this->setRequestVarsIfCpt();
318
+		// convert post_type to model name
319
+		$model_name = str_replace('EE_', '', $this->cpt_details['class_name']);
320
+		// load all tables related to CPT
321
+		$this->setupModelsAndTables($model_name);
322
+		// load and instantiate CPT_*_Strategy
323
+		$CPT_Strategy = $this->cptStrategyClass($model_name);
324
+		// !!!!!!!!!!  IMPORTANT !!!!!!!!!!!!
325
+		// here's the list of available filters in the WP_Query object
326
+		// 'posts_where_paged'
327
+		// 'posts_groupby'
328
+		// 'posts_join_paged'
329
+		// 'posts_orderby'
330
+		// 'posts_distinct'
331
+		// 'post_limits'
332
+		// 'posts_fields'
333
+		// 'posts_join'
334
+		add_filter('posts_fields', array($this, 'postsFields'));
335
+		add_filter('posts_join', array($this, 'postsJoin'));
336
+		add_filter(
337
+			'get_' . $this->post_type . '_metadata',
338
+			array($CPT_Strategy, 'get_EE_post_type_metadata'),
339
+			1,
340
+			4
341
+		);
342
+		add_filter('the_posts', array($this, 'thePosts'), 1, 1);
343
+		if ($this->wp_query->is_main_query()) {
344
+			add_filter('get_edit_post_link', array($this, 'getEditPostLink'), 10, 2);
345
+			$this->addTemplateFilters();
346
+		}
347
+	}
348
+
349
+
350
+	/**
351
+	 * sets some basic query vars that pertain to the CPT
352
+	 *
353
+	 * @access protected
354
+	 * @return void
355
+	 */
356
+	protected function setAdditionalCptDetails()
357
+	{
358
+		// the post or category or term that is triggering EE
359
+		$this->cpt_details['espresso_page'] = $this->current_page->isEspressoPage();
360
+		// requested post name
361
+		$this->cpt_details['post_name'] = $this->request->getRequestParam('post_name');
362
+		// add support for viewing 'private', 'draft', or 'pending' posts
363
+		if (
364
+			isset($this->wp_query->query_vars['p'])
365
+			&& $this->wp_query->query_vars['p'] !== 0
366
+			&& is_user_logged_in()
367
+			&& current_user_can('edit_post', $this->wp_query->query_vars['p'])
368
+		) {
369
+			// we can just inject directly into the WP_Query object
370
+			$this->wp_query->query['post_status'] = array('publish', 'private', 'draft', 'pending');
371
+			// now set the main 'ee' request var so that the appropriate module can load the appropriate template(s)
372
+			$this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
373
+		}
374
+	}
375
+
376
+
377
+	/**
378
+	 * Checks if we're on a EE-CPT archive-or-single page, and if we've never set the EE request var.
379
+	 * If so, sets the 'ee' request variable
380
+	 * so other parts of EE can know what CPT is getting queried.
381
+	 * To Mike's knowledge, this must be called from during or after the pre_get_posts hook
382
+	 * in order for is_archive() and is_single() methods to work properly.
383
+	 *
384
+	 * @return void
385
+	 */
386
+	public function setRequestVarsIfCpt()
387
+	{
388
+		// check if ee action var has been set
389
+		if (! $this->request->requestParamIsSet('ee')) {
390
+			// check that route exists for CPT archive slug
391
+			if (is_archive() && EE_Config::get_route($this->cpt_details['plural_slug'])) {
392
+				// ie: set "ee" to "events"
393
+				$this->request->setRequestParam('ee', $this->cpt_details['plural_slug']);
394
+				// or does it match a single page CPT like /event/
395
+			} elseif (is_single() && EE_Config::get_route($this->cpt_details['singular_slug'])) {
396
+				// ie: set "ee" to "event"
397
+				$this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
398
+			}
399
+		}
400
+	}
401
+
402
+
403
+	/**
404
+	 * setupModelsAndTables
405
+	 *
406
+	 * @access protected
407
+	 * @param string $model_name
408
+	 * @throws EE_Error
409
+	 */
410
+	protected function setupModelsAndTables($model_name)
411
+	{
412
+		// get CPT table data via CPT Model
413
+		$full_model_name = strpos($model_name, 'EEM_') !== 0
414
+			? 'EEM_' . $model_name
415
+			: $model_name;
416
+		$model = $this->loader->getShared($full_model_name);
417
+		if (! $model instanceof EEM_Base) {
418
+			throw new EE_Error(
419
+				sprintf(
420
+					esc_html__(
421
+						'The "%1$s" model could not be loaded.',
422
+						'event_espresso'
423
+					),
424
+					$full_model_name
425
+				)
426
+			);
427
+		}
428
+		$this->setModel($model);
429
+		$this->setModelTables($this->model->get_tables());
430
+		$meta_model = $model_name . '_Meta';
431
+		// is there a Meta Table for this CPT?
432
+		if (
433
+			isset($this->cpt_details['tables'][ $meta_model ])
434
+			&& $this->cpt_details['tables'][ $meta_model ] instanceof EE_Secondary_Table
435
+		) {
436
+			$this->setMetaTable($this->cpt_details['tables'][ $meta_model ]);
437
+		}
438
+	}
439
+
440
+
441
+	/**
442
+	 * cptStrategyClass
443
+	 *
444
+	 * @access protected
445
+	 * @param  string $model_name
446
+	 * @return string
447
+	 */
448
+	protected function cptStrategyClass($model_name)
449
+	{
450
+		// creates classname like:  CPT_Event_Strategy
451
+		$CPT_Strategy_class_name = 'EE_CPT_' . $model_name . '_Strategy';
452
+		// load and instantiate
453
+		$CPT_Strategy = $this->loader->getShared(
454
+			$CPT_Strategy_class_name,
455
+			array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
456
+		);
457
+		if ($CPT_Strategy === null) {
458
+			$CPT_Strategy = $this->loader->getShared(
459
+				'EE_CPT_Default_Strategy',
460
+				array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
461
+			);
462
+		}
463
+		return $CPT_Strategy;
464
+	}
465
+
466
+
467
+	/**
468
+	 * postsFields
469
+	 *
470
+	 * @access public
471
+	 * @param  $SQL
472
+	 * @return string
473
+	 */
474
+	public function postsFields($SQL)
475
+	{
476
+		// does this CPT have a meta table ?
477
+		if ($this->meta_table instanceof EE_Secondary_Table) {
478
+			// adds something like ", wp_esp_event_meta.* " to WP Query SELECT statement
479
+			$SQL .= ', ' . $this->meta_table->get_table_name() . '.* ';
480
+		}
481
+		remove_filter('posts_fields', array($this, 'postsFields'));
482
+		return $SQL;
483
+	}
484
+
485
+
486
+	/**
487
+	 * postsJoin
488
+	 *
489
+	 * @access public
490
+	 * @param  $SQL
491
+	 * @return string
492
+	 */
493
+	public function postsJoin($SQL)
494
+	{
495
+		// does this CPT have a meta table ?
496
+		if ($this->meta_table instanceof EE_Secondary_Table) {
497
+			global $wpdb;
498
+			// adds something like " LEFT JOIN wp_esp_event_meta ON ( wp_esp_event_meta.EVT_ID = wp_posts.ID ) " to WP Query JOIN statement
499
+			$SQL .= ' LEFT JOIN '
500
+					. $this->meta_table->get_table_name()
501
+					. ' ON ( '
502
+					. $this->meta_table->get_table_name()
503
+					. '.'
504
+					. $this->meta_table->get_fk_on_table()
505
+					. ' = '
506
+					. $wpdb->posts
507
+					. '.ID ) ';
508
+		}
509
+		remove_filter('posts_join', array($this, 'postsJoin'));
510
+		return $SQL;
511
+	}
512
+
513
+
514
+	/**
515
+	 * thePosts
516
+	 *
517
+	 * @access public
518
+	 * @param  WP_Post[] $posts
519
+	 * @return WP_Post[]
520
+	 */
521
+	public function thePosts($posts)
522
+	{
523
+		$CPT_class = $this->cpt_details['class_name'];
524
+		// loop thru posts
525
+		if (is_array($posts) && $this->model instanceof EEM_CPT_Base) {
526
+			foreach ($posts as $post) {
527
+				if ($post->post_type === $this->post_type) {
528
+					$post->{$CPT_class} = $this->model->instantiate_class_from_post_object($post);
529
+				}
530
+			}
531
+		}
532
+		remove_filter('the_posts', array($this, 'thePosts'), 1);
533
+		return $posts;
534
+	}
535
+
536
+
537
+	/**
538
+	 * @param $url
539
+	 * @param $ID
540
+	 * @return string
541
+	 */
542
+	public function getEditPostLink($url, $ID)
543
+	{
544
+		// need to make sure we only edit links if our cpt
545
+		global $post;
546
+		// notice if the cpt is registered with `show_ee_ui` set to false, we take that to mean that the WordPress core ui
547
+		// for interacting with the CPT is desired and there is no EE UI for interacting with the CPT in the admin.
548
+		if (
549
+			! $post instanceof WP_Post
550
+			|| $post->post_type !== $this->post_type
551
+			|| (
552
+				isset($this->cpt_details['args']['show_ee_ui'])
553
+				&& ! $this->cpt_details['args']['show_ee_ui']
554
+			)
555
+		) {
556
+			return $url;
557
+		}
558
+		// k made it here so all is good.
559
+		return wp_nonce_url(
560
+			add_query_arg(
561
+				array('page' => $this->post_type, 'post' => $ID, 'action' => 'edit'),
562
+				admin_url('admin.php')
563
+			),
564
+			'edit',
565
+			'edit_nonce'
566
+		);
567
+	}
568
+
569
+
570
+	/**
571
+	 * Execute any template filters.
572
+	 * This method is only called if in main query.
573
+	 *
574
+	 * @return void
575
+	 */
576
+	public function addTemplateFilters()
577
+	{
578
+		// if requested cpt supports page_templates and it's the main query
579
+		if (! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
580
+			// then let's hook into the appropriate query_template hook
581
+			add_filter('single_template', array($this, 'singleCptTemplate'));
582
+		}
583
+	}
584
+
585
+
586
+	/**
587
+	 * Callback for single_template wp filter.
588
+	 * This is used to load the set page_template for a single ee cpt if its set.  If "default" then we load the normal
589
+	 * hierarchy.
590
+	 *
591
+	 * @access public
592
+	 * @param string $current_template Existing default template path derived for this page call.
593
+	 * @return string the path to the full template file.
594
+	 */
595
+	public function singleCptTemplate($current_template)
596
+	{
597
+		$object = get_queried_object();
598
+		// does this called object HAVE a page template set that is something other than the default.
599
+		$template = get_post_meta($object->ID, '_wp_page_template', true);
600
+		// exit early if default or not set or invalid path (accounts for theme changes)
601
+		if (
602
+			$template === 'default'
603
+			|| empty($template)
604
+			|| ! is_readable(get_stylesheet_directory() . '/' . $template)
605
+		) {
606
+			return $current_template;
607
+		}
608
+		// made it here so we SHOULD be able to just locate the template and then return it.
609
+		return locate_template(array($template));
610
+	}
611 611
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
      */
242 242
     public function request()
243 243
     {
244
-        if (! $this->request_handler instanceof EE_Request_Handler) {
244
+        if ( ! $this->request_handler instanceof EE_Request_Handler) {
245 245
             $this->request_handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
246 246
         }
247 247
         return $this->request_handler;
@@ -296,8 +296,8 @@  discard block
 block discarded – undo
296 296
             $all_taxonomies = $taxonomy_definitions->getCustomTaxonomyDefinitions();
297 297
             foreach ($taxonomies as $taxonomy => &$details) {
298 298
                 // add details to our taxonomies if they exist
299
-                $details = isset($all_taxonomies[ $taxonomy ])
300
-                    ? $all_taxonomies[ $taxonomy ]
299
+                $details = isset($all_taxonomies[$taxonomy])
300
+                    ? $all_taxonomies[$taxonomy]
301 301
                     : array();
302 302
             }
303 303
             // ALWAYS unset() variables that were passed by reference
@@ -334,7 +334,7 @@  discard block
 block discarded – undo
334 334
         add_filter('posts_fields', array($this, 'postsFields'));
335 335
         add_filter('posts_join', array($this, 'postsJoin'));
336 336
         add_filter(
337
-            'get_' . $this->post_type . '_metadata',
337
+            'get_'.$this->post_type.'_metadata',
338 338
             array($CPT_Strategy, 'get_EE_post_type_metadata'),
339 339
             1,
340 340
             4
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
     public function setRequestVarsIfCpt()
387 387
     {
388 388
         // check if ee action var has been set
389
-        if (! $this->request->requestParamIsSet('ee')) {
389
+        if ( ! $this->request->requestParamIsSet('ee')) {
390 390
             // check that route exists for CPT archive slug
391 391
             if (is_archive() && EE_Config::get_route($this->cpt_details['plural_slug'])) {
392 392
                 // ie: set "ee" to "events"
@@ -411,10 +411,10 @@  discard block
 block discarded – undo
411 411
     {
412 412
         // get CPT table data via CPT Model
413 413
         $full_model_name = strpos($model_name, 'EEM_') !== 0
414
-            ? 'EEM_' . $model_name
414
+            ? 'EEM_'.$model_name
415 415
             : $model_name;
416 416
         $model = $this->loader->getShared($full_model_name);
417
-        if (! $model instanceof EEM_Base) {
417
+        if ( ! $model instanceof EEM_Base) {
418 418
             throw new EE_Error(
419 419
                 sprintf(
420 420
                     esc_html__(
@@ -427,13 +427,13 @@  discard block
 block discarded – undo
427 427
         }
428 428
         $this->setModel($model);
429 429
         $this->setModelTables($this->model->get_tables());
430
-        $meta_model = $model_name . '_Meta';
430
+        $meta_model = $model_name.'_Meta';
431 431
         // is there a Meta Table for this CPT?
432 432
         if (
433
-            isset($this->cpt_details['tables'][ $meta_model ])
434
-            && $this->cpt_details['tables'][ $meta_model ] instanceof EE_Secondary_Table
433
+            isset($this->cpt_details['tables'][$meta_model])
434
+            && $this->cpt_details['tables'][$meta_model] instanceof EE_Secondary_Table
435 435
         ) {
436
-            $this->setMetaTable($this->cpt_details['tables'][ $meta_model ]);
436
+            $this->setMetaTable($this->cpt_details['tables'][$meta_model]);
437 437
         }
438 438
     }
439 439
 
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
     protected function cptStrategyClass($model_name)
449 449
     {
450 450
         // creates classname like:  CPT_Event_Strategy
451
-        $CPT_Strategy_class_name = 'EE_CPT_' . $model_name . '_Strategy';
451
+        $CPT_Strategy_class_name = 'EE_CPT_'.$model_name.'_Strategy';
452 452
         // load and instantiate
453 453
         $CPT_Strategy = $this->loader->getShared(
454 454
             $CPT_Strategy_class_name,
@@ -476,7 +476,7 @@  discard block
 block discarded – undo
476 476
         // does this CPT have a meta table ?
477 477
         if ($this->meta_table instanceof EE_Secondary_Table) {
478 478
             // adds something like ", wp_esp_event_meta.* " to WP Query SELECT statement
479
-            $SQL .= ', ' . $this->meta_table->get_table_name() . '.* ';
479
+            $SQL .= ', '.$this->meta_table->get_table_name().'.* ';
480 480
         }
481 481
         remove_filter('posts_fields', array($this, 'postsFields'));
482 482
         return $SQL;
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
     public function addTemplateFilters()
577 577
     {
578 578
         // if requested cpt supports page_templates and it's the main query
579
-        if (! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
579
+        if ( ! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
580 580
             // then let's hook into the appropriate query_template hook
581 581
             add_filter('single_template', array($this, 'singleCptTemplate'));
582 582
         }
@@ -601,7 +601,7 @@  discard block
 block discarded – undo
601 601
         if (
602 602
             $template === 'default'
603 603
             || empty($template)
604
-            || ! is_readable(get_stylesheet_directory() . '/' . $template)
604
+            || ! is_readable(get_stylesheet_directory().'/'.$template)
605 605
         ) {
606 606
             return $current_template;
607 607
         }
Please login to merge, or discard this patch.
core/EE_Cron_Tasks.core.php 2 patches
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -38,7 +38,7 @@  discard block
 block discarded – undo
38 38
      */
39 39
     public static function instance()
40 40
     {
41
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
41
+        if ( ! self::$_instance instanceof EE_Cron_Tasks) {
42 42
             self::$_instance = new self();
43 43
         }
44 44
         return self::$_instance;
@@ -72,7 +72,7 @@  discard block
 block discarded – undo
72 72
              */
73 73
             add_action(
74 74
                 'AHEE__EE_System__load_core_configuration__complete',
75
-                function () {
75
+                function() {
76 76
                     EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
77 77
                     EE_Registry::instance()->NET_CFG->update_config(true, false);
78 78
                     add_option('ee_disabled_wp_cron_check', 1, '', false);
@@ -124,16 +124,16 @@  discard block
 block discarded – undo
124 124
             'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
125 125
         );
126 126
         $crons = (array) get_option('cron');
127
-        if (! is_array($crons)) {
127
+        if ( ! is_array($crons)) {
128 128
             return;
129 129
         }
130 130
         foreach ($crons as $timestamp => $cron) {
131 131
             /** @var array[] $cron */
132 132
             foreach ($ee_crons as $ee_cron) {
133
-                if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
133
+                if (isset($cron[$ee_cron]) && is_array($cron[$ee_cron])) {
134 134
                     do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
135
-                    foreach ($cron[ $ee_cron ] as $ee_cron_details) {
136
-                        if (! empty($ee_cron_details['args'])) {
135
+                    foreach ($cron[$ee_cron] as $ee_cron_details) {
136
+                        if ( ! empty($ee_cron_details['args'])) {
137 137
                             do_action(
138 138
                                 'AHEE_log',
139 139
                                 __CLASS__,
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
      */
161 161
     public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
162 162
     {
163
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
163
+        if ( ! method_exists('EE_Cron_Tasks', $cron_task)) {
164 164
             throw new DomainException(
165 165
                 sprintf(
166 166
                     esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
             );
170 170
         }
171 171
         // reschedule the cron if we can't hit the db right now
172
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
172
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
173 173
             foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
174 174
                 // ensure $additional_vars is an array
175 175
                 $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
@@ -250,7 +250,7 @@  discard block
 block discarded – undo
250 250
     {
251 251
         do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
252 252
         if (absint($TXN_ID)) {
253
-            self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
253
+            self::$_update_transactions_with_payment[$TXN_ID] = $PAY_ID;
254 254
             add_action(
255 255
                 'shutdown',
256 256
                 array('EE_Cron_Tasks', 'update_transaction_with_payment'),
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
         EE_Registry::instance()->load_model('Transaction');
298 298
         foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
299 299
             // reschedule the cron if we can't hit the db right now
300
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
300
+            if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
301 301
                 // reset cron job for updating the TXN
302 302
                 EE_Cron_Tasks::schedule_update_transaction_with_payment(
303 303
                     time() + EE_Cron_Tasks::reschedule_timeout,
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
                 // now try to update the TXN with any payments
314 314
                 $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
315 315
             }
316
-            unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
316
+            unset(self::$_update_transactions_with_payment[$TXN_ID]);
317 317
         }
318 318
     }
319 319
 
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
     public static function expired_transaction_check($TXN_ID = 0)
375 375
     {
376 376
         if (absint($TXN_ID)) {
377
-            self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
377
+            self::$_expired_transactions[$TXN_ID] = $TXN_ID;
378 378
             add_action(
379 379
                 'shutdown',
380 380
                 array('EE_Cron_Tasks', 'process_expired_transactions'),
@@ -502,7 +502,7 @@  discard block
 block discarded – undo
502 502
                         break;
503 503
                 }
504 504
             }
505
-            unset(self::$_expired_transactions[ $TXN_ID ]);
505
+            unset(self::$_expired_transactions[$TXN_ID]);
506 506
         }
507 507
     }
508 508
 
@@ -549,7 +549,7 @@  discard block
 block discarded – undo
549 549
             $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
550 550
             $time_diff_for_comparison = apply_filters(
551 551
                 'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
552
-                '-' . $reg_config->gateway_log_lifespan
552
+                '-'.$reg_config->gateway_log_lifespan
553 553
             );
554 554
             EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
555 555
         }
Please login to merge, or discard this patch.
Indentation   +600 added lines, -600 removed lines patch added patch discarded remove patch
@@ -14,607 +14,607 @@
 block discarded – undo
14 14
  */
15 15
 class EE_Cron_Tasks extends EE_Base
16 16
 {
17
-    /**
18
-     * WordPress doesn't allow duplicate crons within 10 minutes of the original,
19
-     * so we'll set our retry time for just over 10 minutes to avoid that
20
-     */
21
-    const reschedule_timeout = 605;
22
-
23
-
24
-    /**
25
-     * @var EE_Cron_Tasks
26
-     */
27
-    private static $_instance;
28
-
29
-
30
-    /**
31
-     * @return EE_Cron_Tasks
32
-     * @throws ReflectionException
33
-     * @throws EE_Error
34
-     * @throws InvalidArgumentException
35
-     * @throws InvalidInterfaceException
36
-     * @throws InvalidDataTypeException
37
-     */
38
-    public static function instance()
39
-    {
40
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
41
-            self::$_instance = new self();
42
-        }
43
-        return self::$_instance;
44
-    }
45
-
46
-
47
-    /**
48
-     * @access private
49
-     * @throws InvalidDataTypeException
50
-     * @throws InvalidInterfaceException
51
-     * @throws InvalidArgumentException
52
-     * @throws EE_Error
53
-     * @throws ReflectionException
54
-     */
55
-    private function __construct()
56
-    {
57
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
58
-        // verify that WP Cron is enabled
59
-        if (
60
-            defined('DISABLE_WP_CRON')
61
-            && DISABLE_WP_CRON
62
-            && is_admin()
63
-            && ! get_option('ee_disabled_wp_cron_check')
64
-        ) {
65
-            /**
66
-             * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
67
-             * config is loaded.
68
-             * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
69
-             * wanting to not have this functionality can just register its own action at a priority after this one to
70
-             * reverse any changes.
71
-             */
72
-            add_action(
73
-                'AHEE__EE_System__load_core_configuration__complete',
74
-                function () {
75
-                    EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
76
-                    EE_Registry::instance()->NET_CFG->update_config(true, false);
77
-                    add_option('ee_disabled_wp_cron_check', 1, '', false);
78
-                }
79
-            );
80
-        }
81
-        // UPDATE TRANSACTION WITH PAYMENT
82
-        add_action(
83
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
84
-            array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
85
-            10,
86
-            2
87
-        );
88
-        // ABANDONED / EXPIRED TRANSACTION CHECK
89
-        add_action(
90
-            'AHEE__EE_Cron_Tasks__expired_transaction_check',
91
-            array('EE_Cron_Tasks', 'expired_transaction_check'),
92
-            10,
93
-            1
94
-        );
95
-        // CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
96
-        add_action(
97
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
98
-            array('EE_Cron_Tasks', 'clean_out_junk_transactions')
99
-        );
100
-        // logging
101
-        add_action(
102
-            'AHEE__EE_System__load_core_configuration__complete',
103
-            array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
104
-        );
105
-        EE_Registry::instance()->load_lib('Messages_Scheduler');
106
-        // clean out old gateway logs
107
-        add_action(
108
-            'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
109
-            array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
110
-        );
111
-    }
112
-
113
-
114
-    /**
115
-     * @access protected
116
-     * @return void
117
-     */
118
-    public static function log_scheduled_ee_crons()
119
-    {
120
-        $ee_crons = array(
121
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
122
-            'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
123
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
124
-        );
125
-        $crons = (array) get_option('cron');
126
-        if (! is_array($crons)) {
127
-            return;
128
-        }
129
-        foreach ($crons as $timestamp => $cron) {
130
-            /** @var array[] $cron */
131
-            foreach ($ee_crons as $ee_cron) {
132
-                if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
133
-                    do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
134
-                    foreach ($cron[ $ee_cron ] as $ee_cron_details) {
135
-                        if (! empty($ee_cron_details['args'])) {
136
-                            do_action(
137
-                                'AHEE_log',
138
-                                __CLASS__,
139
-                                __FUNCTION__,
140
-                                print_r($ee_cron_details['args'], true),
141
-                                "{$ee_cron} args"
142
-                            );
143
-                        }
144
-                    }
145
-                }
146
-            }
147
-        }
148
-    }
149
-
150
-
151
-    /**
152
-     * reschedule_cron_for_transactions_if_maintenance_mode
153
-     * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
154
-     *
155
-     * @param string $cron_task
156
-     * @param array  $TXN_IDs
157
-     * @return bool
158
-     * @throws DomainException
159
-     */
160
-    public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
161
-    {
162
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
163
-            throw new DomainException(
164
-                sprintf(
165
-                    esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
166
-                    $cron_task
167
-                )
168
-            );
169
-        }
170
-        // reschedule the cron if we can't hit the db right now
171
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
172
-            foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
173
-                // ensure $additional_vars is an array
174
-                $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
175
-                // reset cron job for the TXN
176
-                call_user_func_array(
177
-                    array('EE_Cron_Tasks', $cron_task),
178
-                    array_merge(
179
-                        array(
180
-                            time() + (10 * MINUTE_IN_SECONDS),
181
-                            $TXN_ID,
182
-                        ),
183
-                        $additional_vars
184
-                    )
185
-                );
186
-            }
187
-            return true;
188
-        }
189
-        return false;
190
-    }
191
-
192
-
193
-
194
-
195
-    /****************  UPDATE TRANSACTION WITH PAYMENT ****************/
196
-
197
-
198
-    /**
199
-     * array of TXN IDs and the payment
200
-     *
201
-     * @var array
202
-     */
203
-    protected static $_update_transactions_with_payment = array();
204
-
205
-
206
-    /**
207
-     * schedule_update_transaction_with_payment
208
-     * sets a wp_schedule_single_event() for updating any TXNs that may
209
-     * require updating due to recently received payments
210
-     *
211
-     * @param int $timestamp
212
-     * @param int $TXN_ID
213
-     * @param int $PAY_ID
214
-     */
215
-    public static function schedule_update_transaction_with_payment(
216
-        $timestamp,
217
-        $TXN_ID,
218
-        $PAY_ID
219
-    ) {
220
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
221
-        // validate $TXN_ID and $timestamp
222
-        $TXN_ID = absint($TXN_ID);
223
-        $timestamp = absint($timestamp);
224
-        if ($TXN_ID && $timestamp) {
225
-            wp_schedule_single_event(
226
-                $timestamp,
227
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
228
-                array($TXN_ID, $PAY_ID)
229
-            );
230
-        }
231
-    }
232
-
233
-
234
-    /**
235
-     * setup_update_for_transaction_with_payment
236
-     * this is the callback for the action hook:
237
-     * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
238
-     * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
239
-     * The passed TXN_ID and associated payment gets added to an array, and then
240
-     * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
241
-     * 'shutdown' which will actually handle the processing of any
242
-     * transactions requiring updating, because doing so now would be too early
243
-     * and the required resources may not be available
244
-     *
245
-     * @param int $TXN_ID
246
-     * @param int $PAY_ID
247
-     */
248
-    public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0)
249
-    {
250
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
251
-        if (absint($TXN_ID)) {
252
-            self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
253
-            add_action(
254
-                'shutdown',
255
-                array('EE_Cron_Tasks', 'update_transaction_with_payment'),
256
-                5
257
-            );
258
-        }
259
-    }
260
-
261
-
262
-    /**
263
-     * update_transaction_with_payment
264
-     * loops through the self::$_abandoned_transactions array
265
-     * and attempts to finalize any TXNs that have not been completed
266
-     * but have had their sessions expired, most likely due to a user not
267
-     * returning from an off-site payment gateway
268
-     *
269
-     * @throws EE_Error
270
-     * @throws DomainException
271
-     * @throws InvalidDataTypeException
272
-     * @throws InvalidInterfaceException
273
-     * @throws InvalidArgumentException
274
-     * @throws ReflectionException
275
-     * @throws RuntimeException
276
-     */
277
-    public static function update_transaction_with_payment()
278
-    {
279
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
280
-        if (
17
+	/**
18
+	 * WordPress doesn't allow duplicate crons within 10 minutes of the original,
19
+	 * so we'll set our retry time for just over 10 minutes to avoid that
20
+	 */
21
+	const reschedule_timeout = 605;
22
+
23
+
24
+	/**
25
+	 * @var EE_Cron_Tasks
26
+	 */
27
+	private static $_instance;
28
+
29
+
30
+	/**
31
+	 * @return EE_Cron_Tasks
32
+	 * @throws ReflectionException
33
+	 * @throws EE_Error
34
+	 * @throws InvalidArgumentException
35
+	 * @throws InvalidInterfaceException
36
+	 * @throws InvalidDataTypeException
37
+	 */
38
+	public static function instance()
39
+	{
40
+		if (! self::$_instance instanceof EE_Cron_Tasks) {
41
+			self::$_instance = new self();
42
+		}
43
+		return self::$_instance;
44
+	}
45
+
46
+
47
+	/**
48
+	 * @access private
49
+	 * @throws InvalidDataTypeException
50
+	 * @throws InvalidInterfaceException
51
+	 * @throws InvalidArgumentException
52
+	 * @throws EE_Error
53
+	 * @throws ReflectionException
54
+	 */
55
+	private function __construct()
56
+	{
57
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
58
+		// verify that WP Cron is enabled
59
+		if (
60
+			defined('DISABLE_WP_CRON')
61
+			&& DISABLE_WP_CRON
62
+			&& is_admin()
63
+			&& ! get_option('ee_disabled_wp_cron_check')
64
+		) {
65
+			/**
66
+			 * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
67
+			 * config is loaded.
68
+			 * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
69
+			 * wanting to not have this functionality can just register its own action at a priority after this one to
70
+			 * reverse any changes.
71
+			 */
72
+			add_action(
73
+				'AHEE__EE_System__load_core_configuration__complete',
74
+				function () {
75
+					EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
76
+					EE_Registry::instance()->NET_CFG->update_config(true, false);
77
+					add_option('ee_disabled_wp_cron_check', 1, '', false);
78
+				}
79
+			);
80
+		}
81
+		// UPDATE TRANSACTION WITH PAYMENT
82
+		add_action(
83
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
84
+			array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
85
+			10,
86
+			2
87
+		);
88
+		// ABANDONED / EXPIRED TRANSACTION CHECK
89
+		add_action(
90
+			'AHEE__EE_Cron_Tasks__expired_transaction_check',
91
+			array('EE_Cron_Tasks', 'expired_transaction_check'),
92
+			10,
93
+			1
94
+		);
95
+		// CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
96
+		add_action(
97
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
98
+			array('EE_Cron_Tasks', 'clean_out_junk_transactions')
99
+		);
100
+		// logging
101
+		add_action(
102
+			'AHEE__EE_System__load_core_configuration__complete',
103
+			array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
104
+		);
105
+		EE_Registry::instance()->load_lib('Messages_Scheduler');
106
+		// clean out old gateway logs
107
+		add_action(
108
+			'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
109
+			array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
110
+		);
111
+	}
112
+
113
+
114
+	/**
115
+	 * @access protected
116
+	 * @return void
117
+	 */
118
+	public static function log_scheduled_ee_crons()
119
+	{
120
+		$ee_crons = array(
121
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
122
+			'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
123
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
124
+		);
125
+		$crons = (array) get_option('cron');
126
+		if (! is_array($crons)) {
127
+			return;
128
+		}
129
+		foreach ($crons as $timestamp => $cron) {
130
+			/** @var array[] $cron */
131
+			foreach ($ee_crons as $ee_cron) {
132
+				if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
133
+					do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
134
+					foreach ($cron[ $ee_cron ] as $ee_cron_details) {
135
+						if (! empty($ee_cron_details['args'])) {
136
+							do_action(
137
+								'AHEE_log',
138
+								__CLASS__,
139
+								__FUNCTION__,
140
+								print_r($ee_cron_details['args'], true),
141
+								"{$ee_cron} args"
142
+							);
143
+						}
144
+					}
145
+				}
146
+			}
147
+		}
148
+	}
149
+
150
+
151
+	/**
152
+	 * reschedule_cron_for_transactions_if_maintenance_mode
153
+	 * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
154
+	 *
155
+	 * @param string $cron_task
156
+	 * @param array  $TXN_IDs
157
+	 * @return bool
158
+	 * @throws DomainException
159
+	 */
160
+	public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
161
+	{
162
+		if (! method_exists('EE_Cron_Tasks', $cron_task)) {
163
+			throw new DomainException(
164
+				sprintf(
165
+					esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
166
+					$cron_task
167
+				)
168
+			);
169
+		}
170
+		// reschedule the cron if we can't hit the db right now
171
+		if (! EE_Maintenance_Mode::instance()->models_can_query()) {
172
+			foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
173
+				// ensure $additional_vars is an array
174
+				$additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
175
+				// reset cron job for the TXN
176
+				call_user_func_array(
177
+					array('EE_Cron_Tasks', $cron_task),
178
+					array_merge(
179
+						array(
180
+							time() + (10 * MINUTE_IN_SECONDS),
181
+							$TXN_ID,
182
+						),
183
+						$additional_vars
184
+					)
185
+				);
186
+			}
187
+			return true;
188
+		}
189
+		return false;
190
+	}
191
+
192
+
193
+
194
+
195
+	/****************  UPDATE TRANSACTION WITH PAYMENT ****************/
196
+
197
+
198
+	/**
199
+	 * array of TXN IDs and the payment
200
+	 *
201
+	 * @var array
202
+	 */
203
+	protected static $_update_transactions_with_payment = array();
204
+
205
+
206
+	/**
207
+	 * schedule_update_transaction_with_payment
208
+	 * sets a wp_schedule_single_event() for updating any TXNs that may
209
+	 * require updating due to recently received payments
210
+	 *
211
+	 * @param int $timestamp
212
+	 * @param int $TXN_ID
213
+	 * @param int $PAY_ID
214
+	 */
215
+	public static function schedule_update_transaction_with_payment(
216
+		$timestamp,
217
+		$TXN_ID,
218
+		$PAY_ID
219
+	) {
220
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
221
+		// validate $TXN_ID and $timestamp
222
+		$TXN_ID = absint($TXN_ID);
223
+		$timestamp = absint($timestamp);
224
+		if ($TXN_ID && $timestamp) {
225
+			wp_schedule_single_event(
226
+				$timestamp,
227
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
228
+				array($TXN_ID, $PAY_ID)
229
+			);
230
+		}
231
+	}
232
+
233
+
234
+	/**
235
+	 * setup_update_for_transaction_with_payment
236
+	 * this is the callback for the action hook:
237
+	 * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
238
+	 * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
239
+	 * The passed TXN_ID and associated payment gets added to an array, and then
240
+	 * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
241
+	 * 'shutdown' which will actually handle the processing of any
242
+	 * transactions requiring updating, because doing so now would be too early
243
+	 * and the required resources may not be available
244
+	 *
245
+	 * @param int $TXN_ID
246
+	 * @param int $PAY_ID
247
+	 */
248
+	public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0)
249
+	{
250
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
251
+		if (absint($TXN_ID)) {
252
+			self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
253
+			add_action(
254
+				'shutdown',
255
+				array('EE_Cron_Tasks', 'update_transaction_with_payment'),
256
+				5
257
+			);
258
+		}
259
+	}
260
+
261
+
262
+	/**
263
+	 * update_transaction_with_payment
264
+	 * loops through the self::$_abandoned_transactions array
265
+	 * and attempts to finalize any TXNs that have not been completed
266
+	 * but have had their sessions expired, most likely due to a user not
267
+	 * returning from an off-site payment gateway
268
+	 *
269
+	 * @throws EE_Error
270
+	 * @throws DomainException
271
+	 * @throws InvalidDataTypeException
272
+	 * @throws InvalidInterfaceException
273
+	 * @throws InvalidArgumentException
274
+	 * @throws ReflectionException
275
+	 * @throws RuntimeException
276
+	 */
277
+	public static function update_transaction_with_payment()
278
+	{
279
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
280
+		if (
281 281
 // are there any TXNs that need cleaning up ?
282
-            empty(self::$_update_transactions_with_payment)
283
-            // reschedule the cron if we can't hit the db right now
284
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
285
-                'schedule_update_transaction_with_payment',
286
-                self::$_update_transactions_with_payment
287
-            )
288
-        ) {
289
-            return;
290
-        }
291
-        /** @type EE_Payment_Processor $payment_processor */
292
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
293
-        // set revisit flag for payment processor
294
-        $payment_processor->set_revisit();
295
-        // load EEM_Transaction
296
-        EE_Registry::instance()->load_model('Transaction');
297
-        foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
298
-            // reschedule the cron if we can't hit the db right now
299
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
300
-                // reset cron job for updating the TXN
301
-                EE_Cron_Tasks::schedule_update_transaction_with_payment(
302
-                    time() + EE_Cron_Tasks::reschedule_timeout,
303
-                    $TXN_ID,
304
-                    $PAY_ID
305
-                );
306
-                continue;
307
-            }
308
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
309
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
310
-            // verify transaction
311
-            if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
312
-                // now try to update the TXN with any payments
313
-                $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
314
-            }
315
-            unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
316
-        }
317
-    }
318
-
319
-
320
-
321
-    /************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
322
-
323
-
324
-    /*****************  EXPIRED TRANSACTION CHECK *****************/
325
-
326
-
327
-    /**
328
-     * array of TXN IDs
329
-     *
330
-     * @var array
331
-     */
332
-    protected static $_expired_transactions = array();
333
-
334
-
335
-    /**
336
-     * schedule_expired_transaction_check
337
-     * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
338
-     *
339
-     * @param int $timestamp
340
-     * @param int $TXN_ID
341
-     */
342
-    public static function schedule_expired_transaction_check(
343
-        $timestamp,
344
-        $TXN_ID
345
-    ) {
346
-        // validate $TXN_ID and $timestamp
347
-        $TXN_ID = absint($TXN_ID);
348
-        $timestamp = absint($timestamp);
349
-        if ($TXN_ID && $timestamp) {
350
-            wp_schedule_single_event(
351
-                $timestamp,
352
-                'AHEE__EE_Cron_Tasks__expired_transaction_check',
353
-                array($TXN_ID)
354
-            );
355
-        }
356
-    }
357
-
358
-
359
-    /**
360
-     * expired_transaction_check
361
-     * this is the callback for the action hook:
362
-     * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
363
-     * which is utilized by wp_schedule_single_event()
364
-     * in \EED_Single_Page_Checkout::_initialize_transaction().
365
-     * The passed TXN_ID gets added to an array, and then the
366
-     * process_expired_transactions() function is hooked into
367
-     * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
368
-     * processing of any failed transactions, because doing so now would be
369
-     * too early and the required resources may not be available
370
-     *
371
-     * @param int $TXN_ID
372
-     */
373
-    public static function expired_transaction_check($TXN_ID = 0)
374
-    {
375
-        if (absint($TXN_ID)) {
376
-            self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
377
-            add_action(
378
-                'shutdown',
379
-                array('EE_Cron_Tasks', 'process_expired_transactions'),
380
-                5
381
-            );
382
-        }
383
-    }
384
-
385
-
386
-    /**
387
-     * process_expired_transactions
388
-     * loops through the self::$_expired_transactions array and processes any failed TXNs
389
-     *
390
-     * @throws EE_Error
391
-     * @throws InvalidDataTypeException
392
-     * @throws InvalidInterfaceException
393
-     * @throws InvalidArgumentException
394
-     * @throws ReflectionException
395
-     * @throws DomainException
396
-     * @throws RuntimeException
397
-     */
398
-    public static function process_expired_transactions()
399
-    {
400
-        if (
282
+			empty(self::$_update_transactions_with_payment)
283
+			// reschedule the cron if we can't hit the db right now
284
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
285
+				'schedule_update_transaction_with_payment',
286
+				self::$_update_transactions_with_payment
287
+			)
288
+		) {
289
+			return;
290
+		}
291
+		/** @type EE_Payment_Processor $payment_processor */
292
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
293
+		// set revisit flag for payment processor
294
+		$payment_processor->set_revisit();
295
+		// load EEM_Transaction
296
+		EE_Registry::instance()->load_model('Transaction');
297
+		foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
298
+			// reschedule the cron if we can't hit the db right now
299
+			if (! EE_Maintenance_Mode::instance()->models_can_query()) {
300
+				// reset cron job for updating the TXN
301
+				EE_Cron_Tasks::schedule_update_transaction_with_payment(
302
+					time() + EE_Cron_Tasks::reschedule_timeout,
303
+					$TXN_ID,
304
+					$PAY_ID
305
+				);
306
+				continue;
307
+			}
308
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
309
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
310
+			// verify transaction
311
+			if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
312
+				// now try to update the TXN with any payments
313
+				$payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
314
+			}
315
+			unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
316
+		}
317
+	}
318
+
319
+
320
+
321
+	/************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
322
+
323
+
324
+	/*****************  EXPIRED TRANSACTION CHECK *****************/
325
+
326
+
327
+	/**
328
+	 * array of TXN IDs
329
+	 *
330
+	 * @var array
331
+	 */
332
+	protected static $_expired_transactions = array();
333
+
334
+
335
+	/**
336
+	 * schedule_expired_transaction_check
337
+	 * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
338
+	 *
339
+	 * @param int $timestamp
340
+	 * @param int $TXN_ID
341
+	 */
342
+	public static function schedule_expired_transaction_check(
343
+		$timestamp,
344
+		$TXN_ID
345
+	) {
346
+		// validate $TXN_ID and $timestamp
347
+		$TXN_ID = absint($TXN_ID);
348
+		$timestamp = absint($timestamp);
349
+		if ($TXN_ID && $timestamp) {
350
+			wp_schedule_single_event(
351
+				$timestamp,
352
+				'AHEE__EE_Cron_Tasks__expired_transaction_check',
353
+				array($TXN_ID)
354
+			);
355
+		}
356
+	}
357
+
358
+
359
+	/**
360
+	 * expired_transaction_check
361
+	 * this is the callback for the action hook:
362
+	 * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
363
+	 * which is utilized by wp_schedule_single_event()
364
+	 * in \EED_Single_Page_Checkout::_initialize_transaction().
365
+	 * The passed TXN_ID gets added to an array, and then the
366
+	 * process_expired_transactions() function is hooked into
367
+	 * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
368
+	 * processing of any failed transactions, because doing so now would be
369
+	 * too early and the required resources may not be available
370
+	 *
371
+	 * @param int $TXN_ID
372
+	 */
373
+	public static function expired_transaction_check($TXN_ID = 0)
374
+	{
375
+		if (absint($TXN_ID)) {
376
+			self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
377
+			add_action(
378
+				'shutdown',
379
+				array('EE_Cron_Tasks', 'process_expired_transactions'),
380
+				5
381
+			);
382
+		}
383
+	}
384
+
385
+
386
+	/**
387
+	 * process_expired_transactions
388
+	 * loops through the self::$_expired_transactions array and processes any failed TXNs
389
+	 *
390
+	 * @throws EE_Error
391
+	 * @throws InvalidDataTypeException
392
+	 * @throws InvalidInterfaceException
393
+	 * @throws InvalidArgumentException
394
+	 * @throws ReflectionException
395
+	 * @throws DomainException
396
+	 * @throws RuntimeException
397
+	 */
398
+	public static function process_expired_transactions()
399
+	{
400
+		if (
401 401
 // are there any TXNs that need cleaning up ?
402
-            empty(self::$_expired_transactions)
403
-            // reschedule the cron if we can't hit the db right now
404
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
405
-                'schedule_expired_transaction_check',
406
-                self::$_expired_transactions
407
-            )
408
-        ) {
409
-            return;
410
-        }
411
-        /** @type EE_Transaction_Processor $transaction_processor */
412
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
413
-        // set revisit flag for txn processor
414
-        $transaction_processor->set_revisit();
415
-        // load EEM_Transaction
416
-        EE_Registry::instance()->load_model('Transaction');
417
-        foreach (self::$_expired_transactions as $TXN_ID) {
418
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
419
-            // verify transaction and whether it is failed or not
420
-            if ($transaction instanceof EE_Transaction) {
421
-                switch ($transaction->status_ID()) {
422
-                    // Completed TXNs
423
-                    case EEM_Transaction::complete_status_code:
424
-                        // Don't update the transaction/registrations if the Primary Registration is Not Approved.
425
-                        $primary_registration = $transaction->primary_registration();
426
-                        if (
427
-                            $primary_registration instanceof EE_Registration
428
-                            && $primary_registration->status_ID() !== EEM_Registration::status_id_not_approved
429
-                        ) {
430
-                            /** @type EE_Transaction_Processor $transaction_processor */
431
-                            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
432
-                            $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
433
-                                $transaction,
434
-                                $transaction->last_payment()
435
-                            );
436
-                            do_action(
437
-                                'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
438
-                                $transaction
439
-                            );
440
-                        }
441
-                        break;
442
-                    // Overpaid TXNs
443
-                    case EEM_Transaction::overpaid_status_code:
444
-                        do_action(
445
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
446
-                            $transaction
447
-                        );
448
-                        break;
449
-                    // Incomplete TXNs
450
-                    case EEM_Transaction::incomplete_status_code:
451
-                        do_action(
452
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
453
-                            $transaction
454
-                        );
455
-                        // todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
456
-                        break;
457
-                    // Abandoned TXNs
458
-                    case EEM_Transaction::abandoned_status_code:
459
-                        // run hook before updating transaction, primarily so
460
-                        // EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets
461
-                        do_action(
462
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
463
-                            $transaction
464
-                        );
465
-                        // don't finalize the TXN if it has already been completed
466
-                        if ($transaction->all_reg_steps_completed() !== true) {
467
-                            /** @type EE_Payment_Processor $payment_processor */
468
-                            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
469
-                            // let's simulate an IPN here which will trigger any notifications that need to go out
470
-                            $payment_processor->update_txn_based_on_payment(
471
-                                $transaction,
472
-                                $transaction->last_payment(),
473
-                                true,
474
-                                true
475
-                            );
476
-                        }
477
-                        break;
478
-                    // Failed TXNs
479
-                    case EEM_Transaction::failed_status_code:
480
-                        do_action(
481
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
482
-                            $transaction
483
-                        );
484
-                        // todo :
485
-                        // perform garbage collection here and remove clean_out_junk_transactions()
486
-                        // $registrations = $transaction->registrations();
487
-                        // if (! empty($registrations)) {
488
-                        //     foreach ($registrations as $registration) {
489
-                        //         if ($registration instanceof EE_Registration) {
490
-                        //             $delete_registration = true;
491
-                        //             if ($registration->attendee() instanceof EE_Attendee) {
492
-                        //                 $delete_registration = false;
493
-                        //             }
494
-                        //             if ($delete_registration) {
495
-                        //                 $registration->delete_permanently();
496
-                        //                 $registration->delete_related_permanently();
497
-                        //             }
498
-                        //         }
499
-                        //     }
500
-                        // }
501
-                        break;
502
-                }
503
-            }
504
-            unset(self::$_expired_transactions[ $TXN_ID ]);
505
-        }
506
-    }
507
-
508
-
509
-
510
-    /*************  END OF EXPIRED TRANSACTION CHECK  *************/
511
-
512
-
513
-    /************* START CLEAN UP BOT TRANSACTIONS **********************/
514
-
515
-
516
-    /**
517
-     * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'
518
-     * which is setup during activation to run on an hourly cron
519
-     *
520
-     * @throws EE_Error
521
-     * @throws InvalidArgumentException
522
-     * @throws InvalidDataTypeException
523
-     * @throws InvalidInterfaceException
524
-     * @throws DomainException
525
-     */
526
-    public static function clean_out_junk_transactions()
527
-    {
528
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
529
-            EED_Ticket_Sales_Monitor::reset_reservation_counts();
530
-            EEM_Transaction::instance('')->delete_junk_transactions();
531
-            EEM_Registration::instance('')->delete_registrations_with_no_transaction();
532
-            EEM_Line_Item::instance('')->delete_line_items_with_no_transaction();
533
-        }
534
-    }
535
-
536
-
537
-    /**
538
-     * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
539
-     *
540
-     * @throws EE_Error
541
-     * @throws InvalidDataTypeException
542
-     * @throws InvalidInterfaceException
543
-     * @throws InvalidArgumentException
544
-     */
545
-    public static function clean_out_old_gateway_logs()
546
-    {
547
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
548
-            $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
549
-            $time_diff_for_comparison = apply_filters(
550
-                'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
551
-                '-' . $reg_config->gateway_log_lifespan
552
-            );
553
-            EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
554
-        }
555
-    }
556
-
557
-
558
-    /*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
559
-
560
-
561
-    /**
562
-     * @var array
563
-     */
564
-    protected static $_abandoned_transactions = array();
565
-
566
-
567
-    /**
568
-     * @deprecated
569
-     * @param int $timestamp
570
-     * @param int $TXN_ID
571
-     */
572
-    public static function schedule_finalize_abandoned_transactions_check($timestamp, $TXN_ID)
573
-    {
574
-        EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID);
575
-    }
576
-
577
-
578
-    /**
579
-     * @deprecated
580
-     * @param int $TXN_ID
581
-     */
582
-    public static function check_for_abandoned_transactions($TXN_ID = 0)
583
-    {
584
-        EE_Cron_Tasks::expired_transaction_check($TXN_ID);
585
-    }
586
-
587
-
588
-    /**
589
-     * @deprecated
590
-     * @throws EE_Error
591
-     * @throws DomainException
592
-     * @throws InvalidDataTypeException
593
-     * @throws InvalidInterfaceException
594
-     * @throws InvalidArgumentException
595
-     * @throws ReflectionException
596
-     * @throws RuntimeException
597
-     */
598
-    public static function finalize_abandoned_transactions()
599
-    {
600
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
601
-        if (
402
+			empty(self::$_expired_transactions)
403
+			// reschedule the cron if we can't hit the db right now
404
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
405
+				'schedule_expired_transaction_check',
406
+				self::$_expired_transactions
407
+			)
408
+		) {
409
+			return;
410
+		}
411
+		/** @type EE_Transaction_Processor $transaction_processor */
412
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
413
+		// set revisit flag for txn processor
414
+		$transaction_processor->set_revisit();
415
+		// load EEM_Transaction
416
+		EE_Registry::instance()->load_model('Transaction');
417
+		foreach (self::$_expired_transactions as $TXN_ID) {
418
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
419
+			// verify transaction and whether it is failed or not
420
+			if ($transaction instanceof EE_Transaction) {
421
+				switch ($transaction->status_ID()) {
422
+					// Completed TXNs
423
+					case EEM_Transaction::complete_status_code:
424
+						// Don't update the transaction/registrations if the Primary Registration is Not Approved.
425
+						$primary_registration = $transaction->primary_registration();
426
+						if (
427
+							$primary_registration instanceof EE_Registration
428
+							&& $primary_registration->status_ID() !== EEM_Registration::status_id_not_approved
429
+						) {
430
+							/** @type EE_Transaction_Processor $transaction_processor */
431
+							$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
432
+							$transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
433
+								$transaction,
434
+								$transaction->last_payment()
435
+							);
436
+							do_action(
437
+								'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
438
+								$transaction
439
+							);
440
+						}
441
+						break;
442
+					// Overpaid TXNs
443
+					case EEM_Transaction::overpaid_status_code:
444
+						do_action(
445
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
446
+							$transaction
447
+						);
448
+						break;
449
+					// Incomplete TXNs
450
+					case EEM_Transaction::incomplete_status_code:
451
+						do_action(
452
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
453
+							$transaction
454
+						);
455
+						// todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
456
+						break;
457
+					// Abandoned TXNs
458
+					case EEM_Transaction::abandoned_status_code:
459
+						// run hook before updating transaction, primarily so
460
+						// EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets
461
+						do_action(
462
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
463
+							$transaction
464
+						);
465
+						// don't finalize the TXN if it has already been completed
466
+						if ($transaction->all_reg_steps_completed() !== true) {
467
+							/** @type EE_Payment_Processor $payment_processor */
468
+							$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
469
+							// let's simulate an IPN here which will trigger any notifications that need to go out
470
+							$payment_processor->update_txn_based_on_payment(
471
+								$transaction,
472
+								$transaction->last_payment(),
473
+								true,
474
+								true
475
+							);
476
+						}
477
+						break;
478
+					// Failed TXNs
479
+					case EEM_Transaction::failed_status_code:
480
+						do_action(
481
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
482
+							$transaction
483
+						);
484
+						// todo :
485
+						// perform garbage collection here and remove clean_out_junk_transactions()
486
+						// $registrations = $transaction->registrations();
487
+						// if (! empty($registrations)) {
488
+						//     foreach ($registrations as $registration) {
489
+						//         if ($registration instanceof EE_Registration) {
490
+						//             $delete_registration = true;
491
+						//             if ($registration->attendee() instanceof EE_Attendee) {
492
+						//                 $delete_registration = false;
493
+						//             }
494
+						//             if ($delete_registration) {
495
+						//                 $registration->delete_permanently();
496
+						//                 $registration->delete_related_permanently();
497
+						//             }
498
+						//         }
499
+						//     }
500
+						// }
501
+						break;
502
+				}
503
+			}
504
+			unset(self::$_expired_transactions[ $TXN_ID ]);
505
+		}
506
+	}
507
+
508
+
509
+
510
+	/*************  END OF EXPIRED TRANSACTION CHECK  *************/
511
+
512
+
513
+	/************* START CLEAN UP BOT TRANSACTIONS **********************/
514
+
515
+
516
+	/**
517
+	 * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'
518
+	 * which is setup during activation to run on an hourly cron
519
+	 *
520
+	 * @throws EE_Error
521
+	 * @throws InvalidArgumentException
522
+	 * @throws InvalidDataTypeException
523
+	 * @throws InvalidInterfaceException
524
+	 * @throws DomainException
525
+	 */
526
+	public static function clean_out_junk_transactions()
527
+	{
528
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
529
+			EED_Ticket_Sales_Monitor::reset_reservation_counts();
530
+			EEM_Transaction::instance('')->delete_junk_transactions();
531
+			EEM_Registration::instance('')->delete_registrations_with_no_transaction();
532
+			EEM_Line_Item::instance('')->delete_line_items_with_no_transaction();
533
+		}
534
+	}
535
+
536
+
537
+	/**
538
+	 * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
539
+	 *
540
+	 * @throws EE_Error
541
+	 * @throws InvalidDataTypeException
542
+	 * @throws InvalidInterfaceException
543
+	 * @throws InvalidArgumentException
544
+	 */
545
+	public static function clean_out_old_gateway_logs()
546
+	{
547
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
548
+			$reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
549
+			$time_diff_for_comparison = apply_filters(
550
+				'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
551
+				'-' . $reg_config->gateway_log_lifespan
552
+			);
553
+			EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
554
+		}
555
+	}
556
+
557
+
558
+	/*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
559
+
560
+
561
+	/**
562
+	 * @var array
563
+	 */
564
+	protected static $_abandoned_transactions = array();
565
+
566
+
567
+	/**
568
+	 * @deprecated
569
+	 * @param int $timestamp
570
+	 * @param int $TXN_ID
571
+	 */
572
+	public static function schedule_finalize_abandoned_transactions_check($timestamp, $TXN_ID)
573
+	{
574
+		EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID);
575
+	}
576
+
577
+
578
+	/**
579
+	 * @deprecated
580
+	 * @param int $TXN_ID
581
+	 */
582
+	public static function check_for_abandoned_transactions($TXN_ID = 0)
583
+	{
584
+		EE_Cron_Tasks::expired_transaction_check($TXN_ID);
585
+	}
586
+
587
+
588
+	/**
589
+	 * @deprecated
590
+	 * @throws EE_Error
591
+	 * @throws DomainException
592
+	 * @throws InvalidDataTypeException
593
+	 * @throws InvalidInterfaceException
594
+	 * @throws InvalidArgumentException
595
+	 * @throws ReflectionException
596
+	 * @throws RuntimeException
597
+	 */
598
+	public static function finalize_abandoned_transactions()
599
+	{
600
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
601
+		if (
602 602
 // are there any TXNs that need cleaning up ?
603
-            empty(self::$_abandoned_transactions)
604
-            // reschedule the cron if we can't hit the db right now
605
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
606
-                'schedule_expired_transaction_check',
607
-                self::$_abandoned_transactions
608
-            )
609
-        ) {
610
-            return;
611
-        }
612
-        // combine our arrays of transaction IDs
613
-        self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions;
614
-        // and deal with abandoned transactions here now...
615
-        EE_Cron_Tasks::process_expired_transactions();
616
-    }
617
-
618
-
619
-    /*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
603
+			empty(self::$_abandoned_transactions)
604
+			// reschedule the cron if we can't hit the db right now
605
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
606
+				'schedule_expired_transaction_check',
607
+				self::$_abandoned_transactions
608
+			)
609
+		) {
610
+			return;
611
+		}
612
+		// combine our arrays of transaction IDs
613
+		self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions;
614
+		// and deal with abandoned transactions here now...
615
+		EE_Cron_Tasks::process_expired_transactions();
616
+	}
617
+
618
+
619
+	/*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
620 620
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Address.helper.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -30,13 +30,13 @@  discard block
 block discarded – undo
30 30
         $add_wrapper = true
31 31
     ) {
32 32
         // check that incoming object implements the EEI_Address interface
33
-        if (! $obj_with_address instanceof EEI_Address) {
33
+        if ( ! $obj_with_address instanceof EEI_Address) {
34 34
             $msg = esc_html__('The address could not be formatted.', 'event_espresso');
35 35
             $dev_msg = esc_html__(
36 36
                 'The Address Formatter requires passed objects to implement the EEI_Address interface.',
37 37
                 'event_espresso'
38 38
             );
39
-            EE_Error::add_error($msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
39
+            EE_Error::add_error($msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
40 40
             return null;
41 41
         }
42 42
         // obtain an address formatter
@@ -47,7 +47,7 @@  discard block
 block discarded – undo
47 47
             ? EEH_Address::_schema_formatting($formatter, $obj_with_address)
48 48
             : EEH_Address::_regular_formatting($formatter, $obj_with_address, $add_wrapper);
49 49
         $formatted_address = $add_wrapper && ! $use_schema
50
-            ? '<div class="espresso-address-dv">' . $formatted_address . '</div>'
50
+            ? '<div class="espresso-address-dv">'.$formatted_address.'</div>'
51 51
             : $formatted_address;
52 52
         // return the formatted address
53 53
         return $formatted_address;
Please login to merge, or discard this patch.
Indentation   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -10,124 +10,124 @@
 block discarded – undo
10 10
  */
11 11
 class EEH_Address
12 12
 {
13
-    /**
14
-     *    format - output formatted EE object address information
15
-     *
16
-     * @access public
17
-     * @param         object      EEI_Address $obj_with_address
18
-     * @param string  $type       how the address is formatted. for example: 'multiline' or 'inline'
19
-     * @param boolean $use_schema whether to apply schema.org formatting to the address
20
-     * @param bool    $add_wrapper
21
-     * @return string
22
-     */
23
-    public static function format(
24
-        $obj_with_address = null,
25
-        $type = 'multiline',
26
-        $use_schema = true,
27
-        $add_wrapper = true
28
-    ) {
29
-        // check that incoming object implements the EEI_Address interface
30
-        if (! $obj_with_address instanceof EEI_Address) {
31
-            $msg = esc_html__('The address could not be formatted.', 'event_espresso');
32
-            $dev_msg = esc_html__(
33
-                'The Address Formatter requires passed objects to implement the EEI_Address interface.',
34
-                'event_espresso'
35
-            );
36
-            EE_Error::add_error($msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
37
-            return null;
38
-        }
39
-        // obtain an address formatter
40
-        $formatter = EEH_Address::_get_formatter($type);
41
-        // apply schema.org formatting ?
42
-        $use_schema = ! is_admin() ? $use_schema : false;
43
-        $formatted_address = $use_schema
44
-            ? EEH_Address::_schema_formatting($formatter, $obj_with_address)
45
-            : EEH_Address::_regular_formatting($formatter, $obj_with_address, $add_wrapper);
46
-        $formatted_address = $add_wrapper && ! $use_schema
47
-            ? '<div class="espresso-address-dv">' . $formatted_address . '</div>'
48
-            : $formatted_address;
49
-        // return the formatted address
50
-        return $formatted_address;
51
-    }
13
+	/**
14
+	 *    format - output formatted EE object address information
15
+	 *
16
+	 * @access public
17
+	 * @param         object      EEI_Address $obj_with_address
18
+	 * @param string  $type       how the address is formatted. for example: 'multiline' or 'inline'
19
+	 * @param boolean $use_schema whether to apply schema.org formatting to the address
20
+	 * @param bool    $add_wrapper
21
+	 * @return string
22
+	 */
23
+	public static function format(
24
+		$obj_with_address = null,
25
+		$type = 'multiline',
26
+		$use_schema = true,
27
+		$add_wrapper = true
28
+	) {
29
+		// check that incoming object implements the EEI_Address interface
30
+		if (! $obj_with_address instanceof EEI_Address) {
31
+			$msg = esc_html__('The address could not be formatted.', 'event_espresso');
32
+			$dev_msg = esc_html__(
33
+				'The Address Formatter requires passed objects to implement the EEI_Address interface.',
34
+				'event_espresso'
35
+			);
36
+			EE_Error::add_error($msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
37
+			return null;
38
+		}
39
+		// obtain an address formatter
40
+		$formatter = EEH_Address::_get_formatter($type);
41
+		// apply schema.org formatting ?
42
+		$use_schema = ! is_admin() ? $use_schema : false;
43
+		$formatted_address = $use_schema
44
+			? EEH_Address::_schema_formatting($formatter, $obj_with_address)
45
+			: EEH_Address::_regular_formatting($formatter, $obj_with_address, $add_wrapper);
46
+		$formatted_address = $add_wrapper && ! $use_schema
47
+			? '<div class="espresso-address-dv">' . $formatted_address . '</div>'
48
+			: $formatted_address;
49
+		// return the formatted address
50
+		return $formatted_address;
51
+	}
52 52
 
53 53
 
54 54
 
55
-    /**
56
-     *    _get_formatter - obtain the requester formatter class
57
-     *
58
-     * @access private
59
-     * @param string $type how the address is formatted. for example: 'multiline' or 'inline'
60
-     * @return EEI_Address_Formatter
61
-     */
62
-    private static function _get_formatter($type)
63
-    {
64
-        switch ($type) {
65
-            case 'multiline':
66
-                return new EventEspresso\core\services\address\formatters\MultiLineAddressFormatter();
67
-            case 'inline':
68
-                return new EventEspresso\core\services\address\formatters\InlineAddressFormatter();
69
-            default:
70
-                return new EventEspresso\core\services\address\formatters\NullAddressFormatter();
71
-        }
72
-    }
55
+	/**
56
+	 *    _get_formatter - obtain the requester formatter class
57
+	 *
58
+	 * @access private
59
+	 * @param string $type how the address is formatted. for example: 'multiline' or 'inline'
60
+	 * @return EEI_Address_Formatter
61
+	 */
62
+	private static function _get_formatter($type)
63
+	{
64
+		switch ($type) {
65
+			case 'multiline':
66
+				return new EventEspresso\core\services\address\formatters\MultiLineAddressFormatter();
67
+			case 'inline':
68
+				return new EventEspresso\core\services\address\formatters\InlineAddressFormatter();
69
+			default:
70
+				return new EventEspresso\core\services\address\formatters\NullAddressFormatter();
71
+		}
72
+	}
73 73
 
74 74
 
75 75
 
76
-    /**
77
-     *    _regular_formatting
78
-     *    adds formatting to an address
79
-     *
80
-     * @access private
81
-     * @param      object EEI_Address_Formatter $formatter
82
-     * @param      object EEI_Address $obj_with_address
83
-     * @param bool $add_wrapper
84
-     * @return string
85
-     */
86
-    private static function _regular_formatting(
87
-        EEI_Address_Formatter $formatter,
88
-        EEI_Address $obj_with_address,
89
-        $add_wrapper = true
90
-    ) {
91
-        $formatted_address = $add_wrapper ? '<div>' : '';
92
-        $formatted_address .= $formatter->format(
93
-            $obj_with_address->address(),
94
-            $obj_with_address->address2(),
95
-            $obj_with_address->city(),
96
-            $obj_with_address->state_name(),
97
-            $obj_with_address->zip(),
98
-            $obj_with_address->country_name(),
99
-            $obj_with_address->country_ID()
100
-        );
101
-        $formatted_address .= $add_wrapper ? '</div>' : '';
102
-        // return the formatted address
103
-        return $formatted_address;
104
-    }
76
+	/**
77
+	 *    _regular_formatting
78
+	 *    adds formatting to an address
79
+	 *
80
+	 * @access private
81
+	 * @param      object EEI_Address_Formatter $formatter
82
+	 * @param      object EEI_Address $obj_with_address
83
+	 * @param bool $add_wrapper
84
+	 * @return string
85
+	 */
86
+	private static function _regular_formatting(
87
+		EEI_Address_Formatter $formatter,
88
+		EEI_Address $obj_with_address,
89
+		$add_wrapper = true
90
+	) {
91
+		$formatted_address = $add_wrapper ? '<div>' : '';
92
+		$formatted_address .= $formatter->format(
93
+			$obj_with_address->address(),
94
+			$obj_with_address->address2(),
95
+			$obj_with_address->city(),
96
+			$obj_with_address->state_name(),
97
+			$obj_with_address->zip(),
98
+			$obj_with_address->country_name(),
99
+			$obj_with_address->country_ID()
100
+		);
101
+		$formatted_address .= $add_wrapper ? '</div>' : '';
102
+		// return the formatted address
103
+		return $formatted_address;
104
+	}
105 105
 
106 106
 
107 107
 
108
-    /**
109
-     *    _schema_formatting
110
-     *    adds schema.org formatting to an address
111
-     *
112
-     * @access private
113
-     * @param object EEI_Address_Formatter $formatter
114
-     * @param object EEI_Address $obj_with_address
115
-     * @return string
116
-     */
117
-    private static function _schema_formatting(EEI_Address_Formatter $formatter, EEI_Address $obj_with_address)
118
-    {
119
-        $formatted_address = '<div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">';
120
-        $formatted_address .= $formatter->format(
121
-            EEH_Schema::streetAddress($obj_with_address),
122
-            EEH_Schema::postOfficeBoxNumber($obj_with_address),
123
-            EEH_Schema::addressLocality($obj_with_address),
124
-            EEH_Schema::addressRegion($obj_with_address),
125
-            EEH_Schema::postalCode($obj_with_address),
126
-            EEH_Schema::addressCountry($obj_with_address),
127
-            $obj_with_address->country_ID()
128
-        );
129
-        $formatted_address .= '</div>';
130
-        // return the formatted address
131
-        return $formatted_address;
132
-    }
108
+	/**
109
+	 *    _schema_formatting
110
+	 *    adds schema.org formatting to an address
111
+	 *
112
+	 * @access private
113
+	 * @param object EEI_Address_Formatter $formatter
114
+	 * @param object EEI_Address $obj_with_address
115
+	 * @return string
116
+	 */
117
+	private static function _schema_formatting(EEI_Address_Formatter $formatter, EEI_Address $obj_with_address)
118
+	{
119
+		$formatted_address = '<div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">';
120
+		$formatted_address .= $formatter->format(
121
+			EEH_Schema::streetAddress($obj_with_address),
122
+			EEH_Schema::postOfficeBoxNumber($obj_with_address),
123
+			EEH_Schema::addressLocality($obj_with_address),
124
+			EEH_Schema::addressRegion($obj_with_address),
125
+			EEH_Schema::postalCode($obj_with_address),
126
+			EEH_Schema::addressCountry($obj_with_address),
127
+			$obj_with_address->country_ID()
128
+		);
129
+		$formatted_address .= '</div>';
130
+		// return the formatted address
131
+		return $formatted_address;
132
+	}
133 133
 }
Please login to merge, or discard this patch.