Completed
Branch master (4bd299)
by
unknown
04:49
created
PaymentMethods/PayPalCommerce/modules/EED_PayPalOnboard.module.php 2 patches
Indentation   +669 added lines, -669 removed lines patch added patch discarded remove patch
@@ -20,673 +20,673 @@
 block discarded – undo
20 20
  */
21 21
 class EED_PayPalOnboard extends EED_Module
22 22
 {
23
-    /**
24
-     * @return EED_Module
25
-     * @throws EE_Error
26
-     * @throws ReflectionException
27
-     */
28
-    public static function instance(): EED_Module
29
-    {
30
-        return parent::get_instance(__CLASS__);
31
-    }
32
-
33
-
34
-    /**
35
-     * Run - initial module setup.
36
-     *
37
-     * @param WP $WP
38
-     * @return void
39
-     */
40
-    public function run($WP)
41
-    {
42
-    }
43
-
44
-
45
-    /**
46
-     * For hooking into EE Admin Core and other modules.
47
-     *
48
-     * @return void
49
-     */
50
-    public static function set_hooks_admin(): void
51
-    {
52
-        if (DbStatus::isOnline()) {
53
-            // Get onboarding URL.
54
-            add_action('wp_ajax_eeaPpGetOnboardingUrl', [__CLASS__, 'getOnboardingUrl']);
55
-            // Catch the return/redirect from PayPal onboarding page.
56
-            add_action('init', [__CLASS__, 'updateOnboardingStatus'], 10);
57
-            // Return the connection/onboard status.
58
-            add_action('wp_ajax_eeaPpGetOnboardStatus', [__CLASS__, 'getOnboardStatus']);
59
-            // Revoke access.
60
-            add_action('wp_ajax_eeaPpOffboard', [__CLASS__, 'offboard']);
61
-            // Admin notice.
62
-            add_action('admin_init', [__CLASS__, 'adminNotice']);
63
-        }
64
-    }
65
-
66
-
67
-    /**
68
-     * Get the onboarding URL.
69
-     * (AJAX)
70
-     *
71
-     * @return void
72
-     */
73
-    public static function getOnboardingUrl(): void
74
-    {
75
-        $signup_link = '';
76
-        try {
77
-            $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
78
-            if (! $paypal_pm instanceof EE_Payment_Method) {
79
-                PayPalLogger::errorLogAndExit(
80
-                    esc_html__('No payment method.', 'event_espresso'),
81
-                    EED_Module::getRequest()->postParams(),
82
-                    $paypal_pm
83
-                );
84
-            }
85
-            PayPalExtraMetaManager::updateDebugMode($paypal_pm, EED_Module::getRequest()->postParams());
86
-            // $signup_link   = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
87
-            // $token_expired = EED_PayPalOnboard::partnerAccessTokenExpired($paypal_pm);
88
-            // if (! $signup_link || $token_expired) {
89
-            $signup_link = EED_PayPalOnboard::requestOnboardingUrl($paypal_pm);
90
-            // }
91
-            if (! $signup_link) {
92
-                $err_msg = esc_html__('Error! Could not generate a sign-up link.', 'event_espresso');
93
-                PayPalLogger::errorLogAndExit($err_msg, ['signup_link' => $signup_link], $paypal_pm);
94
-            }
95
-            PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL, $signup_link);
96
-        } catch (Exception $exception) {
97
-            PayPalLogger::errorLogAndExit($exception->getMessage());
98
-        }
99
-        // Is it empty (can happen if we didn't get the URL through the API).
100
-        $signup_link = $signup_link ? $signup_link . '?&displayMode=minibrowser' : '#';
101
-        wp_send_json(
102
-            [
103
-                'signup_link' => $signup_link,
104
-            ]
105
-        );
106
-    }
107
-
108
-
109
-    /**
110
-     * Request the sign-up link from PayPal.
111
-     *
112
-     * @param EE_Payment_Method $paypal_pm
113
-     * @param bool              $one_time_request
114
-     * @return string
115
-     * @throws EE_Error
116
-     * @throws Exception
117
-     */
118
-    public static function requestOnboardingUrl(EE_Payment_Method $paypal_pm, bool $one_time_request = false): string
119
-    {
120
-        $signup_link = '';
121
-        // Get the access token.
122
-        $access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
123
-        if (! $access_token) {
124
-            $err_msg = esc_html__('Error! No access token.', 'event_espresso');
125
-            PayPalLogger::errorLog($err_msg, ['access_token' => $access_token], $paypal_pm);
126
-            return '';
127
-        }
128
-        // Request the access token.
129
-        $body_params = EED_PayPalOnboard::signupLinkRequestBody($paypal_pm);
130
-        $bn_code     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
131
-        $post_params = [
132
-            'method'  => 'POST',
133
-            'headers' => [
134
-                'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
135
-                'Content-Type'                  => 'application/json',
136
-                'Authorization'                 => 'Bearer ' . $access_token,
137
-                'PayPal-Partner-Attribution-Id' => $bn_code,
138
-            ],
139
-            'body'    => $body_params,
140
-        ];
141
-        $request_url = Domain::getPayPalApiUrl($paypal_pm) . '/v2/customer/partner-referrals';
142
-        $response    = EED_PayPalOnboard::sendRequest($paypal_pm, $request_url, $post_params);
143
-        // Check the data we received.
144
-        if (isset($response['error']) || empty($response['links'])) {
145
-            // Did the original access token get replaced by any chance ?
146
-            if (! $one_time_request
147
-                && ! empty($response['message'])
148
-                && $response['message'] === 'Access Token not found in cache'
149
-            ) {
150
-                // Clear all PM metadata and try getting the access token One more time.
151
-                PayPalExtraMetaManager::deleteAllData($paypal_pm);
152
-                return EED_PayPalOnboard::requestOnboardingUrl($paypal_pm, true);
153
-            }
154
-            $err_msg = esc_html__('Incoming sign-up link parameter validation failed.', 'event_espresso');
155
-            PayPalLogger::errorLog($err_msg, $response, $paypal_pm);
156
-            return '';
157
-        }
158
-        // Now retrieve that sign-up link.
159
-        foreach ($response['links'] as $link) {
160
-            if ($link['rel'] === 'action_url') {
161
-                $signup_link = $link['href'] ?? '';
162
-            }
163
-        }
164
-        return $signup_link;
165
-    }
166
-
167
-
168
-    /**
169
-     * Get the return URL.
170
-     *
171
-     * @param EE_Payment_Method $paypal_pm
172
-     * @return string
173
-     * @throws Exception
174
-     */
175
-    public static function signupLinkRequestBody(EE_Payment_Method $paypal_pm): string
176
-    {
177
-        $identifier_string = new OneTimeString($paypal_pm->debug_mode());
178
-        $tracking_id       = $identifier_string->value();
179
-        $request           = LoaderFactory::getLoader()->getShared(RequestInterface::class);
180
-        $checkout_type     = $request->getRequestParam('checkout_type', 'EXPRESS_CHECKOUT', DataType::STRING);
181
-        // Save the identifier for future use.
182
-        PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_TRACKING_ID, $tracking_id);
183
-        // Assemble the return URL.
184
-        $return_url = EED_PayPalOnboard::getReturnUrl($paypal_pm);
185
-        return json_encode([
186
-            'tracking_id'             => $tracking_id,
187
-            'operations'              => [
188
-                [
189
-                    'operation'                  => 'API_INTEGRATION',
190
-                    'api_integration_preference' => [
191
-                        'rest_api_integration' => [
192
-                            'integration_method'  => 'PAYPAL',
193
-                            'integration_type'    => 'THIRD_PARTY',
194
-                            'third_party_details' => [
195
-                                'features' => ['PAYMENT', 'REFUND'],
196
-                            ],
197
-                        ],
198
-                    ],
199
-                ],
200
-            ],
201
-            'products'                => [$checkout_type],
202
-            'legal_consents'          => [
203
-                [
204
-                    'type'    => 'SHARE_DATA_CONSENT',
205
-                    'granted' => true,
206
-                ],
207
-            ],
208
-            'partner_config_override' => [
209
-                'return_url' => $return_url,
210
-            ],
211
-        ]);
212
-    }
213
-
214
-
215
-    /**
216
-     * Get the return URL.
217
-     *
218
-     * @param EE_Payment_Method $paypal_pm
219
-     * @return string
220
-     * @throws EE_Error
221
-     * @throws ReflectionException
222
-     */
223
-    public static function getReturnUrl(EE_Payment_Method $paypal_pm): string
224
-    {
225
-        $wp_nonce = EED_Module::getRequest()->getRequestParam('wp_nonce');
226
-        $nonce    = wp_create_nonce(Domain::NONCE_NAME_ONBOARDING_RETURN);
227
-        return add_query_arg(
228
-            [
229
-                'page'                        => 'espresso_payment_settings',
230
-                'webhook_action'              => 'eea_pp_commerce_merchant_onboard',
231
-                'payment_method'              => $paypal_pm->slug(),
232
-                '_wpnonce'                    => $wp_nonce,
233
-                'nonce'                       => $nonce,
234
-                Domain::META_KEY_SANDBOX_MODE => $paypal_pm->debug_mode() ? '1' : '0',
235
-            ],
236
-            admin_url('admin.php')
237
-        );
238
-    }
239
-
240
-
241
-    /**
242
-     * Redirect to the payment method (PP) settings home page.
243
-     *
244
-     * @return void
245
-     */
246
-    public static function redirectToPmSettingsHome(): void
247
-    {
248
-        $get_params = EED_Module::getRequest()->getParams();
249
-        if (empty($get_params['payment_method'])) {
250
-            // Simply do not redirect.
251
-            return;
252
-        }
253
-        $args_to_add = [
254
-            'page'           => 'espresso_payment_settings',
255
-            'payment_method' => $get_params['payment_method'],
256
-        ];
257
-        if (isset($get_params['sandbox_mode'])) {
258
-            $args_to_add[ Domain::META_KEY_SANDBOX_MODE ] = $get_params['sandbox_mode'];
259
-        }
260
-        $home_url = add_query_arg($args_to_add, admin_url('admin.php'));
261
-        wp_redirect($home_url);
262
-        exit;
263
-    }
264
-
265
-
266
-    /**
267
-     * Check user’s onboarding status.
268
-     * This will handle the user return from the auth page and also check the status via the API.
269
-     *
270
-     * @return void
271
-     * @throws EE_Error
272
-     * @throws ReflectionException
273
-     */
274
-    public static function updateOnboardingStatus(): void
275
-    {
276
-        // Check if this is the webhook from PayPal.
277
-        if (! isset($_GET['webhook_action'], $_GET['nonce'])
278
-            || $_GET['webhook_action'] !== 'eea_pp_commerce_merchant_onboard'
279
-        ) {
280
-            return;  // Ignore.
281
-        }
282
-        $get_params = EED_Module::getRequest()->getParams();
283
-        // Get the payment method.
284
-        $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
285
-        // Check the response (GET) parameters.
286
-        if (! EED_PayPalOnboard::onboardingStatusResponseValid($get_params, $paypal_pm)) {
287
-            // Missing parameters. Can't proceed.
288
-            PayPalLogger::errorLog(
289
-                esc_html__('Missing required onboarding parameters.', 'event_espresso'),
290
-                $get_params,
291
-                $paypal_pm
292
-            );
293
-            EED_PayPalOnboard::redirectToPmSettingsHome();
294
-            return;
295
-        }
296
-        // Were the requested permissions granted ?
297
-        if (empty($get_params[ Domain::API_PARAM_PERMISSIONS_GRANTED ])) {
298
-            $error_message = esc_html__(
299
-                'Permissions not granted by merchant or email not confirmed.',
300
-                'event_espresso'
301
-            );
302
-            PayPalLogger::errorLog($error_message, $get_params, $paypal_pm);
303
-            EED_PayPalOnboard::redirectToPmSettingsHome();
304
-            return;
305
-        }
306
-        // Check on the onboarding status (recommended by PP).
307
-        $onboarding_status = EED_PayPalOnboard::trackSellerOnboarding(
308
-            $paypal_pm,
309
-            $get_params[ Domain::META_KEY_SELLER_MERCHANT_ID ]
310
-        );
311
-        if (! isset($onboarding_status['valid']) || ! $onboarding_status['valid']) {
312
-            PayPalLogger::errorLog(
313
-                $onboarding_status['message'],
314
-                array_merge($get_params, $onboarding_status),
315
-                $paypal_pm
316
-            );
317
-            EED_PayPalOnboard::redirectToPmSettingsHome();
318
-            return;
319
-        }
320
-        // Start saving the setup and info.
321
-        PayPalExtraMetaManager::parseAndSaveOptions($paypal_pm, $onboarding_status);
322
-        // Save the credentials.
323
-        PayPalExtraMetaManager::saveSellerApiCredentials($paypal_pm, $get_params);
324
-        // If onboarded successfully, remove the onboarding URL.
325
-        PayPalExtraMetaManager::deletePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
326
-        // Also clen GET params by redirecting, because PP auto redirects to the return_url on closing the onboarding window.
327
-        EED_PayPalOnboard::redirectToPmSettingsHome();
328
-    }
329
-
330
-
331
-    /**
332
-     * Check if all required parameters for the onboarding status check are present.
333
-     *
334
-     * @param array $data
335
-     * @param mixed $paypal_pm
336
-     * @return bool
337
-     */
338
-    public static function onboardingStatusResponseValid(array $data, mixed $paypal_pm): bool
339
-    {
340
-        // Check that we have all the required parameters and the nonce is ok.
341
-        if ($paypal_pm instanceof EE_Payment_Method
342
-            && wp_verify_nonce($data['nonce'], Domain::NONCE_NAME_ONBOARDING_RETURN)
343
-            && ! empty($data[ Domain::API_PARAM_PARTNER_ID ])
344
-            && ! empty($data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
345
-            && isset($data[ Domain::API_PARAM_PERMISSIONS_GRANTED ])
346
-            && isset($data[ Domain::API_PARAM_EMAIL_CONFIRMED ])
347
-        ) {
348
-            return true;
349
-        }
350
-        return false;
351
-    }
352
-
353
-
354
-    /**
355
-     * Get partner access token.
356
-     *
357
-     * @param EE_Payment_Method $paypal_pm
358
-     * @return string
359
-     * @throws EE_Error
360
-     * @throws ReflectionException
361
-     */
362
-    public static function getPartnerAccessToken(EE_Payment_Method $paypal_pm): string
363
-    {
364
-        // Do we have it saved ?
365
-        $access_token = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ACCESS_TOKEN);
366
-        $expired      = EED_PayPalOnboard::partnerAccessTokenExpired($paypal_pm);
367
-        // If we don't have it, request/update it.
368
-        if (! $access_token || $expired) {
369
-            return EED_PayPalOnboard::requestPartnerAccessToken($paypal_pm);
370
-        }
371
-        // Access token is saved as encrypted, so return decrypted.
372
-        return $access_token;
373
-    }
374
-
375
-
376
-    /**
377
-     * Get partner access token.
378
-     *
379
-     * @param EE_Payment_Method $paypal_pm
380
-     * @return bool
381
-     */
382
-    public static function partnerAccessTokenExpired(EE_Payment_Method $paypal_pm): bool
383
-    {
384
-        $expires_at = (int) PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_EXPIRES_IN);
385
-        if (! $expires_at) {
386
-            return true;
387
-        }
388
-        // Validate the token expiration date.
389
-        $now          = time();
390
-        $minutes_left = round(($expires_at - $now) / 60);
391
-        // Count as expired if less than 60 minutes till expiration left.
392
-        if ($minutes_left <= 60) {
393
-            return true;
394
-        }
395
-        return false;
396
-    }
397
-
398
-
399
-    /**
400
-     * Request the partner access token from PayPal and save/update it.
401
-     *
402
-     * @param EE_Payment_Method $paypal_pm
403
-     * @return string
404
-     * @throws EE_Error
405
-     * @throws ReflectionException
406
-     */
407
-    public static function requestPartnerAccessToken(EE_Payment_Method $paypal_pm): string
408
-    {
409
-        $nonce = wp_create_nonce('eea_pp_commerce_get_access_token');
410
-        // Request the access token.
411
-        $post_args = [
412
-            'method' => 'POST',
413
-            'body'   => [
414
-                'nonce'                       => $nonce,
415
-                'api_version'                 => 'v1',
416
-                Domain::META_KEY_SANDBOX_MODE => $paypal_pm->debug_mode() ? '1' : '0',
417
-            ],
418
-        ];
419
-        if (defined('LOCAL_MIDDLEMAN_SERVER')) {
420
-            $post_args['sslverify'] = false;
421
-        }
422
-        $post_url = EED_PayPalOnboard::getMiddlemanBaseUrl($paypal_pm) . 'get_token';
423
-        $response = EED_PayPalOnboard::sendRequest($paypal_pm, $post_url, $post_args);
424
-        if (isset($response['error'])) {
425
-            return '';
426
-        }
427
-        // Check the data we received.
428
-        if (! EED_PayPalOnboard::partnerTokenResponseValid($response, $paypal_pm)) {
429
-            return '';
430
-        }
431
-        // If we are here all seems to be ok. Save the token and it's data.
432
-        $saved = PayPalExtraMetaManager::savePartnerAccessToken($paypal_pm, $response);
433
-        if (! $saved) {
434
-            return '';
435
-        }
436
-        return $response['access_token'];
437
-    }
438
-
439
-
440
-    /**
441
-     * Request seller onboarding status from PayPal.
442
-     *
443
-     * @param EE_Payment_Method $paypal_pm
444
-     * @param string            $merchant_id
445
-     * @return array
446
-     */
447
-    public static function trackSellerOnboarding(EE_Payment_Method $paypal_pm, string $merchant_id): array
448
-    {
449
-        $track_onboarding = EED_PayPalOnboard::getTrackOnboardingApi($paypal_pm, $merchant_id);
450
-        if (! $track_onboarding instanceof TrackSellerOnboarding) {
451
-            $err_msg = esc_html__('Failed to track seller onboarding.', 'event_espresso');
452
-            return ['error' => 'TRACK_ONBOARDING_FAILED', 'message' => $err_msg];
453
-        }
454
-        return $track_onboarding->isValid();
455
-    }
456
-
457
-
458
-    /**
459
-     * Returns the Track Seller Onboarding API.
460
-     *
461
-     * @param EE_Payment_Method $paypal_pm
462
-     * @param string            $merchant_id
463
-     * @return TrackSellerOnboarding|null
464
-     * @throws EE_Error
465
-     * @throws ReflectionException
466
-     */
467
-    public static function getTrackOnboardingApi(
468
-        EE_Payment_Method $paypal_pm,
469
-        string            $merchant_id
470
-    ): ?TrackSellerOnboarding {
471
-        $partner_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_MERCHANT_ID);
472
-        $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
473
-        if (! $paypal_api instanceof PayPalApi || ! $partner_id) {
474
-            return null;
475
-        }
476
-        return new TrackSellerOnboarding($paypal_api, $partner_id, $merchant_id, $paypal_pm->debug_mode());
477
-    }
478
-
479
-
480
-    /**
481
-     * Check the onboard status and return the result.
482
-     * (AJAX)
483
-     *
484
-     * @return void
485
-     */
486
-    public static function getOnboardStatus(): void
487
-    {
488
-        $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
489
-        if (! $paypal_pm instanceof EE_Payment_Method) {
490
-            $err_msg = esc_html__('Could not specify the payment method.', 'event_espresso');
491
-            PayPalLogger::errorLog($err_msg, EED_Module::getRequest()->postParams(), $paypal_pm);
492
-            wp_send_json(['on_board' => false]);
493
-        }
494
-        try {
495
-            $seller_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_MERCHANT_ID) ?? '--';
496
-        } catch (Exception $e) {
497
-            $seller_id = '--';
498
-        }
499
-        wp_send_json(
500
-            [
501
-                'on_board'  => EED_PayPalOnboard::isOnboard($paypal_pm),
502
-                'seller_id' => $seller_id,
503
-            ]
504
-        );
505
-    }
506
-
507
-
508
-    /**
509
-     * De-authorize the seller. Remove all API credentials.
510
-     * (AJAX)
511
-     *
512
-     * @return void
513
-     */
514
-    public static function offboard(): void
515
-    {
516
-        $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
517
-        if (! $paypal_pm instanceof EE_Payment_Method) {
518
-            wp_send_json([
519
-                'error'   => 'INVALID_PM',
520
-                'message' => esc_html__(
521
-                    'Invalid payment method. Please refresh the page and try again.',
522
-                    'event_espresso'
523
-                ),
524
-            ]);
525
-        }
526
-        PayPalExtraMetaManager::deleteAllData($paypal_pm);
527
-        wp_send_json(['success' => true]);
528
-    }
529
-
530
-
531
-    /**
532
-     * Checks if already onboard.
533
-     *
534
-     * @param EE_Payment_Method $payment_method
535
-     * @return boolean
536
-     */
537
-    public static function isOnboard(EE_Payment_Method $payment_method): bool
538
-    {
539
-        $pp_meta_data = PayPalExtraMetaManager::getAllData($payment_method);
540
-        return
541
-            // onborded with a third party integration ?
542
-            (! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
543
-                && ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ])
544
-            )
545
-            // or with the first party integration ?
546
-            || (! empty($pp_meta_data[ Domain::META_KEY_CLIENT_ID ])
547
-                && ! empty($pp_meta_data[ Domain::META_KEY_CLIENT_SECRET ])
548
-                && ! empty($pp_meta_data[ Domain::META_KEY_PAYER_ID ])
549
-            );
550
-    }
551
-
552
-
553
-    /**
554
-     * Send a request and return a decoded response body.
555
-     *
556
-     * @param EE_Payment_Method $paypal_pm
557
-     * @param string            $request_url
558
-     * @param array             $request_args
559
-     * @return array
560
-     */
561
-    public static function sendRequest(EE_Payment_Method $paypal_pm, string $request_url, array $request_args): array
562
-    {
563
-        $error_return = ['error' => true];
564
-        $response     = wp_remote_request($request_url, $request_args);
565
-        if (is_wp_error($response)) {
566
-            $message = $response->get_error_message();
567
-            PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
568
-            $error_return['message'] = $message;
569
-            return $error_return;
570
-        }
571
-        $response_body = (isset($response['body']) && $response['body']) ? json_decode($response['body'], true) : [];
572
-        if (empty($response_body) || isset($response_body['error'])) {
573
-            $message = $response_body['error_description']
574
-                       ?? sprintf(
575
-                           esc_html__('Unknown response received while sending a request to: %1$s', 'event_espresso'),
576
-                           $request_url
577
-                       );
578
-            PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
579
-            $error_return['message'] = $message;
580
-            return $error_return;
581
-        }
582
-        return $response_body;
583
-    }
584
-
585
-
586
-    /**
587
-     * Check the response for a partner token request.
588
-     *
589
-     * @param                   $response
590
-     * @param EE_Payment_Method $paypal_pm
591
-     * @return bool
592
-     */
593
-    public static function partnerTokenResponseValid($response, EE_Payment_Method $paypal_pm): bool
594
-    {
595
-        // Check the data we received.
596
-        if (
597
-            empty($response['nonce'])
598
-            || ! wp_verify_nonce($response['nonce'], 'eea_pp_commerce_get_access_token')
599
-            || empty($response['access_token'])
600
-            || empty($response['app_id'])
601
-            || empty($response['expires_in'])
602
-            || empty($response['partner_client_id'])
603
-            || empty($response['partner_merchant_id'])
604
-        ) {
605
-            // This is an error.
606
-            $err_msg = esc_html__('Incoming parameter validation failed.', 'event_espresso');
607
-            PayPalLogger::errorLog($err_msg, (array) $response, $paypal_pm);
608
-            return false;
609
-        }
610
-        return true;
611
-    }
612
-
613
-
614
-    /**
615
-     * Returns the base URL to the middleman server.
616
-     * If LOCAL_MIDDLEMAN_SERVER is defined, requests will be sent to connect.eventespresso.test
617
-     *
618
-     * @param EE_Payment_Method $payment_method
619
-     * @return string
620
-     * @throws EE_Error
621
-     * @throws ReflectionException
622
-     */
623
-    public static function getMiddlemanBaseUrl(EE_Payment_Method $payment_method): string
624
-    {
625
-        $target = defined('LOCAL_MIDDLEMAN_SERVER') ? 'test' : 'com';
626
-        // If this PM is used under different provider accounts, you might need an account indicator.
627
-        $account = defined('EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR') ? EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR : '';
628
-        $postfix = $payment_method->debug_mode() ? '_sandbox' : '';
629
-        $path    = 'paypal_commerce' . $account . $postfix;
630
-        return 'https://connect.eventespresso.' . $target . '/' . $path . '/';
631
-    }
632
-
633
-
634
-    /**
635
-     * This Payment Method admin notices.
636
-     *
637
-     * @return void
638
-     * @throws EE_Error
639
-     * @throws ReflectionException
640
-     */
641
-    public static function adminNotice()
642
-    {
643
-        // A notice to re-connect if still connected through the first party integration.
644
-        $pp_commerce = EEM_Payment_Method::instance()->get_one_by_slug('paypalcheckout');
645
-        // Show the notice only if PayPal Commerce is active.
646
-        if (! $pp_commerce instanceof EE_Payment_Method
647
-            || ! EED_PayPalOnboard::isOnboard($pp_commerce)
648
-            || EED_PayPalCommerce::isThirdParty($pp_commerce)
649
-        ) {
650
-            return;
651
-        }
652
-        add_action('admin_notices', [__CLASS__, 'reConnectNotice']);
653
-    }
654
-
655
-
656
-    /**
657
-     * Re-connect notice contents.
658
-     *
659
-     * @return void
660
-     * @throws EE_Error
661
-     * @throws ReflectionException
662
-     */
663
-    public static function reConnectNotice()
664
-    {
665
-        $open_anchor = $close_anchor = '';
666
-        $pp_commerce = EEM_Payment_Method::instance()->get_one_by_slug('paypalcheckout');
667
-        if ($pp_commerce instanceof EE_Payment_Method) {
668
-            $pm_page = add_query_arg(
669
-                [
670
-                    'page'           => 'espresso_payment_settings',
671
-                    'webhook_action' => 'eea_pp_commerce_merchant_onboard',
672
-                    'payment_method' => $pp_commerce->slug(),
673
-                ],
674
-                admin_url('admin.php')
675
-            );
676
-            $open_anchor  = "<a href='$pm_page'>";
677
-            $close_anchor = "</a>";
678
-        }
679
-        echo '<div class="error"><p>'
680
-        . sprintf(
681
-            esc_html__(
682
-                '%1$sPayPal Commerce%2$s has updated the API integration type to allow more flexibility with payments. Please disconnect and re-Connect on the %3$sPayment Methods admin%4$s page to update the credentials and allow advanced payment type options.',
683
-                'event_espresso'
684
-            ),
685
-            '<strong>',
686
-            '</strong>',
687
-            $open_anchor,
688
-            $close_anchor
689
-         )
690
-         . '</p></div>';
691
-    }
23
+	/**
24
+	 * @return EED_Module
25
+	 * @throws EE_Error
26
+	 * @throws ReflectionException
27
+	 */
28
+	public static function instance(): EED_Module
29
+	{
30
+		return parent::get_instance(__CLASS__);
31
+	}
32
+
33
+
34
+	/**
35
+	 * Run - initial module setup.
36
+	 *
37
+	 * @param WP $WP
38
+	 * @return void
39
+	 */
40
+	public function run($WP)
41
+	{
42
+	}
43
+
44
+
45
+	/**
46
+	 * For hooking into EE Admin Core and other modules.
47
+	 *
48
+	 * @return void
49
+	 */
50
+	public static function set_hooks_admin(): void
51
+	{
52
+		if (DbStatus::isOnline()) {
53
+			// Get onboarding URL.
54
+			add_action('wp_ajax_eeaPpGetOnboardingUrl', [__CLASS__, 'getOnboardingUrl']);
55
+			// Catch the return/redirect from PayPal onboarding page.
56
+			add_action('init', [__CLASS__, 'updateOnboardingStatus'], 10);
57
+			// Return the connection/onboard status.
58
+			add_action('wp_ajax_eeaPpGetOnboardStatus', [__CLASS__, 'getOnboardStatus']);
59
+			// Revoke access.
60
+			add_action('wp_ajax_eeaPpOffboard', [__CLASS__, 'offboard']);
61
+			// Admin notice.
62
+			add_action('admin_init', [__CLASS__, 'adminNotice']);
63
+		}
64
+	}
65
+
66
+
67
+	/**
68
+	 * Get the onboarding URL.
69
+	 * (AJAX)
70
+	 *
71
+	 * @return void
72
+	 */
73
+	public static function getOnboardingUrl(): void
74
+	{
75
+		$signup_link = '';
76
+		try {
77
+			$paypal_pm = EED_PayPalCommerce::getPaymentMethod();
78
+			if (! $paypal_pm instanceof EE_Payment_Method) {
79
+				PayPalLogger::errorLogAndExit(
80
+					esc_html__('No payment method.', 'event_espresso'),
81
+					EED_Module::getRequest()->postParams(),
82
+					$paypal_pm
83
+				);
84
+			}
85
+			PayPalExtraMetaManager::updateDebugMode($paypal_pm, EED_Module::getRequest()->postParams());
86
+			// $signup_link   = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
87
+			// $token_expired = EED_PayPalOnboard::partnerAccessTokenExpired($paypal_pm);
88
+			// if (! $signup_link || $token_expired) {
89
+			$signup_link = EED_PayPalOnboard::requestOnboardingUrl($paypal_pm);
90
+			// }
91
+			if (! $signup_link) {
92
+				$err_msg = esc_html__('Error! Could not generate a sign-up link.', 'event_espresso');
93
+				PayPalLogger::errorLogAndExit($err_msg, ['signup_link' => $signup_link], $paypal_pm);
94
+			}
95
+			PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL, $signup_link);
96
+		} catch (Exception $exception) {
97
+			PayPalLogger::errorLogAndExit($exception->getMessage());
98
+		}
99
+		// Is it empty (can happen if we didn't get the URL through the API).
100
+		$signup_link = $signup_link ? $signup_link . '?&displayMode=minibrowser' : '#';
101
+		wp_send_json(
102
+			[
103
+				'signup_link' => $signup_link,
104
+			]
105
+		);
106
+	}
107
+
108
+
109
+	/**
110
+	 * Request the sign-up link from PayPal.
111
+	 *
112
+	 * @param EE_Payment_Method $paypal_pm
113
+	 * @param bool              $one_time_request
114
+	 * @return string
115
+	 * @throws EE_Error
116
+	 * @throws Exception
117
+	 */
118
+	public static function requestOnboardingUrl(EE_Payment_Method $paypal_pm, bool $one_time_request = false): string
119
+	{
120
+		$signup_link = '';
121
+		// Get the access token.
122
+		$access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
123
+		if (! $access_token) {
124
+			$err_msg = esc_html__('Error! No access token.', 'event_espresso');
125
+			PayPalLogger::errorLog($err_msg, ['access_token' => $access_token], $paypal_pm);
126
+			return '';
127
+		}
128
+		// Request the access token.
129
+		$body_params = EED_PayPalOnboard::signupLinkRequestBody($paypal_pm);
130
+		$bn_code     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
131
+		$post_params = [
132
+			'method'  => 'POST',
133
+			'headers' => [
134
+				'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
135
+				'Content-Type'                  => 'application/json',
136
+				'Authorization'                 => 'Bearer ' . $access_token,
137
+				'PayPal-Partner-Attribution-Id' => $bn_code,
138
+			],
139
+			'body'    => $body_params,
140
+		];
141
+		$request_url = Domain::getPayPalApiUrl($paypal_pm) . '/v2/customer/partner-referrals';
142
+		$response    = EED_PayPalOnboard::sendRequest($paypal_pm, $request_url, $post_params);
143
+		// Check the data we received.
144
+		if (isset($response['error']) || empty($response['links'])) {
145
+			// Did the original access token get replaced by any chance ?
146
+			if (! $one_time_request
147
+				&& ! empty($response['message'])
148
+				&& $response['message'] === 'Access Token not found in cache'
149
+			) {
150
+				// Clear all PM metadata and try getting the access token One more time.
151
+				PayPalExtraMetaManager::deleteAllData($paypal_pm);
152
+				return EED_PayPalOnboard::requestOnboardingUrl($paypal_pm, true);
153
+			}
154
+			$err_msg = esc_html__('Incoming sign-up link parameter validation failed.', 'event_espresso');
155
+			PayPalLogger::errorLog($err_msg, $response, $paypal_pm);
156
+			return '';
157
+		}
158
+		// Now retrieve that sign-up link.
159
+		foreach ($response['links'] as $link) {
160
+			if ($link['rel'] === 'action_url') {
161
+				$signup_link = $link['href'] ?? '';
162
+			}
163
+		}
164
+		return $signup_link;
165
+	}
166
+
167
+
168
+	/**
169
+	 * Get the return URL.
170
+	 *
171
+	 * @param EE_Payment_Method $paypal_pm
172
+	 * @return string
173
+	 * @throws Exception
174
+	 */
175
+	public static function signupLinkRequestBody(EE_Payment_Method $paypal_pm): string
176
+	{
177
+		$identifier_string = new OneTimeString($paypal_pm->debug_mode());
178
+		$tracking_id       = $identifier_string->value();
179
+		$request           = LoaderFactory::getLoader()->getShared(RequestInterface::class);
180
+		$checkout_type     = $request->getRequestParam('checkout_type', 'EXPRESS_CHECKOUT', DataType::STRING);
181
+		// Save the identifier for future use.
182
+		PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_TRACKING_ID, $tracking_id);
183
+		// Assemble the return URL.
184
+		$return_url = EED_PayPalOnboard::getReturnUrl($paypal_pm);
185
+		return json_encode([
186
+			'tracking_id'             => $tracking_id,
187
+			'operations'              => [
188
+				[
189
+					'operation'                  => 'API_INTEGRATION',
190
+					'api_integration_preference' => [
191
+						'rest_api_integration' => [
192
+							'integration_method'  => 'PAYPAL',
193
+							'integration_type'    => 'THIRD_PARTY',
194
+							'third_party_details' => [
195
+								'features' => ['PAYMENT', 'REFUND'],
196
+							],
197
+						],
198
+					],
199
+				],
200
+			],
201
+			'products'                => [$checkout_type],
202
+			'legal_consents'          => [
203
+				[
204
+					'type'    => 'SHARE_DATA_CONSENT',
205
+					'granted' => true,
206
+				],
207
+			],
208
+			'partner_config_override' => [
209
+				'return_url' => $return_url,
210
+			],
211
+		]);
212
+	}
213
+
214
+
215
+	/**
216
+	 * Get the return URL.
217
+	 *
218
+	 * @param EE_Payment_Method $paypal_pm
219
+	 * @return string
220
+	 * @throws EE_Error
221
+	 * @throws ReflectionException
222
+	 */
223
+	public static function getReturnUrl(EE_Payment_Method $paypal_pm): string
224
+	{
225
+		$wp_nonce = EED_Module::getRequest()->getRequestParam('wp_nonce');
226
+		$nonce    = wp_create_nonce(Domain::NONCE_NAME_ONBOARDING_RETURN);
227
+		return add_query_arg(
228
+			[
229
+				'page'                        => 'espresso_payment_settings',
230
+				'webhook_action'              => 'eea_pp_commerce_merchant_onboard',
231
+				'payment_method'              => $paypal_pm->slug(),
232
+				'_wpnonce'                    => $wp_nonce,
233
+				'nonce'                       => $nonce,
234
+				Domain::META_KEY_SANDBOX_MODE => $paypal_pm->debug_mode() ? '1' : '0',
235
+			],
236
+			admin_url('admin.php')
237
+		);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Redirect to the payment method (PP) settings home page.
243
+	 *
244
+	 * @return void
245
+	 */
246
+	public static function redirectToPmSettingsHome(): void
247
+	{
248
+		$get_params = EED_Module::getRequest()->getParams();
249
+		if (empty($get_params['payment_method'])) {
250
+			// Simply do not redirect.
251
+			return;
252
+		}
253
+		$args_to_add = [
254
+			'page'           => 'espresso_payment_settings',
255
+			'payment_method' => $get_params['payment_method'],
256
+		];
257
+		if (isset($get_params['sandbox_mode'])) {
258
+			$args_to_add[ Domain::META_KEY_SANDBOX_MODE ] = $get_params['sandbox_mode'];
259
+		}
260
+		$home_url = add_query_arg($args_to_add, admin_url('admin.php'));
261
+		wp_redirect($home_url);
262
+		exit;
263
+	}
264
+
265
+
266
+	/**
267
+	 * Check user’s onboarding status.
268
+	 * This will handle the user return from the auth page and also check the status via the API.
269
+	 *
270
+	 * @return void
271
+	 * @throws EE_Error
272
+	 * @throws ReflectionException
273
+	 */
274
+	public static function updateOnboardingStatus(): void
275
+	{
276
+		// Check if this is the webhook from PayPal.
277
+		if (! isset($_GET['webhook_action'], $_GET['nonce'])
278
+			|| $_GET['webhook_action'] !== 'eea_pp_commerce_merchant_onboard'
279
+		) {
280
+			return;  // Ignore.
281
+		}
282
+		$get_params = EED_Module::getRequest()->getParams();
283
+		// Get the payment method.
284
+		$paypal_pm = EED_PayPalCommerce::getPaymentMethod();
285
+		// Check the response (GET) parameters.
286
+		if (! EED_PayPalOnboard::onboardingStatusResponseValid($get_params, $paypal_pm)) {
287
+			// Missing parameters. Can't proceed.
288
+			PayPalLogger::errorLog(
289
+				esc_html__('Missing required onboarding parameters.', 'event_espresso'),
290
+				$get_params,
291
+				$paypal_pm
292
+			);
293
+			EED_PayPalOnboard::redirectToPmSettingsHome();
294
+			return;
295
+		}
296
+		// Were the requested permissions granted ?
297
+		if (empty($get_params[ Domain::API_PARAM_PERMISSIONS_GRANTED ])) {
298
+			$error_message = esc_html__(
299
+				'Permissions not granted by merchant or email not confirmed.',
300
+				'event_espresso'
301
+			);
302
+			PayPalLogger::errorLog($error_message, $get_params, $paypal_pm);
303
+			EED_PayPalOnboard::redirectToPmSettingsHome();
304
+			return;
305
+		}
306
+		// Check on the onboarding status (recommended by PP).
307
+		$onboarding_status = EED_PayPalOnboard::trackSellerOnboarding(
308
+			$paypal_pm,
309
+			$get_params[ Domain::META_KEY_SELLER_MERCHANT_ID ]
310
+		);
311
+		if (! isset($onboarding_status['valid']) || ! $onboarding_status['valid']) {
312
+			PayPalLogger::errorLog(
313
+				$onboarding_status['message'],
314
+				array_merge($get_params, $onboarding_status),
315
+				$paypal_pm
316
+			);
317
+			EED_PayPalOnboard::redirectToPmSettingsHome();
318
+			return;
319
+		}
320
+		// Start saving the setup and info.
321
+		PayPalExtraMetaManager::parseAndSaveOptions($paypal_pm, $onboarding_status);
322
+		// Save the credentials.
323
+		PayPalExtraMetaManager::saveSellerApiCredentials($paypal_pm, $get_params);
324
+		// If onboarded successfully, remove the onboarding URL.
325
+		PayPalExtraMetaManager::deletePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
326
+		// Also clen GET params by redirecting, because PP auto redirects to the return_url on closing the onboarding window.
327
+		EED_PayPalOnboard::redirectToPmSettingsHome();
328
+	}
329
+
330
+
331
+	/**
332
+	 * Check if all required parameters for the onboarding status check are present.
333
+	 *
334
+	 * @param array $data
335
+	 * @param mixed $paypal_pm
336
+	 * @return bool
337
+	 */
338
+	public static function onboardingStatusResponseValid(array $data, mixed $paypal_pm): bool
339
+	{
340
+		// Check that we have all the required parameters and the nonce is ok.
341
+		if ($paypal_pm instanceof EE_Payment_Method
342
+			&& wp_verify_nonce($data['nonce'], Domain::NONCE_NAME_ONBOARDING_RETURN)
343
+			&& ! empty($data[ Domain::API_PARAM_PARTNER_ID ])
344
+			&& ! empty($data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
345
+			&& isset($data[ Domain::API_PARAM_PERMISSIONS_GRANTED ])
346
+			&& isset($data[ Domain::API_PARAM_EMAIL_CONFIRMED ])
347
+		) {
348
+			return true;
349
+		}
350
+		return false;
351
+	}
352
+
353
+
354
+	/**
355
+	 * Get partner access token.
356
+	 *
357
+	 * @param EE_Payment_Method $paypal_pm
358
+	 * @return string
359
+	 * @throws EE_Error
360
+	 * @throws ReflectionException
361
+	 */
362
+	public static function getPartnerAccessToken(EE_Payment_Method $paypal_pm): string
363
+	{
364
+		// Do we have it saved ?
365
+		$access_token = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ACCESS_TOKEN);
366
+		$expired      = EED_PayPalOnboard::partnerAccessTokenExpired($paypal_pm);
367
+		// If we don't have it, request/update it.
368
+		if (! $access_token || $expired) {
369
+			return EED_PayPalOnboard::requestPartnerAccessToken($paypal_pm);
370
+		}
371
+		// Access token is saved as encrypted, so return decrypted.
372
+		return $access_token;
373
+	}
374
+
375
+
376
+	/**
377
+	 * Get partner access token.
378
+	 *
379
+	 * @param EE_Payment_Method $paypal_pm
380
+	 * @return bool
381
+	 */
382
+	public static function partnerAccessTokenExpired(EE_Payment_Method $paypal_pm): bool
383
+	{
384
+		$expires_at = (int) PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_EXPIRES_IN);
385
+		if (! $expires_at) {
386
+			return true;
387
+		}
388
+		// Validate the token expiration date.
389
+		$now          = time();
390
+		$minutes_left = round(($expires_at - $now) / 60);
391
+		// Count as expired if less than 60 minutes till expiration left.
392
+		if ($minutes_left <= 60) {
393
+			return true;
394
+		}
395
+		return false;
396
+	}
397
+
398
+
399
+	/**
400
+	 * Request the partner access token from PayPal and save/update it.
401
+	 *
402
+	 * @param EE_Payment_Method $paypal_pm
403
+	 * @return string
404
+	 * @throws EE_Error
405
+	 * @throws ReflectionException
406
+	 */
407
+	public static function requestPartnerAccessToken(EE_Payment_Method $paypal_pm): string
408
+	{
409
+		$nonce = wp_create_nonce('eea_pp_commerce_get_access_token');
410
+		// Request the access token.
411
+		$post_args = [
412
+			'method' => 'POST',
413
+			'body'   => [
414
+				'nonce'                       => $nonce,
415
+				'api_version'                 => 'v1',
416
+				Domain::META_KEY_SANDBOX_MODE => $paypal_pm->debug_mode() ? '1' : '0',
417
+			],
418
+		];
419
+		if (defined('LOCAL_MIDDLEMAN_SERVER')) {
420
+			$post_args['sslverify'] = false;
421
+		}
422
+		$post_url = EED_PayPalOnboard::getMiddlemanBaseUrl($paypal_pm) . 'get_token';
423
+		$response = EED_PayPalOnboard::sendRequest($paypal_pm, $post_url, $post_args);
424
+		if (isset($response['error'])) {
425
+			return '';
426
+		}
427
+		// Check the data we received.
428
+		if (! EED_PayPalOnboard::partnerTokenResponseValid($response, $paypal_pm)) {
429
+			return '';
430
+		}
431
+		// If we are here all seems to be ok. Save the token and it's data.
432
+		$saved = PayPalExtraMetaManager::savePartnerAccessToken($paypal_pm, $response);
433
+		if (! $saved) {
434
+			return '';
435
+		}
436
+		return $response['access_token'];
437
+	}
438
+
439
+
440
+	/**
441
+	 * Request seller onboarding status from PayPal.
442
+	 *
443
+	 * @param EE_Payment_Method $paypal_pm
444
+	 * @param string            $merchant_id
445
+	 * @return array
446
+	 */
447
+	public static function trackSellerOnboarding(EE_Payment_Method $paypal_pm, string $merchant_id): array
448
+	{
449
+		$track_onboarding = EED_PayPalOnboard::getTrackOnboardingApi($paypal_pm, $merchant_id);
450
+		if (! $track_onboarding instanceof TrackSellerOnboarding) {
451
+			$err_msg = esc_html__('Failed to track seller onboarding.', 'event_espresso');
452
+			return ['error' => 'TRACK_ONBOARDING_FAILED', 'message' => $err_msg];
453
+		}
454
+		return $track_onboarding->isValid();
455
+	}
456
+
457
+
458
+	/**
459
+	 * Returns the Track Seller Onboarding API.
460
+	 *
461
+	 * @param EE_Payment_Method $paypal_pm
462
+	 * @param string            $merchant_id
463
+	 * @return TrackSellerOnboarding|null
464
+	 * @throws EE_Error
465
+	 * @throws ReflectionException
466
+	 */
467
+	public static function getTrackOnboardingApi(
468
+		EE_Payment_Method $paypal_pm,
469
+		string            $merchant_id
470
+	): ?TrackSellerOnboarding {
471
+		$partner_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_MERCHANT_ID);
472
+		$paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
473
+		if (! $paypal_api instanceof PayPalApi || ! $partner_id) {
474
+			return null;
475
+		}
476
+		return new TrackSellerOnboarding($paypal_api, $partner_id, $merchant_id, $paypal_pm->debug_mode());
477
+	}
478
+
479
+
480
+	/**
481
+	 * Check the onboard status and return the result.
482
+	 * (AJAX)
483
+	 *
484
+	 * @return void
485
+	 */
486
+	public static function getOnboardStatus(): void
487
+	{
488
+		$paypal_pm = EED_PayPalCommerce::getPaymentMethod();
489
+		if (! $paypal_pm instanceof EE_Payment_Method) {
490
+			$err_msg = esc_html__('Could not specify the payment method.', 'event_espresso');
491
+			PayPalLogger::errorLog($err_msg, EED_Module::getRequest()->postParams(), $paypal_pm);
492
+			wp_send_json(['on_board' => false]);
493
+		}
494
+		try {
495
+			$seller_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_MERCHANT_ID) ?? '--';
496
+		} catch (Exception $e) {
497
+			$seller_id = '--';
498
+		}
499
+		wp_send_json(
500
+			[
501
+				'on_board'  => EED_PayPalOnboard::isOnboard($paypal_pm),
502
+				'seller_id' => $seller_id,
503
+			]
504
+		);
505
+	}
506
+
507
+
508
+	/**
509
+	 * De-authorize the seller. Remove all API credentials.
510
+	 * (AJAX)
511
+	 *
512
+	 * @return void
513
+	 */
514
+	public static function offboard(): void
515
+	{
516
+		$paypal_pm = EED_PayPalCommerce::getPaymentMethod();
517
+		if (! $paypal_pm instanceof EE_Payment_Method) {
518
+			wp_send_json([
519
+				'error'   => 'INVALID_PM',
520
+				'message' => esc_html__(
521
+					'Invalid payment method. Please refresh the page and try again.',
522
+					'event_espresso'
523
+				),
524
+			]);
525
+		}
526
+		PayPalExtraMetaManager::deleteAllData($paypal_pm);
527
+		wp_send_json(['success' => true]);
528
+	}
529
+
530
+
531
+	/**
532
+	 * Checks if already onboard.
533
+	 *
534
+	 * @param EE_Payment_Method $payment_method
535
+	 * @return boolean
536
+	 */
537
+	public static function isOnboard(EE_Payment_Method $payment_method): bool
538
+	{
539
+		$pp_meta_data = PayPalExtraMetaManager::getAllData($payment_method);
540
+		return
541
+			// onborded with a third party integration ?
542
+			(! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
543
+				&& ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ])
544
+			)
545
+			// or with the first party integration ?
546
+			|| (! empty($pp_meta_data[ Domain::META_KEY_CLIENT_ID ])
547
+				&& ! empty($pp_meta_data[ Domain::META_KEY_CLIENT_SECRET ])
548
+				&& ! empty($pp_meta_data[ Domain::META_KEY_PAYER_ID ])
549
+			);
550
+	}
551
+
552
+
553
+	/**
554
+	 * Send a request and return a decoded response body.
555
+	 *
556
+	 * @param EE_Payment_Method $paypal_pm
557
+	 * @param string            $request_url
558
+	 * @param array             $request_args
559
+	 * @return array
560
+	 */
561
+	public static function sendRequest(EE_Payment_Method $paypal_pm, string $request_url, array $request_args): array
562
+	{
563
+		$error_return = ['error' => true];
564
+		$response     = wp_remote_request($request_url, $request_args);
565
+		if (is_wp_error($response)) {
566
+			$message = $response->get_error_message();
567
+			PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
568
+			$error_return['message'] = $message;
569
+			return $error_return;
570
+		}
571
+		$response_body = (isset($response['body']) && $response['body']) ? json_decode($response['body'], true) : [];
572
+		if (empty($response_body) || isset($response_body['error'])) {
573
+			$message = $response_body['error_description']
574
+					   ?? sprintf(
575
+						   esc_html__('Unknown response received while sending a request to: %1$s', 'event_espresso'),
576
+						   $request_url
577
+					   );
578
+			PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
579
+			$error_return['message'] = $message;
580
+			return $error_return;
581
+		}
582
+		return $response_body;
583
+	}
584
+
585
+
586
+	/**
587
+	 * Check the response for a partner token request.
588
+	 *
589
+	 * @param                   $response
590
+	 * @param EE_Payment_Method $paypal_pm
591
+	 * @return bool
592
+	 */
593
+	public static function partnerTokenResponseValid($response, EE_Payment_Method $paypal_pm): bool
594
+	{
595
+		// Check the data we received.
596
+		if (
597
+			empty($response['nonce'])
598
+			|| ! wp_verify_nonce($response['nonce'], 'eea_pp_commerce_get_access_token')
599
+			|| empty($response['access_token'])
600
+			|| empty($response['app_id'])
601
+			|| empty($response['expires_in'])
602
+			|| empty($response['partner_client_id'])
603
+			|| empty($response['partner_merchant_id'])
604
+		) {
605
+			// This is an error.
606
+			$err_msg = esc_html__('Incoming parameter validation failed.', 'event_espresso');
607
+			PayPalLogger::errorLog($err_msg, (array) $response, $paypal_pm);
608
+			return false;
609
+		}
610
+		return true;
611
+	}
612
+
613
+
614
+	/**
615
+	 * Returns the base URL to the middleman server.
616
+	 * If LOCAL_MIDDLEMAN_SERVER is defined, requests will be sent to connect.eventespresso.test
617
+	 *
618
+	 * @param EE_Payment_Method $payment_method
619
+	 * @return string
620
+	 * @throws EE_Error
621
+	 * @throws ReflectionException
622
+	 */
623
+	public static function getMiddlemanBaseUrl(EE_Payment_Method $payment_method): string
624
+	{
625
+		$target = defined('LOCAL_MIDDLEMAN_SERVER') ? 'test' : 'com';
626
+		// If this PM is used under different provider accounts, you might need an account indicator.
627
+		$account = defined('EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR') ? EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR : '';
628
+		$postfix = $payment_method->debug_mode() ? '_sandbox' : '';
629
+		$path    = 'paypal_commerce' . $account . $postfix;
630
+		return 'https://connect.eventespresso.' . $target . '/' . $path . '/';
631
+	}
632
+
633
+
634
+	/**
635
+	 * This Payment Method admin notices.
636
+	 *
637
+	 * @return void
638
+	 * @throws EE_Error
639
+	 * @throws ReflectionException
640
+	 */
641
+	public static function adminNotice()
642
+	{
643
+		// A notice to re-connect if still connected through the first party integration.
644
+		$pp_commerce = EEM_Payment_Method::instance()->get_one_by_slug('paypalcheckout');
645
+		// Show the notice only if PayPal Commerce is active.
646
+		if (! $pp_commerce instanceof EE_Payment_Method
647
+			|| ! EED_PayPalOnboard::isOnboard($pp_commerce)
648
+			|| EED_PayPalCommerce::isThirdParty($pp_commerce)
649
+		) {
650
+			return;
651
+		}
652
+		add_action('admin_notices', [__CLASS__, 'reConnectNotice']);
653
+	}
654
+
655
+
656
+	/**
657
+	 * Re-connect notice contents.
658
+	 *
659
+	 * @return void
660
+	 * @throws EE_Error
661
+	 * @throws ReflectionException
662
+	 */
663
+	public static function reConnectNotice()
664
+	{
665
+		$open_anchor = $close_anchor = '';
666
+		$pp_commerce = EEM_Payment_Method::instance()->get_one_by_slug('paypalcheckout');
667
+		if ($pp_commerce instanceof EE_Payment_Method) {
668
+			$pm_page = add_query_arg(
669
+				[
670
+					'page'           => 'espresso_payment_settings',
671
+					'webhook_action' => 'eea_pp_commerce_merchant_onboard',
672
+					'payment_method' => $pp_commerce->slug(),
673
+				],
674
+				admin_url('admin.php')
675
+			);
676
+			$open_anchor  = "<a href='$pm_page'>";
677
+			$close_anchor = "</a>";
678
+		}
679
+		echo '<div class="error"><p>'
680
+		. sprintf(
681
+			esc_html__(
682
+				'%1$sPayPal Commerce%2$s has updated the API integration type to allow more flexibility with payments. Please disconnect and re-Connect on the %3$sPayment Methods admin%4$s page to update the credentials and allow advanced payment type options.',
683
+				'event_espresso'
684
+			),
685
+			'<strong>',
686
+			'</strong>',
687
+			$open_anchor,
688
+			$close_anchor
689
+		 )
690
+		 . '</p></div>';
691
+	}
692 692
 }
Please login to merge, or discard this patch.
Spacing   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
         $signup_link = '';
76 76
         try {
77 77
             $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
78
-            if (! $paypal_pm instanceof EE_Payment_Method) {
78
+            if ( ! $paypal_pm instanceof EE_Payment_Method) {
79 79
                 PayPalLogger::errorLogAndExit(
80 80
                     esc_html__('No payment method.', 'event_espresso'),
81 81
                     EED_Module::getRequest()->postParams(),
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
             // if (! $signup_link || $token_expired) {
89 89
             $signup_link = EED_PayPalOnboard::requestOnboardingUrl($paypal_pm);
90 90
             // }
91
-            if (! $signup_link) {
91
+            if ( ! $signup_link) {
92 92
                 $err_msg = esc_html__('Error! Could not generate a sign-up link.', 'event_espresso');
93 93
                 PayPalLogger::errorLogAndExit($err_msg, ['signup_link' => $signup_link], $paypal_pm);
94 94
             }
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
             PayPalLogger::errorLogAndExit($exception->getMessage());
98 98
         }
99 99
         // Is it empty (can happen if we didn't get the URL through the API).
100
-        $signup_link = $signup_link ? $signup_link . '?&displayMode=minibrowser' : '#';
100
+        $signup_link = $signup_link ? $signup_link.'?&displayMode=minibrowser' : '#';
101 101
         wp_send_json(
102 102
             [
103 103
                 'signup_link' => $signup_link,
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
         $signup_link = '';
121 121
         // Get the access token.
122 122
         $access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
123
-        if (! $access_token) {
123
+        if ( ! $access_token) {
124 124
             $err_msg = esc_html__('Error! No access token.', 'event_espresso');
125 125
             PayPalLogger::errorLog($err_msg, ['access_token' => $access_token], $paypal_pm);
126 126
             return '';
@@ -133,17 +133,17 @@  discard block
 block discarded – undo
133 133
             'headers' => [
134 134
                 'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
135 135
                 'Content-Type'                  => 'application/json',
136
-                'Authorization'                 => 'Bearer ' . $access_token,
136
+                'Authorization'                 => 'Bearer '.$access_token,
137 137
                 'PayPal-Partner-Attribution-Id' => $bn_code,
138 138
             ],
139 139
             'body'    => $body_params,
140 140
         ];
141
-        $request_url = Domain::getPayPalApiUrl($paypal_pm) . '/v2/customer/partner-referrals';
141
+        $request_url = Domain::getPayPalApiUrl($paypal_pm).'/v2/customer/partner-referrals';
142 142
         $response    = EED_PayPalOnboard::sendRequest($paypal_pm, $request_url, $post_params);
143 143
         // Check the data we received.
144 144
         if (isset($response['error']) || empty($response['links'])) {
145 145
             // Did the original access token get replaced by any chance ?
146
-            if (! $one_time_request
146
+            if ( ! $one_time_request
147 147
                 && ! empty($response['message'])
148 148
                 && $response['message'] === 'Access Token not found in cache'
149 149
             ) {
@@ -255,7 +255,7 @@  discard block
 block discarded – undo
255 255
             'payment_method' => $get_params['payment_method'],
256 256
         ];
257 257
         if (isset($get_params['sandbox_mode'])) {
258
-            $args_to_add[ Domain::META_KEY_SANDBOX_MODE ] = $get_params['sandbox_mode'];
258
+            $args_to_add[Domain::META_KEY_SANDBOX_MODE] = $get_params['sandbox_mode'];
259 259
         }
260 260
         $home_url = add_query_arg($args_to_add, admin_url('admin.php'));
261 261
         wp_redirect($home_url);
@@ -274,16 +274,16 @@  discard block
 block discarded – undo
274 274
     public static function updateOnboardingStatus(): void
275 275
     {
276 276
         // Check if this is the webhook from PayPal.
277
-        if (! isset($_GET['webhook_action'], $_GET['nonce'])
277
+        if ( ! isset($_GET['webhook_action'], $_GET['nonce'])
278 278
             || $_GET['webhook_action'] !== 'eea_pp_commerce_merchant_onboard'
279 279
         ) {
280
-            return;  // Ignore.
280
+            return; // Ignore.
281 281
         }
282 282
         $get_params = EED_Module::getRequest()->getParams();
283 283
         // Get the payment method.
284 284
         $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
285 285
         // Check the response (GET) parameters.
286
-        if (! EED_PayPalOnboard::onboardingStatusResponseValid($get_params, $paypal_pm)) {
286
+        if ( ! EED_PayPalOnboard::onboardingStatusResponseValid($get_params, $paypal_pm)) {
287 287
             // Missing parameters. Can't proceed.
288 288
             PayPalLogger::errorLog(
289 289
                 esc_html__('Missing required onboarding parameters.', 'event_espresso'),
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
             return;
295 295
         }
296 296
         // Were the requested permissions granted ?
297
-        if (empty($get_params[ Domain::API_PARAM_PERMISSIONS_GRANTED ])) {
297
+        if (empty($get_params[Domain::API_PARAM_PERMISSIONS_GRANTED])) {
298 298
             $error_message = esc_html__(
299 299
                 'Permissions not granted by merchant or email not confirmed.',
300 300
                 'event_espresso'
@@ -306,9 +306,9 @@  discard block
 block discarded – undo
306 306
         // Check on the onboarding status (recommended by PP).
307 307
         $onboarding_status = EED_PayPalOnboard::trackSellerOnboarding(
308 308
             $paypal_pm,
309
-            $get_params[ Domain::META_KEY_SELLER_MERCHANT_ID ]
309
+            $get_params[Domain::META_KEY_SELLER_MERCHANT_ID]
310 310
         );
311
-        if (! isset($onboarding_status['valid']) || ! $onboarding_status['valid']) {
311
+        if ( ! isset($onboarding_status['valid']) || ! $onboarding_status['valid']) {
312 312
             PayPalLogger::errorLog(
313 313
                 $onboarding_status['message'],
314 314
                 array_merge($get_params, $onboarding_status),
@@ -340,10 +340,10 @@  discard block
 block discarded – undo
340 340
         // Check that we have all the required parameters and the nonce is ok.
341 341
         if ($paypal_pm instanceof EE_Payment_Method
342 342
             && wp_verify_nonce($data['nonce'], Domain::NONCE_NAME_ONBOARDING_RETURN)
343
-            && ! empty($data[ Domain::API_PARAM_PARTNER_ID ])
344
-            && ! empty($data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
345
-            && isset($data[ Domain::API_PARAM_PERMISSIONS_GRANTED ])
346
-            && isset($data[ Domain::API_PARAM_EMAIL_CONFIRMED ])
343
+            && ! empty($data[Domain::API_PARAM_PARTNER_ID])
344
+            && ! empty($data[Domain::META_KEY_SELLER_MERCHANT_ID])
345
+            && isset($data[Domain::API_PARAM_PERMISSIONS_GRANTED])
346
+            && isset($data[Domain::API_PARAM_EMAIL_CONFIRMED])
347 347
         ) {
348 348
             return true;
349 349
         }
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
         $access_token = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ACCESS_TOKEN);
366 366
         $expired      = EED_PayPalOnboard::partnerAccessTokenExpired($paypal_pm);
367 367
         // If we don't have it, request/update it.
368
-        if (! $access_token || $expired) {
368
+        if ( ! $access_token || $expired) {
369 369
             return EED_PayPalOnboard::requestPartnerAccessToken($paypal_pm);
370 370
         }
371 371
         // Access token is saved as encrypted, so return decrypted.
@@ -382,7 +382,7 @@  discard block
 block discarded – undo
382 382
     public static function partnerAccessTokenExpired(EE_Payment_Method $paypal_pm): bool
383 383
     {
384 384
         $expires_at = (int) PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_EXPIRES_IN);
385
-        if (! $expires_at) {
385
+        if ( ! $expires_at) {
386 386
             return true;
387 387
         }
388 388
         // Validate the token expiration date.
@@ -419,18 +419,18 @@  discard block
 block discarded – undo
419 419
         if (defined('LOCAL_MIDDLEMAN_SERVER')) {
420 420
             $post_args['sslverify'] = false;
421 421
         }
422
-        $post_url = EED_PayPalOnboard::getMiddlemanBaseUrl($paypal_pm) . 'get_token';
422
+        $post_url = EED_PayPalOnboard::getMiddlemanBaseUrl($paypal_pm).'get_token';
423 423
         $response = EED_PayPalOnboard::sendRequest($paypal_pm, $post_url, $post_args);
424 424
         if (isset($response['error'])) {
425 425
             return '';
426 426
         }
427 427
         // Check the data we received.
428
-        if (! EED_PayPalOnboard::partnerTokenResponseValid($response, $paypal_pm)) {
428
+        if ( ! EED_PayPalOnboard::partnerTokenResponseValid($response, $paypal_pm)) {
429 429
             return '';
430 430
         }
431 431
         // If we are here all seems to be ok. Save the token and it's data.
432 432
         $saved = PayPalExtraMetaManager::savePartnerAccessToken($paypal_pm, $response);
433
-        if (! $saved) {
433
+        if ( ! $saved) {
434 434
             return '';
435 435
         }
436 436
         return $response['access_token'];
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
     public static function trackSellerOnboarding(EE_Payment_Method $paypal_pm, string $merchant_id): array
448 448
     {
449 449
         $track_onboarding = EED_PayPalOnboard::getTrackOnboardingApi($paypal_pm, $merchant_id);
450
-        if (! $track_onboarding instanceof TrackSellerOnboarding) {
450
+        if ( ! $track_onboarding instanceof TrackSellerOnboarding) {
451 451
             $err_msg = esc_html__('Failed to track seller onboarding.', 'event_espresso');
452 452
             return ['error' => 'TRACK_ONBOARDING_FAILED', 'message' => $err_msg];
453 453
         }
@@ -470,7 +470,7 @@  discard block
 block discarded – undo
470 470
     ): ?TrackSellerOnboarding {
471 471
         $partner_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_MERCHANT_ID);
472 472
         $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
473
-        if (! $paypal_api instanceof PayPalApi || ! $partner_id) {
473
+        if ( ! $paypal_api instanceof PayPalApi || ! $partner_id) {
474 474
             return null;
475 475
         }
476 476
         return new TrackSellerOnboarding($paypal_api, $partner_id, $merchant_id, $paypal_pm->debug_mode());
@@ -486,7 +486,7 @@  discard block
 block discarded – undo
486 486
     public static function getOnboardStatus(): void
487 487
     {
488 488
         $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
489
-        if (! $paypal_pm instanceof EE_Payment_Method) {
489
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
490 490
             $err_msg = esc_html__('Could not specify the payment method.', 'event_espresso');
491 491
             PayPalLogger::errorLog($err_msg, EED_Module::getRequest()->postParams(), $paypal_pm);
492 492
             wp_send_json(['on_board' => false]);
@@ -514,7 +514,7 @@  discard block
 block discarded – undo
514 514
     public static function offboard(): void
515 515
     {
516 516
         $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
517
-        if (! $paypal_pm instanceof EE_Payment_Method) {
517
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
518 518
             wp_send_json([
519 519
                 'error'   => 'INVALID_PM',
520 520
                 'message' => esc_html__(
@@ -539,13 +539,13 @@  discard block
 block discarded – undo
539 539
         $pp_meta_data = PayPalExtraMetaManager::getAllData($payment_method);
540 540
         return
541 541
             // onborded with a third party integration ?
542
-            (! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
543
-                && ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ])
542
+            ( ! empty($pp_meta_data[Domain::META_KEY_SELLER_MERCHANT_ID])
543
+                && ! empty($pp_meta_data[Domain::META_KEY_ACCESS_TOKEN])
544 544
             )
545 545
             // or with the first party integration ?
546
-            || (! empty($pp_meta_data[ Domain::META_KEY_CLIENT_ID ])
547
-                && ! empty($pp_meta_data[ Domain::META_KEY_CLIENT_SECRET ])
548
-                && ! empty($pp_meta_data[ Domain::META_KEY_PAYER_ID ])
546
+            || ( ! empty($pp_meta_data[Domain::META_KEY_CLIENT_ID])
547
+                && ! empty($pp_meta_data[Domain::META_KEY_CLIENT_SECRET])
548
+                && ! empty($pp_meta_data[Domain::META_KEY_PAYER_ID])
549 549
             );
550 550
     }
551 551
 
@@ -626,8 +626,8 @@  discard block
 block discarded – undo
626 626
         // If this PM is used under different provider accounts, you might need an account indicator.
627 627
         $account = defined('EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR') ? EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR : '';
628 628
         $postfix = $payment_method->debug_mode() ? '_sandbox' : '';
629
-        $path    = 'paypal_commerce' . $account . $postfix;
630
-        return 'https://connect.eventespresso.' . $target . '/' . $path . '/';
629
+        $path    = 'paypal_commerce'.$account.$postfix;
630
+        return 'https://connect.eventespresso.'.$target.'/'.$path.'/';
631 631
     }
632 632
 
633 633
 
@@ -643,7 +643,7 @@  discard block
 block discarded – undo
643 643
         // A notice to re-connect if still connected through the first party integration.
644 644
         $pp_commerce = EEM_Payment_Method::instance()->get_one_by_slug('paypalcheckout');
645 645
         // Show the notice only if PayPal Commerce is active.
646
-        if (! $pp_commerce instanceof EE_Payment_Method
646
+        if ( ! $pp_commerce instanceof EE_Payment_Method
647 647
             || ! EED_PayPalOnboard::isOnboard($pp_commerce)
648 648
             || EED_PayPalCommerce::isThirdParty($pp_commerce)
649 649
         ) {
Please login to merge, or discard this patch.
PaymentMethods/PayPalCommerce/modules/EED_PayPalCommerce.module.php 2 patches
Indentation   +415 added lines, -415 removed lines patch added patch discarded remove patch
@@ -21,419 +21,419 @@
 block discarded – undo
21 21
  */
22 22
 class EED_PayPalCommerce extends EED_Module
23 23
 {
24
-    /**
25
-     * @return EED_Module
26
-     * @throws EE_Error
27
-     * @throws ReflectionException
28
-     */
29
-    public static function instance(): EED_Module
30
-    {
31
-        return parent::get_instance(__CLASS__);
32
-    }
33
-
34
-
35
-    /**
36
-     * Run - initial module setup.
37
-     *
38
-     * @param WP $WP
39
-     * @return void
40
-     */
41
-    public function run($WP)
42
-    {
43
-    }
44
-
45
-
46
-    /**
47
-     * For hooking into EE Admin Core and other modules.
48
-     *
49
-     * @return void
50
-     */
51
-    public static function set_hooks_admin(): void
52
-    {
53
-        if (DbStatus::isOnline()) {
54
-            // Create an Order.
55
-            add_action('wp_ajax_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
56
-            add_action('wp_ajax_nopriv_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
57
-            // Capture the Order.
58
-            add_action('wp_ajax_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
59
-            add_action('wp_ajax_nopriv_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
60
-            // Log errors from the JS side.
61
-            add_action('wp_ajax_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
62
-            add_action('wp_ajax_nopriv_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
63
-            // Don't load PM on the front-end if not Connected.
64
-            add_filter(
65
-                'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
66
-                [__CLASS__, 'filterPaymentMethods'],
67
-                10,
68
-                3
69
-            );
70
-        }
71
-    }
72
-
73
-
74
-    /**
75
-     * Create the order and return its data as JSON.
76
-     * (AJAX)
77
-     *
78
-     * @return void
79
-     * @throws EE_Error
80
-     * @throws ReflectionException
81
-     */
82
-    public static function createOrderRequest(): void
83
-    {
84
-        $paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
85
-        $request     = EED_Module::getRequest();
86
-        $post_params = $request->postParams();
87
-        if (! $paypal_pm instanceof EE_Payment_Method) {
88
-            PayPalLogger::errorLogAndExit(
89
-                esc_html__('Related payment method not found (create Order).', 'event_espresso'),
90
-                $post_params
91
-            );
92
-        }
93
-        $transaction  = EED_PayPalCommerce::getTransaction();
94
-        $billing_info = $post_params['billing_info'] ?? [];
95
-        if ($billing_info) {
96
-            $billing_info_decoded = json_decode(stripslashes($billing_info), true);
97
-            $billing_info = is_array($billing_info_decoded) ? $billing_info_decoded : [];
98
-        }
99
-        if (! $transaction) {
100
-            PayPalLogger::errorLogAndExit(
101
-                esc_html__('Transaction info not found.', 'event_espresso'),
102
-                $post_params,
103
-                $paypal_pm
104
-            );
105
-        }
106
-        $order_data = EED_PayPalCommerce::createOrder($transaction, $billing_info, $paypal_pm);
107
-        wp_send_json($order_data);
108
-    }
109
-
110
-
111
-    /**
112
-     * Capture the order and return status in JSON.
113
-     * (AJAX)
114
-     *
115
-     * @return void
116
-     */
117
-    public static function captureOrderRequest(): void
118
-    {
119
-        $error_message = false;
120
-        $paypal_pm     = EED_PayPalCommerce::getPaymentMethod();
121
-        if (! $paypal_pm instanceof EE_Payment_Method) {
122
-            $error_message = esc_html__('Payment method not found (capture Order).', 'event_espresso');
123
-        }
124
-        $transaction = EED_PayPalCommerce::getTransaction();
125
-        if (! $transaction) {
126
-            $error_message = esc_html__('Transaction not found.', 'event_espresso');
127
-        }
128
-        $order_id = EED_Module::getRequest()->getRequestParam('order_id', '', DataType::STRING);
129
-        if (! $order_id) {
130
-            $error_message = esc_html__('Order ID missing.', 'event_espresso');
131
-        }
132
-        // We had an error. Log and EXIT.
133
-        if ($error_message) {
134
-            PayPalLogger::errorLogAndExit($error_message, EED_Module::getRequest()->postParams(), $paypal_pm);
135
-        }
136
-        $capture_response = EED_PayPalCommerce::captureOrder($transaction, $paypal_pm, $order_id);
137
-        wp_send_json($capture_response);
138
-    }
139
-
140
-
141
-    /**
142
-     * Create a new Order using the PP API.
143
-     *
144
-     * @param EE_Transaction    $transaction
145
-     * @param array             $billing_info
146
-     * @param EE_Payment_Method $paypal_pm
147
-     * @return array
148
-     * @throws EE_Error
149
-     * @throws ReflectionException
150
-     */
151
-    public static function createOrder(
152
-        EE_Transaction $transaction,
153
-        array $billing_info,
154
-        EE_Payment_Method $paypal_pm
155
-    ): array {
156
-        $create_order_api = EED_PayPalCommerce::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
157
-        if (! $create_order_api instanceof CreateOrder) {
158
-            return [
159
-                'error'   => 'CREATE_ORDER_API_FAULT',
160
-                'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
161
-            ];
162
-        }
163
-        $order = $create_order_api->create();
164
-        if (isset($order['error'])) {
165
-            return [
166
-                'error'   => 'CREATE_ORDER_API_RESPONSE_ERROR',
167
-                'message' => $order['message'],
168
-            ];
169
-        }
170
-        return [
171
-            'pp_order_id' => $order['id'],
172
-        ];
173
-    }
174
-
175
-
176
-    /**
177
-     * Create a new Order using the PP API.
178
-     *
179
-     * @param EE_Transaction    $transaction
180
-     * @param EE_Payment_Method $paypal_pm
181
-     * @param string            $order_id
182
-     * @return array
183
-     */
184
-    public static function captureOrder(
185
-        EE_Transaction $transaction,
186
-        EE_Payment_Method $paypal_pm,
187
-        string $order_id
188
-    ): array {
189
-        $capture_order_api = EED_PayPalCommerce::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
190
-        if (! $capture_order_api instanceof CaptureOrder) {
191
-            return [
192
-                'error'   => 'CAPTURE_ORDER_API_FAULT',
193
-                'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
194
-            ];
195
-        }
196
-        $order = $capture_order_api->capture();
197
-        if (isset($order['error'])) {
198
-            return $order;
199
-        }
200
-        // Attach the transaction ID to this order.
201
-        try {
202
-            $order['ee_txn_id'] = $transaction->ID();
203
-        } catch (Exception $e) {
204
-            // Just don't set the txn id.
205
-        }
206
-        // Save this order details.
207
-        PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_LAST_ORDER, $order);
208
-        $nonce = wp_create_nonce(Domain::CAPTURE_ORDER_NONCE_NAME);
209
-        return [
210
-            'pp_order_nonce'         => $nonce,
211
-            'pp_order_id'            => $order['id'],
212
-            'pp_order_status'        => $order['status'],
213
-            'pp_order_amount'        => $order['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
214
-        ];
215
-    }
216
-
217
-
218
-    /**
219
-     * Create an Order for this transaction.
220
-     *
221
-     * @param EE_Transaction    $transaction
222
-     * @param array             $billing_info
223
-     * @param EE_Payment_Method $paypal_pm
224
-     * @return CreateOrder|null
225
-     */
226
-    public static function getCreateOrderApi(
227
-        EE_Transaction $transaction,
228
-        array $billing_info,
229
-        EE_Payment_Method $paypal_pm
230
-    ): ?CreateOrder {
231
-        $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
232
-        if (! $paypal_api instanceof PayPalApi) {
233
-            return null;
234
-        }
235
-        return new CreateOrder($paypal_api, $transaction, $billing_info);
236
-    }
237
-
238
-
239
-    /**
240
-     * Create an Order for this transaction.
241
-     *
242
-     * @param EE_Transaction    $transaction
243
-     * @param EE_Payment_Method $paypal_pm
244
-     * @param string            $order_id
245
-     * @return CaptureOrder|null
246
-     */
247
-    public static function getCaptureOrderApi(
248
-        EE_Transaction $transaction,
249
-        EE_Payment_Method $paypal_pm,
250
-        string $order_id
251
-    ): ?CaptureOrder {
252
-        $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
253
-        if (! $paypal_api instanceof PayPalApi) {
254
-            return null;
255
-        }
256
-        return new CaptureOrder($paypal_api, $transaction, $order_id);
257
-    }
258
-
259
-
260
-    /**
261
-     * Return a PayPal API object, or false on failure.
262
-     *
263
-     * @param EE_Payment_Method $paypal_pm
264
-     * @return PayPalApi|null
265
-     * @throws EE_Error
266
-     * @throws ReflectionException
267
-     */
268
-    public static function getPayPalApi(EE_Payment_Method $paypal_pm): ?PayPalApi
269
-    {
270
-        // Try getting the first party credentials to determine if this is a first party integration that's active.
271
-        $client_id     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_ID);
272
-        $client_secret = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_SECRET);
273
-        $bn_code       = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
274
-        if ($client_id && $client_secret) {
275
-            return new FirstPartyPayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
276
-        }
277
-        // Third party integration credentials:
278
-        $access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
279
-        if (! $access_token || ! $bn_code) {
280
-            return null;
281
-        }
282
-        $partner_client_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_CLIENT_ID) ?: '';
283
-        $payer_id          = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_MERCHANT_ID) ?: '';
284
-        return new ThirdPartyPayPalApi($access_token, $bn_code, $partner_client_id, $payer_id, $paypal_pm->debug_mode());
285
-    }
286
-
287
-
288
-    /**
289
-     * Requests a client token.
290
-     *
291
-     * @param EE_Payment_Method $paypal_pm
292
-     * @return array
293
-     */
294
-    public static function requestClientToken(EE_Payment_Method $paypal_pm): array
295
-    {
296
-        $error = [
297
-            'error' => 'GET_CLIENT_TOKEN_FAULT'
298
-        ];
299
-        $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
300
-        if (! $paypal_api instanceof PayPalApi) {
301
-            $error['message'] = esc_html__('Got an error while trying to get the client token.', 'event_espresso');
302
-            return $error;
303
-        }
304
-        $client_token_api = new ClientToken($paypal_api, $paypal_pm->debug_mode());
305
-        $client_token = $client_token_api->getToken();
306
-        if (isset($client_token['error'])) {
307
-            return $client_token;
308
-        }
309
-        if (empty($client_token)) {
310
-            $error['message'] = esc_html__('Client token not valid.', 'event_espresso');
311
-            return $error;
312
-        }
313
-        return $client_token;
314
-    }
315
-
316
-
317
-    /**
318
-     * Retrieve the payment method from the provided data.
319
-     *
320
-     * @return EE_Transaction|null
321
-     */
322
-    public static function getTransaction(): ?EE_Transaction
323
-    {
324
-        try {
325
-            $txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
326
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
327
-            if (! $transaction instanceof EE_Transaction) {
328
-                PayPalLogger::errorLog(
329
-                    esc_html__('No transaction found by ID:', 'event_espresso'),
330
-                    EED_Module::getRequest()->postParams()
331
-                );
332
-                return null;
333
-            }
334
-        } catch (Exception $e) {
335
-            return null;
336
-        }
337
-        return $transaction;
338
-    }
339
-
340
-
341
-    /**
342
-     * Return a PayPal API object, or false on failure.
343
-     *
344
-     * @param EE_Payment_Method $paypal_pm
345
-     * @return bool
346
-     */
347
-    public static function isThirdParty(EE_Payment_Method $paypal_pm): bool
348
-    {
349
-        $pp_meta_data = PayPalExtraMetaManager::getAllData($paypal_pm);
350
-        return ! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
351
-            && ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ]);
352
-    }
353
-
354
-
355
-    /**
356
-     * Retrieve the payment method from the provided data.
357
-     *
358
-     * @return EE_Payment_Method|null
359
-     */
360
-    public static function getPaymentMethod(): ?EE_Payment_Method
361
-    {
362
-        try {
363
-            // Check if all required parameters are present.
364
-            $pm_slug        = EED_Module::getRequest()->getRequestParam('payment_method');
365
-            $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_slug);
366
-            if ($payment_method instanceof EE_Payment_Method) {
367
-                return $payment_method;
368
-            }
369
-        } catch (Exception $e) {
370
-            return null;
371
-        }
372
-        return null;
373
-    }
374
-
375
-
376
-    /**
377
-     * Log JS error.
378
-     *
379
-     * @return void
380
-     */
381
-    public static function logJsError(): void
382
-    {
383
-        // Default to the "first" PayPal checkout PM.
384
-        $request        = EED_Module::getRequest();
385
-        $pm_slug        = $request->getRequestParam('pm_slug', Domain::PM_SLUG);
386
-        $payment_method = null;
387
-        $txn_id         = 'unknown';
388
-        try {
389
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pm_slug);
390
-            $txn_id         = sanitize_text_field($request->getRequestParam('txn_id', '-'));
391
-        } catch (Exception $e) {
392
-            // Don't throw out anything, log at least something.
393
-        }
394
-        PayPalLogger::errorLog("JS Error on transaction: {$txn_id}", $request->postParams(), $payment_method);
395
-    }
396
-
397
-
398
-    /**
399
-     * Filter the Payment Methods list.
400
-     *
401
-     * @param EE_Payment_Method[] $payment_methods
402
-     * @param EE_Transaction      $transaction
403
-     * @param string              $scope @see EEM_Payment_Method::get_all_for_events
404
-     * @return array
405
-     */
406
-    public static function filterPaymentMethods(array $payment_methods, $transaction, $scope): array
407
-    {
408
-        // Don't allow this PM on the checkout page if not Connected.
409
-        foreach ($payment_methods as $key => $pm) {
410
-            // It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
411
-            if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
412
-                unset($payment_methods[ $key ]);
413
-            }
414
-        }
415
-        return $payment_methods;
416
-    }
417
-
418
-
419
-    /**
420
-     *  Get all active states.
421
-     *
422
-     * @return array
423
-     * @throws EE_Error
424
-     * @throws ReflectionException
425
-     */
426
-    public static function getActiveStates(): array
427
-    {
428
-        $state_options = [];
429
-        $states        = EEM_State::instance()->get_all_active_states();
430
-        if (! empty($states)) {
431
-            foreach ($states as $numeral => $state) {
432
-                if ($state instanceof EE_State) {
433
-                    $state_options[ $numeral ] = $state->abbrev();
434
-                }
435
-            }
436
-        }
437
-        return $state_options;
438
-    }
24
+	/**
25
+	 * @return EED_Module
26
+	 * @throws EE_Error
27
+	 * @throws ReflectionException
28
+	 */
29
+	public static function instance(): EED_Module
30
+	{
31
+		return parent::get_instance(__CLASS__);
32
+	}
33
+
34
+
35
+	/**
36
+	 * Run - initial module setup.
37
+	 *
38
+	 * @param WP $WP
39
+	 * @return void
40
+	 */
41
+	public function run($WP)
42
+	{
43
+	}
44
+
45
+
46
+	/**
47
+	 * For hooking into EE Admin Core and other modules.
48
+	 *
49
+	 * @return void
50
+	 */
51
+	public static function set_hooks_admin(): void
52
+	{
53
+		if (DbStatus::isOnline()) {
54
+			// Create an Order.
55
+			add_action('wp_ajax_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
56
+			add_action('wp_ajax_nopriv_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
57
+			// Capture the Order.
58
+			add_action('wp_ajax_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
59
+			add_action('wp_ajax_nopriv_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
60
+			// Log errors from the JS side.
61
+			add_action('wp_ajax_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
62
+			add_action('wp_ajax_nopriv_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
63
+			// Don't load PM on the front-end if not Connected.
64
+			add_filter(
65
+				'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
66
+				[__CLASS__, 'filterPaymentMethods'],
67
+				10,
68
+				3
69
+			);
70
+		}
71
+	}
72
+
73
+
74
+	/**
75
+	 * Create the order and return its data as JSON.
76
+	 * (AJAX)
77
+	 *
78
+	 * @return void
79
+	 * @throws EE_Error
80
+	 * @throws ReflectionException
81
+	 */
82
+	public static function createOrderRequest(): void
83
+	{
84
+		$paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
85
+		$request     = EED_Module::getRequest();
86
+		$post_params = $request->postParams();
87
+		if (! $paypal_pm instanceof EE_Payment_Method) {
88
+			PayPalLogger::errorLogAndExit(
89
+				esc_html__('Related payment method not found (create Order).', 'event_espresso'),
90
+				$post_params
91
+			);
92
+		}
93
+		$transaction  = EED_PayPalCommerce::getTransaction();
94
+		$billing_info = $post_params['billing_info'] ?? [];
95
+		if ($billing_info) {
96
+			$billing_info_decoded = json_decode(stripslashes($billing_info), true);
97
+			$billing_info = is_array($billing_info_decoded) ? $billing_info_decoded : [];
98
+		}
99
+		if (! $transaction) {
100
+			PayPalLogger::errorLogAndExit(
101
+				esc_html__('Transaction info not found.', 'event_espresso'),
102
+				$post_params,
103
+				$paypal_pm
104
+			);
105
+		}
106
+		$order_data = EED_PayPalCommerce::createOrder($transaction, $billing_info, $paypal_pm);
107
+		wp_send_json($order_data);
108
+	}
109
+
110
+
111
+	/**
112
+	 * Capture the order and return status in JSON.
113
+	 * (AJAX)
114
+	 *
115
+	 * @return void
116
+	 */
117
+	public static function captureOrderRequest(): void
118
+	{
119
+		$error_message = false;
120
+		$paypal_pm     = EED_PayPalCommerce::getPaymentMethod();
121
+		if (! $paypal_pm instanceof EE_Payment_Method) {
122
+			$error_message = esc_html__('Payment method not found (capture Order).', 'event_espresso');
123
+		}
124
+		$transaction = EED_PayPalCommerce::getTransaction();
125
+		if (! $transaction) {
126
+			$error_message = esc_html__('Transaction not found.', 'event_espresso');
127
+		}
128
+		$order_id = EED_Module::getRequest()->getRequestParam('order_id', '', DataType::STRING);
129
+		if (! $order_id) {
130
+			$error_message = esc_html__('Order ID missing.', 'event_espresso');
131
+		}
132
+		// We had an error. Log and EXIT.
133
+		if ($error_message) {
134
+			PayPalLogger::errorLogAndExit($error_message, EED_Module::getRequest()->postParams(), $paypal_pm);
135
+		}
136
+		$capture_response = EED_PayPalCommerce::captureOrder($transaction, $paypal_pm, $order_id);
137
+		wp_send_json($capture_response);
138
+	}
139
+
140
+
141
+	/**
142
+	 * Create a new Order using the PP API.
143
+	 *
144
+	 * @param EE_Transaction    $transaction
145
+	 * @param array             $billing_info
146
+	 * @param EE_Payment_Method $paypal_pm
147
+	 * @return array
148
+	 * @throws EE_Error
149
+	 * @throws ReflectionException
150
+	 */
151
+	public static function createOrder(
152
+		EE_Transaction $transaction,
153
+		array $billing_info,
154
+		EE_Payment_Method $paypal_pm
155
+	): array {
156
+		$create_order_api = EED_PayPalCommerce::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
157
+		if (! $create_order_api instanceof CreateOrder) {
158
+			return [
159
+				'error'   => 'CREATE_ORDER_API_FAULT',
160
+				'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
161
+			];
162
+		}
163
+		$order = $create_order_api->create();
164
+		if (isset($order['error'])) {
165
+			return [
166
+				'error'   => 'CREATE_ORDER_API_RESPONSE_ERROR',
167
+				'message' => $order['message'],
168
+			];
169
+		}
170
+		return [
171
+			'pp_order_id' => $order['id'],
172
+		];
173
+	}
174
+
175
+
176
+	/**
177
+	 * Create a new Order using the PP API.
178
+	 *
179
+	 * @param EE_Transaction    $transaction
180
+	 * @param EE_Payment_Method $paypal_pm
181
+	 * @param string            $order_id
182
+	 * @return array
183
+	 */
184
+	public static function captureOrder(
185
+		EE_Transaction $transaction,
186
+		EE_Payment_Method $paypal_pm,
187
+		string $order_id
188
+	): array {
189
+		$capture_order_api = EED_PayPalCommerce::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
190
+		if (! $capture_order_api instanceof CaptureOrder) {
191
+			return [
192
+				'error'   => 'CAPTURE_ORDER_API_FAULT',
193
+				'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
194
+			];
195
+		}
196
+		$order = $capture_order_api->capture();
197
+		if (isset($order['error'])) {
198
+			return $order;
199
+		}
200
+		// Attach the transaction ID to this order.
201
+		try {
202
+			$order['ee_txn_id'] = $transaction->ID();
203
+		} catch (Exception $e) {
204
+			// Just don't set the txn id.
205
+		}
206
+		// Save this order details.
207
+		PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_LAST_ORDER, $order);
208
+		$nonce = wp_create_nonce(Domain::CAPTURE_ORDER_NONCE_NAME);
209
+		return [
210
+			'pp_order_nonce'         => $nonce,
211
+			'pp_order_id'            => $order['id'],
212
+			'pp_order_status'        => $order['status'],
213
+			'pp_order_amount'        => $order['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
214
+		];
215
+	}
216
+
217
+
218
+	/**
219
+	 * Create an Order for this transaction.
220
+	 *
221
+	 * @param EE_Transaction    $transaction
222
+	 * @param array             $billing_info
223
+	 * @param EE_Payment_Method $paypal_pm
224
+	 * @return CreateOrder|null
225
+	 */
226
+	public static function getCreateOrderApi(
227
+		EE_Transaction $transaction,
228
+		array $billing_info,
229
+		EE_Payment_Method $paypal_pm
230
+	): ?CreateOrder {
231
+		$paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
232
+		if (! $paypal_api instanceof PayPalApi) {
233
+			return null;
234
+		}
235
+		return new CreateOrder($paypal_api, $transaction, $billing_info);
236
+	}
237
+
238
+
239
+	/**
240
+	 * Create an Order for this transaction.
241
+	 *
242
+	 * @param EE_Transaction    $transaction
243
+	 * @param EE_Payment_Method $paypal_pm
244
+	 * @param string            $order_id
245
+	 * @return CaptureOrder|null
246
+	 */
247
+	public static function getCaptureOrderApi(
248
+		EE_Transaction $transaction,
249
+		EE_Payment_Method $paypal_pm,
250
+		string $order_id
251
+	): ?CaptureOrder {
252
+		$paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
253
+		if (! $paypal_api instanceof PayPalApi) {
254
+			return null;
255
+		}
256
+		return new CaptureOrder($paypal_api, $transaction, $order_id);
257
+	}
258
+
259
+
260
+	/**
261
+	 * Return a PayPal API object, or false on failure.
262
+	 *
263
+	 * @param EE_Payment_Method $paypal_pm
264
+	 * @return PayPalApi|null
265
+	 * @throws EE_Error
266
+	 * @throws ReflectionException
267
+	 */
268
+	public static function getPayPalApi(EE_Payment_Method $paypal_pm): ?PayPalApi
269
+	{
270
+		// Try getting the first party credentials to determine if this is a first party integration that's active.
271
+		$client_id     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_ID);
272
+		$client_secret = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_SECRET);
273
+		$bn_code       = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
274
+		if ($client_id && $client_secret) {
275
+			return new FirstPartyPayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
276
+		}
277
+		// Third party integration credentials:
278
+		$access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
279
+		if (! $access_token || ! $bn_code) {
280
+			return null;
281
+		}
282
+		$partner_client_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_CLIENT_ID) ?: '';
283
+		$payer_id          = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_MERCHANT_ID) ?: '';
284
+		return new ThirdPartyPayPalApi($access_token, $bn_code, $partner_client_id, $payer_id, $paypal_pm->debug_mode());
285
+	}
286
+
287
+
288
+	/**
289
+	 * Requests a client token.
290
+	 *
291
+	 * @param EE_Payment_Method $paypal_pm
292
+	 * @return array
293
+	 */
294
+	public static function requestClientToken(EE_Payment_Method $paypal_pm): array
295
+	{
296
+		$error = [
297
+			'error' => 'GET_CLIENT_TOKEN_FAULT'
298
+		];
299
+		$paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
300
+		if (! $paypal_api instanceof PayPalApi) {
301
+			$error['message'] = esc_html__('Got an error while trying to get the client token.', 'event_espresso');
302
+			return $error;
303
+		}
304
+		$client_token_api = new ClientToken($paypal_api, $paypal_pm->debug_mode());
305
+		$client_token = $client_token_api->getToken();
306
+		if (isset($client_token['error'])) {
307
+			return $client_token;
308
+		}
309
+		if (empty($client_token)) {
310
+			$error['message'] = esc_html__('Client token not valid.', 'event_espresso');
311
+			return $error;
312
+		}
313
+		return $client_token;
314
+	}
315
+
316
+
317
+	/**
318
+	 * Retrieve the payment method from the provided data.
319
+	 *
320
+	 * @return EE_Transaction|null
321
+	 */
322
+	public static function getTransaction(): ?EE_Transaction
323
+	{
324
+		try {
325
+			$txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
326
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
327
+			if (! $transaction instanceof EE_Transaction) {
328
+				PayPalLogger::errorLog(
329
+					esc_html__('No transaction found by ID:', 'event_espresso'),
330
+					EED_Module::getRequest()->postParams()
331
+				);
332
+				return null;
333
+			}
334
+		} catch (Exception $e) {
335
+			return null;
336
+		}
337
+		return $transaction;
338
+	}
339
+
340
+
341
+	/**
342
+	 * Return a PayPal API object, or false on failure.
343
+	 *
344
+	 * @param EE_Payment_Method $paypal_pm
345
+	 * @return bool
346
+	 */
347
+	public static function isThirdParty(EE_Payment_Method $paypal_pm): bool
348
+	{
349
+		$pp_meta_data = PayPalExtraMetaManager::getAllData($paypal_pm);
350
+		return ! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
351
+			&& ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ]);
352
+	}
353
+
354
+
355
+	/**
356
+	 * Retrieve the payment method from the provided data.
357
+	 *
358
+	 * @return EE_Payment_Method|null
359
+	 */
360
+	public static function getPaymentMethod(): ?EE_Payment_Method
361
+	{
362
+		try {
363
+			// Check if all required parameters are present.
364
+			$pm_slug        = EED_Module::getRequest()->getRequestParam('payment_method');
365
+			$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_slug);
366
+			if ($payment_method instanceof EE_Payment_Method) {
367
+				return $payment_method;
368
+			}
369
+		} catch (Exception $e) {
370
+			return null;
371
+		}
372
+		return null;
373
+	}
374
+
375
+
376
+	/**
377
+	 * Log JS error.
378
+	 *
379
+	 * @return void
380
+	 */
381
+	public static function logJsError(): void
382
+	{
383
+		// Default to the "first" PayPal checkout PM.
384
+		$request        = EED_Module::getRequest();
385
+		$pm_slug        = $request->getRequestParam('pm_slug', Domain::PM_SLUG);
386
+		$payment_method = null;
387
+		$txn_id         = 'unknown';
388
+		try {
389
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pm_slug);
390
+			$txn_id         = sanitize_text_field($request->getRequestParam('txn_id', '-'));
391
+		} catch (Exception $e) {
392
+			// Don't throw out anything, log at least something.
393
+		}
394
+		PayPalLogger::errorLog("JS Error on transaction: {$txn_id}", $request->postParams(), $payment_method);
395
+	}
396
+
397
+
398
+	/**
399
+	 * Filter the Payment Methods list.
400
+	 *
401
+	 * @param EE_Payment_Method[] $payment_methods
402
+	 * @param EE_Transaction      $transaction
403
+	 * @param string              $scope @see EEM_Payment_Method::get_all_for_events
404
+	 * @return array
405
+	 */
406
+	public static function filterPaymentMethods(array $payment_methods, $transaction, $scope): array
407
+	{
408
+		// Don't allow this PM on the checkout page if not Connected.
409
+		foreach ($payment_methods as $key => $pm) {
410
+			// It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
411
+			if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
412
+				unset($payment_methods[ $key ]);
413
+			}
414
+		}
415
+		return $payment_methods;
416
+	}
417
+
418
+
419
+	/**
420
+	 *  Get all active states.
421
+	 *
422
+	 * @return array
423
+	 * @throws EE_Error
424
+	 * @throws ReflectionException
425
+	 */
426
+	public static function getActiveStates(): array
427
+	{
428
+		$state_options = [];
429
+		$states        = EEM_State::instance()->get_all_active_states();
430
+		if (! empty($states)) {
431
+			foreach ($states as $numeral => $state) {
432
+				if ($state instanceof EE_State) {
433
+					$state_options[ $numeral ] = $state->abbrev();
434
+				}
435
+			}
436
+		}
437
+		return $state_options;
438
+	}
439 439
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
         $paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
85 85
         $request     = EED_Module::getRequest();
86 86
         $post_params = $request->postParams();
87
-        if (! $paypal_pm instanceof EE_Payment_Method) {
87
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
88 88
             PayPalLogger::errorLogAndExit(
89 89
                 esc_html__('Related payment method not found (create Order).', 'event_espresso'),
90 90
                 $post_params
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
             $billing_info_decoded = json_decode(stripslashes($billing_info), true);
97 97
             $billing_info = is_array($billing_info_decoded) ? $billing_info_decoded : [];
98 98
         }
99
-        if (! $transaction) {
99
+        if ( ! $transaction) {
100 100
             PayPalLogger::errorLogAndExit(
101 101
                 esc_html__('Transaction info not found.', 'event_espresso'),
102 102
                 $post_params,
@@ -118,15 +118,15 @@  discard block
 block discarded – undo
118 118
     {
119 119
         $error_message = false;
120 120
         $paypal_pm     = EED_PayPalCommerce::getPaymentMethod();
121
-        if (! $paypal_pm instanceof EE_Payment_Method) {
121
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
122 122
             $error_message = esc_html__('Payment method not found (capture Order).', 'event_espresso');
123 123
         }
124 124
         $transaction = EED_PayPalCommerce::getTransaction();
125
-        if (! $transaction) {
125
+        if ( ! $transaction) {
126 126
             $error_message = esc_html__('Transaction not found.', 'event_espresso');
127 127
         }
128 128
         $order_id = EED_Module::getRequest()->getRequestParam('order_id', '', DataType::STRING);
129
-        if (! $order_id) {
129
+        if ( ! $order_id) {
130 130
             $error_message = esc_html__('Order ID missing.', 'event_espresso');
131 131
         }
132 132
         // We had an error. Log and EXIT.
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
         EE_Payment_Method $paypal_pm
155 155
     ): array {
156 156
         $create_order_api = EED_PayPalCommerce::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
157
-        if (! $create_order_api instanceof CreateOrder) {
157
+        if ( ! $create_order_api instanceof CreateOrder) {
158 158
             return [
159 159
                 'error'   => 'CREATE_ORDER_API_FAULT',
160 160
                 'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
@@ -187,7 +187,7 @@  discard block
 block discarded – undo
187 187
         string $order_id
188 188
     ): array {
189 189
         $capture_order_api = EED_PayPalCommerce::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
190
-        if (! $capture_order_api instanceof CaptureOrder) {
190
+        if ( ! $capture_order_api instanceof CaptureOrder) {
191 191
             return [
192 192
                 'error'   => 'CAPTURE_ORDER_API_FAULT',
193 193
                 'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
         EE_Payment_Method $paypal_pm
230 230
     ): ?CreateOrder {
231 231
         $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
232
-        if (! $paypal_api instanceof PayPalApi) {
232
+        if ( ! $paypal_api instanceof PayPalApi) {
233 233
             return null;
234 234
         }
235 235
         return new CreateOrder($paypal_api, $transaction, $billing_info);
@@ -250,7 +250,7 @@  discard block
 block discarded – undo
250 250
         string $order_id
251 251
     ): ?CaptureOrder {
252 252
         $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
253
-        if (! $paypal_api instanceof PayPalApi) {
253
+        if ( ! $paypal_api instanceof PayPalApi) {
254 254
             return null;
255 255
         }
256 256
         return new CaptureOrder($paypal_api, $transaction, $order_id);
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
         }
277 277
         // Third party integration credentials:
278 278
         $access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
279
-        if (! $access_token || ! $bn_code) {
279
+        if ( ! $access_token || ! $bn_code) {
280 280
             return null;
281 281
         }
282 282
         $partner_client_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_CLIENT_ID) ?: '';
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
             'error' => 'GET_CLIENT_TOKEN_FAULT'
298 298
         ];
299 299
         $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
300
-        if (! $paypal_api instanceof PayPalApi) {
300
+        if ( ! $paypal_api instanceof PayPalApi) {
301 301
             $error['message'] = esc_html__('Got an error while trying to get the client token.', 'event_espresso');
302 302
             return $error;
303 303
         }
@@ -324,7 +324,7 @@  discard block
 block discarded – undo
324 324
         try {
325 325
             $txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
326 326
             $transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
327
-            if (! $transaction instanceof EE_Transaction) {
327
+            if ( ! $transaction instanceof EE_Transaction) {
328 328
                 PayPalLogger::errorLog(
329 329
                     esc_html__('No transaction found by ID:', 'event_espresso'),
330 330
                     EED_Module::getRequest()->postParams()
@@ -347,8 +347,8 @@  discard block
 block discarded – undo
347 347
     public static function isThirdParty(EE_Payment_Method $paypal_pm): bool
348 348
     {
349 349
         $pp_meta_data = PayPalExtraMetaManager::getAllData($paypal_pm);
350
-        return ! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
351
-            && ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ]);
350
+        return ! empty($pp_meta_data[Domain::META_KEY_SELLER_MERCHANT_ID])
351
+            && ! empty($pp_meta_data[Domain::META_KEY_ACCESS_TOKEN]);
352 352
     }
353 353
 
354 354
 
@@ -409,7 +409,7 @@  discard block
 block discarded – undo
409 409
         foreach ($payment_methods as $key => $pm) {
410 410
             // It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
411 411
             if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
412
-                unset($payment_methods[ $key ]);
412
+                unset($payment_methods[$key]);
413 413
             }
414 414
         }
415 415
         return $payment_methods;
@@ -427,10 +427,10 @@  discard block
 block discarded – undo
427 427
     {
428 428
         $state_options = [];
429 429
         $states        = EEM_State::instance()->get_all_active_states();
430
-        if (! empty($states)) {
430
+        if ( ! empty($states)) {
431 431
             foreach ($states as $numeral => $state) {
432 432
                 if ($state instanceof EE_State) {
433
-                    $state_options[ $numeral ] = $state->abbrev();
433
+                    $state_options[$numeral] = $state->abbrev();
434 434
                 }
435 435
             }
436 436
         }
Please login to merge, or discard this patch.
admin_pages/general_settings/General_Settings_Admin_Page.core.php 2 patches
Indentation   +1455 added lines, -1455 removed lines patch added patch discarded remove patch
@@ -22,1472 +22,1472 @@
 block discarded – undo
22 22
  */
23 23
 class General_Settings_Admin_Page extends EE_Admin_Page
24 24
 {
25
-    /**
26
-     * @var EE_Core_Config
27
-     */
28
-    public $core_config;
29
-
30
-
31
-    /**
32
-     * Initialize basic properties.
33
-     */
34
-    protected function _init_page_props()
35
-    {
36
-        $this->page_slug        = GEN_SET_PG_SLUG;
37
-        $this->page_label       = GEN_SET_LABEL;
38
-        $this->_admin_base_url  = GEN_SET_ADMIN_URL;
39
-        $this->_admin_base_path = GEN_SET_ADMIN;
40
-
41
-        $this->core_config = EE_Registry::instance()->CFG->core;
42
-    }
43
-
44
-
45
-    /**
46
-     * Set ajax hooks
47
-     */
48
-    protected function _ajax_hooks()
49
-    {
50
-        add_action('wp_ajax_espresso_display_country_settings', [$this, 'display_country_settings']);
51
-        add_action('wp_ajax_espresso_display_country_states', [$this, 'display_country_states']);
52
-        add_action('wp_ajax_espresso_delete_state', [$this, 'delete_state'], 10, 3);
53
-        add_action('wp_ajax_espresso_add_new_state', [$this, 'add_new_state']);
54
-    }
55
-
56
-
57
-    /**
58
-     * More page properties initialization.
59
-     */
60
-    protected function _define_page_props()
61
-    {
62
-        $this->_admin_page_title = GEN_SET_LABEL;
63
-        $this->_labels           = ['publishbox' => esc_html__('Update Settings', 'event_espresso')];
64
-    }
65
-
66
-
67
-    /**
68
-     * Set page routes property.
69
-     */
70
-    protected function _set_page_routes()
71
-    {
72
-        $this->_page_routes = [
73
-            'critical_pages'                => [
74
-                'func'       => [$this, '_espresso_page_settings'],
75
-                'capability' => 'manage_options',
76
-            ],
77
-            'update_espresso_page_settings' => [
78
-                'func'       => [$this, '_update_espresso_page_settings'],
79
-                'capability' => 'manage_options',
80
-                'noheader'   => true,
81
-            ],
82
-            'default'                       => [
83
-                'func'       => [$this, '_your_organization_settings'],
84
-                'capability' => 'manage_options',
85
-            ],
86
-
87
-            'update_your_organization_settings' => [
88
-                'func'       => [$this, '_update_your_organization_settings'],
89
-                'capability' => 'manage_options',
90
-                'noheader'   => true,
91
-            ],
92
-
93
-            'admin_option_settings' => [
94
-                'func'       => [$this, '_admin_option_settings'],
95
-                'capability' => 'manage_options',
96
-            ],
97
-
98
-            'update_admin_option_settings' => [
99
-                'func'       => [$this, '_update_admin_option_settings'],
100
-                'capability' => 'manage_options',
101
-                'noheader'   => true,
102
-            ],
103
-
104
-            'country_settings' => [
105
-                'func'       => [$this, '_country_settings'],
106
-                'capability' => 'manage_options',
107
-            ],
108
-
109
-            'update_country_settings' => [
110
-                'func'       => [$this, '_update_country_settings'],
111
-                'capability' => 'manage_options',
112
-                'noheader'   => true,
113
-            ],
114
-
115
-            'display_country_settings' => [
116
-                'func'       => [$this, 'display_country_settings'],
117
-                'capability' => 'manage_options',
118
-                'noheader'   => true,
119
-            ],
120
-
121
-            'add_new_state' => [
122
-                'func'       => [$this, 'add_new_state'],
123
-                'capability' => 'manage_options',
124
-                'noheader'   => true,
125
-            ],
126
-
127
-            'delete_state'            => [
128
-                'func'       => [$this, 'delete_state'],
129
-                'capability' => 'manage_options',
130
-                'noheader'   => true,
131
-            ],
132
-
133
-            'privacy_settings'        => [
134
-                'func'       => [$this, 'privacySettings'],
135
-                'capability' => 'manage_options',
136
-            ],
137
-
138
-            'update_privacy_settings' => [
139
-                'func'               => [$this, 'updatePrivacySettings'],
140
-                'capability'         => 'manage_options',
141
-                'noheader'           => true,
142
-                'headers_sent_route' => 'privacy_settings',
143
-            ],
144
-
145
-            'set_font_size'            => [
146
-                'func'       => [$this, 'setFontSize'],
147
-                'noheader'   => true,
148
-            ],
149
-        ];
150
-    }
151
-
152
-
153
-    /**
154
-     * Set page configuration property
155
-     */
156
-    protected function _set_page_config()
157
-    {
158
-        $this->_page_config = [
159
-            'critical_pages'        => [
160
-                'nav'           => [
161
-                    'label' => esc_html__('Critical Pages', 'event_espresso'),
162
-                    'icon' => 'dashicons-warning',
163
-                    'order' => 50,
164
-                ],
165
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
166
-                'help_tabs'     => [
167
-                    'general_settings_critical_pages_help_tab' => [
168
-                        'title'    => esc_html__('Critical Pages', 'event_espresso'),
169
-                        'filename' => 'general_settings_critical_pages',
170
-                    ],
171
-                ],
172
-                'require_nonce' => false,
173
-            ],
174
-            'default'               => [
175
-                'nav'           => [
176
-                    'label' => esc_html__('Your Organization', 'event_espresso'),
177
-                    'icon' => 'dashicons-admin-home',
178
-                    'order' => 20,
179
-                ],
180
-                'help_tabs'     => [
181
-                    'general_settings_your_organization_help_tab' => [
182
-                        'title'    => esc_html__('Your Organization', 'event_espresso'),
183
-                        'filename' => 'general_settings_your_organization',
184
-                    ],
185
-                ],
186
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
187
-                'require_nonce' => false,
188
-            ],
189
-            'admin_option_settings' => [
190
-                'nav'           => [
191
-                    'label' => esc_html__('Admin Options', 'event_espresso'),
192
-                    'icon' => 'dashicons-admin-settings',
193
-                    'order' => 60,
194
-                ],
195
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
196
-                'help_tabs'     => [
197
-                    'general_settings_admin_options_help_tab' => [
198
-                        'title'    => esc_html__('Admin Options', 'event_espresso'),
199
-                        'filename' => 'general_settings_admin_options',
200
-                    ],
201
-                ],
202
-                'require_nonce' => false,
203
-            ],
204
-            'country_settings'      => [
205
-                'nav'           => [
206
-                    'label' => esc_html__('Countries', 'event_espresso'),
207
-                    'icon' => 'dashicons-admin-site',
208
-                    'order' => 70,
209
-                ],
210
-                'help_tabs'     => [
211
-                    'general_settings_countries_help_tab' => [
212
-                        'title'    => esc_html__('Countries', 'event_espresso'),
213
-                        'filename' => 'general_settings_countries',
214
-                    ],
215
-                ],
216
-                'require_nonce' => false,
217
-            ],
218
-            'privacy_settings'      => [
219
-                'nav'           => [
220
-                    'label' => esc_html__('Privacy', 'event_espresso'),
221
-                    'icon' => 'dashicons-privacy',
222
-                    'order' => 80,
223
-                ],
224
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
225
-                'require_nonce' => false,
226
-            ],
227
-        ];
228
-    }
229
-
230
-
231
-    protected function _add_screen_options()
232
-    {
233
-    }
234
-
235
-
236
-    protected function _add_feature_pointers()
237
-    {
238
-    }
239
-
240
-
241
-    /**
242
-     * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
243
-     */
244
-    public function load_scripts_styles()
245
-    {
246
-        // styles
247
-        wp_enqueue_style('espresso-ui-theme');
248
-        // scripts
249
-        wp_enqueue_script('ee_admin_js');
250
-    }
251
-
252
-
253
-    /**
254
-     * Execute logic running on `admin_init`
255
-     */
256
-    public function admin_init()
257
-    {
258
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(
259
-            esc_html__(
260
-                'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
261
-                'event_espresso'
262
-            )
263
-        );
264
-        EE_Registry::$i18n_js_strings['error_occurred']          = wp_strip_all_tags(
265
-            esc_html__(
266
-                'An error occurred! Please refresh the page and try again.',
267
-                'event_espresso'
268
-            )
269
-        );
270
-        EE_Registry::$i18n_js_strings['confirm_delete_state']    = wp_strip_all_tags(
271
-            esc_html__(
272
-                'Are you sure you want to delete this State / Province?',
273
-                'event_espresso'
274
-            )
275
-        );
276
-        EE_Registry::$i18n_js_strings['ajax_url']                = admin_url(
277
-            'admin-ajax.php?page=espresso_general_settings',
278
-            is_ssl() ? 'https://' : 'http://'
279
-        );
280
-    }
281
-
282
-
283
-    public function admin_notices()
284
-    {
285
-    }
286
-
287
-
288
-    public function admin_footer_scripts()
289
-    {
290
-    }
291
-
292
-
293
-    /**
294
-     * Enqueue scripts and styles for the default route.
295
-     */
296
-    public function load_scripts_styles_default()
297
-    {
298
-        // styles
299
-        wp_enqueue_style('thickbox');
300
-        // scripts
301
-        wp_enqueue_script('media-upload');
302
-        wp_enqueue_script('thickbox');
303
-        wp_register_script(
304
-            'organization_settings',
305
-            GEN_SET_ASSETS_URL . 'your_organization_settings.js',
306
-            ['jquery', 'media-upload', 'thickbox'],
307
-            EVENT_ESPRESSO_VERSION,
308
-            true
309
-        );
310
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
311
-        wp_enqueue_script('organization_settings');
312
-        wp_enqueue_style('organization-css');
313
-        $confirm_image_delete = [
314
-            'text' => wp_strip_all_tags(
315
-                esc_html__(
316
-                    'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
317
-                    'event_espresso'
318
-                )
319
-            ),
320
-        ];
321
-        wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
322
-    }
323
-
324
-
325
-    /**
326
-     * Enqueue scripts and styles for the country settings route.
327
-     */
328
-    public function load_scripts_styles_country_settings()
329
-    {
330
-        // scripts
331
-        wp_register_script(
332
-            'gen_settings_countries',
333
-            GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
334
-            ['ee_admin_js'],
335
-            EVENT_ESPRESSO_VERSION,
336
-            true
337
-        );
338
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
339
-        wp_enqueue_script('gen_settings_countries');
340
-        wp_enqueue_style('organization-css');
341
-    }
342
-
343
-
344
-    /*************        Espresso Pages        *************/
345
-    /**
346
-     * _espresso_page_settings
347
-     *
348
-     * @throws EE_Error
349
-     * @throws DomainException
350
-     * @throws DomainException
351
-     * @throws InvalidDataTypeException
352
-     * @throws InvalidArgumentException
353
-     */
354
-    protected function _espresso_page_settings()
355
-    {
356
-        // Check to make sure all of the main pages are set up properly,
357
-        // if not create the default pages and display an admin notice
358
-        EEH_Activation::verify_default_pages_exist();
359
-        $this->_transient_garbage_collection();
360
-
361
-        $this->_template_args['values'] = $this->_yes_no_values;
362
-
363
-        $this->_template_args['reg_page_id']  = $this->core_config->reg_page_id ?? null;
364
-        $this->_template_args['reg_page_obj'] = isset($this->core_config->reg_page_id)
365
-            ? get_post($this->core_config->reg_page_id)
366
-            : false;
367
-
368
-        $this->_template_args['txn_page_id']  = $this->core_config->txn_page_id ?? null;
369
-        $this->_template_args['txn_page_obj'] = isset($this->core_config->txn_page_id)
370
-            ? get_post($this->core_config->txn_page_id)
371
-            : false;
372
-
373
-        $this->_template_args['thank_you_page_id']  = $this->core_config->thank_you_page_id ?? null;
374
-        $this->_template_args['thank_you_page_obj'] = isset($this->core_config->thank_you_page_id)
375
-            ? get_post($this->core_config->thank_you_page_id)
376
-            : false;
377
-
378
-        $this->_template_args['cancel_page_id']  = $this->core_config->cancel_page_id ?? null;
379
-        $this->_template_args['cancel_page_obj'] = isset($this->core_config->cancel_page_id)
380
-            ? get_post($this->core_config->cancel_page_id)
381
-            : false;
382
-
383
-        $this->_set_add_edit_form_tags('update_espresso_page_settings');
384
-        $this->_set_publish_post_box_vars();
385
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
386
-            GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
387
-            $this->_template_args,
388
-            true
389
-        );
390
-        $this->display_admin_page_with_sidebar();
391
-    }
392
-
393
-
394
-    /**
395
-     * Handler for updating espresso page settings.
396
-     *
397
-     * @throws EE_Error
398
-     */
399
-    protected function _update_espresso_page_settings()
400
-    {
401
-        $this->core_config = EE_Registry::instance()->CFG->core;
402
-        // capture incoming request data && set page IDs
403
-        $this->core_config->reg_page_id       = $this->request->getRequestParam(
404
-            'reg_page_id',
405
-            $this->core_config->reg_page_id,
406
-            DataType::INT
407
-        );
408
-        $this->core_config->txn_page_id       = $this->request->getRequestParam(
409
-            'txn_page_id',
410
-            $this->core_config->txn_page_id,
411
-            DataType::INT
412
-        );
413
-        $this->core_config->thank_you_page_id = $this->request->getRequestParam(
414
-            'thank_you_page_id',
415
-            $this->core_config->thank_you_page_id,
416
-            DataType::INT
417
-        );
418
-        $this->core_config->cancel_page_id    = $this->request->getRequestParam(
419
-            'cancel_page_id',
420
-            $this->core_config->cancel_page_id,
421
-            DataType::INT
422
-        );
423
-
424
-        $this->core_config = apply_filters(
425
-            'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
426
-            $this->core_config,
427
-            $this->request->requestParams()
428
-        );
429
-
430
-        $what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
431
-        $this->_redirect_after_action(
432
-            $this->_update_espresso_configuration(
433
-                $what,
434
-                $this->core_config,
435
-                __FILE__,
436
-                __FUNCTION__,
437
-                __LINE__
438
-            ),
439
-            $what,
440
-            '',
441
-            [
442
-                'action' => 'critical_pages',
443
-            ],
444
-            true
445
-        );
446
-    }
447
-
448
-
449
-    /*************        Your Organization        *************/
450
-
451
-
452
-    /**
453
-     * @throws DomainException
454
-     * @throws EE_Error
455
-     * @throws InvalidArgumentException
456
-     * @throws InvalidDataTypeException
457
-     * @throws InvalidInterfaceException
458
-     */
459
-    protected function _your_organization_settings()
460
-    {
461
-        $this->_template_args['admin_page_content'] = '';
462
-        try {
463
-            /** @var OrganizationSettings $organization_settings_form */
464
-            $organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
465
-
466
-            $this->_template_args['admin_page_content'] = EEH_HTML::div(
467
-                $organization_settings_form->display(),
468
-                '',
469
-                'padding'
470
-            );
471
-        } catch (Exception $e) {
472
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
473
-        }
474
-        $this->_set_add_edit_form_tags('update_your_organization_settings');
475
-        $this->_set_publish_post_box_vars();
476
-        $this->display_admin_page_with_sidebar();
477
-    }
478
-
479
-
480
-    /**
481
-     * Handler for updating organization settings.
482
-     *
483
-     * @throws EE_Error
484
-     */
485
-    protected function _update_your_organization_settings()
486
-    {
487
-        try {
488
-            /** @var OrganizationSettings $organization_settings_form */
489
-            $organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
490
-
491
-            $success = $organization_settings_form->process($this->request->requestParams());
492
-
493
-            EE_Registry::instance()->CFG = apply_filters(
494
-                'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
495
-                EE_Registry::instance()->CFG
496
-            );
497
-        } catch (Exception $e) {
498
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
499
-            $success = false;
500
-        }
501
-
502
-        if ($success) {
503
-            $success = $this->_update_espresso_configuration(
504
-                esc_html__('Your Organization Settings', 'event_espresso'),
505
-                EE_Registry::instance()->CFG,
506
-                __FILE__,
507
-                __FUNCTION__,
508
-                __LINE__
509
-            );
510
-        }
511
-
512
-        $this->_redirect_after_action($success, '', '', ['action' => 'default'], true);
513
-    }
514
-
515
-
516
-
517
-    /*************        Admin Options        *************/
518
-
519
-
520
-    /**
521
-     * _admin_option_settings
522
-     *
523
-     * @throws EE_Error
524
-     * @throws LogicException
525
-     */
526
-    protected function _admin_option_settings()
527
-    {
528
-        $this->_template_args['admin_page_content'] = '';
529
-        try {
530
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
531
-            // still need this for the old school form in Extend_General_Settings_Admin_Page
532
-            $this->_template_args['values'] = $this->_yes_no_values;
533
-            // also need to account for the do_action that was in the old template
534
-            $admin_options_settings_form->setTemplateArgs($this->_template_args);
535
-            $this->_template_args['admin_page_content'] = EEH_HTML::div(
536
-                $admin_options_settings_form->display(),
537
-                '',
538
-                'padding'
539
-            );
540
-        } catch (Exception $e) {
541
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
542
-        }
543
-        $this->_set_add_edit_form_tags('update_admin_option_settings');
544
-        $this->_set_publish_post_box_vars();
545
-        $this->display_admin_page_with_sidebar();
546
-    }
547
-
548
-
549
-    /**
550
-     * _update_admin_option_settings
551
-     *
552
-     * @throws EE_Error
553
-     * @throws InvalidDataTypeException
554
-     * @throws InvalidFormSubmissionException
555
-     * @throws InvalidArgumentException
556
-     * @throws LogicException
557
-     */
558
-    protected function _update_admin_option_settings()
559
-    {
560
-        try {
561
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
562
-            $admin_options_settings_form->process(
563
-                $this->request->getRequestParam(
564
-                    $admin_options_settings_form->slug(),
565
-                    [],
566
-                    DataType::STRING,
567
-                    true
568
-                )
569
-            );
570
-            EE_Registry::instance()->CFG->admin = apply_filters(
571
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
572
-                EE_Registry::instance()->CFG->admin
573
-            );
574
-        } catch (Exception $e) {
575
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
576
-        }
577
-        $this->_redirect_after_action(
578
-            apply_filters(
579
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
580
-                $this->_update_espresso_configuration(
581
-                    esc_html__('Admin Options', 'event_espresso'),
582
-                    EE_Registry::instance()->CFG->admin,
583
-                    __FILE__,
584
-                    __FUNCTION__,
585
-                    __LINE__
586
-                )
587
-            ),
588
-            esc_html__('Admin Options', 'event_espresso'),
589
-            'updated',
590
-            ['action' => 'admin_option_settings']
591
-        );
592
-    }
593
-
594
-
595
-    /*************        Countries        *************/
596
-
597
-
598
-    /**
599
-     * @param string|null $default
600
-     * @return string
601
-     */
602
-    protected function getCountryISO(?string $default = null): string
603
-    {
604
-        $default = $default ?? $this->getCountryIsoForSite();
605
-        $CNT_ISO = $this->request->getRequestParam('country', $default);
606
-        $CNT_ISO = $this->request->getRequestParam('CNT_ISO', $CNT_ISO);
607
-        return strtoupper($CNT_ISO);
608
-    }
609
-
610
-
611
-    /**
612
-     * @return string
613
-     */
614
-    protected function getCountryIsoForSite(): string
615
-    {
616
-        return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
617
-            ? EE_Registry::instance()->CFG->organization->CNT_ISO
618
-            : 'US';
619
-    }
620
-
621
-
622
-    /**
623
-     * @param string          $CNT_ISO
624
-     * @param EE_Country|null $country
625
-     * @return EE_Base_Class|EE_Country
626
-     * @throws EE_Error
627
-     * @throws InvalidArgumentException
628
-     * @throws InvalidDataTypeException
629
-     * @throws InvalidInterfaceException
630
-     * @throws ReflectionException
631
-     */
632
-    protected function verifyOrGetCountryFromIso(string $CNT_ISO, ?EE_Country $country = null)
633
-    {
634
-        /** @var EE_Country $country */
635
-        return $country instanceof EE_Country && $country->ID() === $CNT_ISO
636
-            ? $country
637
-            : EEM_Country::instance()->get_one_by_ID($CNT_ISO);
638
-    }
639
-
640
-
641
-    /**
642
-     * Output Country Settings view.
643
-     *
644
-     * @throws DomainException
645
-     * @throws EE_Error
646
-     * @throws InvalidArgumentException
647
-     * @throws InvalidDataTypeException
648
-     * @throws InvalidInterfaceException
649
-     * @throws ReflectionException
650
-     */
651
-    protected function _country_settings()
652
-    {
653
-        $CNT_ISO = $this->getCountryISO();
654
-
655
-        $this->_template_args['values']    = $this->_yes_no_values;
656
-        $this->_template_args['countries'] = new EE_Question_Form_Input(
657
-            EE_Question::new_instance(
658
-                [
659
-                  'QST_ID'           => 0,
660
-                  'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
661
-                  'QST_system'       => 'admin-country',
662
-                ]
663
-            ),
664
-            EE_Answer::new_instance(
665
-                [
666
-                    'ANS_ID'    => 0,
667
-                    'ANS_value' => $CNT_ISO,
668
-                ]
669
-            ),
670
-            [
671
-                'input_id'       => 'country',
672
-                'input_name'     => 'country',
673
-                'input_prefix'   => '',
674
-                'append_qstn_id' => false,
675
-            ]
676
-        );
677
-
678
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO);
679
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10);
680
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10);
681
-        $this->_template_args['country_details_settings'] = $this->display_country_settings(
682
-            $country->ID(),
683
-            $country
684
-        );
685
-        $this->_template_args['country_states_settings']  = $this->display_country_states(
686
-            $country->ID(),
687
-            $country
688
-        );
689
-        $this->_template_args['CNT_name_for_site']        = $country->name();
690
-
691
-        $this->_set_add_edit_form_tags('update_country_settings');
692
-        $this->_set_publish_post_box_vars();
693
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
694
-            GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
695
-            $this->_template_args,
696
-            true
697
-        );
698
-        $this->display_admin_page_with_no_sidebar();
699
-    }
700
-
701
-
702
-    /**
703
-     * @param string          $CNT_ISO
704
-     * @param EE_Country|null $country
705
-     * @return string
706
-     * @throws DomainException
707
-     * @throws EE_Error
708
-     * @throws InvalidArgumentException
709
-     * @throws InvalidDataTypeException
710
-     * @throws InvalidInterfaceException
711
-     * @throws ReflectionException
712
-     */
713
-    public function display_country_settings(string $CNT_ISO = '', ?EE_Country $country = null): string
714
-    {
715
-        $CNT_ISO          = $this->getCountryISO($CNT_ISO);
716
-        $CNT_ISO_for_site = $this->getCountryIsoForSite();
717
-
718
-        if (! $CNT_ISO) {
719
-            return '';
720
-        }
721
-
722
-        // for ajax
723
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
724
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
725
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10, 2);
726
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10, 2);
727
-        $country                                  = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
728
-        $CNT_cur_disabled                         = $CNT_ISO !== $CNT_ISO_for_site;
729
-        $this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
730
-
731
-        $country_input_types            = [
732
-            'CNT_active'      => [
733
-                'type'             => 'RADIO_BTN',
734
-                'input_name'       => "cntry[$CNT_ISO]",
735
-                'class'            => '',
736
-                'options'          => $this->_yes_no_values,
737
-                'use_desc_4_label' => true,
738
-            ],
739
-            'CNT_ISO'         => [
740
-                'type'       => 'TEXT',
741
-                'input_name' => "cntry[$CNT_ISO]",
742
-                'class'      => 'ee-input-width--small',
743
-            ],
744
-            'CNT_ISO3'        => [
745
-                'type'       => 'TEXT',
746
-                'input_name' => "cntry[$CNT_ISO]",
747
-                'class'      => 'ee-input-width--small',
748
-            ],
749
-            // 'RGN_ID'          => [
750
-            //     'type'       => 'TEXT',
751
-            //     'input_name' => "cntry[$CNT_ISO]",
752
-            //     'class'      => 'ee-input-width--small',
753
-            // ],
754
-            'CNT_name'        => [
755
-                'type'       => 'TEXT',
756
-                'input_name' => "cntry[$CNT_ISO]",
757
-                'class'      => 'ee-input-width--big',
758
-            ],
759
-            'CNT_cur_code'    => [
760
-                'type'       => 'TEXT',
761
-                'input_name' => "cntry[$CNT_ISO]",
762
-                'class'      => 'ee-input-width--small',
763
-                'disabled'   => $CNT_cur_disabled,
764
-            ],
765
-            'CNT_cur_single'  => [
766
-                'type'       => 'TEXT',
767
-                'input_name' => "cntry[$CNT_ISO]",
768
-                'class'      => 'ee-input-width--reg',
769
-                'disabled'   => $CNT_cur_disabled,
770
-            ],
771
-            'CNT_cur_plural'  => [
772
-                'type'       => 'TEXT',
773
-                'input_name' => "cntry[$CNT_ISO]",
774
-                'class'      => 'ee-input-width--reg',
775
-                'disabled'   => $CNT_cur_disabled,
776
-            ],
777
-            'CNT_cur_sign'    => [
778
-                'type'         => 'TEXT',
779
-                'input_name'   => "cntry[$CNT_ISO]",
780
-                'class'        => 'ee-input-width--small',
781
-                'htmlentities' => false,
782
-                'disabled'     => $CNT_cur_disabled,
783
-            ],
784
-            'CNT_cur_sign_b4' => [
785
-                'type'             => 'RADIO_BTN',
786
-                'input_name'       => "cntry[$CNT_ISO]",
787
-                'class'            => '',
788
-                'options'          => $this->_yes_no_values,
789
-                'use_desc_4_label' => true,
790
-                'disabled'         => $CNT_cur_disabled,
791
-            ],
792
-            'CNT_cur_dec_plc' => [
793
-                'type'       => 'RADIO_BTN',
794
-                'input_name' => "cntry[$CNT_ISO]",
795
-                'class'      => '',
796
-                'options'    => [
797
-                    ['id' => 0, 'text' => ''],
798
-                    ['id' => 1, 'text' => ''],
799
-                    ['id' => 2, 'text' => ''],
800
-                    ['id' => 3, 'text' => ''],
801
-                ],
802
-                'disabled'   => $CNT_cur_disabled,
803
-            ],
804
-            'CNT_cur_dec_mrk' => [
805
-                'type'             => 'RADIO_BTN',
806
-                'input_name'       => "cntry[$CNT_ISO]",
807
-                'class'            => '',
808
-                'options'          => [
809
-                    [
810
-                        'id'   => ',',
811
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
812
-                    ],
813
-                    ['id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')],
814
-                ],
815
-                'use_desc_4_label' => true,
816
-                'disabled'         => $CNT_cur_disabled,
817
-            ],
818
-            'CNT_cur_thsnds'  => [
819
-                'type'             => 'RADIO_BTN',
820
-                'input_name'       => "cntry[$CNT_ISO]",
821
-                'class'            => '',
822
-                'options'          => [
823
-                    [
824
-                        'id'   => ',',
825
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
826
-                    ],
827
-                    [
828
-                        'id'   => '.',
829
-                        'text' => esc_html__('. (decimal)', 'event_espresso'),
830
-                    ],
831
-                    [
832
-                        'id'   => '&nbsp;',
833
-                        'text' => esc_html__('(space)', 'event_espresso'),
834
-                    ],
835
-                    [
836
-                        'id'   => '_',
837
-                        'text' => esc_html__('_ (underscore)', 'event_espresso'),
838
-                    ],
839
-                    [
840
-                        'id'   => "'",
841
-                        'text' => esc_html__("' (apostrophe)", 'event_espresso'),
842
-                    ],
843
-                    [
844
-                        'id'   => "",
845
-                        'text' => esc_html__(" (nothing)", 'event_espresso'),
846
-                    ],
847
-                ],
848
-                'use_desc_4_label' => true,
849
-                'disabled'         => $CNT_cur_disabled,
850
-            ],
851
-            'CNT_tel_code'    => [
852
-                'type'       => 'TEXT',
853
-                'input_name' => "cntry[$CNT_ISO]",
854
-                'class'      => 'ee-input-width--small',
855
-            ],
856
-            'CNT_is_EU'       => [
857
-                'type'             => 'RADIO_BTN',
858
-                'input_name'       => "cntry[$CNT_ISO]",
859
-                'class'            => '',
860
-                'options'          => $this->_yes_no_values,
861
-                'use_desc_4_label' => true,
862
-            ],
863
-        ];
864
-        $this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
865
-            $country,
866
-            $country_input_types
867
-        );
868
-        $country_details_settings       = EEH_Template::display_template(
869
-            GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
870
-            $this->_template_args,
871
-            true
872
-        );
873
-
874
-        if (defined('DOING_AJAX')) {
875
-            $notices = EE_Error::get_notices(false, false, false);
876
-            echo wp_json_encode(
877
-                [
878
-                    'return_data' => $country_details_settings,
879
-                    'success'     => $notices['success'],
880
-                    'errors'      => $notices['errors'],
881
-                ]
882
-            );
883
-            die();
884
-        }
885
-        return $country_details_settings;
886
-    }
887
-
888
-
889
-    /**
890
-     * @param string          $CNT_ISO
891
-     * @param EE_Country|null $country
892
-     * @return string
893
-     * @throws DomainException
894
-     * @throws EE_Error
895
-     * @throws InvalidArgumentException
896
-     * @throws InvalidDataTypeException
897
-     * @throws InvalidInterfaceException
898
-     * @throws ReflectionException
899
-     */
900
-    public function display_country_states(string $CNT_ISO = '', ?EE_Country $country = null): string
901
-    {
902
-        $CNT_ISO = $this->getCountryISO($CNT_ISO);
903
-        if (! $CNT_ISO) {
904
-            return '';
905
-        }
906
-        // for ajax
907
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
908
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
909
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'state_form_field_label_wrap'], 10, 2);
910
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'state_form_field_input__wrap'], 10);
911
-        $states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
912
-        if (empty($states)) {
913
-            /** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
914
-            $countrySubRegionDao = $this->loader->getShared(
915
-                'EventEspresso\core\services\address\CountrySubRegionDao'
916
-            );
917
-            if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
918
-                $country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
919
-                if ($countrySubRegionDao->saveCountrySubRegions($country)) {
920
-                    $states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
921
-                }
922
-            }
923
-        }
924
-        if (is_array($states)) {
925
-            foreach ($states as $STA_ID => $state) {
926
-                if ($state instanceof EE_State) {
927
-                    $inputs = EE_Question_Form_Input::generate_question_form_inputs_for_object(
928
-                        $state,
929
-                        [
930
-                            'STA_abbrev' => [
931
-                                'type'             => 'TEXT',
932
-                                'label'            => esc_html__('Code', 'event_espresso'),
933
-                                'input_name'       => "states[$STA_ID]",
934
-                                'class'            => 'ee-input-width--tiny',
935
-                                'add_mobile_label' => true,
936
-                            ],
937
-                            'STA_name'   => [
938
-                                'type'             => 'TEXT',
939
-                                'label'            => esc_html__('Name', 'event_espresso'),
940
-                                'input_name'       => "states[$STA_ID]",
941
-                                'class'            => 'ee-input-width--big',
942
-                                'add_mobile_label' => true,
943
-                            ],
944
-                            'STA_active' => [
945
-                                'type'             => 'RADIO_BTN',
946
-                                'label'            => esc_html__(
947
-                                    'State Appears in Dropdown Select Lists',
948
-                                    'event_espresso'
949
-                                ),
950
-                                'input_name'       => "states[$STA_ID]",
951
-                                'options'          => $this->_yes_no_values,
952
-                                'use_desc_4_label' => true,
953
-                                'add_mobile_label' => true,
954
-                            ],
955
-                        ]
956
-                    );
957
-
958
-                    $delete_state_url = EE_Admin_Page::add_query_args_and_nonce(
959
-                        [
960
-                            'action'     => 'delete_state',
961
-                            'STA_ID'     => $STA_ID,
962
-                            'CNT_ISO'    => $CNT_ISO,
963
-                            'STA_abbrev' => $state->abbrev(),
964
-                        ],
965
-                        GEN_SET_ADMIN_URL
966
-                    );
967
-
968
-                    $this->_template_args['states'][ $STA_ID ]['inputs']           = $inputs;
969
-                    $this->_template_args['states'][ $STA_ID ]['delete_state_url'] = $delete_state_url;
970
-                }
971
-            }
972
-        } else {
973
-            $this->_template_args['states'] = false;
974
-        }
975
-
976
-        $this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
977
-            ['action' => 'add_new_state'],
978
-            GEN_SET_ADMIN_URL
979
-        );
980
-
981
-        $state_details_settings = EEH_Template::display_template(
982
-            GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
983
-            $this->_template_args,
984
-            true
985
-        );
986
-
987
-        if (defined('DOING_AJAX')) {
988
-            $notices = EE_Error::get_notices(false, false, false);
989
-            echo wp_json_encode(
990
-                [
991
-                    'return_data' => $state_details_settings,
992
-                    'success'     => $notices['success'],
993
-                    'errors'      => $notices['errors'],
994
-                ]
995
-            );
996
-            die();
997
-        }
998
-        return $state_details_settings;
999
-    }
1000
-
1001
-
1002
-    /**
1003
-     * @return void
1004
-     * @throws EE_Error
1005
-     * @throws InvalidArgumentException
1006
-     * @throws InvalidDataTypeException
1007
-     * @throws InvalidInterfaceException
1008
-     * @throws ReflectionException
1009
-     */
1010
-    public function add_new_state()
1011
-    {
1012
-        $success = true;
1013
-        $CNT_ISO = $this->getCountryISO('');
1014
-        if (! $CNT_ISO) {
1015
-            EE_Error::add_error(
1016
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1017
-                __FILE__,
1018
-                __FUNCTION__,
1019
-                __LINE__
1020
-            );
1021
-            $success = false;
1022
-        }
1023
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1024
-        if (! $STA_abbrev) {
1025
-            EE_Error::add_error(
1026
-                esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1027
-                __FILE__,
1028
-                __FUNCTION__,
1029
-                __LINE__
1030
-            );
1031
-            $success = false;
1032
-        }
1033
-        $STA_name = $this->request->getRequestParam('STA_name');
1034
-        if (! $STA_name) {
1035
-            EE_Error::add_error(
1036
-                esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1037
-                __FILE__,
1038
-                __FUNCTION__,
1039
-                __LINE__
1040
-            );
1041
-            $success = false;
1042
-        }
1043
-
1044
-        if ($success) {
1045
-            $cols_n_values = [
1046
-                'CNT_ISO'    => $CNT_ISO,
1047
-                'STA_abbrev' => $STA_abbrev,
1048
-                'STA_name'   => $STA_name,
1049
-                'STA_active' => true,
1050
-            ];
1051
-            $success       = EEM_State::instance()->insert($cols_n_values);
1052
-            EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1053
-        }
1054
-
1055
-        if (defined('DOING_AJAX')) {
1056
-            $notices = EE_Error::get_notices(false, false, false);
1057
-            echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1058
-            die();
1059
-        }
1060
-        $this->_redirect_after_action(
1061
-            $success,
1062
-            esc_html__('State', 'event_espresso'),
1063
-            'added',
1064
-            ['action' => 'country_settings']
1065
-        );
1066
-    }
1067
-
1068
-
1069
-    /**
1070
-     * @return void
1071
-     * @throws EE_Error
1072
-     * @throws InvalidArgumentException
1073
-     * @throws InvalidDataTypeException
1074
-     * @throws InvalidInterfaceException
1075
-     * @throws ReflectionException
1076
-     */
1077
-    public function delete_state()
1078
-    {
1079
-        $CNT_ISO    = $this->getCountryISO();
1080
-        $STA_ID     = $this->request->getRequestParam('STA_ID');
1081
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1082
-
1083
-        if (! $STA_ID) {
1084
-            EE_Error::add_error(
1085
-                esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1086
-                __FILE__,
1087
-                __FUNCTION__,
1088
-                __LINE__
1089
-            );
1090
-            return;
1091
-        }
1092
-
1093
-        $success = EEM_State::instance()->delete_by_ID($STA_ID);
1094
-        if ($success !== false) {
1095
-            do_action(
1096
-                'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1097
-                $CNT_ISO,
1098
-                $STA_ID,
1099
-                ['STA_abbrev' => $STA_abbrev]
1100
-            );
1101
-            EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1102
-        }
1103
-        if (defined('DOING_AJAX')) {
1104
-            $notices                = EE_Error::get_notices(false);
1105
-            $notices['return_data'] = true;
1106
-            echo wp_json_encode($notices);
1107
-            die();
1108
-        }
1109
-        $this->_redirect_after_action(
1110
-            $success,
1111
-            esc_html__('State', 'event_espresso'),
1112
-            'deleted',
1113
-            ['action' => 'country_settings']
1114
-        );
1115
-    }
1116
-
1117
-
1118
-    /**
1119
-     * @return void
1120
-     * @throws EE_Error
1121
-     * @throws InvalidArgumentException
1122
-     * @throws InvalidDataTypeException
1123
-     * @throws InvalidInterfaceException
1124
-     * @throws ReflectionException
1125
-     */
1126
-    protected function _update_country_settings()
1127
-    {
1128
-        $CNT_ISO = $this->getCountryISO();
1129
-        if (! $CNT_ISO) {
1130
-            EE_Error::add_error(
1131
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1132
-                __FILE__,
1133
-                __FUNCTION__,
1134
-                __LINE__
1135
-            );
1136
-            return;
1137
-        }
1138
-
1139
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1140
-
1141
-        $cols_n_values                    = [];
1142
-        $cols_n_values['CNT_ISO3']        = strtoupper(
1143
-            $this->request->getRequestParam(
1144
-                "cntry[$CNT_ISO][CNT_ISO3]",
1145
-                $country->ISO3()
1146
-            )
1147
-        );
1148
-        $cols_n_values['CNT_name']        = $this->request->getRequestParam(
1149
-            "cntry[$CNT_ISO][CNT_name]",
1150
-            $country->name()
1151
-        );
1152
-        $cols_n_values['CNT_cur_code']    = strtoupper(
1153
-            $this->request->getRequestParam(
1154
-                "cntry[$CNT_ISO][CNT_cur_code]",
1155
-                $country->currency_code()
1156
-            )
1157
-        );
1158
-        $cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1159
-            "cntry[$CNT_ISO][CNT_cur_single]",
1160
-            $country->currency_name_single()
1161
-        );
1162
-        $cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1163
-            "cntry[$CNT_ISO][CNT_cur_plural]",
1164
-            $country->currency_name_plural()
1165
-        );
1166
-        $cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1167
-            "cntry[$CNT_ISO][CNT_cur_sign]",
1168
-            $country->currency_sign()
1169
-        );
1170
-        $cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1171
-            "cntry[$CNT_ISO][CNT_cur_sign_b4]",
1172
-            $country->currency_sign_before(),
1173
-            DataType::BOOL
1174
-        );
1175
-        $cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1176
-            "cntry[$CNT_ISO][CNT_cur_dec_plc]",
1177
-            $country->currency_decimal_places()
1178
-        );
1179
-        $cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1180
-            "cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1181
-            $country->currency_decimal_mark()
1182
-        );
1183
-        $cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1184
-            "cntry[$CNT_ISO][CNT_cur_thsnds]",
1185
-            $country->currency_thousands_separator()
1186
-        );
1187
-        $cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1188
-            "cntry[$CNT_ISO][CNT_tel_code]",
1189
-            $country->telephoneCode()
1190
-        );
1191
-        $cols_n_values['CNT_active']      = $this->request->getRequestParam(
1192
-            "cntry[$CNT_ISO][CNT_active]",
1193
-            $country->isActive(),
1194
-            DataType::BOOL
1195
-        );
1196
-        $cols_n_values['CNT_is_EU']      = $this->request->getRequestParam(
1197
-            "cntry[$CNT_ISO][CNT_is_EU]",
1198
-            $country->isEU(),
1199
-            DataType::BOOL
1200
-        );
1201
-
1202
-        // allow filtering of country data
1203
-        $cols_n_values = apply_filters(
1204
-            'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1205
-            $cols_n_values
1206
-        );
1207
-
1208
-        // where values
1209
-        $where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1210
-        // run the update
1211
-        $success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1212
-
1213
-        // allow filtering of states data
1214
-        $states = apply_filters(
1215
-            'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1216
-            $this->request->getRequestParam('states', [], DataType::STRING, true)
1217
-        );
1218
-
1219
-        if (! empty($states) && $success !== false) {
1220
-            // loop thru state data ( looks like : states[75][STA_name] )
1221
-            foreach ($states as $STA_ID => $state) {
1222
-                $cols_n_values = [
1223
-                    'CNT_ISO'    => $CNT_ISO,
1224
-                    'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1225
-                    'STA_name'   => sanitize_text_field($state['STA_name']),
1226
-                    'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1227
-                ];
1228
-                // where values
1229
-                $where_cols_n_values = [['STA_ID' => $STA_ID]];
1230
-                // run the update
1231
-                $success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1232
-                if ($success !== false) {
1233
-                    do_action(
1234
-                        'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1235
-                        $CNT_ISO,
1236
-                        $STA_ID,
1237
-                        $cols_n_values
1238
-                    );
1239
-                }
1240
-            }
1241
-        }
1242
-        // check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1243
-        if (
1244
-            isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1245
-            && $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1246
-        ) {
1247
-            EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1248
-            EE_Registry::instance()->CFG->update_espresso_config();
1249
-        }
1250
-
1251
-        if ($success !== false) {
1252
-            EE_Error::add_success(
1253
-                esc_html__('Country Settings updated successfully.', 'event_espresso')
1254
-            );
1255
-        }
1256
-        $this->_redirect_after_action(
1257
-            $success,
1258
-            '',
1259
-            '',
1260
-            ['action' => 'country_settings', 'country' => $CNT_ISO],
1261
-            true
1262
-        );
1263
-    }
1264
-
1265
-
1266
-    /**
1267
-     * form_form_field_label_wrap
1268
-     *
1269
-     * @param string $label
1270
-     * @return string
1271
-     */
1272
-    public function country_form_field_label_wrap(string $label): string
1273
-    {
1274
-        return '
25
+	/**
26
+	 * @var EE_Core_Config
27
+	 */
28
+	public $core_config;
29
+
30
+
31
+	/**
32
+	 * Initialize basic properties.
33
+	 */
34
+	protected function _init_page_props()
35
+	{
36
+		$this->page_slug        = GEN_SET_PG_SLUG;
37
+		$this->page_label       = GEN_SET_LABEL;
38
+		$this->_admin_base_url  = GEN_SET_ADMIN_URL;
39
+		$this->_admin_base_path = GEN_SET_ADMIN;
40
+
41
+		$this->core_config = EE_Registry::instance()->CFG->core;
42
+	}
43
+
44
+
45
+	/**
46
+	 * Set ajax hooks
47
+	 */
48
+	protected function _ajax_hooks()
49
+	{
50
+		add_action('wp_ajax_espresso_display_country_settings', [$this, 'display_country_settings']);
51
+		add_action('wp_ajax_espresso_display_country_states', [$this, 'display_country_states']);
52
+		add_action('wp_ajax_espresso_delete_state', [$this, 'delete_state'], 10, 3);
53
+		add_action('wp_ajax_espresso_add_new_state', [$this, 'add_new_state']);
54
+	}
55
+
56
+
57
+	/**
58
+	 * More page properties initialization.
59
+	 */
60
+	protected function _define_page_props()
61
+	{
62
+		$this->_admin_page_title = GEN_SET_LABEL;
63
+		$this->_labels           = ['publishbox' => esc_html__('Update Settings', 'event_espresso')];
64
+	}
65
+
66
+
67
+	/**
68
+	 * Set page routes property.
69
+	 */
70
+	protected function _set_page_routes()
71
+	{
72
+		$this->_page_routes = [
73
+			'critical_pages'                => [
74
+				'func'       => [$this, '_espresso_page_settings'],
75
+				'capability' => 'manage_options',
76
+			],
77
+			'update_espresso_page_settings' => [
78
+				'func'       => [$this, '_update_espresso_page_settings'],
79
+				'capability' => 'manage_options',
80
+				'noheader'   => true,
81
+			],
82
+			'default'                       => [
83
+				'func'       => [$this, '_your_organization_settings'],
84
+				'capability' => 'manage_options',
85
+			],
86
+
87
+			'update_your_organization_settings' => [
88
+				'func'       => [$this, '_update_your_organization_settings'],
89
+				'capability' => 'manage_options',
90
+				'noheader'   => true,
91
+			],
92
+
93
+			'admin_option_settings' => [
94
+				'func'       => [$this, '_admin_option_settings'],
95
+				'capability' => 'manage_options',
96
+			],
97
+
98
+			'update_admin_option_settings' => [
99
+				'func'       => [$this, '_update_admin_option_settings'],
100
+				'capability' => 'manage_options',
101
+				'noheader'   => true,
102
+			],
103
+
104
+			'country_settings' => [
105
+				'func'       => [$this, '_country_settings'],
106
+				'capability' => 'manage_options',
107
+			],
108
+
109
+			'update_country_settings' => [
110
+				'func'       => [$this, '_update_country_settings'],
111
+				'capability' => 'manage_options',
112
+				'noheader'   => true,
113
+			],
114
+
115
+			'display_country_settings' => [
116
+				'func'       => [$this, 'display_country_settings'],
117
+				'capability' => 'manage_options',
118
+				'noheader'   => true,
119
+			],
120
+
121
+			'add_new_state' => [
122
+				'func'       => [$this, 'add_new_state'],
123
+				'capability' => 'manage_options',
124
+				'noheader'   => true,
125
+			],
126
+
127
+			'delete_state'            => [
128
+				'func'       => [$this, 'delete_state'],
129
+				'capability' => 'manage_options',
130
+				'noheader'   => true,
131
+			],
132
+
133
+			'privacy_settings'        => [
134
+				'func'       => [$this, 'privacySettings'],
135
+				'capability' => 'manage_options',
136
+			],
137
+
138
+			'update_privacy_settings' => [
139
+				'func'               => [$this, 'updatePrivacySettings'],
140
+				'capability'         => 'manage_options',
141
+				'noheader'           => true,
142
+				'headers_sent_route' => 'privacy_settings',
143
+			],
144
+
145
+			'set_font_size'            => [
146
+				'func'       => [$this, 'setFontSize'],
147
+				'noheader'   => true,
148
+			],
149
+		];
150
+	}
151
+
152
+
153
+	/**
154
+	 * Set page configuration property
155
+	 */
156
+	protected function _set_page_config()
157
+	{
158
+		$this->_page_config = [
159
+			'critical_pages'        => [
160
+				'nav'           => [
161
+					'label' => esc_html__('Critical Pages', 'event_espresso'),
162
+					'icon' => 'dashicons-warning',
163
+					'order' => 50,
164
+				],
165
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
166
+				'help_tabs'     => [
167
+					'general_settings_critical_pages_help_tab' => [
168
+						'title'    => esc_html__('Critical Pages', 'event_espresso'),
169
+						'filename' => 'general_settings_critical_pages',
170
+					],
171
+				],
172
+				'require_nonce' => false,
173
+			],
174
+			'default'               => [
175
+				'nav'           => [
176
+					'label' => esc_html__('Your Organization', 'event_espresso'),
177
+					'icon' => 'dashicons-admin-home',
178
+					'order' => 20,
179
+				],
180
+				'help_tabs'     => [
181
+					'general_settings_your_organization_help_tab' => [
182
+						'title'    => esc_html__('Your Organization', 'event_espresso'),
183
+						'filename' => 'general_settings_your_organization',
184
+					],
185
+				],
186
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
187
+				'require_nonce' => false,
188
+			],
189
+			'admin_option_settings' => [
190
+				'nav'           => [
191
+					'label' => esc_html__('Admin Options', 'event_espresso'),
192
+					'icon' => 'dashicons-admin-settings',
193
+					'order' => 60,
194
+				],
195
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
196
+				'help_tabs'     => [
197
+					'general_settings_admin_options_help_tab' => [
198
+						'title'    => esc_html__('Admin Options', 'event_espresso'),
199
+						'filename' => 'general_settings_admin_options',
200
+					],
201
+				],
202
+				'require_nonce' => false,
203
+			],
204
+			'country_settings'      => [
205
+				'nav'           => [
206
+					'label' => esc_html__('Countries', 'event_espresso'),
207
+					'icon' => 'dashicons-admin-site',
208
+					'order' => 70,
209
+				],
210
+				'help_tabs'     => [
211
+					'general_settings_countries_help_tab' => [
212
+						'title'    => esc_html__('Countries', 'event_espresso'),
213
+						'filename' => 'general_settings_countries',
214
+					],
215
+				],
216
+				'require_nonce' => false,
217
+			],
218
+			'privacy_settings'      => [
219
+				'nav'           => [
220
+					'label' => esc_html__('Privacy', 'event_espresso'),
221
+					'icon' => 'dashicons-privacy',
222
+					'order' => 80,
223
+				],
224
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
225
+				'require_nonce' => false,
226
+			],
227
+		];
228
+	}
229
+
230
+
231
+	protected function _add_screen_options()
232
+	{
233
+	}
234
+
235
+
236
+	protected function _add_feature_pointers()
237
+	{
238
+	}
239
+
240
+
241
+	/**
242
+	 * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
243
+	 */
244
+	public function load_scripts_styles()
245
+	{
246
+		// styles
247
+		wp_enqueue_style('espresso-ui-theme');
248
+		// scripts
249
+		wp_enqueue_script('ee_admin_js');
250
+	}
251
+
252
+
253
+	/**
254
+	 * Execute logic running on `admin_init`
255
+	 */
256
+	public function admin_init()
257
+	{
258
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(
259
+			esc_html__(
260
+				'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
261
+				'event_espresso'
262
+			)
263
+		);
264
+		EE_Registry::$i18n_js_strings['error_occurred']          = wp_strip_all_tags(
265
+			esc_html__(
266
+				'An error occurred! Please refresh the page and try again.',
267
+				'event_espresso'
268
+			)
269
+		);
270
+		EE_Registry::$i18n_js_strings['confirm_delete_state']    = wp_strip_all_tags(
271
+			esc_html__(
272
+				'Are you sure you want to delete this State / Province?',
273
+				'event_espresso'
274
+			)
275
+		);
276
+		EE_Registry::$i18n_js_strings['ajax_url']                = admin_url(
277
+			'admin-ajax.php?page=espresso_general_settings',
278
+			is_ssl() ? 'https://' : 'http://'
279
+		);
280
+	}
281
+
282
+
283
+	public function admin_notices()
284
+	{
285
+	}
286
+
287
+
288
+	public function admin_footer_scripts()
289
+	{
290
+	}
291
+
292
+
293
+	/**
294
+	 * Enqueue scripts and styles for the default route.
295
+	 */
296
+	public function load_scripts_styles_default()
297
+	{
298
+		// styles
299
+		wp_enqueue_style('thickbox');
300
+		// scripts
301
+		wp_enqueue_script('media-upload');
302
+		wp_enqueue_script('thickbox');
303
+		wp_register_script(
304
+			'organization_settings',
305
+			GEN_SET_ASSETS_URL . 'your_organization_settings.js',
306
+			['jquery', 'media-upload', 'thickbox'],
307
+			EVENT_ESPRESSO_VERSION,
308
+			true
309
+		);
310
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
311
+		wp_enqueue_script('organization_settings');
312
+		wp_enqueue_style('organization-css');
313
+		$confirm_image_delete = [
314
+			'text' => wp_strip_all_tags(
315
+				esc_html__(
316
+					'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
317
+					'event_espresso'
318
+				)
319
+			),
320
+		];
321
+		wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
322
+	}
323
+
324
+
325
+	/**
326
+	 * Enqueue scripts and styles for the country settings route.
327
+	 */
328
+	public function load_scripts_styles_country_settings()
329
+	{
330
+		// scripts
331
+		wp_register_script(
332
+			'gen_settings_countries',
333
+			GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
334
+			['ee_admin_js'],
335
+			EVENT_ESPRESSO_VERSION,
336
+			true
337
+		);
338
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
339
+		wp_enqueue_script('gen_settings_countries');
340
+		wp_enqueue_style('organization-css');
341
+	}
342
+
343
+
344
+	/*************        Espresso Pages        *************/
345
+	/**
346
+	 * _espresso_page_settings
347
+	 *
348
+	 * @throws EE_Error
349
+	 * @throws DomainException
350
+	 * @throws DomainException
351
+	 * @throws InvalidDataTypeException
352
+	 * @throws InvalidArgumentException
353
+	 */
354
+	protected function _espresso_page_settings()
355
+	{
356
+		// Check to make sure all of the main pages are set up properly,
357
+		// if not create the default pages and display an admin notice
358
+		EEH_Activation::verify_default_pages_exist();
359
+		$this->_transient_garbage_collection();
360
+
361
+		$this->_template_args['values'] = $this->_yes_no_values;
362
+
363
+		$this->_template_args['reg_page_id']  = $this->core_config->reg_page_id ?? null;
364
+		$this->_template_args['reg_page_obj'] = isset($this->core_config->reg_page_id)
365
+			? get_post($this->core_config->reg_page_id)
366
+			: false;
367
+
368
+		$this->_template_args['txn_page_id']  = $this->core_config->txn_page_id ?? null;
369
+		$this->_template_args['txn_page_obj'] = isset($this->core_config->txn_page_id)
370
+			? get_post($this->core_config->txn_page_id)
371
+			: false;
372
+
373
+		$this->_template_args['thank_you_page_id']  = $this->core_config->thank_you_page_id ?? null;
374
+		$this->_template_args['thank_you_page_obj'] = isset($this->core_config->thank_you_page_id)
375
+			? get_post($this->core_config->thank_you_page_id)
376
+			: false;
377
+
378
+		$this->_template_args['cancel_page_id']  = $this->core_config->cancel_page_id ?? null;
379
+		$this->_template_args['cancel_page_obj'] = isset($this->core_config->cancel_page_id)
380
+			? get_post($this->core_config->cancel_page_id)
381
+			: false;
382
+
383
+		$this->_set_add_edit_form_tags('update_espresso_page_settings');
384
+		$this->_set_publish_post_box_vars();
385
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
386
+			GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
387
+			$this->_template_args,
388
+			true
389
+		);
390
+		$this->display_admin_page_with_sidebar();
391
+	}
392
+
393
+
394
+	/**
395
+	 * Handler for updating espresso page settings.
396
+	 *
397
+	 * @throws EE_Error
398
+	 */
399
+	protected function _update_espresso_page_settings()
400
+	{
401
+		$this->core_config = EE_Registry::instance()->CFG->core;
402
+		// capture incoming request data && set page IDs
403
+		$this->core_config->reg_page_id       = $this->request->getRequestParam(
404
+			'reg_page_id',
405
+			$this->core_config->reg_page_id,
406
+			DataType::INT
407
+		);
408
+		$this->core_config->txn_page_id       = $this->request->getRequestParam(
409
+			'txn_page_id',
410
+			$this->core_config->txn_page_id,
411
+			DataType::INT
412
+		);
413
+		$this->core_config->thank_you_page_id = $this->request->getRequestParam(
414
+			'thank_you_page_id',
415
+			$this->core_config->thank_you_page_id,
416
+			DataType::INT
417
+		);
418
+		$this->core_config->cancel_page_id    = $this->request->getRequestParam(
419
+			'cancel_page_id',
420
+			$this->core_config->cancel_page_id,
421
+			DataType::INT
422
+		);
423
+
424
+		$this->core_config = apply_filters(
425
+			'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
426
+			$this->core_config,
427
+			$this->request->requestParams()
428
+		);
429
+
430
+		$what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
431
+		$this->_redirect_after_action(
432
+			$this->_update_espresso_configuration(
433
+				$what,
434
+				$this->core_config,
435
+				__FILE__,
436
+				__FUNCTION__,
437
+				__LINE__
438
+			),
439
+			$what,
440
+			'',
441
+			[
442
+				'action' => 'critical_pages',
443
+			],
444
+			true
445
+		);
446
+	}
447
+
448
+
449
+	/*************        Your Organization        *************/
450
+
451
+
452
+	/**
453
+	 * @throws DomainException
454
+	 * @throws EE_Error
455
+	 * @throws InvalidArgumentException
456
+	 * @throws InvalidDataTypeException
457
+	 * @throws InvalidInterfaceException
458
+	 */
459
+	protected function _your_organization_settings()
460
+	{
461
+		$this->_template_args['admin_page_content'] = '';
462
+		try {
463
+			/** @var OrganizationSettings $organization_settings_form */
464
+			$organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
465
+
466
+			$this->_template_args['admin_page_content'] = EEH_HTML::div(
467
+				$organization_settings_form->display(),
468
+				'',
469
+				'padding'
470
+			);
471
+		} catch (Exception $e) {
472
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
473
+		}
474
+		$this->_set_add_edit_form_tags('update_your_organization_settings');
475
+		$this->_set_publish_post_box_vars();
476
+		$this->display_admin_page_with_sidebar();
477
+	}
478
+
479
+
480
+	/**
481
+	 * Handler for updating organization settings.
482
+	 *
483
+	 * @throws EE_Error
484
+	 */
485
+	protected function _update_your_organization_settings()
486
+	{
487
+		try {
488
+			/** @var OrganizationSettings $organization_settings_form */
489
+			$organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
490
+
491
+			$success = $organization_settings_form->process($this->request->requestParams());
492
+
493
+			EE_Registry::instance()->CFG = apply_filters(
494
+				'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
495
+				EE_Registry::instance()->CFG
496
+			);
497
+		} catch (Exception $e) {
498
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
499
+			$success = false;
500
+		}
501
+
502
+		if ($success) {
503
+			$success = $this->_update_espresso_configuration(
504
+				esc_html__('Your Organization Settings', 'event_espresso'),
505
+				EE_Registry::instance()->CFG,
506
+				__FILE__,
507
+				__FUNCTION__,
508
+				__LINE__
509
+			);
510
+		}
511
+
512
+		$this->_redirect_after_action($success, '', '', ['action' => 'default'], true);
513
+	}
514
+
515
+
516
+
517
+	/*************        Admin Options        *************/
518
+
519
+
520
+	/**
521
+	 * _admin_option_settings
522
+	 *
523
+	 * @throws EE_Error
524
+	 * @throws LogicException
525
+	 */
526
+	protected function _admin_option_settings()
527
+	{
528
+		$this->_template_args['admin_page_content'] = '';
529
+		try {
530
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
531
+			// still need this for the old school form in Extend_General_Settings_Admin_Page
532
+			$this->_template_args['values'] = $this->_yes_no_values;
533
+			// also need to account for the do_action that was in the old template
534
+			$admin_options_settings_form->setTemplateArgs($this->_template_args);
535
+			$this->_template_args['admin_page_content'] = EEH_HTML::div(
536
+				$admin_options_settings_form->display(),
537
+				'',
538
+				'padding'
539
+			);
540
+		} catch (Exception $e) {
541
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
542
+		}
543
+		$this->_set_add_edit_form_tags('update_admin_option_settings');
544
+		$this->_set_publish_post_box_vars();
545
+		$this->display_admin_page_with_sidebar();
546
+	}
547
+
548
+
549
+	/**
550
+	 * _update_admin_option_settings
551
+	 *
552
+	 * @throws EE_Error
553
+	 * @throws InvalidDataTypeException
554
+	 * @throws InvalidFormSubmissionException
555
+	 * @throws InvalidArgumentException
556
+	 * @throws LogicException
557
+	 */
558
+	protected function _update_admin_option_settings()
559
+	{
560
+		try {
561
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
562
+			$admin_options_settings_form->process(
563
+				$this->request->getRequestParam(
564
+					$admin_options_settings_form->slug(),
565
+					[],
566
+					DataType::STRING,
567
+					true
568
+				)
569
+			);
570
+			EE_Registry::instance()->CFG->admin = apply_filters(
571
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
572
+				EE_Registry::instance()->CFG->admin
573
+			);
574
+		} catch (Exception $e) {
575
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
576
+		}
577
+		$this->_redirect_after_action(
578
+			apply_filters(
579
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
580
+				$this->_update_espresso_configuration(
581
+					esc_html__('Admin Options', 'event_espresso'),
582
+					EE_Registry::instance()->CFG->admin,
583
+					__FILE__,
584
+					__FUNCTION__,
585
+					__LINE__
586
+				)
587
+			),
588
+			esc_html__('Admin Options', 'event_espresso'),
589
+			'updated',
590
+			['action' => 'admin_option_settings']
591
+		);
592
+	}
593
+
594
+
595
+	/*************        Countries        *************/
596
+
597
+
598
+	/**
599
+	 * @param string|null $default
600
+	 * @return string
601
+	 */
602
+	protected function getCountryISO(?string $default = null): string
603
+	{
604
+		$default = $default ?? $this->getCountryIsoForSite();
605
+		$CNT_ISO = $this->request->getRequestParam('country', $default);
606
+		$CNT_ISO = $this->request->getRequestParam('CNT_ISO', $CNT_ISO);
607
+		return strtoupper($CNT_ISO);
608
+	}
609
+
610
+
611
+	/**
612
+	 * @return string
613
+	 */
614
+	protected function getCountryIsoForSite(): string
615
+	{
616
+		return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
617
+			? EE_Registry::instance()->CFG->organization->CNT_ISO
618
+			: 'US';
619
+	}
620
+
621
+
622
+	/**
623
+	 * @param string          $CNT_ISO
624
+	 * @param EE_Country|null $country
625
+	 * @return EE_Base_Class|EE_Country
626
+	 * @throws EE_Error
627
+	 * @throws InvalidArgumentException
628
+	 * @throws InvalidDataTypeException
629
+	 * @throws InvalidInterfaceException
630
+	 * @throws ReflectionException
631
+	 */
632
+	protected function verifyOrGetCountryFromIso(string $CNT_ISO, ?EE_Country $country = null)
633
+	{
634
+		/** @var EE_Country $country */
635
+		return $country instanceof EE_Country && $country->ID() === $CNT_ISO
636
+			? $country
637
+			: EEM_Country::instance()->get_one_by_ID($CNT_ISO);
638
+	}
639
+
640
+
641
+	/**
642
+	 * Output Country Settings view.
643
+	 *
644
+	 * @throws DomainException
645
+	 * @throws EE_Error
646
+	 * @throws InvalidArgumentException
647
+	 * @throws InvalidDataTypeException
648
+	 * @throws InvalidInterfaceException
649
+	 * @throws ReflectionException
650
+	 */
651
+	protected function _country_settings()
652
+	{
653
+		$CNT_ISO = $this->getCountryISO();
654
+
655
+		$this->_template_args['values']    = $this->_yes_no_values;
656
+		$this->_template_args['countries'] = new EE_Question_Form_Input(
657
+			EE_Question::new_instance(
658
+				[
659
+				  'QST_ID'           => 0,
660
+				  'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
661
+				  'QST_system'       => 'admin-country',
662
+				]
663
+			),
664
+			EE_Answer::new_instance(
665
+				[
666
+					'ANS_ID'    => 0,
667
+					'ANS_value' => $CNT_ISO,
668
+				]
669
+			),
670
+			[
671
+				'input_id'       => 'country',
672
+				'input_name'     => 'country',
673
+				'input_prefix'   => '',
674
+				'append_qstn_id' => false,
675
+			]
676
+		);
677
+
678
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO);
679
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10);
680
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10);
681
+		$this->_template_args['country_details_settings'] = $this->display_country_settings(
682
+			$country->ID(),
683
+			$country
684
+		);
685
+		$this->_template_args['country_states_settings']  = $this->display_country_states(
686
+			$country->ID(),
687
+			$country
688
+		);
689
+		$this->_template_args['CNT_name_for_site']        = $country->name();
690
+
691
+		$this->_set_add_edit_form_tags('update_country_settings');
692
+		$this->_set_publish_post_box_vars();
693
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
694
+			GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
695
+			$this->_template_args,
696
+			true
697
+		);
698
+		$this->display_admin_page_with_no_sidebar();
699
+	}
700
+
701
+
702
+	/**
703
+	 * @param string          $CNT_ISO
704
+	 * @param EE_Country|null $country
705
+	 * @return string
706
+	 * @throws DomainException
707
+	 * @throws EE_Error
708
+	 * @throws InvalidArgumentException
709
+	 * @throws InvalidDataTypeException
710
+	 * @throws InvalidInterfaceException
711
+	 * @throws ReflectionException
712
+	 */
713
+	public function display_country_settings(string $CNT_ISO = '', ?EE_Country $country = null): string
714
+	{
715
+		$CNT_ISO          = $this->getCountryISO($CNT_ISO);
716
+		$CNT_ISO_for_site = $this->getCountryIsoForSite();
717
+
718
+		if (! $CNT_ISO) {
719
+			return '';
720
+		}
721
+
722
+		// for ajax
723
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
724
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
725
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10, 2);
726
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10, 2);
727
+		$country                                  = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
728
+		$CNT_cur_disabled                         = $CNT_ISO !== $CNT_ISO_for_site;
729
+		$this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
730
+
731
+		$country_input_types            = [
732
+			'CNT_active'      => [
733
+				'type'             => 'RADIO_BTN',
734
+				'input_name'       => "cntry[$CNT_ISO]",
735
+				'class'            => '',
736
+				'options'          => $this->_yes_no_values,
737
+				'use_desc_4_label' => true,
738
+			],
739
+			'CNT_ISO'         => [
740
+				'type'       => 'TEXT',
741
+				'input_name' => "cntry[$CNT_ISO]",
742
+				'class'      => 'ee-input-width--small',
743
+			],
744
+			'CNT_ISO3'        => [
745
+				'type'       => 'TEXT',
746
+				'input_name' => "cntry[$CNT_ISO]",
747
+				'class'      => 'ee-input-width--small',
748
+			],
749
+			// 'RGN_ID'          => [
750
+			//     'type'       => 'TEXT',
751
+			//     'input_name' => "cntry[$CNT_ISO]",
752
+			//     'class'      => 'ee-input-width--small',
753
+			// ],
754
+			'CNT_name'        => [
755
+				'type'       => 'TEXT',
756
+				'input_name' => "cntry[$CNT_ISO]",
757
+				'class'      => 'ee-input-width--big',
758
+			],
759
+			'CNT_cur_code'    => [
760
+				'type'       => 'TEXT',
761
+				'input_name' => "cntry[$CNT_ISO]",
762
+				'class'      => 'ee-input-width--small',
763
+				'disabled'   => $CNT_cur_disabled,
764
+			],
765
+			'CNT_cur_single'  => [
766
+				'type'       => 'TEXT',
767
+				'input_name' => "cntry[$CNT_ISO]",
768
+				'class'      => 'ee-input-width--reg',
769
+				'disabled'   => $CNT_cur_disabled,
770
+			],
771
+			'CNT_cur_plural'  => [
772
+				'type'       => 'TEXT',
773
+				'input_name' => "cntry[$CNT_ISO]",
774
+				'class'      => 'ee-input-width--reg',
775
+				'disabled'   => $CNT_cur_disabled,
776
+			],
777
+			'CNT_cur_sign'    => [
778
+				'type'         => 'TEXT',
779
+				'input_name'   => "cntry[$CNT_ISO]",
780
+				'class'        => 'ee-input-width--small',
781
+				'htmlentities' => false,
782
+				'disabled'     => $CNT_cur_disabled,
783
+			],
784
+			'CNT_cur_sign_b4' => [
785
+				'type'             => 'RADIO_BTN',
786
+				'input_name'       => "cntry[$CNT_ISO]",
787
+				'class'            => '',
788
+				'options'          => $this->_yes_no_values,
789
+				'use_desc_4_label' => true,
790
+				'disabled'         => $CNT_cur_disabled,
791
+			],
792
+			'CNT_cur_dec_plc' => [
793
+				'type'       => 'RADIO_BTN',
794
+				'input_name' => "cntry[$CNT_ISO]",
795
+				'class'      => '',
796
+				'options'    => [
797
+					['id' => 0, 'text' => ''],
798
+					['id' => 1, 'text' => ''],
799
+					['id' => 2, 'text' => ''],
800
+					['id' => 3, 'text' => ''],
801
+				],
802
+				'disabled'   => $CNT_cur_disabled,
803
+			],
804
+			'CNT_cur_dec_mrk' => [
805
+				'type'             => 'RADIO_BTN',
806
+				'input_name'       => "cntry[$CNT_ISO]",
807
+				'class'            => '',
808
+				'options'          => [
809
+					[
810
+						'id'   => ',',
811
+						'text' => esc_html__(', (comma)', 'event_espresso'),
812
+					],
813
+					['id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')],
814
+				],
815
+				'use_desc_4_label' => true,
816
+				'disabled'         => $CNT_cur_disabled,
817
+			],
818
+			'CNT_cur_thsnds'  => [
819
+				'type'             => 'RADIO_BTN',
820
+				'input_name'       => "cntry[$CNT_ISO]",
821
+				'class'            => '',
822
+				'options'          => [
823
+					[
824
+						'id'   => ',',
825
+						'text' => esc_html__(', (comma)', 'event_espresso'),
826
+					],
827
+					[
828
+						'id'   => '.',
829
+						'text' => esc_html__('. (decimal)', 'event_espresso'),
830
+					],
831
+					[
832
+						'id'   => '&nbsp;',
833
+						'text' => esc_html__('(space)', 'event_espresso'),
834
+					],
835
+					[
836
+						'id'   => '_',
837
+						'text' => esc_html__('_ (underscore)', 'event_espresso'),
838
+					],
839
+					[
840
+						'id'   => "'",
841
+						'text' => esc_html__("' (apostrophe)", 'event_espresso'),
842
+					],
843
+					[
844
+						'id'   => "",
845
+						'text' => esc_html__(" (nothing)", 'event_espresso'),
846
+					],
847
+				],
848
+				'use_desc_4_label' => true,
849
+				'disabled'         => $CNT_cur_disabled,
850
+			],
851
+			'CNT_tel_code'    => [
852
+				'type'       => 'TEXT',
853
+				'input_name' => "cntry[$CNT_ISO]",
854
+				'class'      => 'ee-input-width--small',
855
+			],
856
+			'CNT_is_EU'       => [
857
+				'type'             => 'RADIO_BTN',
858
+				'input_name'       => "cntry[$CNT_ISO]",
859
+				'class'            => '',
860
+				'options'          => $this->_yes_no_values,
861
+				'use_desc_4_label' => true,
862
+			],
863
+		];
864
+		$this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
865
+			$country,
866
+			$country_input_types
867
+		);
868
+		$country_details_settings       = EEH_Template::display_template(
869
+			GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
870
+			$this->_template_args,
871
+			true
872
+		);
873
+
874
+		if (defined('DOING_AJAX')) {
875
+			$notices = EE_Error::get_notices(false, false, false);
876
+			echo wp_json_encode(
877
+				[
878
+					'return_data' => $country_details_settings,
879
+					'success'     => $notices['success'],
880
+					'errors'      => $notices['errors'],
881
+				]
882
+			);
883
+			die();
884
+		}
885
+		return $country_details_settings;
886
+	}
887
+
888
+
889
+	/**
890
+	 * @param string          $CNT_ISO
891
+	 * @param EE_Country|null $country
892
+	 * @return string
893
+	 * @throws DomainException
894
+	 * @throws EE_Error
895
+	 * @throws InvalidArgumentException
896
+	 * @throws InvalidDataTypeException
897
+	 * @throws InvalidInterfaceException
898
+	 * @throws ReflectionException
899
+	 */
900
+	public function display_country_states(string $CNT_ISO = '', ?EE_Country $country = null): string
901
+	{
902
+		$CNT_ISO = $this->getCountryISO($CNT_ISO);
903
+		if (! $CNT_ISO) {
904
+			return '';
905
+		}
906
+		// for ajax
907
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
908
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
909
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'state_form_field_label_wrap'], 10, 2);
910
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'state_form_field_input__wrap'], 10);
911
+		$states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
912
+		if (empty($states)) {
913
+			/** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
914
+			$countrySubRegionDao = $this->loader->getShared(
915
+				'EventEspresso\core\services\address\CountrySubRegionDao'
916
+			);
917
+			if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
918
+				$country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
919
+				if ($countrySubRegionDao->saveCountrySubRegions($country)) {
920
+					$states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
921
+				}
922
+			}
923
+		}
924
+		if (is_array($states)) {
925
+			foreach ($states as $STA_ID => $state) {
926
+				if ($state instanceof EE_State) {
927
+					$inputs = EE_Question_Form_Input::generate_question_form_inputs_for_object(
928
+						$state,
929
+						[
930
+							'STA_abbrev' => [
931
+								'type'             => 'TEXT',
932
+								'label'            => esc_html__('Code', 'event_espresso'),
933
+								'input_name'       => "states[$STA_ID]",
934
+								'class'            => 'ee-input-width--tiny',
935
+								'add_mobile_label' => true,
936
+							],
937
+							'STA_name'   => [
938
+								'type'             => 'TEXT',
939
+								'label'            => esc_html__('Name', 'event_espresso'),
940
+								'input_name'       => "states[$STA_ID]",
941
+								'class'            => 'ee-input-width--big',
942
+								'add_mobile_label' => true,
943
+							],
944
+							'STA_active' => [
945
+								'type'             => 'RADIO_BTN',
946
+								'label'            => esc_html__(
947
+									'State Appears in Dropdown Select Lists',
948
+									'event_espresso'
949
+								),
950
+								'input_name'       => "states[$STA_ID]",
951
+								'options'          => $this->_yes_no_values,
952
+								'use_desc_4_label' => true,
953
+								'add_mobile_label' => true,
954
+							],
955
+						]
956
+					);
957
+
958
+					$delete_state_url = EE_Admin_Page::add_query_args_and_nonce(
959
+						[
960
+							'action'     => 'delete_state',
961
+							'STA_ID'     => $STA_ID,
962
+							'CNT_ISO'    => $CNT_ISO,
963
+							'STA_abbrev' => $state->abbrev(),
964
+						],
965
+						GEN_SET_ADMIN_URL
966
+					);
967
+
968
+					$this->_template_args['states'][ $STA_ID ]['inputs']           = $inputs;
969
+					$this->_template_args['states'][ $STA_ID ]['delete_state_url'] = $delete_state_url;
970
+				}
971
+			}
972
+		} else {
973
+			$this->_template_args['states'] = false;
974
+		}
975
+
976
+		$this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
977
+			['action' => 'add_new_state'],
978
+			GEN_SET_ADMIN_URL
979
+		);
980
+
981
+		$state_details_settings = EEH_Template::display_template(
982
+			GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
983
+			$this->_template_args,
984
+			true
985
+		);
986
+
987
+		if (defined('DOING_AJAX')) {
988
+			$notices = EE_Error::get_notices(false, false, false);
989
+			echo wp_json_encode(
990
+				[
991
+					'return_data' => $state_details_settings,
992
+					'success'     => $notices['success'],
993
+					'errors'      => $notices['errors'],
994
+				]
995
+			);
996
+			die();
997
+		}
998
+		return $state_details_settings;
999
+	}
1000
+
1001
+
1002
+	/**
1003
+	 * @return void
1004
+	 * @throws EE_Error
1005
+	 * @throws InvalidArgumentException
1006
+	 * @throws InvalidDataTypeException
1007
+	 * @throws InvalidInterfaceException
1008
+	 * @throws ReflectionException
1009
+	 */
1010
+	public function add_new_state()
1011
+	{
1012
+		$success = true;
1013
+		$CNT_ISO = $this->getCountryISO('');
1014
+		if (! $CNT_ISO) {
1015
+			EE_Error::add_error(
1016
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1017
+				__FILE__,
1018
+				__FUNCTION__,
1019
+				__LINE__
1020
+			);
1021
+			$success = false;
1022
+		}
1023
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1024
+		if (! $STA_abbrev) {
1025
+			EE_Error::add_error(
1026
+				esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1027
+				__FILE__,
1028
+				__FUNCTION__,
1029
+				__LINE__
1030
+			);
1031
+			$success = false;
1032
+		}
1033
+		$STA_name = $this->request->getRequestParam('STA_name');
1034
+		if (! $STA_name) {
1035
+			EE_Error::add_error(
1036
+				esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1037
+				__FILE__,
1038
+				__FUNCTION__,
1039
+				__LINE__
1040
+			);
1041
+			$success = false;
1042
+		}
1043
+
1044
+		if ($success) {
1045
+			$cols_n_values = [
1046
+				'CNT_ISO'    => $CNT_ISO,
1047
+				'STA_abbrev' => $STA_abbrev,
1048
+				'STA_name'   => $STA_name,
1049
+				'STA_active' => true,
1050
+			];
1051
+			$success       = EEM_State::instance()->insert($cols_n_values);
1052
+			EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1053
+		}
1054
+
1055
+		if (defined('DOING_AJAX')) {
1056
+			$notices = EE_Error::get_notices(false, false, false);
1057
+			echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1058
+			die();
1059
+		}
1060
+		$this->_redirect_after_action(
1061
+			$success,
1062
+			esc_html__('State', 'event_espresso'),
1063
+			'added',
1064
+			['action' => 'country_settings']
1065
+		);
1066
+	}
1067
+
1068
+
1069
+	/**
1070
+	 * @return void
1071
+	 * @throws EE_Error
1072
+	 * @throws InvalidArgumentException
1073
+	 * @throws InvalidDataTypeException
1074
+	 * @throws InvalidInterfaceException
1075
+	 * @throws ReflectionException
1076
+	 */
1077
+	public function delete_state()
1078
+	{
1079
+		$CNT_ISO    = $this->getCountryISO();
1080
+		$STA_ID     = $this->request->getRequestParam('STA_ID');
1081
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1082
+
1083
+		if (! $STA_ID) {
1084
+			EE_Error::add_error(
1085
+				esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1086
+				__FILE__,
1087
+				__FUNCTION__,
1088
+				__LINE__
1089
+			);
1090
+			return;
1091
+		}
1092
+
1093
+		$success = EEM_State::instance()->delete_by_ID($STA_ID);
1094
+		if ($success !== false) {
1095
+			do_action(
1096
+				'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1097
+				$CNT_ISO,
1098
+				$STA_ID,
1099
+				['STA_abbrev' => $STA_abbrev]
1100
+			);
1101
+			EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1102
+		}
1103
+		if (defined('DOING_AJAX')) {
1104
+			$notices                = EE_Error::get_notices(false);
1105
+			$notices['return_data'] = true;
1106
+			echo wp_json_encode($notices);
1107
+			die();
1108
+		}
1109
+		$this->_redirect_after_action(
1110
+			$success,
1111
+			esc_html__('State', 'event_espresso'),
1112
+			'deleted',
1113
+			['action' => 'country_settings']
1114
+		);
1115
+	}
1116
+
1117
+
1118
+	/**
1119
+	 * @return void
1120
+	 * @throws EE_Error
1121
+	 * @throws InvalidArgumentException
1122
+	 * @throws InvalidDataTypeException
1123
+	 * @throws InvalidInterfaceException
1124
+	 * @throws ReflectionException
1125
+	 */
1126
+	protected function _update_country_settings()
1127
+	{
1128
+		$CNT_ISO = $this->getCountryISO();
1129
+		if (! $CNT_ISO) {
1130
+			EE_Error::add_error(
1131
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1132
+				__FILE__,
1133
+				__FUNCTION__,
1134
+				__LINE__
1135
+			);
1136
+			return;
1137
+		}
1138
+
1139
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1140
+
1141
+		$cols_n_values                    = [];
1142
+		$cols_n_values['CNT_ISO3']        = strtoupper(
1143
+			$this->request->getRequestParam(
1144
+				"cntry[$CNT_ISO][CNT_ISO3]",
1145
+				$country->ISO3()
1146
+			)
1147
+		);
1148
+		$cols_n_values['CNT_name']        = $this->request->getRequestParam(
1149
+			"cntry[$CNT_ISO][CNT_name]",
1150
+			$country->name()
1151
+		);
1152
+		$cols_n_values['CNT_cur_code']    = strtoupper(
1153
+			$this->request->getRequestParam(
1154
+				"cntry[$CNT_ISO][CNT_cur_code]",
1155
+				$country->currency_code()
1156
+			)
1157
+		);
1158
+		$cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1159
+			"cntry[$CNT_ISO][CNT_cur_single]",
1160
+			$country->currency_name_single()
1161
+		);
1162
+		$cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1163
+			"cntry[$CNT_ISO][CNT_cur_plural]",
1164
+			$country->currency_name_plural()
1165
+		);
1166
+		$cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1167
+			"cntry[$CNT_ISO][CNT_cur_sign]",
1168
+			$country->currency_sign()
1169
+		);
1170
+		$cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1171
+			"cntry[$CNT_ISO][CNT_cur_sign_b4]",
1172
+			$country->currency_sign_before(),
1173
+			DataType::BOOL
1174
+		);
1175
+		$cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1176
+			"cntry[$CNT_ISO][CNT_cur_dec_plc]",
1177
+			$country->currency_decimal_places()
1178
+		);
1179
+		$cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1180
+			"cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1181
+			$country->currency_decimal_mark()
1182
+		);
1183
+		$cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1184
+			"cntry[$CNT_ISO][CNT_cur_thsnds]",
1185
+			$country->currency_thousands_separator()
1186
+		);
1187
+		$cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1188
+			"cntry[$CNT_ISO][CNT_tel_code]",
1189
+			$country->telephoneCode()
1190
+		);
1191
+		$cols_n_values['CNT_active']      = $this->request->getRequestParam(
1192
+			"cntry[$CNT_ISO][CNT_active]",
1193
+			$country->isActive(),
1194
+			DataType::BOOL
1195
+		);
1196
+		$cols_n_values['CNT_is_EU']      = $this->request->getRequestParam(
1197
+			"cntry[$CNT_ISO][CNT_is_EU]",
1198
+			$country->isEU(),
1199
+			DataType::BOOL
1200
+		);
1201
+
1202
+		// allow filtering of country data
1203
+		$cols_n_values = apply_filters(
1204
+			'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1205
+			$cols_n_values
1206
+		);
1207
+
1208
+		// where values
1209
+		$where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1210
+		// run the update
1211
+		$success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1212
+
1213
+		// allow filtering of states data
1214
+		$states = apply_filters(
1215
+			'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1216
+			$this->request->getRequestParam('states', [], DataType::STRING, true)
1217
+		);
1218
+
1219
+		if (! empty($states) && $success !== false) {
1220
+			// loop thru state data ( looks like : states[75][STA_name] )
1221
+			foreach ($states as $STA_ID => $state) {
1222
+				$cols_n_values = [
1223
+					'CNT_ISO'    => $CNT_ISO,
1224
+					'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1225
+					'STA_name'   => sanitize_text_field($state['STA_name']),
1226
+					'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1227
+				];
1228
+				// where values
1229
+				$where_cols_n_values = [['STA_ID' => $STA_ID]];
1230
+				// run the update
1231
+				$success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1232
+				if ($success !== false) {
1233
+					do_action(
1234
+						'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1235
+						$CNT_ISO,
1236
+						$STA_ID,
1237
+						$cols_n_values
1238
+					);
1239
+				}
1240
+			}
1241
+		}
1242
+		// check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1243
+		if (
1244
+			isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1245
+			&& $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1246
+		) {
1247
+			EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1248
+			EE_Registry::instance()->CFG->update_espresso_config();
1249
+		}
1250
+
1251
+		if ($success !== false) {
1252
+			EE_Error::add_success(
1253
+				esc_html__('Country Settings updated successfully.', 'event_espresso')
1254
+			);
1255
+		}
1256
+		$this->_redirect_after_action(
1257
+			$success,
1258
+			'',
1259
+			'',
1260
+			['action' => 'country_settings', 'country' => $CNT_ISO],
1261
+			true
1262
+		);
1263
+	}
1264
+
1265
+
1266
+	/**
1267
+	 * form_form_field_label_wrap
1268
+	 *
1269
+	 * @param string $label
1270
+	 * @return string
1271
+	 */
1272
+	public function country_form_field_label_wrap(string $label): string
1273
+	{
1274
+		return '
1275 1275
 			<tr>
1276 1276
 				<th>
1277 1277
 					' . $label . '
1278 1278
 				</th>';
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * form_form_field_input__wrap
1284
-     *
1285
-     * @param string $input
1286
-     * @return string
1287
-     */
1288
-    public function country_form_field_input__wrap(string $input): string
1289
-    {
1290
-        return '
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * form_form_field_input__wrap
1284
+	 *
1285
+	 * @param string $input
1286
+	 * @return string
1287
+	 */
1288
+	public function country_form_field_input__wrap(string $input): string
1289
+	{
1290
+		return '
1291 1291
 				<td class="general-settings-country-input-td">
1292 1292
 					' . $input . '
1293 1293
 				</td>
1294 1294
 			</tr>';
1295
-    }
1296
-
1297
-
1298
-    /**
1299
-     * form_form_field_label_wrap
1300
-     *
1301
-     * @param string $label
1302
-     * @param string $required_text
1303
-     * @return string
1304
-     */
1305
-    public function state_form_field_label_wrap(string $label, string $required_text): string
1306
-    {
1307
-        return $required_text;
1308
-    }
1309
-
1310
-
1311
-    /**
1312
-     * form_form_field_input__wrap
1313
-     *
1314
-     * @param string $input
1315
-     * @return string
1316
-     */
1317
-    public function state_form_field_input__wrap(string $input): string
1318
-    {
1319
-        return '
1295
+	}
1296
+
1297
+
1298
+	/**
1299
+	 * form_form_field_label_wrap
1300
+	 *
1301
+	 * @param string $label
1302
+	 * @param string $required_text
1303
+	 * @return string
1304
+	 */
1305
+	public function state_form_field_label_wrap(string $label, string $required_text): string
1306
+	{
1307
+		return $required_text;
1308
+	}
1309
+
1310
+
1311
+	/**
1312
+	 * form_form_field_input__wrap
1313
+	 *
1314
+	 * @param string $input
1315
+	 * @return string
1316
+	 */
1317
+	public function state_form_field_input__wrap(string $input): string
1318
+	{
1319
+		return '
1320 1320
 				<td class="general-settings-country-state-input-td">
1321 1321
 					' . $input . '
1322 1322
 				</td>';
1323
-    }
1324
-
1325
-
1326
-    /***********/
1327
-
1328
-
1329
-    /**
1330
-     * displays edit and view links for critical EE pages
1331
-     *
1332
-     * @param int $ee_page_id
1333
-     * @return string
1334
-     */
1335
-    public static function edit_view_links(int $ee_page_id): string
1336
-    {
1337
-        $edit_url = add_query_arg(
1338
-            ['post' => $ee_page_id, 'action' => 'edit'],
1339
-            admin_url('post.php')
1340
-        );
1341
-        $links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1342
-        $links    .= ' &nbsp;|&nbsp; ';
1343
-        $links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1344
-
1345
-        return $links;
1346
-    }
1347
-
1348
-
1349
-    /**
1350
-     * displays page and shortcode status for critical EE pages
1351
-     *
1352
-     * @param WP_Post $ee_page
1353
-     * @param string  $shortcode
1354
-     * @return string
1355
-     */
1356
-    public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1357
-    {
1358
-        // page status
1359
-        if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1360
-            $pg_class  = 'ee-status-bg--success';
1361
-            $pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1362
-        } else {
1363
-            $pg_class  = 'ee-status-bg--error';
1364
-            $pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1365
-        }
1366
-
1367
-        // shortcode status
1368
-        if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1369
-            $sc_class  = 'ee-status-bg--success';
1370
-            $sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1371
-        } else {
1372
-            $sc_class  = 'ee-status-bg--error';
1373
-            $sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1374
-        }
1375
-
1376
-        return '
1323
+	}
1324
+
1325
+
1326
+	/***********/
1327
+
1328
+
1329
+	/**
1330
+	 * displays edit and view links for critical EE pages
1331
+	 *
1332
+	 * @param int $ee_page_id
1333
+	 * @return string
1334
+	 */
1335
+	public static function edit_view_links(int $ee_page_id): string
1336
+	{
1337
+		$edit_url = add_query_arg(
1338
+			['post' => $ee_page_id, 'action' => 'edit'],
1339
+			admin_url('post.php')
1340
+		);
1341
+		$links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1342
+		$links    .= ' &nbsp;|&nbsp; ';
1343
+		$links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1344
+
1345
+		return $links;
1346
+	}
1347
+
1348
+
1349
+	/**
1350
+	 * displays page and shortcode status for critical EE pages
1351
+	 *
1352
+	 * @param WP_Post $ee_page
1353
+	 * @param string  $shortcode
1354
+	 * @return string
1355
+	 */
1356
+	public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1357
+	{
1358
+		// page status
1359
+		if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1360
+			$pg_class  = 'ee-status-bg--success';
1361
+			$pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1362
+		} else {
1363
+			$pg_class  = 'ee-status-bg--error';
1364
+			$pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1365
+		}
1366
+
1367
+		// shortcode status
1368
+		if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1369
+			$sc_class  = 'ee-status-bg--success';
1370
+			$sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1371
+		} else {
1372
+			$sc_class  = 'ee-status-bg--error';
1373
+			$sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1374
+		}
1375
+
1376
+		return '
1377 1377
         <span class="ee-page-status ' . $pg_class . '"><strong>' . $pg_status . '</strong></span>
1378 1378
         <span class="ee-page-status ' . $sc_class . '"><strong>' . $sc_status . '</strong></span>';
1379
-    }
1380
-
1381
-
1382
-    /**
1383
-     * generates a dropdown of all parent pages - copied from WP core
1384
-     *
1385
-     * @param int  $default
1386
-     * @param int  $parent
1387
-     * @param int  $level
1388
-     * @param bool $echo
1389
-     * @return string;
1390
-     */
1391
-    public static function page_settings_dropdown(
1392
-        int $default = 0,
1393
-        int $parent = 0,
1394
-        int $level = 0,
1395
-        bool $echo = true
1396
-    ): string {
1397
-        global $wpdb;
1398
-        $items  = $wpdb->get_results(
1399
-            $wpdb->prepare(
1400
-                "SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' AND post_status != 'trash' ORDER BY menu_order",
1401
-                $parent
1402
-            )
1403
-        );
1404
-        $output = '';
1405
-
1406
-        if ($items) {
1407
-            $level = absint($level);
1408
-            foreach ($items as $item) {
1409
-                $ID         = absint($item->ID);
1410
-                $post_title = wp_strip_all_tags($item->post_title);
1411
-                $pad        = str_repeat('&nbsp;', $level * 3);
1412
-                $option     = "\n\t";
1413
-                $option     .= '<option class="level-' . $level . '" ';
1414
-                $option     .= 'value="' . $ID . '" ';
1415
-                $option     .= $ID === absint($default) ? ' selected' : '';
1416
-                $option     .= '>';
1417
-                $option     .= "$pad {$post_title}";
1418
-                $option     .= '</option>';
1419
-                $output     .= $option;
1420
-                ob_start();
1421
-                parent_dropdown($default, $item->ID, $level + 1);
1422
-                $output .= ob_get_clean();
1423
-            }
1424
-        }
1425
-        if ($echo) {
1426
-            echo wp_kses($output, AllowedTags::getWithFormTags());
1427
-            return '';
1428
-        }
1429
-        return $output;
1430
-    }
1431
-
1432
-
1433
-    /**
1434
-     * Loads the scripts for the privacy settings form
1435
-     */
1436
-    public function load_scripts_styles_privacy_settings()
1437
-    {
1438
-        $form_handler = $this->loader->getShared(
1439
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1440
-        );
1441
-        $form_handler->enqueueStylesAndScripts();
1442
-    }
1443
-
1444
-
1445
-    /**
1446
-     * display the privacy settings form
1447
-     *
1448
-     * @throws EE_Error
1449
-     */
1450
-    public function privacySettings()
1451
-    {
1452
-        $this->_set_add_edit_form_tags('update_privacy_settings');
1453
-        $this->_set_publish_post_box_vars();
1454
-        $form_handler                               = $this->loader->getShared(
1455
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1456
-        );
1457
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
1458
-            $form_handler->display(),
1459
-            '',
1460
-            'padding'
1461
-        );
1462
-        $this->display_admin_page_with_sidebar();
1463
-    }
1464
-
1465
-
1466
-    /**
1467
-     * Update the privacy settings from form data
1468
-     *
1469
-     * @throws EE_Error
1470
-     */
1471
-    public function updatePrivacySettings()
1472
-    {
1473
-        $form_handler = $this->loader->getShared(
1474
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1475
-        );
1476
-        $success      = $form_handler->process($this->get_request_data());
1477
-        $this->_redirect_after_action(
1478
-            $success,
1479
-            esc_html__('Registration Form Options', 'event_espresso'),
1480
-            'updated',
1481
-            ['action' => 'privacy_settings']
1482
-        );
1483
-    }
1484
-
1485
-
1486
-    public function setFontSize()
1487
-    {
1488
-        AdminFontSize::setAdminFontSize(
1489
-            $this->request->getRequestParam('font_size', AdminFontSize::FONT_SIZE_DEFAULT)
1490
-        );
1491
-        wp_safe_redirect($this->request->getServerParam('HTTP_REFERER'));
1492
-    }
1379
+	}
1380
+
1381
+
1382
+	/**
1383
+	 * generates a dropdown of all parent pages - copied from WP core
1384
+	 *
1385
+	 * @param int  $default
1386
+	 * @param int  $parent
1387
+	 * @param int  $level
1388
+	 * @param bool $echo
1389
+	 * @return string;
1390
+	 */
1391
+	public static function page_settings_dropdown(
1392
+		int $default = 0,
1393
+		int $parent = 0,
1394
+		int $level = 0,
1395
+		bool $echo = true
1396
+	): string {
1397
+		global $wpdb;
1398
+		$items  = $wpdb->get_results(
1399
+			$wpdb->prepare(
1400
+				"SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' AND post_status != 'trash' ORDER BY menu_order",
1401
+				$parent
1402
+			)
1403
+		);
1404
+		$output = '';
1405
+
1406
+		if ($items) {
1407
+			$level = absint($level);
1408
+			foreach ($items as $item) {
1409
+				$ID         = absint($item->ID);
1410
+				$post_title = wp_strip_all_tags($item->post_title);
1411
+				$pad        = str_repeat('&nbsp;', $level * 3);
1412
+				$option     = "\n\t";
1413
+				$option     .= '<option class="level-' . $level . '" ';
1414
+				$option     .= 'value="' . $ID . '" ';
1415
+				$option     .= $ID === absint($default) ? ' selected' : '';
1416
+				$option     .= '>';
1417
+				$option     .= "$pad {$post_title}";
1418
+				$option     .= '</option>';
1419
+				$output     .= $option;
1420
+				ob_start();
1421
+				parent_dropdown($default, $item->ID, $level + 1);
1422
+				$output .= ob_get_clean();
1423
+			}
1424
+		}
1425
+		if ($echo) {
1426
+			echo wp_kses($output, AllowedTags::getWithFormTags());
1427
+			return '';
1428
+		}
1429
+		return $output;
1430
+	}
1431
+
1432
+
1433
+	/**
1434
+	 * Loads the scripts for the privacy settings form
1435
+	 */
1436
+	public function load_scripts_styles_privacy_settings()
1437
+	{
1438
+		$form_handler = $this->loader->getShared(
1439
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1440
+		);
1441
+		$form_handler->enqueueStylesAndScripts();
1442
+	}
1443
+
1444
+
1445
+	/**
1446
+	 * display the privacy settings form
1447
+	 *
1448
+	 * @throws EE_Error
1449
+	 */
1450
+	public function privacySettings()
1451
+	{
1452
+		$this->_set_add_edit_form_tags('update_privacy_settings');
1453
+		$this->_set_publish_post_box_vars();
1454
+		$form_handler                               = $this->loader->getShared(
1455
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1456
+		);
1457
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
1458
+			$form_handler->display(),
1459
+			'',
1460
+			'padding'
1461
+		);
1462
+		$this->display_admin_page_with_sidebar();
1463
+	}
1464
+
1465
+
1466
+	/**
1467
+	 * Update the privacy settings from form data
1468
+	 *
1469
+	 * @throws EE_Error
1470
+	 */
1471
+	public function updatePrivacySettings()
1472
+	{
1473
+		$form_handler = $this->loader->getShared(
1474
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1475
+		);
1476
+		$success      = $form_handler->process($this->get_request_data());
1477
+		$this->_redirect_after_action(
1478
+			$success,
1479
+			esc_html__('Registration Form Options', 'event_espresso'),
1480
+			'updated',
1481
+			['action' => 'privacy_settings']
1482
+		);
1483
+	}
1484
+
1485
+
1486
+	public function setFontSize()
1487
+	{
1488
+		AdminFontSize::setAdminFontSize(
1489
+			$this->request->getRequestParam('font_size', AdminFontSize::FONT_SIZE_DEFAULT)
1490
+		);
1491
+		wp_safe_redirect($this->request->getServerParam('HTTP_REFERER'));
1492
+	}
1493 1493
 }
Please login to merge, or discard this patch.
Spacing   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -261,19 +261,19 @@  discard block
 block discarded – undo
261 261
                 'event_espresso'
262 262
             )
263 263
         );
264
-        EE_Registry::$i18n_js_strings['error_occurred']          = wp_strip_all_tags(
264
+        EE_Registry::$i18n_js_strings['error_occurred'] = wp_strip_all_tags(
265 265
             esc_html__(
266 266
                 'An error occurred! Please refresh the page and try again.',
267 267
                 'event_espresso'
268 268
             )
269 269
         );
270
-        EE_Registry::$i18n_js_strings['confirm_delete_state']    = wp_strip_all_tags(
270
+        EE_Registry::$i18n_js_strings['confirm_delete_state'] = wp_strip_all_tags(
271 271
             esc_html__(
272 272
                 'Are you sure you want to delete this State / Province?',
273 273
                 'event_espresso'
274 274
             )
275 275
         );
276
-        EE_Registry::$i18n_js_strings['ajax_url']                = admin_url(
276
+        EE_Registry::$i18n_js_strings['ajax_url'] = admin_url(
277 277
             'admin-ajax.php?page=espresso_general_settings',
278 278
             is_ssl() ? 'https://' : 'http://'
279 279
         );
@@ -302,12 +302,12 @@  discard block
 block discarded – undo
302 302
         wp_enqueue_script('thickbox');
303 303
         wp_register_script(
304 304
             'organization_settings',
305
-            GEN_SET_ASSETS_URL . 'your_organization_settings.js',
305
+            GEN_SET_ASSETS_URL.'your_organization_settings.js',
306 306
             ['jquery', 'media-upload', 'thickbox'],
307 307
             EVENT_ESPRESSO_VERSION,
308 308
             true
309 309
         );
310
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
310
+        wp_register_style('organization-css', GEN_SET_ASSETS_URL.'organization.css', [], EVENT_ESPRESSO_VERSION);
311 311
         wp_enqueue_script('organization_settings');
312 312
         wp_enqueue_style('organization-css');
313 313
         $confirm_image_delete = [
@@ -330,12 +330,12 @@  discard block
 block discarded – undo
330 330
         // scripts
331 331
         wp_register_script(
332 332
             'gen_settings_countries',
333
-            GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
333
+            GEN_SET_ASSETS_URL.'gen_settings_countries.js',
334 334
             ['ee_admin_js'],
335 335
             EVENT_ESPRESSO_VERSION,
336 336
             true
337 337
         );
338
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
338
+        wp_register_style('organization-css', GEN_SET_ASSETS_URL.'organization.css', [], EVENT_ESPRESSO_VERSION);
339 339
         wp_enqueue_script('gen_settings_countries');
340 340
         wp_enqueue_style('organization-css');
341 341
     }
@@ -383,7 +383,7 @@  discard block
 block discarded – undo
383 383
         $this->_set_add_edit_form_tags('update_espresso_page_settings');
384 384
         $this->_set_publish_post_box_vars();
385 385
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
386
-            GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
386
+            GEN_SET_TEMPLATE_PATH.'espresso_page_settings.template.php',
387 387
             $this->_template_args,
388 388
             true
389 389
         );
@@ -400,12 +400,12 @@  discard block
 block discarded – undo
400 400
     {
401 401
         $this->core_config = EE_Registry::instance()->CFG->core;
402 402
         // capture incoming request data && set page IDs
403
-        $this->core_config->reg_page_id       = $this->request->getRequestParam(
403
+        $this->core_config->reg_page_id = $this->request->getRequestParam(
404 404
             'reg_page_id',
405 405
             $this->core_config->reg_page_id,
406 406
             DataType::INT
407 407
         );
408
-        $this->core_config->txn_page_id       = $this->request->getRequestParam(
408
+        $this->core_config->txn_page_id = $this->request->getRequestParam(
409 409
             'txn_page_id',
410 410
             $this->core_config->txn_page_id,
411 411
             DataType::INT
@@ -415,7 +415,7 @@  discard block
 block discarded – undo
415 415
             $this->core_config->thank_you_page_id,
416 416
             DataType::INT
417 417
         );
418
-        $this->core_config->cancel_page_id    = $this->request->getRequestParam(
418
+        $this->core_config->cancel_page_id = $this->request->getRequestParam(
419 419
             'cancel_page_id',
420 420
             $this->core_config->cancel_page_id,
421 421
             DataType::INT
@@ -682,16 +682,16 @@  discard block
 block discarded – undo
682 682
             $country->ID(),
683 683
             $country
684 684
         );
685
-        $this->_template_args['country_states_settings']  = $this->display_country_states(
685
+        $this->_template_args['country_states_settings'] = $this->display_country_states(
686 686
             $country->ID(),
687 687
             $country
688 688
         );
689
-        $this->_template_args['CNT_name_for_site']        = $country->name();
689
+        $this->_template_args['CNT_name_for_site'] = $country->name();
690 690
 
691 691
         $this->_set_add_edit_form_tags('update_country_settings');
692 692
         $this->_set_publish_post_box_vars();
693 693
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
694
-            GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
694
+            GEN_SET_TEMPLATE_PATH.'countries_settings.template.php',
695 695
             $this->_template_args,
696 696
             true
697 697
         );
@@ -715,7 +715,7 @@  discard block
 block discarded – undo
715 715
         $CNT_ISO          = $this->getCountryISO($CNT_ISO);
716 716
         $CNT_ISO_for_site = $this->getCountryIsoForSite();
717 717
 
718
-        if (! $CNT_ISO) {
718
+        if ( ! $CNT_ISO) {
719 719
             return '';
720 720
         }
721 721
 
@@ -728,7 +728,7 @@  discard block
 block discarded – undo
728 728
         $CNT_cur_disabled                         = $CNT_ISO !== $CNT_ISO_for_site;
729 729
         $this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
730 730
 
731
-        $country_input_types            = [
731
+        $country_input_types = [
732 732
             'CNT_active'      => [
733 733
                 'type'             => 'RADIO_BTN',
734 734
                 'input_name'       => "cntry[$CNT_ISO]",
@@ -865,8 +865,8 @@  discard block
 block discarded – undo
865 865
             $country,
866 866
             $country_input_types
867 867
         );
868
-        $country_details_settings       = EEH_Template::display_template(
869
-            GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
868
+        $country_details_settings = EEH_Template::display_template(
869
+            GEN_SET_TEMPLATE_PATH.'country_details_settings.template.php',
870 870
             $this->_template_args,
871 871
             true
872 872
         );
@@ -900,7 +900,7 @@  discard block
 block discarded – undo
900 900
     public function display_country_states(string $CNT_ISO = '', ?EE_Country $country = null): string
901 901
     {
902 902
         $CNT_ISO = $this->getCountryISO($CNT_ISO);
903
-        if (! $CNT_ISO) {
903
+        if ( ! $CNT_ISO) {
904 904
             return '';
905 905
         }
906 906
         // for ajax
@@ -965,8 +965,8 @@  discard block
 block discarded – undo
965 965
                         GEN_SET_ADMIN_URL
966 966
                     );
967 967
 
968
-                    $this->_template_args['states'][ $STA_ID ]['inputs']           = $inputs;
969
-                    $this->_template_args['states'][ $STA_ID ]['delete_state_url'] = $delete_state_url;
968
+                    $this->_template_args['states'][$STA_ID]['inputs']           = $inputs;
969
+                    $this->_template_args['states'][$STA_ID]['delete_state_url'] = $delete_state_url;
970 970
                 }
971 971
             }
972 972
         } else {
@@ -979,7 +979,7 @@  discard block
 block discarded – undo
979 979
         );
980 980
 
981 981
         $state_details_settings = EEH_Template::display_template(
982
-            GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
982
+            GEN_SET_TEMPLATE_PATH.'state_details_settings.template.php',
983 983
             $this->_template_args,
984 984
             true
985 985
         );
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
     {
1012 1012
         $success = true;
1013 1013
         $CNT_ISO = $this->getCountryISO('');
1014
-        if (! $CNT_ISO) {
1014
+        if ( ! $CNT_ISO) {
1015 1015
             EE_Error::add_error(
1016 1016
                 esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1017 1017
                 __FILE__,
@@ -1021,7 +1021,7 @@  discard block
 block discarded – undo
1021 1021
             $success = false;
1022 1022
         }
1023 1023
         $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1024
-        if (! $STA_abbrev) {
1024
+        if ( ! $STA_abbrev) {
1025 1025
             EE_Error::add_error(
1026 1026
                 esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1027 1027
                 __FILE__,
@@ -1031,7 +1031,7 @@  discard block
 block discarded – undo
1031 1031
             $success = false;
1032 1032
         }
1033 1033
         $STA_name = $this->request->getRequestParam('STA_name');
1034
-        if (! $STA_name) {
1034
+        if ( ! $STA_name) {
1035 1035
             EE_Error::add_error(
1036 1036
                 esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1037 1037
                 __FILE__,
@@ -1048,7 +1048,7 @@  discard block
 block discarded – undo
1048 1048
                 'STA_name'   => $STA_name,
1049 1049
                 'STA_active' => true,
1050 1050
             ];
1051
-            $success       = EEM_State::instance()->insert($cols_n_values);
1051
+            $success = EEM_State::instance()->insert($cols_n_values);
1052 1052
             EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1053 1053
         }
1054 1054
 
@@ -1080,7 +1080,7 @@  discard block
 block discarded – undo
1080 1080
         $STA_ID     = $this->request->getRequestParam('STA_ID');
1081 1081
         $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1082 1082
 
1083
-        if (! $STA_ID) {
1083
+        if ( ! $STA_ID) {
1084 1084
             EE_Error::add_error(
1085 1085
                 esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1086 1086
                 __FILE__,
@@ -1126,7 +1126,7 @@  discard block
 block discarded – undo
1126 1126
     protected function _update_country_settings()
1127 1127
     {
1128 1128
         $CNT_ISO = $this->getCountryISO();
1129
-        if (! $CNT_ISO) {
1129
+        if ( ! $CNT_ISO) {
1130 1130
             EE_Error::add_error(
1131 1131
                 esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1132 1132
                 __FILE__,
@@ -1145,25 +1145,25 @@  discard block
 block discarded – undo
1145 1145
                 $country->ISO3()
1146 1146
             )
1147 1147
         );
1148
-        $cols_n_values['CNT_name']        = $this->request->getRequestParam(
1148
+        $cols_n_values['CNT_name'] = $this->request->getRequestParam(
1149 1149
             "cntry[$CNT_ISO][CNT_name]",
1150 1150
             $country->name()
1151 1151
         );
1152
-        $cols_n_values['CNT_cur_code']    = strtoupper(
1152
+        $cols_n_values['CNT_cur_code'] = strtoupper(
1153 1153
             $this->request->getRequestParam(
1154 1154
                 "cntry[$CNT_ISO][CNT_cur_code]",
1155 1155
                 $country->currency_code()
1156 1156
             )
1157 1157
         );
1158
-        $cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1158
+        $cols_n_values['CNT_cur_single'] = $this->request->getRequestParam(
1159 1159
             "cntry[$CNT_ISO][CNT_cur_single]",
1160 1160
             $country->currency_name_single()
1161 1161
         );
1162
-        $cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1162
+        $cols_n_values['CNT_cur_plural'] = $this->request->getRequestParam(
1163 1163
             "cntry[$CNT_ISO][CNT_cur_plural]",
1164 1164
             $country->currency_name_plural()
1165 1165
         );
1166
-        $cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1166
+        $cols_n_values['CNT_cur_sign'] = $this->request->getRequestParam(
1167 1167
             "cntry[$CNT_ISO][CNT_cur_sign]",
1168 1168
             $country->currency_sign()
1169 1169
         );
@@ -1180,20 +1180,20 @@  discard block
 block discarded – undo
1180 1180
             "cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1181 1181
             $country->currency_decimal_mark()
1182 1182
         );
1183
-        $cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1183
+        $cols_n_values['CNT_cur_thsnds'] = $this->request->getRequestParam(
1184 1184
             "cntry[$CNT_ISO][CNT_cur_thsnds]",
1185 1185
             $country->currency_thousands_separator()
1186 1186
         );
1187
-        $cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1187
+        $cols_n_values['CNT_tel_code'] = $this->request->getRequestParam(
1188 1188
             "cntry[$CNT_ISO][CNT_tel_code]",
1189 1189
             $country->telephoneCode()
1190 1190
         );
1191
-        $cols_n_values['CNT_active']      = $this->request->getRequestParam(
1191
+        $cols_n_values['CNT_active'] = $this->request->getRequestParam(
1192 1192
             "cntry[$CNT_ISO][CNT_active]",
1193 1193
             $country->isActive(),
1194 1194
             DataType::BOOL
1195 1195
         );
1196
-        $cols_n_values['CNT_is_EU']      = $this->request->getRequestParam(
1196
+        $cols_n_values['CNT_is_EU'] = $this->request->getRequestParam(
1197 1197
             "cntry[$CNT_ISO][CNT_is_EU]",
1198 1198
             $country->isEU(),
1199 1199
             DataType::BOOL
@@ -1216,7 +1216,7 @@  discard block
 block discarded – undo
1216 1216
             $this->request->getRequestParam('states', [], DataType::STRING, true)
1217 1217
         );
1218 1218
 
1219
-        if (! empty($states) && $success !== false) {
1219
+        if ( ! empty($states) && $success !== false) {
1220 1220
             // loop thru state data ( looks like : states[75][STA_name] )
1221 1221
             foreach ($states as $STA_ID => $state) {
1222 1222
                 $cols_n_values = [
@@ -1274,7 +1274,7 @@  discard block
 block discarded – undo
1274 1274
         return '
1275 1275
 			<tr>
1276 1276
 				<th>
1277
-					' . $label . '
1277
+					' . $label.'
1278 1278
 				</th>';
1279 1279
     }
1280 1280
 
@@ -1289,7 +1289,7 @@  discard block
 block discarded – undo
1289 1289
     {
1290 1290
         return '
1291 1291
 				<td class="general-settings-country-input-td">
1292
-					' . $input . '
1292
+					' . $input.'
1293 1293
 				</td>
1294 1294
 			</tr>';
1295 1295
     }
@@ -1318,7 +1318,7 @@  discard block
 block discarded – undo
1318 1318
     {
1319 1319
         return '
1320 1320
 				<td class="general-settings-country-state-input-td">
1321
-					' . $input . '
1321
+					' . $input.'
1322 1322
 				</td>';
1323 1323
     }
1324 1324
 
@@ -1338,9 +1338,9 @@  discard block
 block discarded – undo
1338 1338
             ['post' => $ee_page_id, 'action' => 'edit'],
1339 1339
             admin_url('post.php')
1340 1340
         );
1341
-        $links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1341
+        $links = '<a href="'.esc_url_raw($edit_url).'" >'.esc_html__('Edit', 'event_espresso').'</a>';
1342 1342
         $links    .= ' &nbsp;|&nbsp; ';
1343
-        $links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1343
+        $links    .= '<a href="'.get_permalink($ee_page_id).'" >'.esc_html__('View', 'event_espresso').'</a>';
1344 1344
 
1345 1345
         return $links;
1346 1346
     }
@@ -1374,8 +1374,8 @@  discard block
 block discarded – undo
1374 1374
         }
1375 1375
 
1376 1376
         return '
1377
-        <span class="ee-page-status ' . $pg_class . '"><strong>' . $pg_status . '</strong></span>
1378
-        <span class="ee-page-status ' . $sc_class . '"><strong>' . $sc_status . '</strong></span>';
1377
+        <span class="ee-page-status ' . $pg_class.'"><strong>'.$pg_status.'</strong></span>
1378
+        <span class="ee-page-status ' . $sc_class.'"><strong>'.$sc_status.'</strong></span>';
1379 1379
     }
1380 1380
 
1381 1381
 
@@ -1395,7 +1395,7 @@  discard block
 block discarded – undo
1395 1395
         bool $echo = true
1396 1396
     ): string {
1397 1397
         global $wpdb;
1398
-        $items  = $wpdb->get_results(
1398
+        $items = $wpdb->get_results(
1399 1399
             $wpdb->prepare(
1400 1400
                 "SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' AND post_status != 'trash' ORDER BY menu_order",
1401 1401
                 $parent
@@ -1410,8 +1410,8 @@  discard block
 block discarded – undo
1410 1410
                 $post_title = wp_strip_all_tags($item->post_title);
1411 1411
                 $pad        = str_repeat('&nbsp;', $level * 3);
1412 1412
                 $option     = "\n\t";
1413
-                $option     .= '<option class="level-' . $level . '" ';
1414
-                $option     .= 'value="' . $ID . '" ';
1413
+                $option     .= '<option class="level-'.$level.'" ';
1414
+                $option     .= 'value="'.$ID.'" ';
1415 1415
                 $option     .= $ID === absint($default) ? ' selected' : '';
1416 1416
                 $option     .= '>';
1417 1417
                 $option     .= "$pad {$post_title}";
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_List_Table.class.php 1 patch
Indentation   +577 added lines, -577 removed lines patch added patch discarded remove patch
@@ -14,177 +14,177 @@  discard block
 block discarded – undo
14 14
  */
15 15
 class Events_Admin_List_Table extends EE_Admin_List_Table
16 16
 {
17
-    /**
18
-     * @var Events_Admin_Page
19
-     */
20
-    protected EE_Admin_Page $_admin_page;
21
-
22
-    /**
23
-     * @var EE_Datetime
24
-     */
25
-    private $_dtt;
26
-
27
-
28
-    /**
29
-     * Initial setup of data properties for the list table.
30
-     *
31
-     * @throws Exception
32
-     */
33
-    protected function _setup_data()
34
-    {
35
-        $this->_data           = $this->_admin_page->get_events($this->_per_page, $this->_current_page);
36
-        $this->_all_data_count = $this->_admin_page->get_events(0, 0, true);
37
-    }
38
-
39
-
40
-    /**
41
-     * Set up of additional properties for the list table.
42
-     *
43
-     * @throws EE_Error
44
-     * @throws ReflectionException
45
-     */
46
-    protected function _set_properties()
47
-    {
48
-        $this->_wp_list_args    = [
49
-            'singular' => esc_html__('event', 'event_espresso'),
50
-            'plural'   => esc_html__('events', 'event_espresso'),
51
-            'ajax'     => true, // for now
52
-            'screen'   => $this->_admin_page->get_current_screen()->id,
53
-        ];
54
-        $approved_registrations = esc_html__('Approved Registrations', 'event_espresso');
55
-        $this->_columns         = [
56
-            'cb'              => '<input type="checkbox" />',
57
-            'id'              => esc_html__('ID', 'event_espresso'),
58
-            'name'            => esc_html__('Name', 'event_espresso'),
59
-            'author'          => esc_html__('Author', 'event_espresso'),
60
-            'venue'           => esc_html__('Venue', 'event_espresso'),
61
-            'start_date_time' => esc_html__('Event Start', 'event_espresso'),
62
-            'reg_begins'      => esc_html__('On Sale', 'event_espresso'),
63
-            'attendees'       => '
17
+	/**
18
+	 * @var Events_Admin_Page
19
+	 */
20
+	protected EE_Admin_Page $_admin_page;
21
+
22
+	/**
23
+	 * @var EE_Datetime
24
+	 */
25
+	private $_dtt;
26
+
27
+
28
+	/**
29
+	 * Initial setup of data properties for the list table.
30
+	 *
31
+	 * @throws Exception
32
+	 */
33
+	protected function _setup_data()
34
+	{
35
+		$this->_data           = $this->_admin_page->get_events($this->_per_page, $this->_current_page);
36
+		$this->_all_data_count = $this->_admin_page->get_events(0, 0, true);
37
+	}
38
+
39
+
40
+	/**
41
+	 * Set up of additional properties for the list table.
42
+	 *
43
+	 * @throws EE_Error
44
+	 * @throws ReflectionException
45
+	 */
46
+	protected function _set_properties()
47
+	{
48
+		$this->_wp_list_args    = [
49
+			'singular' => esc_html__('event', 'event_espresso'),
50
+			'plural'   => esc_html__('events', 'event_espresso'),
51
+			'ajax'     => true, // for now
52
+			'screen'   => $this->_admin_page->get_current_screen()->id,
53
+		];
54
+		$approved_registrations = esc_html__('Approved Registrations', 'event_espresso');
55
+		$this->_columns         = [
56
+			'cb'              => '<input type="checkbox" />',
57
+			'id'              => esc_html__('ID', 'event_espresso'),
58
+			'name'            => esc_html__('Name', 'event_espresso'),
59
+			'author'          => esc_html__('Author', 'event_espresso'),
60
+			'venue'           => esc_html__('Venue', 'event_espresso'),
61
+			'start_date_time' => esc_html__('Event Start', 'event_espresso'),
62
+			'reg_begins'      => esc_html__('On Sale', 'event_espresso'),
63
+			'attendees'       => '
64 64
                 <span class="dashicons dashicons-groups ee-status-color--RAP ee-aria-tooltip"
65 65
                     aria-label="' . $approved_registrations . '"></span>
66 66
                 <span class="screen-reader-text">' . $approved_registrations . '</span>',
67
-            'actions'         => $this->actionsColumnHeader(),
68
-        ];
69
-        $this->addConditionalColumns();
70
-        $this->_sortable_columns = [
71
-            'id'              => ['EVT_ID' => true],
72
-            'name'            => ['EVT_name' => false],
73
-            'author'          => ['EVT_wp_user' => false],
74
-            'venue'           => ['Venue.VNU_name' => false],
75
-            'start_date_time' => ['Datetime.DTT_EVT_start' => false],
76
-            'reg_begins'      => ['Datetime.Ticket.TKT_start_date' => false],
77
-        ];
78
-
79
-        $this->_primary_column = 'id';
80
-        $this->_hidden_columns = ['author', 'event_category'];
81
-    }
82
-
83
-
84
-    /**
85
-     * @return array
86
-     */
87
-    protected function _get_table_filters()
88
-    {
89
-        return []; // no filters with decaf
90
-    }
91
-
92
-
93
-    /**
94
-     * Setup of views properties.
95
-     *
96
-     * @throws InvalidDataTypeException
97
-     * @throws InvalidInterfaceException
98
-     * @throws InvalidArgumentException
99
-     * @throws EE_Error
100
-     * @throws EE_Error
101
-     * @throws EE_Error
102
-     */
103
-    protected function _add_view_counts()
104
-    {
105
-        $this->_views['all']['count']   = $this->_admin_page->total_events();
106
-        $this->_views['draft']['count'] = $this->_admin_page->total_events_draft();
107
-        if (
108
-            EE_Registry::instance()->CAP->current_user_can(
109
-                'ee_delete_events',
110
-                'espresso_events_trash_events'
111
-            )
112
-        ) {
113
-            $this->_views['trash']['count'] = $this->_admin_page->total_trashed_events();
114
-        }
115
-    }
116
-
117
-
118
-    /**
119
-     * @param EE_Event $item
120
-     * @return string
121
-     */
122
-    protected function _get_row_class($item): string
123
-    {
124
-        $class = parent::_get_row_class($item);
125
-        if ($this->_has_checkbox_column) {
126
-            $class .= ' has-checkbox-column';
127
-        }
128
-        return $class;
129
-    }
130
-
131
-
132
-    /**
133
-     * @param EE_Event $item
134
-     * @return string
135
-     * @throws EE_Error
136
-     * @throws ReflectionException
137
-     */
138
-    public function column_cb($item): string
139
-    {
140
-        if (! $item instanceof EE_Event) {
141
-            return '';
142
-        }
143
-        $this->_dtt = $item->primary_datetime(); // set this for use in other columns
144
-        $content    = sprintf(
145
-            '<input type="checkbox" name="EVT_IDs[]" value="%s" />',
146
-            $item->ID()
147
-        );
148
-        return $this->columnContent('cb', $content, 'center');
149
-    }
150
-
151
-
152
-    /**
153
-     * @param EE_Event $event
154
-     * @return string
155
-     * @throws EE_Error
156
-     * @throws ReflectionException
157
-     */
158
-    public function column_id(EE_Event $event): string
159
-    {
160
-        $content = '<span class="ee-entity-id">' . $event->ID() . '</span>';
161
-        $content .= '<span class="show-on-mobile-view-only">';
162
-        $content .= $this->column_name($event, false);
163
-        $content .= '</span>';
164
-        return $this->columnContent('id', $content, 'end');
165
-    }
166
-
167
-
168
-    /**
169
-     * @param EE_Event $event
170
-     * @param bool     $prep_content
171
-     * @return string
172
-     * @throws EE_Error
173
-     * @throws ReflectionException
174
-     */
175
-    public function column_name(EE_Event $event, bool $prep_content = true): string
176
-    {
177
-        $edit_query_args = [
178
-            'action' => 'edit',
179
-            'post'   => $event->ID(),
180
-        ];
181
-        $edit_link       = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
182
-        $actions         = $this->_column_name_action_setup($event);
183
-        $status          = esc_attr($event->get_active_status());
184
-        $pretty_status   = EEH_Template::pretty_status($status, false, 'sentence');
185
-        $status_dot      = '<span class="ee-status-dot ee-status-bg--' . $status . '"></span>';
186
-        $visibility      = $event->get_visibility_status();
187
-        $content         = '
67
+			'actions'         => $this->actionsColumnHeader(),
68
+		];
69
+		$this->addConditionalColumns();
70
+		$this->_sortable_columns = [
71
+			'id'              => ['EVT_ID' => true],
72
+			'name'            => ['EVT_name' => false],
73
+			'author'          => ['EVT_wp_user' => false],
74
+			'venue'           => ['Venue.VNU_name' => false],
75
+			'start_date_time' => ['Datetime.DTT_EVT_start' => false],
76
+			'reg_begins'      => ['Datetime.Ticket.TKT_start_date' => false],
77
+		];
78
+
79
+		$this->_primary_column = 'id';
80
+		$this->_hidden_columns = ['author', 'event_category'];
81
+	}
82
+
83
+
84
+	/**
85
+	 * @return array
86
+	 */
87
+	protected function _get_table_filters()
88
+	{
89
+		return []; // no filters with decaf
90
+	}
91
+
92
+
93
+	/**
94
+	 * Setup of views properties.
95
+	 *
96
+	 * @throws InvalidDataTypeException
97
+	 * @throws InvalidInterfaceException
98
+	 * @throws InvalidArgumentException
99
+	 * @throws EE_Error
100
+	 * @throws EE_Error
101
+	 * @throws EE_Error
102
+	 */
103
+	protected function _add_view_counts()
104
+	{
105
+		$this->_views['all']['count']   = $this->_admin_page->total_events();
106
+		$this->_views['draft']['count'] = $this->_admin_page->total_events_draft();
107
+		if (
108
+			EE_Registry::instance()->CAP->current_user_can(
109
+				'ee_delete_events',
110
+				'espresso_events_trash_events'
111
+			)
112
+		) {
113
+			$this->_views['trash']['count'] = $this->_admin_page->total_trashed_events();
114
+		}
115
+	}
116
+
117
+
118
+	/**
119
+	 * @param EE_Event $item
120
+	 * @return string
121
+	 */
122
+	protected function _get_row_class($item): string
123
+	{
124
+		$class = parent::_get_row_class($item);
125
+		if ($this->_has_checkbox_column) {
126
+			$class .= ' has-checkbox-column';
127
+		}
128
+		return $class;
129
+	}
130
+
131
+
132
+	/**
133
+	 * @param EE_Event $item
134
+	 * @return string
135
+	 * @throws EE_Error
136
+	 * @throws ReflectionException
137
+	 */
138
+	public function column_cb($item): string
139
+	{
140
+		if (! $item instanceof EE_Event) {
141
+			return '';
142
+		}
143
+		$this->_dtt = $item->primary_datetime(); // set this for use in other columns
144
+		$content    = sprintf(
145
+			'<input type="checkbox" name="EVT_IDs[]" value="%s" />',
146
+			$item->ID()
147
+		);
148
+		return $this->columnContent('cb', $content, 'center');
149
+	}
150
+
151
+
152
+	/**
153
+	 * @param EE_Event $event
154
+	 * @return string
155
+	 * @throws EE_Error
156
+	 * @throws ReflectionException
157
+	 */
158
+	public function column_id(EE_Event $event): string
159
+	{
160
+		$content = '<span class="ee-entity-id">' . $event->ID() . '</span>';
161
+		$content .= '<span class="show-on-mobile-view-only">';
162
+		$content .= $this->column_name($event, false);
163
+		$content .= '</span>';
164
+		return $this->columnContent('id', $content, 'end');
165
+	}
166
+
167
+
168
+	/**
169
+	 * @param EE_Event $event
170
+	 * @param bool     $prep_content
171
+	 * @return string
172
+	 * @throws EE_Error
173
+	 * @throws ReflectionException
174
+	 */
175
+	public function column_name(EE_Event $event, bool $prep_content = true): string
176
+	{
177
+		$edit_query_args = [
178
+			'action' => 'edit',
179
+			'post'   => $event->ID(),
180
+		];
181
+		$edit_link       = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
182
+		$actions         = $this->_column_name_action_setup($event);
183
+		$status          = esc_attr($event->get_active_status());
184
+		$pretty_status   = EEH_Template::pretty_status($status, false, 'sentence');
185
+		$status_dot      = '<span class="ee-status-dot ee-status-bg--' . $status . '"></span>';
186
+		$visibility      = $event->get_visibility_status();
187
+		$content         = '
188 188
             <div class="ee-layout-row ee-layout-row--fixed">
189 189
                 <a  class="row-title ee-status-color--' . $status . ' ee-aria-tooltip"
190 190
                     aria-label="' . $pretty_status . '"
@@ -193,416 +193,416 @@  discard block
 block discarded – undo
193 193
                     ' . $status_dot . $event->name() . '
194 194
                 </a>
195 195
                 ' . (
196
-                    $visibility
197
-                    ? '<span class="ee-event-visibility-status ee-status-text-small">(' . esc_html($visibility) . ')</span>'
198
-                    : ''
199
-                ) . '
196
+					$visibility
197
+					? '<span class="ee-event-visibility-status ee-status-text-small">(' . esc_html($visibility) . ')</span>'
198
+					: ''
199
+				) . '
200 200
             </div>';
201 201
 
202
-        $content .= $this->row_actions($actions);
203
-
204
-        return $prep_content ? $this->columnContent('name', $content) : $content;
205
-    }
206
-
207
-
208
-    /**
209
-     * Just a method for setting up the actions for the name column
210
-     *
211
-     * @param EE_Event $event
212
-     * @return array array of actions
213
-     * @throws EE_Error
214
-     * @throws InvalidArgumentException
215
-     * @throws InvalidDataTypeException
216
-     * @throws InvalidInterfaceException
217
-     * @throws ReflectionException
218
-     */
219
-    protected function _column_name_action_setup(EE_Event $event): array
220
-    {
221
-        // todo: remove when attendees is active
222
-        if (! defined('REG_ADMIN_URL')) {
223
-            define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
224
-        }
225
-        $actions            = [];
226
-        $restore_event_link = '';
227
-        $delete_event_link  = '';
228
-        $trash_event_link   = '';
229
-        if (
230
-            EE_Registry::instance()->CAP->current_user_can(
231
-                'ee_edit_event',
232
-                'espresso_events_edit',
233
-                $event->ID()
234
-            )
235
-        ) {
236
-            $edit_query_args = [
237
-                'action' => 'edit',
238
-                'post'   => $event->ID(),
239
-            ];
240
-            $edit_link       = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
241
-            $actions['edit'] = '<a href="' . $edit_link . '" class="ee-aria-tooltip" '
242
-                               . ' aria-label="' . esc_attr__('Edit Event', 'event_espresso') . '">'
243
-                               . esc_html__('Edit', 'event_espresso')
244
-                               . '</a>';
245
-        }
246
-        if (
247
-            EE_Registry::instance()->CAP->current_user_can(
248
-                'ee_read_registrations',
249
-                'espresso_registrations_view_registration'
250
-            )
251
-            && EE_Registry::instance()->CAP->current_user_can(
252
-                'ee_read_event',
253
-                'espresso_registrations_view_registration',
254
-                $event->ID()
255
-            )
256
-        ) {
257
-            $attendees_query_args = [
258
-                'action'   => 'default',
259
-                'event_id' => $event->ID(),
260
-            ];
261
-            $attendees_link       = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
262
-            $actions['attendees'] = '<a href="' . $attendees_link . '" class="ee-aria-tooltip"'
263
-                                    . ' aria-label="' . esc_attr__('View Registrations', 'event_espresso') . '">'
264
-                                    . esc_html__('Registrations', 'event_espresso')
265
-                                    . '</a>';
266
-        }
267
-        if (
268
-            EE_Registry::instance()->CAP->current_user_can(
269
-                'ee_delete_event',
270
-                'espresso_events_trash_event',
271
-                $event->ID()
272
-            )
273
-        ) {
274
-            $trash_event_query_args = [
275
-                'action' => 'trash_event',
276
-                'EVT_ID' => $event->ID(),
277
-            ];
278
-            $trash_event_link       = EE_Admin_Page::add_query_args_and_nonce(
279
-                $trash_event_query_args,
280
-                EVENTS_ADMIN_URL
281
-            );
282
-        }
283
-        if (
284
-            EE_Registry::instance()->CAP->current_user_can(
285
-                'ee_delete_event',
286
-                'espresso_events_restore_event',
287
-                $event->ID()
288
-            )
289
-        ) {
290
-            $restore_event_query_args = [
291
-                'action' => 'restore_event',
292
-                'EVT_ID' => $event->ID(),
293
-            ];
294
-            $restore_event_link       = EE_Admin_Page::add_query_args_and_nonce(
295
-                $restore_event_query_args,
296
-                EVENTS_ADMIN_URL
297
-            );
298
-        }
299
-        if (
300
-            EE_Registry::instance()->CAP->current_user_can(
301
-                'ee_delete_event',
302
-                'espresso_events_delete_event',
303
-                $event->ID()
304
-            )
305
-        ) {
306
-            $delete_event_query_args = [
307
-                'action' => 'delete_event',
308
-                'EVT_ID' => $event->ID(),
309
-            ];
310
-            $delete_event_link       = EE_Admin_Page::add_query_args_and_nonce(
311
-                $delete_event_query_args,
312
-                EVENTS_ADMIN_URL
313
-            );
314
-        }
315
-        $view_link       = get_permalink($event->ID());
316
-        $actions['view'] = '<a href="' . $view_link . '" class="ee-aria-tooltip"'
317
-                           . ' aria-label="' . esc_attr__('View Event', 'event_espresso') . '">'
318
-                           . esc_html__('View', 'event_espresso')
319
-                           . '</a>';
320
-        if ($event->get('status') === 'trash') {
321
-            if (
322
-                EE_Registry::instance()->CAP->current_user_can(
323
-                    'ee_delete_event',
324
-                    'espresso_events_restore_event',
325
-                    $event->ID()
326
-                )
327
-            ) {
328
-                $actions['restore_from_trash'] = '<a href="' . $restore_event_link . '" class="ee-aria-tooltip"'
329
-                                                 . ' aria-label="' . esc_attr__('Restore from Trash', 'event_espresso')
330
-                                                 . '">'
331
-                                                 . esc_html__('Restore from Trash', 'event_espresso')
332
-                                                 . '</a>';
333
-            }
334
-            if (
335
-                EE_Registry::instance()->CAP->current_user_can(
336
-                    'ee_delete_event',
337
-                    'espresso_events_delete_event',
338
-                    $event->ID()
339
-                )
340
-            ) {
341
-                $actions['delete'] = '<a href="' . $delete_event_link . '" class="ee-aria-tooltip"'
342
-                                     . ' aria-label="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
343
-                                     . esc_html__('Delete Permanently', 'event_espresso')
344
-                                     . '</a>';
345
-            }
346
-        } else {
347
-            if (
348
-                EE_Registry::instance()->CAP->current_user_can(
349
-                    'ee_delete_event',
350
-                    'espresso_events_trash_event',
351
-                    $event->ID()
352
-                )
353
-            ) {
354
-                $actions['move to trash'] = '<a href="' . $trash_event_link . '" class="ee-aria-tooltip"'
355
-                                            . ' aria-label="' . esc_attr__('Trash Event', 'event_espresso') . '">'
356
-                                            . esc_html__('Trash', 'event_espresso')
357
-                                            . '</a>';
358
-            }
359
-        }
360
-        return $actions;
361
-    }
362
-
363
-
364
-    /**
365
-     * @param EE_Event $event
366
-     * @return string
367
-     * @throws EE_Error
368
-     * @throws ReflectionException
369
-     */
370
-    public function column_author(EE_Event $event): string
371
-    {
372
-        // user author info
373
-        $event_author = get_userdata($event->wp_user());
374
-        $gravatar     = get_avatar($event->wp_user(), '24');
375
-        // filter link
376
-        $query_args = [
377
-            'action'      => 'default',
378
-            'EVT_wp_user' => $event->wp_user(),
379
-        ];
380
-        $filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
381
-        $content    = '<div class="ee-layout-row ee-layout-row--fixed">';
382
-        $content    .= '  <a href="' . $filter_url . '" class="ee-event-author ee-aria-tooltip"'
383
-                       . ' aria-label="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
384
-                       . $gravatar . $event_author->display_name
385
-                       . '</a>';
386
-        $content    .= '</div>';
387
-        return $this->columnContent('author', $content);
388
-    }
389
-
390
-
391
-    /**
392
-     * @param EE_Event $event
393
-     * @return string
394
-     * @throws EE_Error
395
-     * @throws ReflectionException
396
-     */
397
-    public function column_event_category(EE_Event $event): string
398
-    {
399
-        $event_categories = $event->get_all_event_categories();
400
-        $content          = implode(
401
-            ', ',
402
-            array_map(
403
-                function (EE_Term $category) {
404
-                    return $category->name();
405
-                },
406
-                $event_categories
407
-            )
408
-        );
409
-        return $this->columnContent('event_category', $content);
410
-    }
411
-
412
-
413
-    /**
414
-     * @param EE_Event $event
415
-     * @return string
416
-     * @throws EE_Error
417
-     * @throws ReflectionException
418
-     */
419
-    public function column_venue(EE_Event $event): string
420
-    {
421
-        $venue   = $event->get_first_related('Venue');
422
-        $content = ! empty($venue)
423
-            ? $venue->name()
424
-            : '';
425
-        return $this->columnContent('venue', $content);
426
-    }
427
-
428
-
429
-    /**
430
-     * @param EE_Event $event
431
-     * @return string
432
-     * @throws EE_Error
433
-     * @throws ReflectionException
434
-     */
435
-    public function column_start_date_time(EE_Event $event): string
436
-    {
437
-        $content = $this->_dtt instanceof EE_Datetime
438
-            ? $this->_dtt->get_i18n_datetime('DTT_EVT_start')
439
-            : esc_html__('No Date was saved for this Event', 'event_espresso');
440
-        return $this->columnContent('start_date_time', $content);
441
-    }
442
-
443
-
444
-    /**
445
-     * @param EE_Event $event
446
-     * @return string
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     */
450
-    public function column_reg_begins(EE_Event $event): string
451
-    {
452
-        $reg_start = $event->get_ticket_with_earliest_start_time();
453
-        $content   = $reg_start instanceof EE_Ticket
454
-            ? $reg_start->get_i18n_datetime('TKT_start_date')
455
-            : esc_html__('No Tickets have been setup for this Event', 'event_espresso');
456
-        return $this->columnContent('reg_begins', $content);
457
-    }
458
-
459
-
460
-    /**
461
-     * @param EE_Event $event
462
-     * @return string
463
-     * @throws EE_Error
464
-     * @throws InvalidArgumentException
465
-     * @throws InvalidDataTypeException
466
-     * @throws InvalidInterfaceException
467
-     * @throws ReflectionException
468
-     */
469
-    public function column_attendees(EE_Event $event): string
470
-    {
471
-        $attendees_query_args = [
472
-            'action'   => 'default',
473
-            'event_id' => $event->ID(),
474
-            '_reg_status' => EEM_Registration::status_id_approved,
475
-        ];
476
-        $attendees_link       = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
477
-        $registered_attendees = EEM_Registration::instance()->get_event_registration_count($event->ID());
478
-
479
-        $content              = EE_Registry::instance()->CAP->current_user_can(
480
-            'ee_read_event',
481
-            'espresso_registrations_view_registration',
482
-            $event->ID()
483
-        ) && EE_Registry::instance()->CAP->current_user_can(
484
-            'ee_read_registrations',
485
-            'espresso_registrations_view_registration'
486
-        )
487
-            ? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
488
-            : $registered_attendees;
489
-        return $this->columnContent('attendees', $content, 'center');
490
-    }
491
-
492
-
493
-    /**
494
-     * @param EE_Event $event
495
-     * @return float
496
-     * @throws EE_Error
497
-     * @throws InvalidArgumentException
498
-     * @throws InvalidDataTypeException
499
-     * @throws InvalidInterfaceException
500
-     * @throws ReflectionException
501
-     */
502
-    public function column_tkts_sold(EE_Event $event): float
503
-    {
504
-        $content = EEM_Ticket::instance()->sum([['Datetime.EVT_ID' => $event->ID()]], 'TKT_sold');
505
-        return $this->columnContent('tkts_sold', $content);
506
-    }
507
-
508
-
509
-    /**
510
-     * @param EE_Event $event
511
-     * @return string
512
-     * @throws EE_Error
513
-     * @throws InvalidArgumentException
514
-     * @throws InvalidDataTypeException
515
-     * @throws InvalidInterfaceException
516
-     * @throws ReflectionException
517
-     */
518
-    public function column_actions(EE_Event $event): string
519
-    {
520
-        // todo: remove when attendees is active
521
-        if (! defined('REG_ADMIN_URL')) {
522
-            define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
523
-        }
524
-        $action_links   = [];
525
-        $view_link      = get_permalink($event->ID());
526
-        $action_links[] = '<a href="' . $view_link . '" class="ee-aria-tooltip button button--icon-only"'
527
-                          . ' aria-label="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">
202
+		$content .= $this->row_actions($actions);
203
+
204
+		return $prep_content ? $this->columnContent('name', $content) : $content;
205
+	}
206
+
207
+
208
+	/**
209
+	 * Just a method for setting up the actions for the name column
210
+	 *
211
+	 * @param EE_Event $event
212
+	 * @return array array of actions
213
+	 * @throws EE_Error
214
+	 * @throws InvalidArgumentException
215
+	 * @throws InvalidDataTypeException
216
+	 * @throws InvalidInterfaceException
217
+	 * @throws ReflectionException
218
+	 */
219
+	protected function _column_name_action_setup(EE_Event $event): array
220
+	{
221
+		// todo: remove when attendees is active
222
+		if (! defined('REG_ADMIN_URL')) {
223
+			define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
224
+		}
225
+		$actions            = [];
226
+		$restore_event_link = '';
227
+		$delete_event_link  = '';
228
+		$trash_event_link   = '';
229
+		if (
230
+			EE_Registry::instance()->CAP->current_user_can(
231
+				'ee_edit_event',
232
+				'espresso_events_edit',
233
+				$event->ID()
234
+			)
235
+		) {
236
+			$edit_query_args = [
237
+				'action' => 'edit',
238
+				'post'   => $event->ID(),
239
+			];
240
+			$edit_link       = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
241
+			$actions['edit'] = '<a href="' . $edit_link . '" class="ee-aria-tooltip" '
242
+							   . ' aria-label="' . esc_attr__('Edit Event', 'event_espresso') . '">'
243
+							   . esc_html__('Edit', 'event_espresso')
244
+							   . '</a>';
245
+		}
246
+		if (
247
+			EE_Registry::instance()->CAP->current_user_can(
248
+				'ee_read_registrations',
249
+				'espresso_registrations_view_registration'
250
+			)
251
+			&& EE_Registry::instance()->CAP->current_user_can(
252
+				'ee_read_event',
253
+				'espresso_registrations_view_registration',
254
+				$event->ID()
255
+			)
256
+		) {
257
+			$attendees_query_args = [
258
+				'action'   => 'default',
259
+				'event_id' => $event->ID(),
260
+			];
261
+			$attendees_link       = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
262
+			$actions['attendees'] = '<a href="' . $attendees_link . '" class="ee-aria-tooltip"'
263
+									. ' aria-label="' . esc_attr__('View Registrations', 'event_espresso') . '">'
264
+									. esc_html__('Registrations', 'event_espresso')
265
+									. '</a>';
266
+		}
267
+		if (
268
+			EE_Registry::instance()->CAP->current_user_can(
269
+				'ee_delete_event',
270
+				'espresso_events_trash_event',
271
+				$event->ID()
272
+			)
273
+		) {
274
+			$trash_event_query_args = [
275
+				'action' => 'trash_event',
276
+				'EVT_ID' => $event->ID(),
277
+			];
278
+			$trash_event_link       = EE_Admin_Page::add_query_args_and_nonce(
279
+				$trash_event_query_args,
280
+				EVENTS_ADMIN_URL
281
+			);
282
+		}
283
+		if (
284
+			EE_Registry::instance()->CAP->current_user_can(
285
+				'ee_delete_event',
286
+				'espresso_events_restore_event',
287
+				$event->ID()
288
+			)
289
+		) {
290
+			$restore_event_query_args = [
291
+				'action' => 'restore_event',
292
+				'EVT_ID' => $event->ID(),
293
+			];
294
+			$restore_event_link       = EE_Admin_Page::add_query_args_and_nonce(
295
+				$restore_event_query_args,
296
+				EVENTS_ADMIN_URL
297
+			);
298
+		}
299
+		if (
300
+			EE_Registry::instance()->CAP->current_user_can(
301
+				'ee_delete_event',
302
+				'espresso_events_delete_event',
303
+				$event->ID()
304
+			)
305
+		) {
306
+			$delete_event_query_args = [
307
+				'action' => 'delete_event',
308
+				'EVT_ID' => $event->ID(),
309
+			];
310
+			$delete_event_link       = EE_Admin_Page::add_query_args_and_nonce(
311
+				$delete_event_query_args,
312
+				EVENTS_ADMIN_URL
313
+			);
314
+		}
315
+		$view_link       = get_permalink($event->ID());
316
+		$actions['view'] = '<a href="' . $view_link . '" class="ee-aria-tooltip"'
317
+						   . ' aria-label="' . esc_attr__('View Event', 'event_espresso') . '">'
318
+						   . esc_html__('View', 'event_espresso')
319
+						   . '</a>';
320
+		if ($event->get('status') === 'trash') {
321
+			if (
322
+				EE_Registry::instance()->CAP->current_user_can(
323
+					'ee_delete_event',
324
+					'espresso_events_restore_event',
325
+					$event->ID()
326
+				)
327
+			) {
328
+				$actions['restore_from_trash'] = '<a href="' . $restore_event_link . '" class="ee-aria-tooltip"'
329
+												 . ' aria-label="' . esc_attr__('Restore from Trash', 'event_espresso')
330
+												 . '">'
331
+												 . esc_html__('Restore from Trash', 'event_espresso')
332
+												 . '</a>';
333
+			}
334
+			if (
335
+				EE_Registry::instance()->CAP->current_user_can(
336
+					'ee_delete_event',
337
+					'espresso_events_delete_event',
338
+					$event->ID()
339
+				)
340
+			) {
341
+				$actions['delete'] = '<a href="' . $delete_event_link . '" class="ee-aria-tooltip"'
342
+									 . ' aria-label="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
343
+									 . esc_html__('Delete Permanently', 'event_espresso')
344
+									 . '</a>';
345
+			}
346
+		} else {
347
+			if (
348
+				EE_Registry::instance()->CAP->current_user_can(
349
+					'ee_delete_event',
350
+					'espresso_events_trash_event',
351
+					$event->ID()
352
+				)
353
+			) {
354
+				$actions['move to trash'] = '<a href="' . $trash_event_link . '" class="ee-aria-tooltip"'
355
+											. ' aria-label="' . esc_attr__('Trash Event', 'event_espresso') . '">'
356
+											. esc_html__('Trash', 'event_espresso')
357
+											. '</a>';
358
+			}
359
+		}
360
+		return $actions;
361
+	}
362
+
363
+
364
+	/**
365
+	 * @param EE_Event $event
366
+	 * @return string
367
+	 * @throws EE_Error
368
+	 * @throws ReflectionException
369
+	 */
370
+	public function column_author(EE_Event $event): string
371
+	{
372
+		// user author info
373
+		$event_author = get_userdata($event->wp_user());
374
+		$gravatar     = get_avatar($event->wp_user(), '24');
375
+		// filter link
376
+		$query_args = [
377
+			'action'      => 'default',
378
+			'EVT_wp_user' => $event->wp_user(),
379
+		];
380
+		$filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
381
+		$content    = '<div class="ee-layout-row ee-layout-row--fixed">';
382
+		$content    .= '  <a href="' . $filter_url . '" class="ee-event-author ee-aria-tooltip"'
383
+					   . ' aria-label="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
384
+					   . $gravatar . $event_author->display_name
385
+					   . '</a>';
386
+		$content    .= '</div>';
387
+		return $this->columnContent('author', $content);
388
+	}
389
+
390
+
391
+	/**
392
+	 * @param EE_Event $event
393
+	 * @return string
394
+	 * @throws EE_Error
395
+	 * @throws ReflectionException
396
+	 */
397
+	public function column_event_category(EE_Event $event): string
398
+	{
399
+		$event_categories = $event->get_all_event_categories();
400
+		$content          = implode(
401
+			', ',
402
+			array_map(
403
+				function (EE_Term $category) {
404
+					return $category->name();
405
+				},
406
+				$event_categories
407
+			)
408
+		);
409
+		return $this->columnContent('event_category', $content);
410
+	}
411
+
412
+
413
+	/**
414
+	 * @param EE_Event $event
415
+	 * @return string
416
+	 * @throws EE_Error
417
+	 * @throws ReflectionException
418
+	 */
419
+	public function column_venue(EE_Event $event): string
420
+	{
421
+		$venue   = $event->get_first_related('Venue');
422
+		$content = ! empty($venue)
423
+			? $venue->name()
424
+			: '';
425
+		return $this->columnContent('venue', $content);
426
+	}
427
+
428
+
429
+	/**
430
+	 * @param EE_Event $event
431
+	 * @return string
432
+	 * @throws EE_Error
433
+	 * @throws ReflectionException
434
+	 */
435
+	public function column_start_date_time(EE_Event $event): string
436
+	{
437
+		$content = $this->_dtt instanceof EE_Datetime
438
+			? $this->_dtt->get_i18n_datetime('DTT_EVT_start')
439
+			: esc_html__('No Date was saved for this Event', 'event_espresso');
440
+		return $this->columnContent('start_date_time', $content);
441
+	}
442
+
443
+
444
+	/**
445
+	 * @param EE_Event $event
446
+	 * @return string
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 */
450
+	public function column_reg_begins(EE_Event $event): string
451
+	{
452
+		$reg_start = $event->get_ticket_with_earliest_start_time();
453
+		$content   = $reg_start instanceof EE_Ticket
454
+			? $reg_start->get_i18n_datetime('TKT_start_date')
455
+			: esc_html__('No Tickets have been setup for this Event', 'event_espresso');
456
+		return $this->columnContent('reg_begins', $content);
457
+	}
458
+
459
+
460
+	/**
461
+	 * @param EE_Event $event
462
+	 * @return string
463
+	 * @throws EE_Error
464
+	 * @throws InvalidArgumentException
465
+	 * @throws InvalidDataTypeException
466
+	 * @throws InvalidInterfaceException
467
+	 * @throws ReflectionException
468
+	 */
469
+	public function column_attendees(EE_Event $event): string
470
+	{
471
+		$attendees_query_args = [
472
+			'action'   => 'default',
473
+			'event_id' => $event->ID(),
474
+			'_reg_status' => EEM_Registration::status_id_approved,
475
+		];
476
+		$attendees_link       = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
477
+		$registered_attendees = EEM_Registration::instance()->get_event_registration_count($event->ID());
478
+
479
+		$content              = EE_Registry::instance()->CAP->current_user_can(
480
+			'ee_read_event',
481
+			'espresso_registrations_view_registration',
482
+			$event->ID()
483
+		) && EE_Registry::instance()->CAP->current_user_can(
484
+			'ee_read_registrations',
485
+			'espresso_registrations_view_registration'
486
+		)
487
+			? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
488
+			: $registered_attendees;
489
+		return $this->columnContent('attendees', $content, 'center');
490
+	}
491
+
492
+
493
+	/**
494
+	 * @param EE_Event $event
495
+	 * @return float
496
+	 * @throws EE_Error
497
+	 * @throws InvalidArgumentException
498
+	 * @throws InvalidDataTypeException
499
+	 * @throws InvalidInterfaceException
500
+	 * @throws ReflectionException
501
+	 */
502
+	public function column_tkts_sold(EE_Event $event): float
503
+	{
504
+		$content = EEM_Ticket::instance()->sum([['Datetime.EVT_ID' => $event->ID()]], 'TKT_sold');
505
+		return $this->columnContent('tkts_sold', $content);
506
+	}
507
+
508
+
509
+	/**
510
+	 * @param EE_Event $event
511
+	 * @return string
512
+	 * @throws EE_Error
513
+	 * @throws InvalidArgumentException
514
+	 * @throws InvalidDataTypeException
515
+	 * @throws InvalidInterfaceException
516
+	 * @throws ReflectionException
517
+	 */
518
+	public function column_actions(EE_Event $event): string
519
+	{
520
+		// todo: remove when attendees is active
521
+		if (! defined('REG_ADMIN_URL')) {
522
+			define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
523
+		}
524
+		$action_links   = [];
525
+		$view_link      = get_permalink($event->ID());
526
+		$action_links[] = '<a href="' . $view_link . '" class="ee-aria-tooltip button button--icon-only"'
527
+						  . ' aria-label="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">
528 528
                           <span class="dashicons dashicons-visibility"></span></a>';
529
-        if (
530
-            EE_Registry::instance()->CAP->current_user_can(
531
-                'ee_edit_event',
532
-                'espresso_events_edit',
533
-                $event->ID()
534
-            )
535
-        ) {
536
-            $edit_query_args = [
537
-                'action' => 'edit',
538
-                'post'   => $event->ID(),
539
-            ];
540
-            $edit_link       = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
541
-            $action_links[]  = '<a href="' . $edit_link . '" class="ee-aria-tooltip button button--icon-only"'
542
-                               . ' aria-label="' . esc_attr__('Edit Event', 'event_espresso') . '">'
543
-                               . '<span class="dashicons dashicons-calendar-alt"></span>'
544
-                               . '</a>';
545
-        }
546
-        if (
547
-            EE_Registry::instance()->CAP->current_user_can(
548
-                'ee_read_registrations',
549
-                'espresso_registrations_view_registration'
550
-            )
551
-            && EE_Registry::instance()->CAP->current_user_can(
552
-                'ee_read_event',
553
-                'espresso_registrations_view_registration',
554
-                $event->ID()
555
-            )
556
-        ) {
557
-            $attendees_query_args = [
558
-                'action'   => 'default',
559
-                'event_id' => $event->ID(),
560
-            ];
561
-            $attendees_link       = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
562
-            $action_links[]       = '<a href="' . $attendees_link . '" class="ee-aria-tooltip button button--icon-only"'
563
-                                    . ' aria-label="' . esc_attr__('View Registrants', 'event_espresso') . '">'
564
-                                    . '<span class="dashicons dashicons-groups"></span>'
565
-                                    . '</a>';
566
-        }
567
-        $action_links = apply_filters(
568
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
569
-            $action_links,
570
-            $event
571
-        );
572
-        $content      = $this->_action_string(
573
-            implode("\n\t", $action_links),
574
-            $event,
575
-            'div',
576
-            'event-overview-actions ee-list-table-actions'
577
-        );
578
-        return $this->columnContent('actions', $this->actionsModalMenu($content));
579
-    }
580
-
581
-
582
-    /**
583
-     * Helper for adding columns conditionally
584
-     *
585
-     * @throws EE_Error
586
-     * @throws InvalidArgumentException
587
-     * @throws InvalidDataTypeException
588
-     * @throws InvalidInterfaceException
589
-     * @throws ReflectionException
590
-     */
591
-    private function addConditionalColumns()
592
-    {
593
-        $event_category_count = EEM_Term::instance()->count(
594
-            [['Term_Taxonomy.taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY]]
595
-        );
596
-        if ($event_category_count === 0) {
597
-            return;
598
-        }
599
-        $column_array = [];
600
-        foreach ($this->_columns as $column => $column_label) {
601
-            $column_array[ $column ] = $column_label;
602
-            if ($column === 'venue') {
603
-                $column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
604
-            }
605
-        }
606
-        $this->_columns = $column_array;
607
-    }
529
+		if (
530
+			EE_Registry::instance()->CAP->current_user_can(
531
+				'ee_edit_event',
532
+				'espresso_events_edit',
533
+				$event->ID()
534
+			)
535
+		) {
536
+			$edit_query_args = [
537
+				'action' => 'edit',
538
+				'post'   => $event->ID(),
539
+			];
540
+			$edit_link       = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
541
+			$action_links[]  = '<a href="' . $edit_link . '" class="ee-aria-tooltip button button--icon-only"'
542
+							   . ' aria-label="' . esc_attr__('Edit Event', 'event_espresso') . '">'
543
+							   . '<span class="dashicons dashicons-calendar-alt"></span>'
544
+							   . '</a>';
545
+		}
546
+		if (
547
+			EE_Registry::instance()->CAP->current_user_can(
548
+				'ee_read_registrations',
549
+				'espresso_registrations_view_registration'
550
+			)
551
+			&& EE_Registry::instance()->CAP->current_user_can(
552
+				'ee_read_event',
553
+				'espresso_registrations_view_registration',
554
+				$event->ID()
555
+			)
556
+		) {
557
+			$attendees_query_args = [
558
+				'action'   => 'default',
559
+				'event_id' => $event->ID(),
560
+			];
561
+			$attendees_link       = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
562
+			$action_links[]       = '<a href="' . $attendees_link . '" class="ee-aria-tooltip button button--icon-only"'
563
+									. ' aria-label="' . esc_attr__('View Registrants', 'event_espresso') . '">'
564
+									. '<span class="dashicons dashicons-groups"></span>'
565
+									. '</a>';
566
+		}
567
+		$action_links = apply_filters(
568
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
569
+			$action_links,
570
+			$event
571
+		);
572
+		$content      = $this->_action_string(
573
+			implode("\n\t", $action_links),
574
+			$event,
575
+			'div',
576
+			'event-overview-actions ee-list-table-actions'
577
+		);
578
+		return $this->columnContent('actions', $this->actionsModalMenu($content));
579
+	}
580
+
581
+
582
+	/**
583
+	 * Helper for adding columns conditionally
584
+	 *
585
+	 * @throws EE_Error
586
+	 * @throws InvalidArgumentException
587
+	 * @throws InvalidDataTypeException
588
+	 * @throws InvalidInterfaceException
589
+	 * @throws ReflectionException
590
+	 */
591
+	private function addConditionalColumns()
592
+	{
593
+		$event_category_count = EEM_Term::instance()->count(
594
+			[['Term_Taxonomy.taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY]]
595
+		);
596
+		if ($event_category_count === 0) {
597
+			return;
598
+		}
599
+		$column_array = [];
600
+		foreach ($this->_columns as $column => $column_label) {
601
+			$column_array[ $column ] = $column_label;
602
+			if ($column === 'venue') {
603
+				$column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
604
+			}
605
+		}
606
+		$this->_columns = $column_array;
607
+	}
608 608
 }
Please login to merge, or discard this patch.
admin_pages/registrations/EE_Registrations_List_Table.class.php 2 patches
Indentation   +1045 added lines, -1045 removed lines patch added patch discarded remove patch
@@ -18,615 +18,615 @@  discard block
 block discarded – undo
18 18
  */
19 19
 class EE_Registrations_List_Table extends EE_Admin_List_Table
20 20
 {
21
-    /**
22
-     * @var Registrations_Admin_Page
23
-     */
24
-    protected EE_Admin_Page $_admin_page;
25
-
26
-    protected RegistrationsListTableUserCapabilities $caps_handler;
27
-
28
-    private array $_status;
29
-
30
-    /**
31
-     * An array of transaction details for the related transaction to the registration being processed.
32
-     * This is set via the _set_related_details method.
33
-     *
34
-     * @var array
35
-     */
36
-    protected array $_transaction_details = [];
37
-
38
-    /**
39
-     * An array of event details for the related event to the registration being processed.
40
-     * This is set via the _set_related_details method.
41
-     *
42
-     * @var array
43
-     */
44
-    protected array $_event_details = [];
45
-
46
-    private array $filters = [];
47
-
48
-    private int $EVT_ID = 0;
49
-
50
-    private int $DTT_ID = 0;
51
-
52
-    private int $TKT_ID = 0;
53
-
54
-
55
-    /**
56
-     * @param Registrations_Admin_Page $admin_page
57
-     */
58
-    public function __construct(Registrations_Admin_Page $admin_page)
59
-    {
60
-        $this->caps_handler = new RegistrationsListTableUserCapabilities(EE_Registry::instance()->CAP);
61
-        $this->request      = $this->request ?? LoaderFactory::getShared(RequestInterface::class);
62
-        $this->setupFilters();
63
-        parent::__construct($admin_page);
64
-        $this->_status = $this->_admin_page->get_registration_status_array();
65
-    }
66
-
67
-
68
-    private function setupFilters()
69
-    {
70
-        // for event filtering
71
-        $this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INTEGER);
72
-        $this->EVT_ID = $this->request->getRequestParam('event_id', $this->EVT_ID, DataType::INTEGER);
73
-        // for datetime filtering
74
-        $this->DTT_ID = $this->request->getRequestParam('DTT_ID', 0, DataType::INTEGER);
75
-        $this->DTT_ID = $this->request->getRequestParam('datetime_id', $this->DTT_ID, DataType::INTEGER);
76
-        // for ticket filtering
77
-        $this->TKT_ID = $this->request->getRequestParam('TKT_ID', 0, DataType::INTEGER);
78
-        $this->TKT_ID = $this->request->getRequestParam('ticket_id', $this->TKT_ID, DataType::INTEGER);
79
-
80
-        $filters = [
81
-            'event_id'    => $this->EVT_ID,
82
-            'datetime_id' => $this->DTT_ID,
83
-            'ticket_id'   => $this->TKT_ID,
84
-        ];
85
-        foreach ($filters as $filter_key => $filter_value) {
86
-            if ($filter_value) {
87
-                $this->filters[ $filter_key ] = $filter_value;
88
-            }
89
-        }
90
-
91
-        add_filter(
92
-            'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
93
-            [$this, 'filterExtraQueryArgs'],
94
-            10,
95
-            2
96
-        );
97
-    }
98
-
99
-
100
-    /**
101
-     * @param array         $extra_query_args
102
-     * @param EE_Admin_Page $admin_page
103
-     * @return void
104
-     * @since 5.0.13.p
105
-     */
106
-    public function filterExtraQueryArgs(array $extra_query_args, EE_Admin_Page $admin_page): array
107
-    {
108
-        if ($admin_page instanceof Registrations_Admin_Page) {
109
-            foreach ($admin_page->get_views() as $view_details) {
110
-                foreach ($this->filters as $filter_key => $filter_value) {
111
-                    $extra_query_args[ $view_details['slug'] ][ $filter_key ] = $filter_value;
112
-                }
113
-            }
114
-        }
115
-        return $extra_query_args;
116
-    }
117
-
118
-
119
-    /**
120
-     * @return void
121
-     * @throws EE_Error
122
-     * @throws ReflectionException
123
-     */
124
-    protected function _setup_data()
125
-    {
126
-        $this->_data           = $this->_admin_page->get_registrations($this->_per_page);
127
-        $this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true);
128
-    }
129
-
130
-
131
-    /**
132
-     * @return void
133
-     */
134
-    protected function _set_properties()
135
-    {
136
-        $this->_wp_list_args = [
137
-            'singular' => esc_html__('registration', 'event_espresso'),
138
-            'plural'   => esc_html__('registrations', 'event_espresso'),
139
-            'ajax'     => true,
140
-            'screen'   => $this->_admin_page->get_current_screen()->id,
141
-        ];
142
-
143
-        if ($this->EVT_ID) {
144
-            $this->_columns = [
145
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
146
-                'id'               => esc_html__('ID', 'event_espresso'),
147
-                'ATT_fname'        => esc_html__('Name', 'event_espresso'),
148
-                'ATT_email'        => esc_html__('Email', 'event_espresso'),
149
-                '_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
150
-                'PRC_amount'       => esc_html__('TKT Price', 'event_espresso'),
151
-                '_REG_final_price' => esc_html__('Final Price', 'event_espresso'),
152
-                'TXN_total'        => esc_html__('Total Txn', 'event_espresso'),
153
-                'TXN_paid'         => esc_html__('Paid', 'event_espresso'),
154
-                'actions'          => $this->actionsColumnHeader(),
155
-            ];
156
-        } else {
157
-            $this->_columns = [
158
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
159
-                'id'               => esc_html__('ID', 'event_espresso'),
160
-                'ATT_fname'        => esc_html__('Name', 'event_espresso'),
161
-                '_REG_date'        => esc_html__('TXN Date', 'event_espresso'),
162
-                'event_name'       => esc_html__('Event', 'event_espresso'),
163
-                'DTT_EVT_start'    => esc_html__('Event Date', 'event_espresso'),
164
-                '_REG_final_price' => esc_html__('Price', 'event_espresso'),
165
-                '_REG_paid'        => esc_html__('Paid', 'event_espresso'),
166
-                'actions'          => $this->actionsColumnHeader(),
167
-            ];
168
-        }
169
-
170
-        $this->_primary_column   = 'id';
171
-        $this->_sortable_columns = [
172
-            '_REG_date'     => ['_REG_date' => true],   // true means its already sorted
173
-            /**
174
-             * Allows users to change the default sort if they wish.
175
-             * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
176
-             * name.
177
-             */
178
-            'ATT_fname'     => [
179
-                'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
180
-                true,
181
-                $this,
182
-            ]
183
-                ? ['ATT_lname' => false]
184
-                : ['ATT_fname' => false],
185
-            'event_name'    => ['event_name' => false],
186
-            'DTT_EVT_start' => ['DTT_EVT_start' => false],
187
-            'id'            => ['REG_ID' => false],
188
-        ];
189
-        $this->_hidden_columns   = [];
190
-
191
-        $csv_report = RegistrationsCsvReportParams::getRequestParams(
192
-            $this->getReturnUrl(),
193
-            $this->_admin_page->get_request_data(),
194
-            $this->EVT_ID,
195
-            $this->DTT_ID
196
-        );
197
-        if (! empty($csv_report)) {
198
-            $this->_bottom_buttons['csv_reg_report'] = $csv_report;
199
-        }
200
-    }
201
-
202
-
203
-    /**
204
-     * This simply sets up the row class for the table rows.
205
-     * Allows for easier overriding of child methods for setting up sorting.
206
-     *
207
-     * @param EE_Registration $item the current item
208
-     * @return string
209
-     */
210
-    protected function _get_row_class($item): string
211
-    {
212
-        $class = parent::_get_row_class($item);
213
-        if ($this->_has_checkbox_column) {
214
-            $class .= ' has-checkbox-column';
215
-        }
216
-        return $class;
217
-    }
218
-
219
-
220
-    /**
221
-     * Set the $_transaction_details property if not set yet.
222
-     *
223
-     * @param EE_Registration $registration
224
-     * @throws EE_Error
225
-     * @throws InvalidArgumentException
226
-     * @throws ReflectionException
227
-     * @throws InvalidDataTypeException
228
-     * @throws InvalidInterfaceException
229
-     */
230
-    protected function _set_related_details(EE_Registration $registration)
231
-    {
232
-        $transaction                = $registration->transaction();
233
-        $status                     = $transaction->status_ID();
234
-        $this->_transaction_details = [
235
-            'transaction' => $transaction,
236
-            'status'      => $status,
237
-            'id'          => $transaction->ID(),
238
-            'title_attr'  => sprintf(
239
-                esc_html__('View Transaction Details (%s)', 'event_espresso'),
240
-                EEH_Template::pretty_status($status, false, 'sentence')
241
-            ),
242
-        ];
243
-        try {
244
-            $event = $registration->event();
245
-        } catch (EntityNotFoundException $e) {
246
-            $event = null;
247
-        }
248
-        $status               = $event instanceof EE_Event
249
-            ? $event->get_active_status()
250
-            : EE_Datetime::inactive;
251
-        $this->_event_details = [
252
-            'event'      => $event,
253
-            'status'     => $status,
254
-            'id'         => $event instanceof EE_Event
255
-                ? $event->ID()
256
-                : 0,
257
-            'title_attr' => sprintf(
258
-                esc_html__('Edit Event (%s)', 'event_espresso'),
259
-                EEH_Template::pretty_status($status, false, 'sentence')
260
-            ),
261
-        ];
262
-    }
263
-
264
-
265
-    /**
266
-     * @return array
267
-     * @throws EE_Error
268
-     * @throws ReflectionException
269
-     */
270
-    protected function _get_table_filters()
271
-    {
272
-        $filters = [];
273
-        // todo we're currently using old functions here. We need to move things into the Events_Admin_Page() class as
274
-        // methods.
275
-        $cur_date     = $this->request->getRequestParam('month_range', '');
276
-        $cur_category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INTEGER);
277
-        $reg_status   = $this->request->getRequestParam('_reg_status', '');
278
-        $filters[]    = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
279
-        $filters[]    = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
280
-        $status       = [];
281
-        $status[]     = ['id' => 0, 'text' => esc_html__('Select Status', 'event_espresso')];
282
-        foreach ($this->_status as $key => $value) {
283
-            $status[] = ['id' => $key, 'text' => $value];
284
-        }
285
-        if ($this->_view !== 'incomplete') {
286
-            $filters[] = EEH_Form_Fields::select_input(
287
-                '_reg_status',
288
-                $status,
289
-                $reg_status ? strtoupper($reg_status) : ''
290
-            );
291
-        }
292
-        foreach ($this->filters as $filter_key => $filter_value) {
293
-            $filters[] = EEH_Form_Fields::hidden_input($filter_key, $filter_value, 'reg_' . $filter_key);
294
-        }
295
-        return $filters;
296
-    }
297
-
298
-
299
-    /**
300
-     * @return void
301
-     * @throws EE_Error
302
-     * @throws InvalidArgumentException
303
-     * @throws InvalidDataTypeException
304
-     * @throws InvalidInterfaceException
305
-     * @throws ReflectionException
306
-     */
307
-    protected function _add_view_counts()
308
-    {
309
-        $this->_views['all']['count']       = $this->_total_registrations();
310
-        $this->_views['today']['count']     = $this->_total_registrations_today();
311
-        $this->_views['yesterday']['count'] = $this->totalRegistrationsYesterday();
312
-        $this->_views['month']['count']     = $this->_total_registrations_this_month();
313
-        if ($this->caps_handler->userCanTrashRegistrations()) {
314
-            $this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
315
-            $this->_views['trash']['count']      = $this->_total_registrations('trash');
316
-        }
317
-    }
318
-
319
-
320
-    private function addWhereParamsForFilters(array $where = []): array
321
-    {
322
-        if ($this->EVT_ID) {
323
-            $where['EVT_ID'] = $this->EVT_ID;
324
-        }
325
-        if ($this->DTT_ID) {
326
-            $where['Ticket.Datetime.DTT_ID'] = $this->DTT_ID;
327
-        }
328
-        if ($this->TKT_ID) {
329
-            $where['TKT_ID'] = $this->TKT_ID;
330
-        }
331
-        return $where;
332
-    }
333
-
334
-
335
-    /**
336
-     * @param string $view
337
-     * @return int
338
-     * @throws EE_Error
339
-     * @throws ReflectionException
340
-     */
341
-    protected function _total_registrations(string $view = ''): int
342
-    {
343
-        $where = $this->addWhereParamsForFilters();
344
-        switch ($view) {
345
-            case 'trash':
346
-                return EEM_Registration::instance()->count_deleted([$where]);
347
-            case 'incomplete':
348
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
349
-                break;
350
-            default:
351
-                $where['STS_ID'] = ['!=', EEM_Registration::status_id_incomplete];
352
-        }
353
-        return EEM_Registration::instance()->count([$where]);
354
-    }
355
-
356
-
357
-    /**
358
-     * @return int
359
-     * @throws EE_Error
360
-     * @throws ReflectionException
361
-     */
362
-    protected function _total_registrations_this_month(): int
363
-    {
364
-        $current_time   = current_time('timestamp');
365
-        $year_and_month = date('Y-m', $current_time);
366
-        $days_in_month  = date('t', $current_time);
367
-
368
-        $start_date = "$year_and_month-01";
369
-        $end_date   = "$year_and_month-$days_in_month";
370
-
371
-        return $this->totalRegistrationsForDateRange($start_date, $end_date);
372
-    }
373
-
374
-
375
-    /**
376
-     * @return int
377
-     * @throws EE_Error
378
-     * @throws ReflectionException
379
-     */
380
-    protected function _total_registrations_today(): int
381
-    {
382
-        $today = date('Y-m-d', current_time('timestamp'));
383
-        return $this->totalRegistrationsForDateRange($today, $today);
384
-    }
385
-
386
-
387
-    /**
388
-     * @return int
389
-     * @throws EE_Error
390
-     * @throws ReflectionException
391
-     */
392
-    protected function totalRegistrationsYesterday(): int
393
-    {
394
-        $yesterday = date('Y-m-d', current_time('timestamp') - DAY_IN_SECONDS);
395
-        return $this->totalRegistrationsForDateRange($yesterday, $yesterday);
396
-    }
397
-
398
-
399
-    /**
400
-     * @param string $start_date earlier date string in format 'Y-m-d'
401
-     * @param string $end_date   later date string in format 'Y-m-d'
402
-     * @return int
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     */
406
-    private function totalRegistrationsForDateRange(string $start_date, string $end_date): int
407
-    {
408
-        $where = $this->addWhereParamsForFilters(
409
-            [
410
-                'REG_date' => [
411
-                    'BETWEEN',
412
-                    [
413
-                        EEM_Registration::instance()->convert_datetime_for_query(
414
-                            'REG_date',
415
-                            "$start_date 00:00:00",
416
-                            'Y-m-d H:i:s'
417
-                        ),
418
-                        EEM_Registration::instance()->convert_datetime_for_query(
419
-                            'REG_date',
420
-                            "$end_date  23:59:59",
421
-                            'Y-m-d H:i:s'
422
-                        ),
423
-                    ],
424
-                ],
425
-                'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
426
-            ]
427
-        );
428
-        return EEM_Registration::instance()->count([$where]);
429
-    }
430
-
431
-
432
-    /**
433
-     * @param EE_Registration $item
434
-     * @return string
435
-     * @throws EE_Error
436
-     * @throws InvalidArgumentException
437
-     * @throws InvalidDataTypeException
438
-     * @throws InvalidInterfaceException
439
-     * @throws ReflectionException
440
-     */
441
-    public function column_cb($item): string
442
-    {
443
-        /** checkbox/lock **/
444
-        $REG_ID        = $item->ID();
445
-        $transaction   = $item->transaction();
446
-        $payment_count = $transaction->count_related('Payment');
447
-
448
-        $content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
449
-        $content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
450
-            ? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
21
+	/**
22
+	 * @var Registrations_Admin_Page
23
+	 */
24
+	protected EE_Admin_Page $_admin_page;
25
+
26
+	protected RegistrationsListTableUserCapabilities $caps_handler;
27
+
28
+	private array $_status;
29
+
30
+	/**
31
+	 * An array of transaction details for the related transaction to the registration being processed.
32
+	 * This is set via the _set_related_details method.
33
+	 *
34
+	 * @var array
35
+	 */
36
+	protected array $_transaction_details = [];
37
+
38
+	/**
39
+	 * An array of event details for the related event to the registration being processed.
40
+	 * This is set via the _set_related_details method.
41
+	 *
42
+	 * @var array
43
+	 */
44
+	protected array $_event_details = [];
45
+
46
+	private array $filters = [];
47
+
48
+	private int $EVT_ID = 0;
49
+
50
+	private int $DTT_ID = 0;
51
+
52
+	private int $TKT_ID = 0;
53
+
54
+
55
+	/**
56
+	 * @param Registrations_Admin_Page $admin_page
57
+	 */
58
+	public function __construct(Registrations_Admin_Page $admin_page)
59
+	{
60
+		$this->caps_handler = new RegistrationsListTableUserCapabilities(EE_Registry::instance()->CAP);
61
+		$this->request      = $this->request ?? LoaderFactory::getShared(RequestInterface::class);
62
+		$this->setupFilters();
63
+		parent::__construct($admin_page);
64
+		$this->_status = $this->_admin_page->get_registration_status_array();
65
+	}
66
+
67
+
68
+	private function setupFilters()
69
+	{
70
+		// for event filtering
71
+		$this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INTEGER);
72
+		$this->EVT_ID = $this->request->getRequestParam('event_id', $this->EVT_ID, DataType::INTEGER);
73
+		// for datetime filtering
74
+		$this->DTT_ID = $this->request->getRequestParam('DTT_ID', 0, DataType::INTEGER);
75
+		$this->DTT_ID = $this->request->getRequestParam('datetime_id', $this->DTT_ID, DataType::INTEGER);
76
+		// for ticket filtering
77
+		$this->TKT_ID = $this->request->getRequestParam('TKT_ID', 0, DataType::INTEGER);
78
+		$this->TKT_ID = $this->request->getRequestParam('ticket_id', $this->TKT_ID, DataType::INTEGER);
79
+
80
+		$filters = [
81
+			'event_id'    => $this->EVT_ID,
82
+			'datetime_id' => $this->DTT_ID,
83
+			'ticket_id'   => $this->TKT_ID,
84
+		];
85
+		foreach ($filters as $filter_key => $filter_value) {
86
+			if ($filter_value) {
87
+				$this->filters[ $filter_key ] = $filter_value;
88
+			}
89
+		}
90
+
91
+		add_filter(
92
+			'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
93
+			[$this, 'filterExtraQueryArgs'],
94
+			10,
95
+			2
96
+		);
97
+	}
98
+
99
+
100
+	/**
101
+	 * @param array         $extra_query_args
102
+	 * @param EE_Admin_Page $admin_page
103
+	 * @return void
104
+	 * @since 5.0.13.p
105
+	 */
106
+	public function filterExtraQueryArgs(array $extra_query_args, EE_Admin_Page $admin_page): array
107
+	{
108
+		if ($admin_page instanceof Registrations_Admin_Page) {
109
+			foreach ($admin_page->get_views() as $view_details) {
110
+				foreach ($this->filters as $filter_key => $filter_value) {
111
+					$extra_query_args[ $view_details['slug'] ][ $filter_key ] = $filter_value;
112
+				}
113
+			}
114
+		}
115
+		return $extra_query_args;
116
+	}
117
+
118
+
119
+	/**
120
+	 * @return void
121
+	 * @throws EE_Error
122
+	 * @throws ReflectionException
123
+	 */
124
+	protected function _setup_data()
125
+	{
126
+		$this->_data           = $this->_admin_page->get_registrations($this->_per_page);
127
+		$this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true);
128
+	}
129
+
130
+
131
+	/**
132
+	 * @return void
133
+	 */
134
+	protected function _set_properties()
135
+	{
136
+		$this->_wp_list_args = [
137
+			'singular' => esc_html__('registration', 'event_espresso'),
138
+			'plural'   => esc_html__('registrations', 'event_espresso'),
139
+			'ajax'     => true,
140
+			'screen'   => $this->_admin_page->get_current_screen()->id,
141
+		];
142
+
143
+		if ($this->EVT_ID) {
144
+			$this->_columns = [
145
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
146
+				'id'               => esc_html__('ID', 'event_espresso'),
147
+				'ATT_fname'        => esc_html__('Name', 'event_espresso'),
148
+				'ATT_email'        => esc_html__('Email', 'event_espresso'),
149
+				'_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
150
+				'PRC_amount'       => esc_html__('TKT Price', 'event_espresso'),
151
+				'_REG_final_price' => esc_html__('Final Price', 'event_espresso'),
152
+				'TXN_total'        => esc_html__('Total Txn', 'event_espresso'),
153
+				'TXN_paid'         => esc_html__('Paid', 'event_espresso'),
154
+				'actions'          => $this->actionsColumnHeader(),
155
+			];
156
+		} else {
157
+			$this->_columns = [
158
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
159
+				'id'               => esc_html__('ID', 'event_espresso'),
160
+				'ATT_fname'        => esc_html__('Name', 'event_espresso'),
161
+				'_REG_date'        => esc_html__('TXN Date', 'event_espresso'),
162
+				'event_name'       => esc_html__('Event', 'event_espresso'),
163
+				'DTT_EVT_start'    => esc_html__('Event Date', 'event_espresso'),
164
+				'_REG_final_price' => esc_html__('Price', 'event_espresso'),
165
+				'_REG_paid'        => esc_html__('Paid', 'event_espresso'),
166
+				'actions'          => $this->actionsColumnHeader(),
167
+			];
168
+		}
169
+
170
+		$this->_primary_column   = 'id';
171
+		$this->_sortable_columns = [
172
+			'_REG_date'     => ['_REG_date' => true],   // true means its already sorted
173
+			/**
174
+			 * Allows users to change the default sort if they wish.
175
+			 * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
176
+			 * name.
177
+			 */
178
+			'ATT_fname'     => [
179
+				'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
180
+				true,
181
+				$this,
182
+			]
183
+				? ['ATT_lname' => false]
184
+				: ['ATT_fname' => false],
185
+			'event_name'    => ['event_name' => false],
186
+			'DTT_EVT_start' => ['DTT_EVT_start' => false],
187
+			'id'            => ['REG_ID' => false],
188
+		];
189
+		$this->_hidden_columns   = [];
190
+
191
+		$csv_report = RegistrationsCsvReportParams::getRequestParams(
192
+			$this->getReturnUrl(),
193
+			$this->_admin_page->get_request_data(),
194
+			$this->EVT_ID,
195
+			$this->DTT_ID
196
+		);
197
+		if (! empty($csv_report)) {
198
+			$this->_bottom_buttons['csv_reg_report'] = $csv_report;
199
+		}
200
+	}
201
+
202
+
203
+	/**
204
+	 * This simply sets up the row class for the table rows.
205
+	 * Allows for easier overriding of child methods for setting up sorting.
206
+	 *
207
+	 * @param EE_Registration $item the current item
208
+	 * @return string
209
+	 */
210
+	protected function _get_row_class($item): string
211
+	{
212
+		$class = parent::_get_row_class($item);
213
+		if ($this->_has_checkbox_column) {
214
+			$class .= ' has-checkbox-column';
215
+		}
216
+		return $class;
217
+	}
218
+
219
+
220
+	/**
221
+	 * Set the $_transaction_details property if not set yet.
222
+	 *
223
+	 * @param EE_Registration $registration
224
+	 * @throws EE_Error
225
+	 * @throws InvalidArgumentException
226
+	 * @throws ReflectionException
227
+	 * @throws InvalidDataTypeException
228
+	 * @throws InvalidInterfaceException
229
+	 */
230
+	protected function _set_related_details(EE_Registration $registration)
231
+	{
232
+		$transaction                = $registration->transaction();
233
+		$status                     = $transaction->status_ID();
234
+		$this->_transaction_details = [
235
+			'transaction' => $transaction,
236
+			'status'      => $status,
237
+			'id'          => $transaction->ID(),
238
+			'title_attr'  => sprintf(
239
+				esc_html__('View Transaction Details (%s)', 'event_espresso'),
240
+				EEH_Template::pretty_status($status, false, 'sentence')
241
+			),
242
+		];
243
+		try {
244
+			$event = $registration->event();
245
+		} catch (EntityNotFoundException $e) {
246
+			$event = null;
247
+		}
248
+		$status               = $event instanceof EE_Event
249
+			? $event->get_active_status()
250
+			: EE_Datetime::inactive;
251
+		$this->_event_details = [
252
+			'event'      => $event,
253
+			'status'     => $status,
254
+			'id'         => $event instanceof EE_Event
255
+				? $event->ID()
256
+				: 0,
257
+			'title_attr' => sprintf(
258
+				esc_html__('Edit Event (%s)', 'event_espresso'),
259
+				EEH_Template::pretty_status($status, false, 'sentence')
260
+			),
261
+		];
262
+	}
263
+
264
+
265
+	/**
266
+	 * @return array
267
+	 * @throws EE_Error
268
+	 * @throws ReflectionException
269
+	 */
270
+	protected function _get_table_filters()
271
+	{
272
+		$filters = [];
273
+		// todo we're currently using old functions here. We need to move things into the Events_Admin_Page() class as
274
+		// methods.
275
+		$cur_date     = $this->request->getRequestParam('month_range', '');
276
+		$cur_category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INTEGER);
277
+		$reg_status   = $this->request->getRequestParam('_reg_status', '');
278
+		$filters[]    = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
279
+		$filters[]    = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
280
+		$status       = [];
281
+		$status[]     = ['id' => 0, 'text' => esc_html__('Select Status', 'event_espresso')];
282
+		foreach ($this->_status as $key => $value) {
283
+			$status[] = ['id' => $key, 'text' => $value];
284
+		}
285
+		if ($this->_view !== 'incomplete') {
286
+			$filters[] = EEH_Form_Fields::select_input(
287
+				'_reg_status',
288
+				$status,
289
+				$reg_status ? strtoupper($reg_status) : ''
290
+			);
291
+		}
292
+		foreach ($this->filters as $filter_key => $filter_value) {
293
+			$filters[] = EEH_Form_Fields::hidden_input($filter_key, $filter_value, 'reg_' . $filter_key);
294
+		}
295
+		return $filters;
296
+	}
297
+
298
+
299
+	/**
300
+	 * @return void
301
+	 * @throws EE_Error
302
+	 * @throws InvalidArgumentException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws InvalidInterfaceException
305
+	 * @throws ReflectionException
306
+	 */
307
+	protected function _add_view_counts()
308
+	{
309
+		$this->_views['all']['count']       = $this->_total_registrations();
310
+		$this->_views['today']['count']     = $this->_total_registrations_today();
311
+		$this->_views['yesterday']['count'] = $this->totalRegistrationsYesterday();
312
+		$this->_views['month']['count']     = $this->_total_registrations_this_month();
313
+		if ($this->caps_handler->userCanTrashRegistrations()) {
314
+			$this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
315
+			$this->_views['trash']['count']      = $this->_total_registrations('trash');
316
+		}
317
+	}
318
+
319
+
320
+	private function addWhereParamsForFilters(array $where = []): array
321
+	{
322
+		if ($this->EVT_ID) {
323
+			$where['EVT_ID'] = $this->EVT_ID;
324
+		}
325
+		if ($this->DTT_ID) {
326
+			$where['Ticket.Datetime.DTT_ID'] = $this->DTT_ID;
327
+		}
328
+		if ($this->TKT_ID) {
329
+			$where['TKT_ID'] = $this->TKT_ID;
330
+		}
331
+		return $where;
332
+	}
333
+
334
+
335
+	/**
336
+	 * @param string $view
337
+	 * @return int
338
+	 * @throws EE_Error
339
+	 * @throws ReflectionException
340
+	 */
341
+	protected function _total_registrations(string $view = ''): int
342
+	{
343
+		$where = $this->addWhereParamsForFilters();
344
+		switch ($view) {
345
+			case 'trash':
346
+				return EEM_Registration::instance()->count_deleted([$where]);
347
+			case 'incomplete':
348
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
349
+				break;
350
+			default:
351
+				$where['STS_ID'] = ['!=', EEM_Registration::status_id_incomplete];
352
+		}
353
+		return EEM_Registration::instance()->count([$where]);
354
+	}
355
+
356
+
357
+	/**
358
+	 * @return int
359
+	 * @throws EE_Error
360
+	 * @throws ReflectionException
361
+	 */
362
+	protected function _total_registrations_this_month(): int
363
+	{
364
+		$current_time   = current_time('timestamp');
365
+		$year_and_month = date('Y-m', $current_time);
366
+		$days_in_month  = date('t', $current_time);
367
+
368
+		$start_date = "$year_and_month-01";
369
+		$end_date   = "$year_and_month-$days_in_month";
370
+
371
+		return $this->totalRegistrationsForDateRange($start_date, $end_date);
372
+	}
373
+
374
+
375
+	/**
376
+	 * @return int
377
+	 * @throws EE_Error
378
+	 * @throws ReflectionException
379
+	 */
380
+	protected function _total_registrations_today(): int
381
+	{
382
+		$today = date('Y-m-d', current_time('timestamp'));
383
+		return $this->totalRegistrationsForDateRange($today, $today);
384
+	}
385
+
386
+
387
+	/**
388
+	 * @return int
389
+	 * @throws EE_Error
390
+	 * @throws ReflectionException
391
+	 */
392
+	protected function totalRegistrationsYesterday(): int
393
+	{
394
+		$yesterday = date('Y-m-d', current_time('timestamp') - DAY_IN_SECONDS);
395
+		return $this->totalRegistrationsForDateRange($yesterday, $yesterday);
396
+	}
397
+
398
+
399
+	/**
400
+	 * @param string $start_date earlier date string in format 'Y-m-d'
401
+	 * @param string $end_date   later date string in format 'Y-m-d'
402
+	 * @return int
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 */
406
+	private function totalRegistrationsForDateRange(string $start_date, string $end_date): int
407
+	{
408
+		$where = $this->addWhereParamsForFilters(
409
+			[
410
+				'REG_date' => [
411
+					'BETWEEN',
412
+					[
413
+						EEM_Registration::instance()->convert_datetime_for_query(
414
+							'REG_date',
415
+							"$start_date 00:00:00",
416
+							'Y-m-d H:i:s'
417
+						),
418
+						EEM_Registration::instance()->convert_datetime_for_query(
419
+							'REG_date',
420
+							"$end_date  23:59:59",
421
+							'Y-m-d H:i:s'
422
+						),
423
+					],
424
+				],
425
+				'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
426
+			]
427
+		);
428
+		return EEM_Registration::instance()->count([$where]);
429
+	}
430
+
431
+
432
+	/**
433
+	 * @param EE_Registration $item
434
+	 * @return string
435
+	 * @throws EE_Error
436
+	 * @throws InvalidArgumentException
437
+	 * @throws InvalidDataTypeException
438
+	 * @throws InvalidInterfaceException
439
+	 * @throws ReflectionException
440
+	 */
441
+	public function column_cb($item): string
442
+	{
443
+		/** checkbox/lock **/
444
+		$REG_ID        = $item->ID();
445
+		$transaction   = $item->transaction();
446
+		$payment_count = $transaction->count_related('Payment');
447
+
448
+		$content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
449
+		$content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
450
+			? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
451 451
                     aria-label="' . $this->lockedRegMessage() . '"></span>'
452
-            : '';
453
-        return $this->columnContent('cb', $content, 'center');
454
-    }
455
-
456
-
457
-    private function lockedRegMessage(): string
458
-    {
459
-        return esc_html__(
460
-            'This lock-icon means that this registration cannot be trashed.  Registrations that belong to a transaction that has payments cannot be trashed.  If you wish to trash this registration then you must delete all payments attached to the related transaction first.',
461
-            'event_espresso'
462
-        );
463
-    }
464
-
465
-
466
-    /**
467
-     * @param EE_Registration $registration
468
-     * @return string
469
-     * @throws EE_Error
470
-     * @throws InvalidArgumentException
471
-     * @throws InvalidDataTypeException
472
-     * @throws InvalidInterfaceException
473
-     * @throws ReflectionException
474
-     */
475
-    public function column_id(EE_Registration $registration): string
476
-    {
477
-        $content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
478
-        $content .= '<span class="show-on-mobile-view-only">';
479
-        $content .= $this->column_ATT_fname($registration, false);
480
-        $content .= '</span>';
481
-
482
-        return $this->columnContent('id', $content, 'end');
483
-    }
484
-
485
-
486
-    /**
487
-     * @param EE_Registration $registration
488
-     * @param bool            $prep_content
489
-     * @return string
490
-     * @throws EE_Error
491
-     * @throws ReflectionException
492
-     */
493
-    public function column_ATT_fname(EE_Registration $registration, bool $prep_content = true): string
494
-    {
495
-        $status         = esc_attr($registration->status_ID());
496
-        $pretty_status  = EEH_Template::pretty_status($status, false, 'sentence');
497
-        $prime_reg_star = $registration->count() === 1
498
-            ? '<sup><span class="dashicons dashicons-star-filled gold-icon"></span></sup>'
499
-            : '';
500
-
501
-        $group_count = '
452
+			: '';
453
+		return $this->columnContent('cb', $content, 'center');
454
+	}
455
+
456
+
457
+	private function lockedRegMessage(): string
458
+	{
459
+		return esc_html__(
460
+			'This lock-icon means that this registration cannot be trashed.  Registrations that belong to a transaction that has payments cannot be trashed.  If you wish to trash this registration then you must delete all payments attached to the related transaction first.',
461
+			'event_espresso'
462
+		);
463
+	}
464
+
465
+
466
+	/**
467
+	 * @param EE_Registration $registration
468
+	 * @return string
469
+	 * @throws EE_Error
470
+	 * @throws InvalidArgumentException
471
+	 * @throws InvalidDataTypeException
472
+	 * @throws InvalidInterfaceException
473
+	 * @throws ReflectionException
474
+	 */
475
+	public function column_id(EE_Registration $registration): string
476
+	{
477
+		$content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
478
+		$content .= '<span class="show-on-mobile-view-only">';
479
+		$content .= $this->column_ATT_fname($registration, false);
480
+		$content .= '</span>';
481
+
482
+		return $this->columnContent('id', $content, 'end');
483
+	}
484
+
485
+
486
+	/**
487
+	 * @param EE_Registration $registration
488
+	 * @param bool            $prep_content
489
+	 * @return string
490
+	 * @throws EE_Error
491
+	 * @throws ReflectionException
492
+	 */
493
+	public function column_ATT_fname(EE_Registration $registration, bool $prep_content = true): string
494
+	{
495
+		$status         = esc_attr($registration->status_ID());
496
+		$pretty_status  = EEH_Template::pretty_status($status, false, 'sentence');
497
+		$prime_reg_star = $registration->count() === 1
498
+			? '<sup><span class="dashicons dashicons-star-filled gold-icon"></span></sup>'
499
+			: '';
500
+
501
+		$group_count = '
502 502
             <span class="reg-count-group-size" >
503 503
                 ' . sprintf(
504
-                esc_html__('(%1$s / %2$s)', 'event_espresso'),
505
-                $registration->count(),
506
-                $registration->group_size()
507
-            ) . '
504
+				esc_html__('(%1$s / %2$s)', 'event_espresso'),
505
+				$registration->count(),
506
+				$registration->group_size()
507
+			) . '
508 508
             </span >';
509 509
 
510
-        $content = '
510
+		$content = '
511 511
         <div class="ee-layout-row">
512 512
             <span aria-label="' . $pretty_status . '"
513 513
                   class="ee-status-dot ee-status-bg--' . $status . ' ee-aria-tooltip"
514 514
             ></span>
515 515
             ' . $this->viewRegistrationLink($registration, $status)
516
-            . $prime_reg_star
517
-            . $group_count . '
516
+			. $prime_reg_star
517
+			. $group_count . '
518 518
             <span class="spacer"></span>
519 519
             <span>
520 520
                 ' . sprintf(
521
-                esc_html__('Reg Code: %s', 'event_espresso'),
522
-                $registration->get('REG_code')
523
-            ) . '
521
+				esc_html__('Reg Code: %s', 'event_espresso'),
522
+				$registration->get('REG_code')
523
+			) . '
524 524
             </span>
525 525
         </div>';
526 526
 
527
-        $url_params = ['_REG_ID' => $registration->ID()];
528
-        if ($this->EVT_ID) {
529
-            $url_params['event_id'] = $this->EVT_ID;
530
-        }
531
-        // trash/restore/delete actions
532
-        $actions = $this->trashRegistrationLink($registration, $url_params);
533
-        $actions = $this->restoreRegistrationLink($registration, $url_params, $actions);
534
-        $actions = $this->deleteRegistrationLink($registration, $url_params, $actions);
535
-
536
-        $content = sprintf('%1$s %2$s', $content, $this->row_actions($actions));
537
-
538
-        return $prep_content ? $this->columnContent('ATT_fname', $content) : $content;
539
-    }
540
-
541
-
542
-    /**
543
-     * @param EE_Registration $registration
544
-     * @param bool            $prep_content
545
-     * @return string
546
-     * @throws EE_Error
547
-     * @throws ReflectionException
548
-     */
549
-    public function column__REG_date(EE_Registration $registration, bool $prep_content = true): string
550
-    {
551
-        $this->_set_related_details($registration);
552
-        // Build row actions
553
-        $content = $this->caps_handler->userCanViewTransaction()
554
-            ? '<a class="ee-aria-tooltip ee-status-color--' . $this->_transaction_details['status'] . '" href="'
555
-            . $this->viewTransactionUrl()
556
-            . '" aria-label="'
557
-            . esc_attr($this->_transaction_details['title_attr'])
558
-            . '">'
559
-            . $registration->get_i18n_datetime('REG_date', 'M jS Y g:i a')
560
-            . '</a>'
561
-            : $registration->get_i18n_datetime('REG_date');
562
-
563
-        return $prep_content ? $this->columnContent('_REG_date', $content) : $content;
564
-    }
565
-
566
-
567
-    /**
568
-     * @param EE_Registration $registration
569
-     * @return string
570
-     * @throws EE_Error
571
-     * @throws InvalidArgumentException
572
-     * @throws InvalidDataTypeException
573
-     * @throws InvalidInterfaceException
574
-     * @throws ReflectionException
575
-     */
576
-    public function column_event_name(EE_Registration $registration): string
577
-    {
578
-        $this->_set_related_details($registration);
579
-        $EVT_ID                  = $registration->event_ID();
580
-        $event_name              = $registration->event_name();
581
-        $event_name              = $event_name ?: esc_html__("No Associated Event", 'event_espresso');
582
-        $event_name              = wp_trim_words($event_name, 30, '...');
583
-        $edit_event              = $this->editEventLink($EVT_ID, $event_name);
584
-        $actions['event_filter'] = $this->eventFilterLink($EVT_ID, $event_name);
585
-        $content                 = sprintf('%1$s %2$s', $edit_event, $this->row_actions($actions));
586
-
587
-        return $this->columnContent('event_name', $content);
588
-    }
589
-
590
-
591
-    /**
592
-     * @param EE_Registration $registration
593
-     * @return string
594
-     * @throws EE_Error
595
-     * @throws InvalidArgumentException
596
-     * @throws InvalidDataTypeException
597
-     * @throws InvalidInterfaceException
598
-     * @throws ReflectionException
599
-     */
600
-    public function column_DTT_EVT_start(EE_Registration $registration): string
601
-    {
602
-        $datetime_strings = [];
603
-        $ticket           = $registration->ticket();
604
-        if ($ticket instanceof EE_Ticket) {
605
-            $remove_defaults = ['default_where_conditions' => 'none'];
606
-            $datetimes       = $ticket->datetimes($remove_defaults);
607
-            foreach ($datetimes as $datetime) {
608
-                $datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start', 'M jS Y g:i a');
609
-            }
610
-            $content = $this->generateDisplayForDatetimes($datetime_strings);
611
-        } else {
612
-            $content = esc_html__('There is no ticket on this registration', 'event_espresso');
613
-        }
614
-        return $this->columnContent('DTT_EVT_start', $content);
615
-    }
616
-
617
-
618
-    /**
619
-     * Receives an array of datetime strings to display and converts them to the html container for the column.
620
-     *
621
-     * @param array $datetime_strings
622
-     * @return string
623
-     */
624
-    public function generateDisplayForDatetimes(array $datetime_strings): string
625
-    {
626
-        // get first item for initial visibility
627
-        $content = (string) array_shift($datetime_strings);
628
-        if (! empty($datetime_strings)) {
629
-            $content .= '
527
+		$url_params = ['_REG_ID' => $registration->ID()];
528
+		if ($this->EVT_ID) {
529
+			$url_params['event_id'] = $this->EVT_ID;
530
+		}
531
+		// trash/restore/delete actions
532
+		$actions = $this->trashRegistrationLink($registration, $url_params);
533
+		$actions = $this->restoreRegistrationLink($registration, $url_params, $actions);
534
+		$actions = $this->deleteRegistrationLink($registration, $url_params, $actions);
535
+
536
+		$content = sprintf('%1$s %2$s', $content, $this->row_actions($actions));
537
+
538
+		return $prep_content ? $this->columnContent('ATT_fname', $content) : $content;
539
+	}
540
+
541
+
542
+	/**
543
+	 * @param EE_Registration $registration
544
+	 * @param bool            $prep_content
545
+	 * @return string
546
+	 * @throws EE_Error
547
+	 * @throws ReflectionException
548
+	 */
549
+	public function column__REG_date(EE_Registration $registration, bool $prep_content = true): string
550
+	{
551
+		$this->_set_related_details($registration);
552
+		// Build row actions
553
+		$content = $this->caps_handler->userCanViewTransaction()
554
+			? '<a class="ee-aria-tooltip ee-status-color--' . $this->_transaction_details['status'] . '" href="'
555
+			. $this->viewTransactionUrl()
556
+			. '" aria-label="'
557
+			. esc_attr($this->_transaction_details['title_attr'])
558
+			. '">'
559
+			. $registration->get_i18n_datetime('REG_date', 'M jS Y g:i a')
560
+			. '</a>'
561
+			: $registration->get_i18n_datetime('REG_date');
562
+
563
+		return $prep_content ? $this->columnContent('_REG_date', $content) : $content;
564
+	}
565
+
566
+
567
+	/**
568
+	 * @param EE_Registration $registration
569
+	 * @return string
570
+	 * @throws EE_Error
571
+	 * @throws InvalidArgumentException
572
+	 * @throws InvalidDataTypeException
573
+	 * @throws InvalidInterfaceException
574
+	 * @throws ReflectionException
575
+	 */
576
+	public function column_event_name(EE_Registration $registration): string
577
+	{
578
+		$this->_set_related_details($registration);
579
+		$EVT_ID                  = $registration->event_ID();
580
+		$event_name              = $registration->event_name();
581
+		$event_name              = $event_name ?: esc_html__("No Associated Event", 'event_espresso');
582
+		$event_name              = wp_trim_words($event_name, 30, '...');
583
+		$edit_event              = $this->editEventLink($EVT_ID, $event_name);
584
+		$actions['event_filter'] = $this->eventFilterLink($EVT_ID, $event_name);
585
+		$content                 = sprintf('%1$s %2$s', $edit_event, $this->row_actions($actions));
586
+
587
+		return $this->columnContent('event_name', $content);
588
+	}
589
+
590
+
591
+	/**
592
+	 * @param EE_Registration $registration
593
+	 * @return string
594
+	 * @throws EE_Error
595
+	 * @throws InvalidArgumentException
596
+	 * @throws InvalidDataTypeException
597
+	 * @throws InvalidInterfaceException
598
+	 * @throws ReflectionException
599
+	 */
600
+	public function column_DTT_EVT_start(EE_Registration $registration): string
601
+	{
602
+		$datetime_strings = [];
603
+		$ticket           = $registration->ticket();
604
+		if ($ticket instanceof EE_Ticket) {
605
+			$remove_defaults = ['default_where_conditions' => 'none'];
606
+			$datetimes       = $ticket->datetimes($remove_defaults);
607
+			foreach ($datetimes as $datetime) {
608
+				$datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start', 'M jS Y g:i a');
609
+			}
610
+			$content = $this->generateDisplayForDatetimes($datetime_strings);
611
+		} else {
612
+			$content = esc_html__('There is no ticket on this registration', 'event_espresso');
613
+		}
614
+		return $this->columnContent('DTT_EVT_start', $content);
615
+	}
616
+
617
+
618
+	/**
619
+	 * Receives an array of datetime strings to display and converts them to the html container for the column.
620
+	 *
621
+	 * @param array $datetime_strings
622
+	 * @return string
623
+	 */
624
+	public function generateDisplayForDatetimes(array $datetime_strings): string
625
+	{
626
+		// get first item for initial visibility
627
+		$content = (string) array_shift($datetime_strings);
628
+		if (! empty($datetime_strings)) {
629
+			$content .= '
630 630
                 <div class="ee-registration-event-datetimes-container-wrap">
631 631
                     <button aria-label="' . esc_attr__('Click to view all dates', 'event_espresso') . '"
632 632
                           class="ee-aria-tooltip button button--secondary button--tiny button--icon-only ee-js ee-more-datetimes-toggle"
@@ -637,535 +637,535 @@  discard block
 block discarded – undo
637 637
                         ' . implode("", $datetime_strings) . '
638 638
                     </div>
639 639
                 </div>';
640
-        }
641
-        return $content;
642
-    }
643
-
644
-
645
-    /**
646
-     * @param EE_Registration $registration
647
-     * @return string
648
-     * @throws EE_Error
649
-     * @throws InvalidArgumentException
650
-     * @throws InvalidDataTypeException
651
-     * @throws InvalidInterfaceException
652
-     * @throws ReflectionException
653
-     */
654
-    public function column_ATT_email(EE_Registration $registration): string
655
-    {
656
-        $attendee = $registration->get_first_related('Attendee');
657
-        $content  = ! $attendee instanceof EE_Attendee
658
-            ? esc_html__('No attached contact record.', 'event_espresso')
659
-            : $attendee->email();
660
-        return $this->columnContent('ATT_email', $content);
661
-    }
662
-
663
-
664
-    /**
665
-     * @param EE_Registration $registration
666
-     * @return string
667
-     * @throws EE_Error
668
-     * @throws ReflectionException
669
-     */
670
-    public function column__REG_count(EE_Registration $registration): string
671
-    {
672
-        $content = sprintf(
673
-            esc_html__('%1$s / %2$s', 'event_espresso'),
674
-            $registration->count(),
675
-            $registration->group_size()
676
-        );
677
-        return $this->columnContent('_REG_count', $content);
678
-    }
679
-
680
-
681
-    /**
682
-     * @param EE_Registration $registration
683
-     * @return string
684
-     * @throws EE_Error
685
-     * @throws ReflectionException
686
-     */
687
-    public function column_PRC_amount(EE_Registration $registration): string
688
-    {
689
-        $ticket = $registration->ticket();
690
-
691
-        $content = $this->EVT_ID && $ticket instanceof EE_Ticket
692
-            ? '<div class="TKT_name">' . $ticket->name() . '</div>'
693
-            : '';
694
-
695
-        $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
696
-        $content        .= $registration->final_price() > 0
697
-            ? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
640
+		}
641
+		return $content;
642
+	}
643
+
644
+
645
+	/**
646
+	 * @param EE_Registration $registration
647
+	 * @return string
648
+	 * @throws EE_Error
649
+	 * @throws InvalidArgumentException
650
+	 * @throws InvalidDataTypeException
651
+	 * @throws InvalidInterfaceException
652
+	 * @throws ReflectionException
653
+	 */
654
+	public function column_ATT_email(EE_Registration $registration): string
655
+	{
656
+		$attendee = $registration->get_first_related('Attendee');
657
+		$content  = ! $attendee instanceof EE_Attendee
658
+			? esc_html__('No attached contact record.', 'event_espresso')
659
+			: $attendee->email();
660
+		return $this->columnContent('ATT_email', $content);
661
+	}
662
+
663
+
664
+	/**
665
+	 * @param EE_Registration $registration
666
+	 * @return string
667
+	 * @throws EE_Error
668
+	 * @throws ReflectionException
669
+	 */
670
+	public function column__REG_count(EE_Registration $registration): string
671
+	{
672
+		$content = sprintf(
673
+			esc_html__('%1$s / %2$s', 'event_espresso'),
674
+			$registration->count(),
675
+			$registration->group_size()
676
+		);
677
+		return $this->columnContent('_REG_count', $content);
678
+	}
679
+
680
+
681
+	/**
682
+	 * @param EE_Registration $registration
683
+	 * @return string
684
+	 * @throws EE_Error
685
+	 * @throws ReflectionException
686
+	 */
687
+	public function column_PRC_amount(EE_Registration $registration): string
688
+	{
689
+		$ticket = $registration->ticket();
690
+
691
+		$content = $this->EVT_ID && $ticket instanceof EE_Ticket
692
+			? '<div class="TKT_name">' . $ticket->name() . '</div>'
693
+			: '';
694
+
695
+		$payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
696
+		$content        .= $registration->final_price() > 0
697
+			? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
698 698
                 ' . $registration->pretty_final_price() . '
699 699
                </span>'
700
-            // free event
701
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
702
-
703
-        return $this->columnContent('PRC_amount', $content, 'end');
704
-    }
705
-
706
-
707
-    /**
708
-     * @param EE_Registration $registration
709
-     * @return string
710
-     * @throws EE_Error
711
-     * @throws ReflectionException
712
-     */
713
-    public function column__REG_final_price(EE_Registration $registration): string
714
-    {
715
-        $ticket  = $registration->ticket();
716
-        $content = $this->EVT_ID || ! $ticket instanceof EE_Ticket
717
-            ? ''
718
-            : '<span class="TKT_name ee-status-color--' . $ticket->ticket_status() . '">' . $ticket->name() . '</span>';
719
-
720
-        $content .= '<span class="reg-overview-paid-event-spn">' . $registration->pretty_final_price() . '</span>';
721
-        return $this->columnContent('_REG_final_price', $content, 'end');
722
-    }
723
-
724
-
725
-    /**
726
-     * @param EE_Registration $registration
727
-     * @return string
728
-     * @throws EE_Error
729
-     * @throws ReflectionException
730
-     */
731
-    public function column__REG_paid(EE_Registration $registration): string
732
-    {
733
-        $payment_method      = $registration->payment_method();
734
-        $payment_method_name = $payment_method instanceof EE_Payment_Method
735
-            ? $payment_method->admin_name()
736
-            : esc_html__('Unknown', 'event_espresso');
737
-
738
-        $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
739
-        $content        = '
700
+			// free event
701
+			: '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
702
+
703
+		return $this->columnContent('PRC_amount', $content, 'end');
704
+	}
705
+
706
+
707
+	/**
708
+	 * @param EE_Registration $registration
709
+	 * @return string
710
+	 * @throws EE_Error
711
+	 * @throws ReflectionException
712
+	 */
713
+	public function column__REG_final_price(EE_Registration $registration): string
714
+	{
715
+		$ticket  = $registration->ticket();
716
+		$content = $this->EVT_ID || ! $ticket instanceof EE_Ticket
717
+			? ''
718
+			: '<span class="TKT_name ee-status-color--' . $ticket->ticket_status() . '">' . $ticket->name() . '</span>';
719
+
720
+		$content .= '<span class="reg-overview-paid-event-spn">' . $registration->pretty_final_price() . '</span>';
721
+		return $this->columnContent('_REG_final_price', $content, 'end');
722
+	}
723
+
724
+
725
+	/**
726
+	 * @param EE_Registration $registration
727
+	 * @return string
728
+	 * @throws EE_Error
729
+	 * @throws ReflectionException
730
+	 */
731
+	public function column__REG_paid(EE_Registration $registration): string
732
+	{
733
+		$payment_method      = $registration->payment_method();
734
+		$payment_method_name = $payment_method instanceof EE_Payment_Method
735
+			? $payment_method->admin_name()
736
+			: esc_html__('Unknown', 'event_espresso');
737
+
738
+		$payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
739
+		$content        = '
740 740
             <span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
741 741
                 ' . $registration->pretty_paid() . '
742 742
             </span>';
743
-        if ($registration->paid() > 0) {
744
-            $content .= '<span class="ee-status-text-small">'
745
-                . sprintf(
746
-                    esc_html__('...via %s', 'event_espresso'),
747
-                    $payment_method_name
748
-                )
749
-                . '</span>';
750
-        }
751
-        return $this->columnContent('_REG_paid', $content, 'end');
752
-    }
753
-
754
-
755
-    /**
756
-     * @param EE_Registration $registration
757
-     * @return string
758
-     * @throws EE_Error
759
-     * @throws EntityNotFoundException
760
-     * @throws InvalidArgumentException
761
-     * @throws InvalidDataTypeException
762
-     * @throws InvalidInterfaceException
763
-     * @throws ReflectionException
764
-     */
765
-    public function column_TXN_total(EE_Registration $registration): string
766
-    {
767
-        if ($registration->transaction()) {
768
-            $content = $this->caps_handler->userCanViewTransaction()
769
-                ? '
743
+		if ($registration->paid() > 0) {
744
+			$content .= '<span class="ee-status-text-small">'
745
+				. sprintf(
746
+					esc_html__('...via %s', 'event_espresso'),
747
+					$payment_method_name
748
+				)
749
+				. '</span>';
750
+		}
751
+		return $this->columnContent('_REG_paid', $content, 'end');
752
+	}
753
+
754
+
755
+	/**
756
+	 * @param EE_Registration $registration
757
+	 * @return string
758
+	 * @throws EE_Error
759
+	 * @throws EntityNotFoundException
760
+	 * @throws InvalidArgumentException
761
+	 * @throws InvalidDataTypeException
762
+	 * @throws InvalidInterfaceException
763
+	 * @throws ReflectionException
764
+	 */
765
+	public function column_TXN_total(EE_Registration $registration): string
766
+	{
767
+		if ($registration->transaction()) {
768
+			$content = $this->caps_handler->userCanViewTransaction()
769
+				? '
770 770
                     <a class="ee-aria-tooltip ee-status-color--' . $registration->transaction()->status_ID() . '"
771 771
                         href="' . $this->viewTransactionUrl() . '"
772 772
                         aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
773 773
                     >
774 774
                         ' . $registration->transaction()->pretty_total() . '
775 775
                     </a>'
776
-                : $registration->transaction()->pretty_total();
777
-        } else {
778
-            $content = esc_html__("None", "event_espresso");
779
-        }
780
-        return $this->columnContent('TXN_total', $content, 'end');
781
-    }
782
-
783
-
784
-    /**
785
-     * @param EE_Registration $registration
786
-     * @return string
787
-     * @throws EE_Error
788
-     * @throws EntityNotFoundException
789
-     * @throws InvalidArgumentException
790
-     * @throws InvalidDataTypeException
791
-     * @throws InvalidInterfaceException
792
-     * @throws ReflectionException
793
-     */
794
-    public function column_TXN_paid(EE_Registration $registration): string
795
-    {
796
-        $content = '&nbsp;';
797
-        $align   = 'end';
798
-        if ($registration->count() === 1) {
799
-            $transaction = $registration->transaction()
800
-                ? $registration->transaction()
801
-                : EE_Transaction::new_instance();
802
-            if ($transaction->paid() >= $transaction->total()) {
803
-                $align   = 'center';
804
-                $content = '<span class="dashicons dashicons-yes green-icon"></span>';
805
-            } else {
806
-                $content = $this->caps_handler->userCanViewTransaction()
807
-                    ? '
776
+				: $registration->transaction()->pretty_total();
777
+		} else {
778
+			$content = esc_html__("None", "event_espresso");
779
+		}
780
+		return $this->columnContent('TXN_total', $content, 'end');
781
+	}
782
+
783
+
784
+	/**
785
+	 * @param EE_Registration $registration
786
+	 * @return string
787
+	 * @throws EE_Error
788
+	 * @throws EntityNotFoundException
789
+	 * @throws InvalidArgumentException
790
+	 * @throws InvalidDataTypeException
791
+	 * @throws InvalidInterfaceException
792
+	 * @throws ReflectionException
793
+	 */
794
+	public function column_TXN_paid(EE_Registration $registration): string
795
+	{
796
+		$content = '&nbsp;';
797
+		$align   = 'end';
798
+		if ($registration->count() === 1) {
799
+			$transaction = $registration->transaction()
800
+				? $registration->transaction()
801
+				: EE_Transaction::new_instance();
802
+			if ($transaction->paid() >= $transaction->total()) {
803
+				$align   = 'center';
804
+				$content = '<span class="dashicons dashicons-yes green-icon"></span>';
805
+			} else {
806
+				$content = $this->caps_handler->userCanViewTransaction()
807
+					? '
808 808
                     <a class="ee-aria-tooltip ee-status-color--' . $transaction->status_ID() . '"
809 809
                         href="' . $this->viewTransactionUrl() . '"
810 810
                         aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
811 811
                     >
812 812
                         ' . $registration->transaction()->pretty_paid() . '
813 813
                     </a>'
814
-                    : $registration->transaction()->pretty_paid();
815
-            }
816
-        }
817
-        return $this->columnContent('TXN_paid', $content, $align);
818
-    }
819
-
820
-
821
-    /**
822
-     * @param EE_Registration $registration
823
-     * @return string
824
-     * @throws EE_Error
825
-     * @throws InvalidArgumentException
826
-     * @throws InvalidDataTypeException
827
-     * @throws InvalidInterfaceException
828
-     * @throws ReflectionException
829
-     */
830
-    public function column_actions(EE_Registration $registration): string
831
-    {
832
-        $attendee = $registration->attendee();
833
-        $this->_set_related_details($registration);
834
-
835
-        // Build and filter row actions
836
-        $actions = apply_filters(
837
-            'FHEE__EE_Registrations_List_Table__column_actions__actions',
838
-            [
839
-                'view_lnk'               => $this->viewRegistrationAction($registration),
840
-                'edit_lnk'               => $this->editContactAction($registration, $attendee),
841
-                'resend_reg_lnk'         => $this->resendRegistrationMessageAction($registration, $attendee),
842
-                'view_txn_lnk'           => $this->viewTransactionAction(),
843
-                'dl_invoice_lnk'         => $this->viewTransactionInvoiceAction($registration, $attendee),
844
-                'filtered_messages_link' => $this->viewNotificationsAction($registration),
845
-            ],
846
-            $registration,
847
-            $this
848
-        );
849
-
850
-        $content = $this->_action_string(
851
-            implode('', $actions),
852
-            $registration,
853
-            'div',
854
-            'reg-overview-actions ee-list-table-actions'
855
-        );
856
-
857
-        return $this->columnContent('actions', $this->actionsModalMenu($content));
858
-    }
859
-
860
-
861
-    /**
862
-     * @throws EE_Error
863
-     * @throws ReflectionException
864
-     */
865
-    private function viewRegistrationUrl(EE_Registration $registration): string
866
-    {
867
-        return EE_Admin_Page::add_query_args_and_nonce(
868
-            [
869
-                'action'  => 'view_registration',
870
-                '_REG_ID' => $registration->ID(),
871
-            ],
872
-            REG_ADMIN_URL
873
-        );
874
-    }
875
-
876
-
877
-    /**
878
-     * @throws EE_Error
879
-     * @throws ReflectionException
880
-     */
881
-    private function viewRegistrationLink(
882
-        EE_Registration $registration,
883
-        string $status
884
-    ): string {
885
-        $attendee      = $registration->attendee();
886
-        $attendee_name = $attendee instanceof EE_Attendee
887
-            ? $attendee->full_name()
888
-            : '';
889
-        return $this->caps_handler->userCanReadRegistration($registration)
890
-            ? '
814
+					: $registration->transaction()->pretty_paid();
815
+			}
816
+		}
817
+		return $this->columnContent('TXN_paid', $content, $align);
818
+	}
819
+
820
+
821
+	/**
822
+	 * @param EE_Registration $registration
823
+	 * @return string
824
+	 * @throws EE_Error
825
+	 * @throws InvalidArgumentException
826
+	 * @throws InvalidDataTypeException
827
+	 * @throws InvalidInterfaceException
828
+	 * @throws ReflectionException
829
+	 */
830
+	public function column_actions(EE_Registration $registration): string
831
+	{
832
+		$attendee = $registration->attendee();
833
+		$this->_set_related_details($registration);
834
+
835
+		// Build and filter row actions
836
+		$actions = apply_filters(
837
+			'FHEE__EE_Registrations_List_Table__column_actions__actions',
838
+			[
839
+				'view_lnk'               => $this->viewRegistrationAction($registration),
840
+				'edit_lnk'               => $this->editContactAction($registration, $attendee),
841
+				'resend_reg_lnk'         => $this->resendRegistrationMessageAction($registration, $attendee),
842
+				'view_txn_lnk'           => $this->viewTransactionAction(),
843
+				'dl_invoice_lnk'         => $this->viewTransactionInvoiceAction($registration, $attendee),
844
+				'filtered_messages_link' => $this->viewNotificationsAction($registration),
845
+			],
846
+			$registration,
847
+			$this
848
+		);
849
+
850
+		$content = $this->_action_string(
851
+			implode('', $actions),
852
+			$registration,
853
+			'div',
854
+			'reg-overview-actions ee-list-table-actions'
855
+		);
856
+
857
+		return $this->columnContent('actions', $this->actionsModalMenu($content));
858
+	}
859
+
860
+
861
+	/**
862
+	 * @throws EE_Error
863
+	 * @throws ReflectionException
864
+	 */
865
+	private function viewRegistrationUrl(EE_Registration $registration): string
866
+	{
867
+		return EE_Admin_Page::add_query_args_and_nonce(
868
+			[
869
+				'action'  => 'view_registration',
870
+				'_REG_ID' => $registration->ID(),
871
+			],
872
+			REG_ADMIN_URL
873
+		);
874
+	}
875
+
876
+
877
+	/**
878
+	 * @throws EE_Error
879
+	 * @throws ReflectionException
880
+	 */
881
+	private function viewRegistrationLink(
882
+		EE_Registration $registration,
883
+		string $status
884
+	): string {
885
+		$attendee      = $registration->attendee();
886
+		$attendee_name = $attendee instanceof EE_Attendee
887
+			? $attendee->full_name()
888
+			: '';
889
+		return $this->caps_handler->userCanReadRegistration($registration)
890
+			? '
891 891
             <a  href="' . $this->viewRegistrationUrl($registration) . '"
892 892
                 class="row-title ee-status-color--' . $status . ' ee-aria-tooltip"
893 893
                 aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
894 894
             >
895 895
                 ' . $attendee_name . '
896 896
             </a>'
897
-            : $attendee_name;
898
-    }
899
-
900
-
901
-    /**
902
-     * @throws EE_Error
903
-     * @throws ReflectionException
904
-     */
905
-    private function viewRegistrationAction(EE_Registration $registration): string
906
-    {
907
-        return $this->caps_handler->userCanReadRegistration($registration)
908
-            ? '
897
+			: $attendee_name;
898
+	}
899
+
900
+
901
+	/**
902
+	 * @throws EE_Error
903
+	 * @throws ReflectionException
904
+	 */
905
+	private function viewRegistrationAction(EE_Registration $registration): string
906
+	{
907
+		return $this->caps_handler->userCanReadRegistration($registration)
908
+			? '
909 909
             <a  href="' . $this->viewRegistrationUrl($registration) . '"
910 910
                 class="ee-aria-tooltip button button--icon-only"
911 911
                 aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
912 912
             >
913 913
                 <span class="dashicons dashicons-clipboard"></span>
914 914
             </a>'
915
-            : '';
916
-    }
917
-
918
-
919
-    private function editContactAction(EE_Registration $registration, ?EE_Attendee $attendee = null): string
920
-    {
921
-        if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanEditContacts()) {
922
-            $edit_link_url = EE_Admin_Page::add_query_args_and_nonce(
923
-                [
924
-                    'action' => 'edit_attendee',
925
-                    'post'   => $registration->attendee_ID(),
926
-                ],
927
-                REG_ADMIN_URL
928
-            );
929
-            return '
915
+			: '';
916
+	}
917
+
918
+
919
+	private function editContactAction(EE_Registration $registration, ?EE_Attendee $attendee = null): string
920
+	{
921
+		if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanEditContacts()) {
922
+			$edit_link_url = EE_Admin_Page::add_query_args_and_nonce(
923
+				[
924
+					'action' => 'edit_attendee',
925
+					'post'   => $registration->attendee_ID(),
926
+				],
927
+				REG_ADMIN_URL
928
+			);
929
+			return '
930 930
                 <a href="' . $edit_link_url . '"
931 931
                    aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso') . '"
932 932
                    class="ee-aria-tooltip button button--secondary button--icon-only"
933 933
                 >
934 934
                     <span class="dashicons dashicons-admin-users"></span>
935 935
                 </a>';
936
-        }
937
-        return '';
938
-    }
939
-
940
-
941
-    /**
942
-     * @throws EE_Error
943
-     * @throws ReflectionException
944
-     */
945
-    private function resendRegistrationMessageAction(
946
-        EE_Registration $registration,
947
-        ?EE_Attendee $attendee = null
948
-    ): string {
949
-        if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanResendMessage($registration)) {
950
-            $resend_reg_link_url = EE_Admin_Page::add_query_args_and_nonce(
951
-                [
952
-                    'action'  => 'resend_registration',
953
-                    '_REG_ID' => $registration->ID(),
954
-                ],
955
-                REG_ADMIN_URL,
956
-                true
957
-            );
958
-            return '
936
+		}
937
+		return '';
938
+	}
939
+
940
+
941
+	/**
942
+	 * @throws EE_Error
943
+	 * @throws ReflectionException
944
+	 */
945
+	private function resendRegistrationMessageAction(
946
+		EE_Registration $registration,
947
+		?EE_Attendee $attendee = null
948
+	): string {
949
+		if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanResendMessage($registration)) {
950
+			$resend_reg_link_url = EE_Admin_Page::add_query_args_and_nonce(
951
+				[
952
+					'action'  => 'resend_registration',
953
+					'_REG_ID' => $registration->ID(),
954
+				],
955
+				REG_ADMIN_URL,
956
+				true
957
+			);
958
+			return '
959 959
 			    <a href="' . $resend_reg_link_url . '" aria-label="'
960
-                . esc_attr__('Resend Registration Details', 'event_espresso')
961
-                . '" class="ee-aria-tooltip button button--icon-only">
960
+				. esc_attr__('Resend Registration Details', 'event_espresso')
961
+				. '" class="ee-aria-tooltip button button--icon-only">
962 962
 			        <span class="dashicons dashicons-email-alt"></span>
963 963
 			    </a>';
964
-        }
965
-        return '';
966
-    }
967
-
968
-
969
-    private function viewTransactionUrl(): string
970
-    {
971
-        return EE_Admin_Page::add_query_args_and_nonce(
972
-            [
973
-                'action' => 'view_transaction',
974
-                'TXN_ID' => $this->_transaction_details['id'],
975
-            ],
976
-            TXN_ADMIN_URL
977
-        );
978
-    }
979
-
980
-
981
-    private function viewTransactionAction(): string
982
-    {
983
-        if ($this->caps_handler->userCanViewTransaction()) {
984
-            return '
964
+		}
965
+		return '';
966
+	}
967
+
968
+
969
+	private function viewTransactionUrl(): string
970
+	{
971
+		return EE_Admin_Page::add_query_args_and_nonce(
972
+			[
973
+				'action' => 'view_transaction',
974
+				'TXN_ID' => $this->_transaction_details['id'],
975
+			],
976
+			TXN_ADMIN_URL
977
+		);
978
+	}
979
+
980
+
981
+	private function viewTransactionAction(): string
982
+	{
983
+		if ($this->caps_handler->userCanViewTransaction()) {
984
+			return '
985 985
                 <a class="ee-aria-tooltip button button--icon-only"
986 986
                    href="' . $this->viewTransactionUrl() . '"
987 987
                    aria-label="' . $this->_transaction_details['title_attr'] . '"
988 988
                 >
989 989
                     <span class="dashicons dashicons-cart"></span>
990 990
                 </a>';
991
-        }
992
-        return '';
993
-    }
994
-
995
-
996
-    /**
997
-     * @throws EE_Error
998
-     * @throws ReflectionException
999
-     */
1000
-    private function viewTransactionInvoiceAction(
1001
-        EE_Registration $registration,
1002
-        ?EE_Attendee $attendee = null
1003
-    ): string {
1004
-        // only show invoice link if message type is active.
1005
-        if (
1006
-            $attendee instanceof EE_Attendee
1007
-            && $registration->is_primary_registrant()
1008
-            && EEH_MSG_Template::is_mt_active('invoice')
1009
-        ) {
1010
-            return '
991
+		}
992
+		return '';
993
+	}
994
+
995
+
996
+	/**
997
+	 * @throws EE_Error
998
+	 * @throws ReflectionException
999
+	 */
1000
+	private function viewTransactionInvoiceAction(
1001
+		EE_Registration $registration,
1002
+		?EE_Attendee $attendee = null
1003
+	): string {
1004
+		// only show invoice link if message type is active.
1005
+		if (
1006
+			$attendee instanceof EE_Attendee
1007
+			&& $registration->is_primary_registrant()
1008
+			&& EEH_MSG_Template::is_mt_active('invoice')
1009
+		) {
1010
+			return '
1011 1011
                 <a aria-label="' . esc_attr__('View Transaction Invoice', 'event_espresso')
1012
-                . '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
1012
+				. '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
1013 1013
                     <span class="dashicons dashicons-media-spreadsheet"></span>
1014 1014
                 </a>';
1015
-        }
1016
-        return '';
1017
-    }
1018
-
1019
-
1020
-    /**
1021
-     * @throws ReflectionException
1022
-     * @throws EE_Error
1023
-     */
1024
-    private function viewNotificationsAction(EE_Registration $registration): string
1025
-    {
1026
-        // message list table link (filtered by REG_ID
1027
-        return $this->caps_handler->userCanReadGlobalMessages()
1028
-            ? EEH_MSG_Template::get_message_action_link(
1029
-                'see_notifications_for',
1030
-                null,
1031
-                ['_REG_ID' => $registration->ID()]
1032
-            )
1033
-            : '';
1034
-    }
1035
-
1036
-
1037
-    /**
1038
-     * @throws EE_Error
1039
-     * @throws ReflectionException
1040
-     */
1041
-    private function trashRegistrationLink(
1042
-        EE_Registration $registration,
1043
-        array $url_params
1044
-    ): array {
1045
-        $actions = [];
1046
-        // can't trash what's already trashed
1047
-        if ($this->_view === 'trash') {
1048
-            return $actions;
1049
-        }
1050
-
1051
-        // check caps
1052
-        if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1053
-            return $actions;
1054
-        }
1055
-
1056
-        // don't delete registrations that have payments applied
1057
-        $transaction   = $registration->transaction();
1058
-        $payment_count = $transaction instanceof EE_Transaction
1059
-            ? $transaction->count_related('Payment')
1060
-            : 0;
1061
-
1062
-        if ($payment_count > 0) {
1063
-            return $actions;
1064
-        }
1065
-
1066
-        $url_params['action'] = 'trash_registrations';
1067
-        $trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1068
-        $actions['trash']     = '
1015
+		}
1016
+		return '';
1017
+	}
1018
+
1019
+
1020
+	/**
1021
+	 * @throws ReflectionException
1022
+	 * @throws EE_Error
1023
+	 */
1024
+	private function viewNotificationsAction(EE_Registration $registration): string
1025
+	{
1026
+		// message list table link (filtered by REG_ID
1027
+		return $this->caps_handler->userCanReadGlobalMessages()
1028
+			? EEH_MSG_Template::get_message_action_link(
1029
+				'see_notifications_for',
1030
+				null,
1031
+				['_REG_ID' => $registration->ID()]
1032
+			)
1033
+			: '';
1034
+	}
1035
+
1036
+
1037
+	/**
1038
+	 * @throws EE_Error
1039
+	 * @throws ReflectionException
1040
+	 */
1041
+	private function trashRegistrationLink(
1042
+		EE_Registration $registration,
1043
+		array $url_params
1044
+	): array {
1045
+		$actions = [];
1046
+		// can't trash what's already trashed
1047
+		if ($this->_view === 'trash') {
1048
+			return $actions;
1049
+		}
1050
+
1051
+		// check caps
1052
+		if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1053
+			return $actions;
1054
+		}
1055
+
1056
+		// don't delete registrations that have payments applied
1057
+		$transaction   = $registration->transaction();
1058
+		$payment_count = $transaction instanceof EE_Transaction
1059
+			? $transaction->count_related('Payment')
1060
+			: 0;
1061
+
1062
+		if ($payment_count > 0) {
1063
+			return $actions;
1064
+		}
1065
+
1066
+		$url_params['action'] = 'trash_registrations';
1067
+		$trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1068
+		$actions['trash']     = '
1069 1069
             <a class="ee-aria-tooltip"
1070 1070
                 href="' . $trash_link_url . '"
1071 1071
                 aria-label="' . esc_attr__('Trash Registration', 'event_espresso') . '"
1072 1072
             >
1073 1073
                 ' . esc_html__('Trash', 'event_espresso') . '
1074 1074
             </a>';
1075
-        return $actions;
1076
-    }
1077
-
1078
-
1079
-    /**
1080
-     * @throws EE_Error
1081
-     * @throws ReflectionException
1082
-     */
1083
-    private function restoreRegistrationLink(
1084
-        EE_Registration $registration,
1085
-        array $url_params,
1086
-        array $actions
1087
-    ): array {
1088
-        // can't restore what's not trashed
1089
-        if ($this->_view !== 'trash') {
1090
-            return $actions;
1091
-        }
1092
-
1093
-        // restore registration link
1094
-        if ($this->caps_handler->userCanRestoreRegistration($registration)) {
1095
-            $url_params['action'] = 'restore_registrations';
1096
-            $restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1097
-            $actions['restore']   = '
1075
+		return $actions;
1076
+	}
1077
+
1078
+
1079
+	/**
1080
+	 * @throws EE_Error
1081
+	 * @throws ReflectionException
1082
+	 */
1083
+	private function restoreRegistrationLink(
1084
+		EE_Registration $registration,
1085
+		array $url_params,
1086
+		array $actions
1087
+	): array {
1088
+		// can't restore what's not trashed
1089
+		if ($this->_view !== 'trash') {
1090
+			return $actions;
1091
+		}
1092
+
1093
+		// restore registration link
1094
+		if ($this->caps_handler->userCanRestoreRegistration($registration)) {
1095
+			$url_params['action'] = 'restore_registrations';
1096
+			$restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1097
+			$actions['restore']   = '
1098 1098
                 <a class="ee-aria-tooltip"
1099 1099
                     href="' . $restore_link_url . '"
1100 1100
                     aria-label="' . esc_attr__('Restore Registration', 'event_espresso') . '"
1101 1101
                 >
1102 1102
                     ' . esc_html__('Restore', 'event_espresso') . '
1103 1103
                 </a>';
1104
-        }
1105
-
1106
-        return $actions;
1107
-    }
1108
-
1109
-
1110
-    /**
1111
-     * @throws EE_Error
1112
-     * @throws ReflectionException
1113
-     */
1114
-    private function deleteRegistrationLink(
1115
-        EE_Registration $registration,
1116
-        array $url_params,
1117
-        array $actions
1118
-    ): array {
1119
-        if ($this->_view === 'trash' && $this->caps_handler->userCanDeleteRegistration($registration)) {
1120
-            $url_params['action'] = 'delete_registrations';
1121
-            $delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1122
-            $actions['delete']    = '
1104
+		}
1105
+
1106
+		return $actions;
1107
+	}
1108
+
1109
+
1110
+	/**
1111
+	 * @throws EE_Error
1112
+	 * @throws ReflectionException
1113
+	 */
1114
+	private function deleteRegistrationLink(
1115
+		EE_Registration $registration,
1116
+		array $url_params,
1117
+		array $actions
1118
+	): array {
1119
+		if ($this->_view === 'trash' && $this->caps_handler->userCanDeleteRegistration($registration)) {
1120
+			$url_params['action'] = 'delete_registrations';
1121
+			$delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1122
+			$actions['delete']    = '
1123 1123
                 <a class="ee-aria-tooltip"
1124 1124
                     href="' . $delete_link_url . '"
1125 1125
                     aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso') . '"
1126 1126
                 >
1127 1127
                     ' . esc_html__('Delete', 'event_espresso') . '
1128 1128
                 </a>';
1129
-        }
1130
-        return $actions;
1131
-    }
1132
-
1133
-
1134
-    private function editEventLink(int $EVT_ID, string $event_name): string
1135
-    {
1136
-        if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1137
-            return $event_name;
1138
-        }
1139
-        $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
1140
-            ['action' => 'edit', 'post' => $EVT_ID],
1141
-            EVENTS_ADMIN_URL
1142
-        );
1143
-        return '
1129
+		}
1130
+		return $actions;
1131
+	}
1132
+
1133
+
1134
+	private function editEventLink(int $EVT_ID, string $event_name): string
1135
+	{
1136
+		if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1137
+			return $event_name;
1138
+		}
1139
+		$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
1140
+			['action' => 'edit', 'post' => $EVT_ID],
1141
+			EVENTS_ADMIN_URL
1142
+		);
1143
+		return '
1144 1144
             <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'] . '"
1145 1145
                 href="' . $edit_event_url . '"
1146 1146
                 aria-label="' . esc_attr($this->_event_details['title_attr']) . '"
1147 1147
             >
1148 1148
                 ' . $event_name . '
1149 1149
             </a>';
1150
-    }
1150
+	}
1151 1151
 
1152 1152
 
1153
-    private function eventFilterLink(int $EVT_ID, string $event_name): string
1154
-    {
1155
-        if (! $EVT_ID) {
1156
-            return '';
1157
-        }
1158
-        $event_filter_url = EE_Admin_Page::add_query_args_and_nonce(['event_id' => $EVT_ID], REG_ADMIN_URL);
1159
-        return '
1153
+	private function eventFilterLink(int $EVT_ID, string $event_name): string
1154
+	{
1155
+		if (! $EVT_ID) {
1156
+			return '';
1157
+		}
1158
+		$event_filter_url = EE_Admin_Page::add_query_args_and_nonce(['event_id' => $EVT_ID], REG_ADMIN_URL);
1159
+		return '
1160 1160
             <a  class="ee-aria-tooltip ee-event-filter-link"
1161 1161
                 href="' . $event_filter_url . '"
1162 1162
                 aria-label="' . sprintf(
1163
-                esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1164
-                $event_name
1165
-            ) . '"
1163
+				esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1164
+				$event_name
1165
+			) . '"
1166 1166
             >
1167 1167
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1168
-            . esc_html__('View Registrations', 'event_espresso') . '
1168
+			. esc_html__('View Registrations', 'event_espresso') . '
1169 1169
             </a>';
1170
-    }
1170
+	}
1171 1171
 }
Please login to merge, or discard this patch.
Spacing   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
         ];
85 85
         foreach ($filters as $filter_key => $filter_value) {
86 86
             if ($filter_value) {
87
-                $this->filters[ $filter_key ] = $filter_value;
87
+                $this->filters[$filter_key] = $filter_value;
88 88
             }
89 89
         }
90 90
 
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
         if ($admin_page instanceof Registrations_Admin_Page) {
109 109
             foreach ($admin_page->get_views() as $view_details) {
110 110
                 foreach ($this->filters as $filter_key => $filter_value) {
111
-                    $extra_query_args[ $view_details['slug'] ][ $filter_key ] = $filter_value;
111
+                    $extra_query_args[$view_details['slug']][$filter_key] = $filter_value;
112 112
                 }
113 113
             }
114 114
         }
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
 
170 170
         $this->_primary_column   = 'id';
171 171
         $this->_sortable_columns = [
172
-            '_REG_date'     => ['_REG_date' => true],   // true means its already sorted
172
+            '_REG_date'     => ['_REG_date' => true], // true means its already sorted
173 173
             /**
174 174
              * Allows users to change the default sort if they wish.
175 175
              * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
             'DTT_EVT_start' => ['DTT_EVT_start' => false],
187 187
             'id'            => ['REG_ID' => false],
188 188
         ];
189
-        $this->_hidden_columns   = [];
189
+        $this->_hidden_columns = [];
190 190
 
191 191
         $csv_report = RegistrationsCsvReportParams::getRequestParams(
192 192
             $this->getReturnUrl(),
@@ -194,7 +194,7 @@  discard block
 block discarded – undo
194 194
             $this->EVT_ID,
195 195
             $this->DTT_ID
196 196
         );
197
-        if (! empty($csv_report)) {
197
+        if ( ! empty($csv_report)) {
198 198
             $this->_bottom_buttons['csv_reg_report'] = $csv_report;
199 199
         }
200 200
     }
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
             );
291 291
         }
292 292
         foreach ($this->filters as $filter_key => $filter_value) {
293
-            $filters[] = EEH_Form_Fields::hidden_input($filter_key, $filter_value, 'reg_' . $filter_key);
293
+            $filters[] = EEH_Form_Fields::hidden_input($filter_key, $filter_value, 'reg_'.$filter_key);
294 294
         }
295 295
         return $filters;
296 296
     }
@@ -445,10 +445,10 @@  discard block
 block discarded – undo
445 445
         $transaction   = $item->transaction();
446 446
         $payment_count = $transaction->count_related('Payment');
447 447
 
448
-        $content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
448
+        $content = '<input type="checkbox" name="_REG_ID[]" value="'.$REG_ID.'" />';
449 449
         $content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
450 450
             ? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
451
-                    aria-label="' . $this->lockedRegMessage() . '"></span>'
451
+                    aria-label="' . $this->lockedRegMessage().'"></span>'
452 452
             : '';
453 453
         return $this->columnContent('cb', $content, 'center');
454 454
     }
@@ -474,7 +474,7 @@  discard block
 block discarded – undo
474 474
      */
475 475
     public function column_id(EE_Registration $registration): string
476 476
     {
477
-        $content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
477
+        $content = '<span class="ee-entity-id">'.$registration->ID().'</span>';
478 478
         $content .= '<span class="show-on-mobile-view-only">';
479 479
         $content .= $this->column_ATT_fname($registration, false);
480 480
         $content .= '</span>';
@@ -504,23 +504,23 @@  discard block
 block discarded – undo
504 504
                 esc_html__('(%1$s / %2$s)', 'event_espresso'),
505 505
                 $registration->count(),
506 506
                 $registration->group_size()
507
-            ) . '
507
+            ).'
508 508
             </span >';
509 509
 
510 510
         $content = '
511 511
         <div class="ee-layout-row">
512
-            <span aria-label="' . $pretty_status . '"
513
-                  class="ee-status-dot ee-status-bg--' . $status . ' ee-aria-tooltip"
512
+            <span aria-label="' . $pretty_status.'"
513
+                  class="ee-status-dot ee-status-bg--' . $status.' ee-aria-tooltip"
514 514
             ></span>
515 515
             ' . $this->viewRegistrationLink($registration, $status)
516 516
             . $prime_reg_star
517
-            . $group_count . '
517
+            . $group_count.'
518 518
             <span class="spacer"></span>
519 519
             <span>
520 520
                 ' . sprintf(
521 521
                 esc_html__('Reg Code: %s', 'event_espresso'),
522 522
                 $registration->get('REG_code')
523
-            ) . '
523
+            ).'
524 524
             </span>
525 525
         </div>';
526 526
 
@@ -551,7 +551,7 @@  discard block
 block discarded – undo
551 551
         $this->_set_related_details($registration);
552 552
         // Build row actions
553 553
         $content = $this->caps_handler->userCanViewTransaction()
554
-            ? '<a class="ee-aria-tooltip ee-status-color--' . $this->_transaction_details['status'] . '" href="'
554
+            ? '<a class="ee-aria-tooltip ee-status-color--'.$this->_transaction_details['status'].'" href="'
555 555
             . $this->viewTransactionUrl()
556 556
             . '" aria-label="'
557 557
             . esc_attr($this->_transaction_details['title_attr'])
@@ -625,16 +625,16 @@  discard block
 block discarded – undo
625 625
     {
626 626
         // get first item for initial visibility
627 627
         $content = (string) array_shift($datetime_strings);
628
-        if (! empty($datetime_strings)) {
628
+        if ( ! empty($datetime_strings)) {
629 629
             $content .= '
630 630
                 <div class="ee-registration-event-datetimes-container-wrap">
631
-                    <button aria-label="' . esc_attr__('Click to view all dates', 'event_espresso') . '"
631
+                    <button aria-label="' . esc_attr__('Click to view all dates', 'event_espresso').'"
632 632
                           class="ee-aria-tooltip button button--secondary button--tiny button--icon-only ee-js ee-more-datetimes-toggle"
633 633
                     >
634 634
                         <span class="dashicons dashicons-admin-collapse"></span>
635 635
                     </button>
636 636
                     <div class="ee-registration-event-datetimes-container more-items hidden">
637
-                        ' . implode("", $datetime_strings) . '
637
+                        ' . implode("", $datetime_strings).'
638 638
                     </div>
639 639
                 </div>';
640 640
         }
@@ -689,16 +689,16 @@  discard block
 block discarded – undo
689 689
         $ticket = $registration->ticket();
690 690
 
691 691
         $content = $this->EVT_ID && $ticket instanceof EE_Ticket
692
-            ? '<div class="TKT_name">' . $ticket->name() . '</div>'
692
+            ? '<div class="TKT_name">'.$ticket->name().'</div>'
693 693
             : '';
694 694
 
695 695
         $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
696
-        $content        .= $registration->final_price() > 0
697
-            ? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
698
-                ' . $registration->pretty_final_price() . '
696
+        $content .= $registration->final_price() > 0
697
+            ? '<span class="reg-overview-paid-event-spn ee-status-color--'.$payment_status.'">
698
+                ' . $registration->pretty_final_price().'
699 699
                </span>'
700 700
             // free event
701
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
701
+            : '<span class="reg-overview-free-event-spn">'.esc_html__('free', 'event_espresso').'</span>';
702 702
 
703 703
         return $this->columnContent('PRC_amount', $content, 'end');
704 704
     }
@@ -715,9 +715,9 @@  discard block
 block discarded – undo
715 715
         $ticket  = $registration->ticket();
716 716
         $content = $this->EVT_ID || ! $ticket instanceof EE_Ticket
717 717
             ? ''
718
-            : '<span class="TKT_name ee-status-color--' . $ticket->ticket_status() . '">' . $ticket->name() . '</span>';
718
+            : '<span class="TKT_name ee-status-color--'.$ticket->ticket_status().'">'.$ticket->name().'</span>';
719 719
 
720
-        $content .= '<span class="reg-overview-paid-event-spn">' . $registration->pretty_final_price() . '</span>';
720
+        $content .= '<span class="reg-overview-paid-event-spn">'.$registration->pretty_final_price().'</span>';
721 721
         return $this->columnContent('_REG_final_price', $content, 'end');
722 722
     }
723 723
 
@@ -737,8 +737,8 @@  discard block
 block discarded – undo
737 737
 
738 738
         $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
739 739
         $content        = '
740
-            <span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
741
-                ' . $registration->pretty_paid() . '
740
+            <span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status.'">
741
+                ' . $registration->pretty_paid().'
742 742
             </span>';
743 743
         if ($registration->paid() > 0) {
744 744
             $content .= '<span class="ee-status-text-small">'
@@ -767,11 +767,11 @@  discard block
 block discarded – undo
767 767
         if ($registration->transaction()) {
768 768
             $content = $this->caps_handler->userCanViewTransaction()
769 769
                 ? '
770
-                    <a class="ee-aria-tooltip ee-status-color--' . $registration->transaction()->status_ID() . '"
771
-                        href="' . $this->viewTransactionUrl() . '"
772
-                        aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
770
+                    <a class="ee-aria-tooltip ee-status-color--' . $registration->transaction()->status_ID().'"
771
+                        href="' . $this->viewTransactionUrl().'"
772
+                        aria-label="' . esc_attr__('View Transaction', 'event_espresso').'"
773 773
                     >
774
-                        ' . $registration->transaction()->pretty_total() . '
774
+                        ' . $registration->transaction()->pretty_total().'
775 775
                     </a>'
776 776
                 : $registration->transaction()->pretty_total();
777 777
         } else {
@@ -805,11 +805,11 @@  discard block
 block discarded – undo
805 805
             } else {
806 806
                 $content = $this->caps_handler->userCanViewTransaction()
807 807
                     ? '
808
-                    <a class="ee-aria-tooltip ee-status-color--' . $transaction->status_ID() . '"
809
-                        href="' . $this->viewTransactionUrl() . '"
810
-                        aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
808
+                    <a class="ee-aria-tooltip ee-status-color--' . $transaction->status_ID().'"
809
+                        href="' . $this->viewTransactionUrl().'"
810
+                        aria-label="' . esc_attr__('View Transaction', 'event_espresso').'"
811 811
                     >
812
-                        ' . $registration->transaction()->pretty_paid() . '
812
+                        ' . $registration->transaction()->pretty_paid().'
813 813
                     </a>'
814 814
                     : $registration->transaction()->pretty_paid();
815 815
             }
@@ -888,11 +888,11 @@  discard block
 block discarded – undo
888 888
             : '';
889 889
         return $this->caps_handler->userCanReadRegistration($registration)
890 890
             ? '
891
-            <a  href="' . $this->viewRegistrationUrl($registration) . '"
892
-                class="row-title ee-status-color--' . $status . ' ee-aria-tooltip"
893
-                aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
891
+            <a  href="' . $this->viewRegistrationUrl($registration).'"
892
+                class="row-title ee-status-color--' . $status.' ee-aria-tooltip"
893
+                aria-label="' . esc_attr__('View Registration Details', 'event_espresso').'"
894 894
             >
895
-                ' . $attendee_name . '
895
+                ' . $attendee_name.'
896 896
             </a>'
897 897
             : $attendee_name;
898 898
     }
@@ -906,9 +906,9 @@  discard block
 block discarded – undo
906 906
     {
907 907
         return $this->caps_handler->userCanReadRegistration($registration)
908 908
             ? '
909
-            <a  href="' . $this->viewRegistrationUrl($registration) . '"
909
+            <a  href="' . $this->viewRegistrationUrl($registration).'"
910 910
                 class="ee-aria-tooltip button button--icon-only"
911
-                aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
911
+                aria-label="' . esc_attr__('View Registration Details', 'event_espresso').'"
912 912
             >
913 913
                 <span class="dashicons dashicons-clipboard"></span>
914 914
             </a>'
@@ -927,8 +927,8 @@  discard block
 block discarded – undo
927 927
                 REG_ADMIN_URL
928 928
             );
929 929
             return '
930
-                <a href="' . $edit_link_url . '"
931
-                   aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso') . '"
930
+                <a href="' . $edit_link_url.'"
931
+                   aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso').'"
932 932
                    class="ee-aria-tooltip button button--secondary button--icon-only"
933 933
                 >
934 934
                     <span class="dashicons dashicons-admin-users"></span>
@@ -956,7 +956,7 @@  discard block
 block discarded – undo
956 956
                 true
957 957
             );
958 958
             return '
959
-			    <a href="' . $resend_reg_link_url . '" aria-label="'
959
+			    <a href="' . $resend_reg_link_url.'" aria-label="'
960 960
                 . esc_attr__('Resend Registration Details', 'event_espresso')
961 961
                 . '" class="ee-aria-tooltip button button--icon-only">
962 962
 			        <span class="dashicons dashicons-email-alt"></span>
@@ -983,8 +983,8 @@  discard block
 block discarded – undo
983 983
         if ($this->caps_handler->userCanViewTransaction()) {
984 984
             return '
985 985
                 <a class="ee-aria-tooltip button button--icon-only"
986
-                   href="' . $this->viewTransactionUrl() . '"
987
-                   aria-label="' . $this->_transaction_details['title_attr'] . '"
986
+                   href="' . $this->viewTransactionUrl().'"
987
+                   aria-label="' . $this->_transaction_details['title_attr'].'"
988 988
                 >
989 989
                     <span class="dashicons dashicons-cart"></span>
990 990
                 </a>';
@@ -1009,7 +1009,7 @@  discard block
 block discarded – undo
1009 1009
         ) {
1010 1010
             return '
1011 1011
                 <a aria-label="' . esc_attr__('View Transaction Invoice', 'event_espresso')
1012
-                . '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
1012
+                . '" target="_blank" href="'.$registration->invoice_url().'" class="ee-aria-tooltip button button--icon-only">
1013 1013
                     <span class="dashicons dashicons-media-spreadsheet"></span>
1014 1014
                 </a>';
1015 1015
         }
@@ -1049,7 +1049,7 @@  discard block
 block discarded – undo
1049 1049
         }
1050 1050
 
1051 1051
         // check caps
1052
-        if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1052
+        if ( ! $this->caps_handler->userCanTrashRegistration($registration)) {
1053 1053
             return $actions;
1054 1054
         }
1055 1055
 
@@ -1067,10 +1067,10 @@  discard block
 block discarded – undo
1067 1067
         $trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1068 1068
         $actions['trash']     = '
1069 1069
             <a class="ee-aria-tooltip"
1070
-                href="' . $trash_link_url . '"
1071
-                aria-label="' . esc_attr__('Trash Registration', 'event_espresso') . '"
1070
+                href="' . $trash_link_url.'"
1071
+                aria-label="' . esc_attr__('Trash Registration', 'event_espresso').'"
1072 1072
             >
1073
-                ' . esc_html__('Trash', 'event_espresso') . '
1073
+                ' . esc_html__('Trash', 'event_espresso').'
1074 1074
             </a>';
1075 1075
         return $actions;
1076 1076
     }
@@ -1096,10 +1096,10 @@  discard block
 block discarded – undo
1096 1096
             $restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1097 1097
             $actions['restore']   = '
1098 1098
                 <a class="ee-aria-tooltip"
1099
-                    href="' . $restore_link_url . '"
1100
-                    aria-label="' . esc_attr__('Restore Registration', 'event_espresso') . '"
1099
+                    href="' . $restore_link_url.'"
1100
+                    aria-label="' . esc_attr__('Restore Registration', 'event_espresso').'"
1101 1101
                 >
1102
-                    ' . esc_html__('Restore', 'event_espresso') . '
1102
+                    ' . esc_html__('Restore', 'event_espresso').'
1103 1103
                 </a>';
1104 1104
         }
1105 1105
 
@@ -1121,10 +1121,10 @@  discard block
 block discarded – undo
1121 1121
             $delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1122 1122
             $actions['delete']    = '
1123 1123
                 <a class="ee-aria-tooltip"
1124
-                    href="' . $delete_link_url . '"
1125
-                    aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso') . '"
1124
+                    href="' . $delete_link_url.'"
1125
+                    aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso').'"
1126 1126
                 >
1127
-                    ' . esc_html__('Delete', 'event_espresso') . '
1127
+                    ' . esc_html__('Delete', 'event_espresso').'
1128 1128
                 </a>';
1129 1129
         }
1130 1130
         return $actions;
@@ -1133,7 +1133,7 @@  discard block
 block discarded – undo
1133 1133
 
1134 1134
     private function editEventLink(int $EVT_ID, string $event_name): string
1135 1135
     {
1136
-        if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1136
+        if ( ! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1137 1137
             return $event_name;
1138 1138
         }
1139 1139
         $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
@@ -1141,31 +1141,31 @@  discard block
 block discarded – undo
1141 1141
             EVENTS_ADMIN_URL
1142 1142
         );
1143 1143
         return '
1144
-            <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'] . '"
1145
-                href="' . $edit_event_url . '"
1146
-                aria-label="' . esc_attr($this->_event_details['title_attr']) . '"
1144
+            <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'].'"
1145
+                href="' . $edit_event_url.'"
1146
+                aria-label="' . esc_attr($this->_event_details['title_attr']).'"
1147 1147
             >
1148
-                ' . $event_name . '
1148
+                ' . $event_name.'
1149 1149
             </a>';
1150 1150
     }
1151 1151
 
1152 1152
 
1153 1153
     private function eventFilterLink(int $EVT_ID, string $event_name): string
1154 1154
     {
1155
-        if (! $EVT_ID) {
1155
+        if ( ! $EVT_ID) {
1156 1156
             return '';
1157 1157
         }
1158 1158
         $event_filter_url = EE_Admin_Page::add_query_args_and_nonce(['event_id' => $EVT_ID], REG_ADMIN_URL);
1159 1159
         return '
1160 1160
             <a  class="ee-aria-tooltip ee-event-filter-link"
1161
-                href="' . $event_filter_url . '"
1161
+                href="' . $event_filter_url.'"
1162 1162
                 aria-label="' . sprintf(
1163 1163
                 esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1164 1164
                 $event_name
1165
-            ) . '"
1165
+            ).'"
1166 1166
             >
1167 1167
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1168
-            . esc_html__('View Registrations', 'event_espresso') . '
1168
+            . esc_html__('View Registrations', 'event_espresso').'
1169 1169
             </a>';
1170 1170
     }
1171 1171
 }
Please login to merge, or discard this patch.
admin_pages/messages/help_tabs/messages_settings_messengers.help_tab.php 1 patch
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -3,79 +3,79 @@
 block discarded – undo
3 3
 </p>
4 4
 <p>
5 5
     <?php esc_html_e(
6
-        'You can select Messengers via the tabs across the top of the settings page. The available messengers you see depends on what version of Event Espresso you have and what addons are installed. Every install include an "Email" messenger tab.  When you click one of those tabs it will display that messenger.',
7
-        'event_espresso'
8
-    ); ?>
6
+		'You can select Messengers via the tabs across the top of the settings page. The available messengers you see depends on what version of Event Espresso you have and what addons are installed. Every install include an "Email" messenger tab.  When you click one of those tabs it will display that messenger.',
7
+		'event_espresso'
8
+	); ?>
9 9
 </p>
10 10
 <p>
11 11
     <?php esc_html_e(
12
-        'There are two ways to determine whether a messenger is active or not.  The first way is via the messenger tab itself.',
13
-        'event_espresso'
14
-    ); ?>
12
+		'There are two ways to determine whether a messenger is active or not.  The first way is via the messenger tab itself.',
13
+		'event_espresso'
14
+	); ?>
15 15
 </p>
16 16
 <p>
17 17
     <?php printf(
18
-        esc_html__(
19
-            'The green colored gear %s indicates that this messenger is currently active.',
20
-            'event_espresso'
21
-        ),
22
-        '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png' . '"'
23
-        . ' alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />'
24
-    );
25
-    printf(
26
-        esc_html__(
27
-            ' The white colored gear %s indicates the messenger is inactive. This is very helpful for seeing at a glance all the messengers that are active when you first view the page.',
28
-            'event_espresso'
29
-        ),
30
-        '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
31
-        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />'
32
-    ); ?>
18
+		esc_html__(
19
+			'The green colored gear %s indicates that this messenger is currently active.',
20
+			'event_espresso'
21
+		),
22
+		'<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png' . '"'
23
+		. ' alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />'
24
+	);
25
+	printf(
26
+		esc_html__(
27
+			' The white colored gear %s indicates the messenger is inactive. This is very helpful for seeing at a glance all the messengers that are active when you first view the page.',
28
+			'event_espresso'
29
+		),
30
+		'<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
31
+		. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />'
32
+	); ?>
33 33
 </p>
34 34
 <p>
35 35
     <?php esc_html_e(
36
-        'The second way to determine whether a messenger is active or not is via the "on/off" button in the top right corner of the active messenger displayed content:',
37
-        'event_espresso'
38
-    ); ?>
36
+		'The second way to determine whether a messenger is active or not is via the "on/off" button in the top right corner of the active messenger displayed content:',
37
+		'event_espresso'
38
+	); ?>
39 39
 </p>
40 40
 <p>
41 41
     <?php printf(
42
-        esc_html__(
43
-            '%1$s means of course that the messenger is active and %2$s means the messenger is inactive.',
44
-            'event_espresso'
45
-        ),
46
-        '<div class="ee-switch">'
47
-        . '<input class="ee-switch__input" type="checkbox" checked disabled>'
48
-        . '<label class="ee-switch__toggle" for="ee-on-off-toggle-on" style="min-width:unset !important; padding: 0;"></label>'
49
-        . '</div>',
50
-        '<div class="ee-switch">'
51
-        . '<input class="ee-switch__input" type="checkbox" disabled>'
52
-        . '<label class="ee-switch__toggle" for="ee-on-off-toggle-off" style="min-width:unset !important; padding: 0;"></label>'
53
-        . '</div>'
54
-    ); ?>
42
+		esc_html__(
43
+			'%1$s means of course that the messenger is active and %2$s means the messenger is inactive.',
44
+			'event_espresso'
45
+		),
46
+		'<div class="ee-switch">'
47
+		. '<input class="ee-switch__input" type="checkbox" checked disabled>'
48
+		. '<label class="ee-switch__toggle" for="ee-on-off-toggle-on" style="min-width:unset !important; padding: 0;"></label>'
49
+		. '</div>',
50
+		'<div class="ee-switch">'
51
+		. '<input class="ee-switch__input" type="checkbox" disabled>'
52
+		. '<label class="ee-switch__toggle" for="ee-on-off-toggle-off" style="min-width:unset !important; padding: 0;"></label>'
53
+		. '</div>'
54
+	); ?>
55 55
 </p>
56 56
 <p>
57 57
     <?php
58
-    esc_html_e(
59
-        'The on/off toggle is also what you use to activate or deactivate a messenger.',
60
-        'event_espresso'
61
-    ); ?>
58
+	esc_html_e(
59
+		'The on/off toggle is also what you use to activate or deactivate a messenger.',
60
+		'event_espresso'
61
+	); ?>
62 62
 </p>
63 63
 <p>
64 64
     <?php esc_html_e(
65
-        'What happens when you click the toggle to activate is the messenger is activated and the system determines what default message types are activated with the messenger.  Then, if there are any default settings for either the messenger or message types those settings are saved.  Next, the system will generate any default templates (if none have been generated before, if there are previously generated templates then they are reactivated).  Finally, you will see the display change to reflect that the messenger is active. If the messenger has settings you can modify them then. Any message types that have settings will also automatically expand so you can see the default settings and make any changes as necessary to fit your needs. Usually the defaults are sufficient however.',
66
-        'event_espresso'
67
-    ); ?>
65
+		'What happens when you click the toggle to activate is the messenger is activated and the system determines what default message types are activated with the messenger.  Then, if there are any default settings for either the messenger or message types those settings are saved.  Next, the system will generate any default templates (if none have been generated before, if there are previously generated templates then they are reactivated).  Finally, you will see the display change to reflect that the messenger is active. If the messenger has settings you can modify them then. Any message types that have settings will also automatically expand so you can see the default settings and make any changes as necessary to fit your needs. Usually the defaults are sufficient however.',
66
+		'event_espresso'
67
+	); ?>
68 68
 </p>
69 69
 <p>
70 70
     <?php esc_html_e(
71
-        'When you deactivate a messenger, the system will first check if there are any custom event templates for that messenger. If there are you will be unable to deactivate the messenger. This is a fail safe to make sure you know that no messages will go out for those specific events so you don\'t accidentally deactivate.  If this check passes, then the system will deactivate any global templates for that messenger (note the templates are not erased, they just become inactive, so if you decide to reactivate the messenger later all your customizations are preserved). Then the display will change to reflect the deactivation.',
72
-        'event_espresso'
73
-    ); ?>
71
+		'When you deactivate a messenger, the system will first check if there are any custom event templates for that messenger. If there are you will be unable to deactivate the messenger. This is a fail safe to make sure you know that no messages will go out for those specific events so you don\'t accidentally deactivate.  If this check passes, then the system will deactivate any global templates for that messenger (note the templates are not erased, they just become inactive, so if you decide to reactivate the messenger later all your customizations are preserved). Then the display will change to reflect the deactivation.',
72
+		'event_espresso'
73
+	); ?>
74 74
 </p>
75 75
 <p>
76 76
     <strong><?php esc_html_e('Important', 'event_espresso'); ?></strong><br />
77 77
     <?php esc_html_e(
78
-        'Although customizations made to global templates are preserved when a messenger is deactivated, any settings for that messenger (or the message types that were attached to it) are lost on deactivation.  Also, once you deactivate a messenger, no more messages will be delivered using that messenger for any of your events.',
79
-        'event_espresso'
80
-    ); ?>
78
+		'Although customizations made to global templates are preserved when a messenger is deactivated, any settings for that messenger (or the message types that were attached to it) are lost on deactivation.  Also, once you deactivate a messenger, no more messages will be delivered using that messenger for any of your events.',
79
+		'event_espresso'
80
+	); ?>
81 81
 </p>
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 2 patches
Indentation   +1714 added lines, -1714 removed lines patch added patch discarded remove patch
@@ -19,1718 +19,1718 @@
 block discarded – undo
19 19
  */
20 20
 class EED_Single_Page_Checkout extends EED_Module
21 21
 {
22
-    /**
23
-     * $_initialized - has the SPCO controller already been initialized ?
24
-     */
25
-    private static bool $_initialized = false;
26
-
27
-
28
-    /**
29
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
30
-     */
31
-    private static bool $_checkout_verified = true;
32
-
33
-    /**
34
-     * $_reg_steps_array - holds initial array of reg steps
35
-     *
36
-     * @var array $_reg_steps_array
37
-     */
38
-    private static array $_reg_steps_array = [];
39
-
40
-    /**
41
-     * $checkout - EE_Checkout object for handling the properties of the current checkout process
42
-     */
43
-    public ?EE_Checkout $checkout = null;
44
-
45
-    protected ?RequestInterface $request = null;
46
-
47
-    private bool $debug = false;    //  true    false
48
-
49
-
50
-    /**
51
-     * @return EED_Single_Page_Checkout|EED_Module
52
-     * @throws EE_Error
53
-     * @throws ReflectionException
54
-     */
55
-    public static function instance()
56
-    {
57
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
58
-        return parent::get_instance(__CLASS__);
59
-    }
60
-
61
-
62
-    /**
63
-     * @return EE_CART
64
-     */
65
-    public function cart(): EE_CART
66
-    {
67
-        return $this->checkout->cart;
68
-    }
69
-
70
-
71
-    /**
72
-     * @return RequestInterface
73
-     * @since   4.10.14.p
74
-     */
75
-    public static function getRequest(): RequestInterface
76
-    {
77
-        return LoaderFactory::getLoader()->getShared(RequestInterface::class);
78
-    }
79
-
80
-
81
-    /**
82
-     * @return EE_Transaction
83
-     */
84
-    public function transaction(): EE_Transaction
85
-    {
86
-        return $this->checkout->transaction;
87
-    }
88
-
89
-
90
-    /**
91
-     *    set_hooks - for hooking into EE Core, other modules, etc
92
-     *
93
-     * @return    void
94
-     * @throws EE_Error
95
-     */
96
-    public static function set_hooks()
97
-    {
98
-        EED_Single_Page_Checkout::set_definitions();
99
-    }
100
-
101
-
102
-    /**
103
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
104
-     *
105
-     * @return    void
106
-     * @throws EE_Error
107
-     */
108
-    public static function set_hooks_admin()
109
-    {
110
-        EED_Single_Page_Checkout::set_definitions();
111
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
112
-            return;
113
-        }
114
-        // going to start an output buffer in case anything gets accidentally output
115
-        // that might disrupt our JSON response
116
-        ob_start();
117
-        EED_Single_Page_Checkout::load_reg_steps();
118
-        // set ajax hooks
119
-        add_action('wp_ajax_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
120
-        add_action('wp_ajax_nopriv_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
121
-        add_action('wp_ajax_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
122
-        add_action('wp_ajax_nopriv_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
123
-        add_action('wp_ajax_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
124
-        add_action('wp_ajax_nopriv_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
125
-    }
126
-
127
-
128
-    /**
129
-     *    process ajax request
130
-     *
131
-     * @param string $ajax_action
132
-     * @throws EE_Error
133
-     * @throws ReflectionException
134
-     */
135
-    public static function process_ajax_request(string $ajax_action)
136
-    {
137
-        $request = EED_Single_Page_Checkout::getRequest();
138
-        $request->setRequestParam('action', $ajax_action);
139
-        EED_Single_Page_Checkout::instance()->_initialize();
140
-    }
141
-
142
-
143
-    /**
144
-     * ajax display registration step
145
-     *
146
-     * @throws EE_Error
147
-     * @throws ReflectionException
148
-     */
149
-    public static function display_reg_step()
150
-    {
151
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
152
-    }
153
-
154
-
155
-    /**
156
-     * ajax process registration step
157
-     *
158
-     * @throws EE_Error
159
-     * @throws ReflectionException
160
-     */
161
-    public static function process_reg_step()
162
-    {
163
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
164
-    }
165
-
166
-
167
-    /**
168
-     * ajax process registration step
169
-     *
170
-     * @throws EE_Error
171
-     * @throws ReflectionException
172
-     */
173
-    public static function update_reg_step()
174
-    {
175
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
176
-    }
177
-
178
-
179
-    /**
180
-     * update_checkout
181
-     *
182
-     * @return void
183
-     * @throws ReflectionException
184
-     * @throws EE_Error
185
-     */
186
-    public static function update_checkout()
187
-    {
188
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
189
-    }
190
-
191
-
192
-    /**
193
-     *    set_definitions
194
-     *
195
-     * @return    void
196
-     * @throws EE_Error
197
-     */
198
-    public static function set_definitions()
199
-    {
200
-        if (defined('SPCO_BASE_PATH')) {
201
-            return;
202
-        }
203
-        define(
204
-            'SPCO_BASE_PATH',
205
-            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
206
-        );
207
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
208
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
209
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
210
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
211
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
212
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
213
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
214
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
215
-            EED_Single_Page_Checkout::getRegistrationExpirationNotice();
216
-    }
217
-
218
-
219
-    /**
220
-     * load_reg_steps
221
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
222
-     *
223
-     * @throws EE_Error
224
-     */
225
-    public static function load_reg_steps()
226
-    {
227
-        static $reg_steps_loaded = false;
228
-        if ($reg_steps_loaded) {
229
-            return;
230
-        }
231
-        // filter list of reg_steps
232
-        $reg_steps_to_load = (array) apply_filters(
233
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
234
-            EED_Single_Page_Checkout::get_reg_steps()
235
-        );
236
-        // sort by key (order)
237
-        ksort($reg_steps_to_load);
238
-        // loop through folders
239
-        foreach ($reg_steps_to_load as $order => $reg_step) {
240
-            // we need a
241
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
242
-                // copy over to the reg_steps_array
243
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
244
-                // register custom key route for each reg step
245
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
246
-                EE_Config::register_route(
247
-                    $reg_step['slug'],
248
-                    'EED_Single_Page_Checkout',
249
-                    'run',
250
-                    'step'
251
-                );
252
-                // add AJAX or other hooks
253
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
254
-                    // setup autoloaders if necessary
255
-                    if (! class_exists($reg_step['class_name'])) {
256
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
257
-                            $reg_step['file_path'],
258
-                            true
259
-                        );
260
-                    }
261
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
262
-                        call_user_func([$reg_step['class_name'], 'set_hooks']);
263
-                    }
264
-                }
265
-            }
266
-        }
267
-        $reg_steps_loaded = true;
268
-    }
269
-
270
-
271
-    /**
272
-     *    get_reg_steps
273
-     *
274
-     * @return    array
275
-     */
276
-    public static function get_reg_steps(): array
277
-    {
278
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
279
-        if (empty($reg_steps)) {
280
-            $reg_steps = [
281
-                10  => [
282
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
283
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
284
-                    'slug'       => 'attendee_information',
285
-                    'has_hooks'  => false,
286
-                ],
287
-                30  => [
288
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
289
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
290
-                    'slug'       => 'payment_options',
291
-                    'has_hooks'  => true,
292
-                ],
293
-                999 => [
294
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
295
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
296
-                    'slug'       => 'finalize_registration',
297
-                    'has_hooks'  => false,
298
-                ],
299
-            ];
300
-        }
301
-        return $reg_steps;
302
-    }
303
-
304
-
305
-    /**
306
-     * @return array|string
307
-     * @throws EE_Error
308
-     * @throws ReflectionException
309
-     */
310
-    public static function registration_checkout_for_admin()
311
-    {
312
-        $request = EED_Single_Page_Checkout::getRequest();
313
-        $request->setRequestParam('step', 'attendee_information');
314
-        $request->setRequestParam('action', 'display_spco_reg_step');
315
-        $request->setRequestParam('process_form_submission', false);
316
-        EED_Single_Page_Checkout::instance()->_initialize();
317
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
318
-        return EED_Single_Page_Checkout::getResponse()->getOutput();
319
-    }
320
-
321
-
322
-    /**
323
-     * @return EE_Transaction|null
324
-     * @throws EE_Error
325
-     * @throws ReflectionException
326
-     */
327
-    public static function process_registration_from_admin(): ?EE_Transaction
328
-    {
329
-        $request = EED_Single_Page_Checkout::getRequest();
330
-        $request->setRequestParam('step', 'attendee_information');
331
-        $request->setRequestParam('action', 'process_reg_step');
332
-        $request->setRequestParam('process_form_submission', true);
333
-        EED_Single_Page_Checkout::instance()->_initialize();
334
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
335
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
336
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
337
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
338
-                if ($final_reg_step->process_reg_step()) {
339
-                    $final_reg_step->set_completed();
340
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
341
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
342
-                }
343
-            }
344
-        }
345
-        return null;
346
-    }
347
-
348
-
349
-    /**
350
-     *    run
351
-     *
352
-     * @param WP_Query|null $WP_Query
353
-     * @return    void
354
-     */
355
-    public function run($WP_Query)
356
-    {
357
-        if (
358
-            $WP_Query instanceof WP_Query
359
-            && $WP_Query->is_main_query()
360
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
361
-            && $this->_is_reg_checkout()
362
-        ) {
363
-            $this->_initialize();
364
-        }
365
-    }
366
-
367
-
368
-    /**
369
-     * determines whether current url matches reg page url
370
-     *
371
-     * @return bool
372
-     */
373
-    protected function _is_reg_checkout(): bool
374
-    {
375
-        // get current permalink for reg page without any extra query args
376
-        $reg_page_url = get_permalink(EE_Config::instance()->core->reg_page_id);
377
-        // get request URI for current request, but without the scheme or host
378
-        $current_request_uri = EEH_URL::filter_input_server_url();
379
-        $current_request_uri = html_entity_decode($current_request_uri);
380
-        // get array of query args from the current request URI
381
-        $query_args = EEH_URL::get_query_string($current_request_uri);
382
-        // grab page id if it is set
383
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
384
-        // and remove the page id from the query args (we will re-add it later)
385
-        unset($query_args['page_id']);
386
-        // now strip all query args from current request URI
387
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
388
-        // and re-add the page id if it was set
389
-        if ($page_id) {
390
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
391
-        }
392
-        // remove slashes and ?
393
-        $current_request_uri = trim($current_request_uri, '?/');
394
-        // is current request URI part of the known full reg page URL ?
395
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
396
-    }
397
-
398
-
399
-    /**
400
-     * @param WP_Query $wp_query
401
-     * @return    void
402
-     * @throws EE_Error
403
-     * @throws ReflectionException
404
-     */
405
-    public static function init(WP_Query $wp_query)
406
-    {
407
-        EED_Single_Page_Checkout::instance()->run($wp_query);
408
-    }
409
-
410
-
411
-    /**
412
-     * @return void
413
-     */
414
-    private function _initialize()
415
-    {
416
-        // ensure SPCO doesn't run twice
417
-        if (EED_Single_Page_Checkout::$_initialized) {
418
-            return;
419
-        }
420
-        try {
421
-            $this->request = EED_Single_Page_Checkout::getRequest();
422
-            EED_Single_Page_Checkout::load_reg_steps();
423
-            $this->_verify_session();
424
-            // set up the EE_Checkout object
425
-            $this->checkout = $this->_initialize_checkout();
426
-            // filter checkout
427
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
428
-            // get the $_GET
429
-            $this->_get_request_vars();
430
-            if ($this->_block_bots()) {
431
-                return;
432
-            }
433
-            // filter continue_reg
434
-            $this->checkout->continue_reg = apply_filters(
435
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
436
-                true,
437
-                $this->checkout
438
-            );
439
-            // load the reg steps array
440
-            if (! $this->_load_and_instantiate_reg_steps()) {
441
-                EED_Single_Page_Checkout::$_initialized = true;
442
-                return;
443
-            }
444
-            // set the current step
445
-            $this->checkout->set_current_step($this->checkout->step);
446
-            // and the next step
447
-            $this->checkout->set_next_step();
448
-            // verify that everything has been set up correctly
449
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
450
-                EED_Single_Page_Checkout::$_initialized = true;
451
-                return;
452
-            }
453
-            do_action('AHEE__Single_Page_Checkout___initialize__after_final_verifications', $this->checkout);
454
-            // lock the transaction
455
-            $this->checkout->transaction->lock();
456
-            // make sure all of our cached objects are added to their respective model entity mappers
457
-            $this->checkout->refresh_all_entities();
458
-            // set amount owing
459
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
460
-            // initialize each reg step, which gives them the chance to potentially alter the process
461
-            $this->_initialize_reg_steps();
462
-            // DEBUG LOG
463
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
464
-            // get reg form
465
-            if (! $this->_check_form_submission()) {
466
-                EED_Single_Page_Checkout::$_initialized = true;
467
-                return;
468
-            }
469
-            // checkout the action!!!
470
-            $this->_process_form_action();
471
-            // add some style and make it dance
472
-            $this->add_styles_and_scripts($this);
473
-            // kk... SPCO has successfully run
474
-            EED_Single_Page_Checkout::$_initialized = true;
475
-            // set no cache headers and constants
476
-            EE_System::do_not_cache();
477
-            // add anchor
478
-            add_action('loop_start', [$this, 'set_checkout_anchor'], 1);
479
-            // remove transaction lock
480
-            add_action('shutdown', [$this, 'unlock_transaction'], 1);
481
-        } catch (Exception $e) {
482
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
483
-        }
484
-    }
485
-
486
-
487
-    /**
488
-     * checks that the session is valid and not expired
489
-     *
490
-     * @throws EE_Error
491
-     * @throws ReflectionException
492
-     */
493
-    private function _verify_session()
494
-    {
495
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
496
-            throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
497
-        }
498
-        $clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
499
-        // is session still valid ?
500
-        if (
501
-            $clear_session_requested
502
-            || (
503
-                EE_Registry::instance()->SSN->expired()
504
-                && $this->request->getRequestParam('e_reg_url_link') === ''
505
-            )
506
-        ) {
507
-            $this->checkout = new EE_Checkout();
508
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
509
-            // EE_Registry::instance()->SSN->reset_cart();
510
-            // EE_Registry::instance()->SSN->reset_checkout();
511
-            // EE_Registry::instance()->SSN->reset_transaction();
512
-            if (! $clear_session_requested) {
513
-                EE_Error::add_attention(
514
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
515
-                    __FILE__,
516
-                    __FUNCTION__,
517
-                    __LINE__
518
-                );
519
-            }
520
-            // EE_Registry::instance()->SSN->reset_expired();
521
-        }
522
-    }
523
-
524
-
525
-    /**
526
-     * loads and instantiates EE_Checkout
527
-     *
528
-     * @return EE_Checkout
529
-     * @throws EE_Error
530
-     * @throws ReflectionException
531
-     */
532
-    private function _initialize_checkout(): EE_Checkout
533
-    {
534
-        // look in session for existing checkout
535
-        /** @type EE_Checkout $checkout */
536
-        $checkout = EE_Registry::instance()->SSN->checkout();
537
-        // verify
538
-        if (! $checkout instanceof EE_Checkout) {
539
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
540
-            $checkout = EE_Registry::instance()->load_file(
541
-                SPCO_INC_PATH,
542
-                'EE_Checkout',
543
-                'class',
544
-                [],
545
-                false
546
-            );
547
-        } else {
548
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
549
-                $this->unlock_transaction();
550
-                wp_safe_redirect($checkout->redirect_url);
551
-                exit();
552
-            }
553
-        }
554
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
555
-        // verify again
556
-        if (! $checkout instanceof EE_Checkout) {
557
-            throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
558
-        }
559
-        // reset anything that needs a clean slate for each request
560
-        $checkout->reset_for_current_request();
561
-        return $checkout;
562
-    }
563
-
564
-
565
-    /**
566
-     * @return void
567
-     */
568
-    private function _get_request_vars()
569
-    {
570
-        // make sure this request is marked as belonging to EE
571
-        /** @var CurrentPage $current_page */
572
-        $current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class);
573
-        $current_page->setEspressoPage(true);
574
-        // which step is being requested ?
575
-        $this->checkout->step = $this->request->getRequestParam('step', $this->_get_first_step());
576
-        // which step is being edited ?
577
-        $this->checkout->edit_step = $this->request->getRequestParam('edit_step');
578
-        // and what we're doing on the current step
579
-        $this->checkout->action = $this->request->getRequestParam('action', 'display_spco_reg_step');
580
-        // timestamp
581
-        $this->checkout->uts = $this->request->getRequestParam('uts', 0, 'int');
582
-        // returning to edit ?
583
-        $this->checkout->reg_url_link = $this->request->getRequestParam('e_reg_url_link');
584
-        // add reg url link to registration query params
585
-        if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
586
-            $this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
587
-        }
588
-        // or some other kind of revisit ?
589
-        $this->checkout->revisit = $this->request->getRequestParam('revisit', false, 'bool');
590
-        // and whether to generate a reg form for this request
591
-        $this->checkout->generate_reg_form = $this->request->getRequestParam('generate_reg_form', true, 'bool');
592
-        // and whether to process a reg form submission for this request
593
-        $this->checkout->process_form_submission = $this->request->getRequestParam(
594
-            'process_form_submission',
595
-            $this->checkout->action === 'process_reg_step',
596
-            'bool'
597
-        );
598
-        $this->checkout->process_form_submission = filter_var(
599
-            $this->checkout->action !== 'display_spco_reg_step'
600
-                ? $this->checkout->process_form_submission
601
-                : false,
602
-            FILTER_VALIDATE_BOOLEAN
603
-        );
604
-        $this->_display_request_vars();
605
-    }
606
-
607
-
608
-    /**
609
-     * @return void
610
-     */
611
-    protected function _display_request_vars()
612
-    {
613
-        if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
614
-            return;
615
-        }
616
-        EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
617
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
618
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
619
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
620
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
621
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
622
-        EEH_Debug_Tools::printr(
623
-            $this->checkout->generate_reg_form,
624
-            '$this->checkout->generate_reg_form',
625
-            __FILE__,
626
-            __LINE__
627
-        );
628
-        EEH_Debug_Tools::printr(
629
-            $this->checkout->process_form_submission,
630
-            '$this->checkout->process_form_submission',
631
-            __FILE__,
632
-            __LINE__
633
-        );
634
-    }
635
-
636
-
637
-    /**
638
-     * _block_bots
639
-     * checks that the incoming request has either of the following set:
640
-     *  a UTS (unix timestamp) which indicates that the request was redirected from the Ticket Selector
641
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
642
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
643
-     * then where you coming from man?
644
-     *
645
-     * @return boolean
646
-     */
647
-    private function _block_bots(): bool
648
-    {
649
-        return EED_Invalid_Checkout_Access::getInvalidCheckoutAccess()->checkoutAccessIsInvalid($this->checkout);
650
-    }
651
-
652
-
653
-    /**
654
-     *  gets slug for first step in $_reg_steps_array
655
-     *
656
-     * @return string
657
-     */
658
-    private function _get_first_step(): string
659
-    {
660
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
661
-        return $first_step['slug'] ?? 'attendee_information';
662
-    }
663
-
664
-
665
-    /**
666
-     * instantiates each reg step based on the loaded reg_steps array
667
-     *
668
-     * @return bool
669
-     * @throws EE_Error
670
-     * @throws InvalidArgumentException
671
-     * @throws InvalidDataTypeException
672
-     * @throws InvalidInterfaceException
673
-     * @throws ReflectionException
674
-     */
675
-    private function _load_and_instantiate_reg_steps(): bool
676
-    {
677
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
678
-        // have reg_steps already been instantiated ?
679
-        if (
680
-            empty($this->checkout->reg_steps)
681
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
682
-        ) {
683
-            // if not, then loop through raw reg steps array
684
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
685
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
686
-                    return false;
687
-                }
688
-            }
689
-            if (isset($this->checkout->reg_steps['registration_confirmation'])) {
690
-                // skip the registration_confirmation page ?
691
-                // just remove it from the reg steps array
692
-                $this->checkout->remove_reg_step('registration_confirmation', false);
693
-            }
694
-            // filter the array for good luck
695
-            $this->checkout->reg_steps = apply_filters(
696
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
697
-                $this->checkout->reg_steps
698
-            );
699
-            // finally re-sort based on the reg step class order properties
700
-            $this->checkout->sort_reg_steps();
701
-        } else {
702
-            foreach ($this->checkout->reg_steps as $reg_step) {
703
-                // set all current step stati to FALSE
704
-                $reg_step->set_is_current_step(false);
705
-            }
706
-        }
707
-        if (empty($this->checkout->reg_steps)) {
708
-            EE_Error::add_error(
709
-                esc_html__('No Reg Steps were loaded..', 'event_espresso'),
710
-                __FILE__,
711
-                __FUNCTION__,
712
-                __LINE__
713
-            );
714
-            return false;
715
-        }
716
-        // make reg step details available to JS
717
-        $this->checkout->set_reg_step_JSON_info();
718
-        return true;
719
-    }
720
-
721
-
722
-    /**
723
-     * @param array $reg_step
724
-     * @param int   $order
725
-     * @return bool
726
-     * @throws EE_Error
727
-     * @throws ReflectionException
728
-     */
729
-    private function _load_and_instantiate_reg_step(array $reg_step = [], int $order = 0): bool
730
-    {
731
-        // we need a file_path, class_name, and slug to add a reg step
732
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
733
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
734
-            if (
735
-                $this->checkout->reg_url_link
736
-                && $this->checkout->step !== $reg_step['slug']
737
-                && $reg_step['slug'] !== 'finalize_registration'
738
-                // normally at this point we would NOT load the reg step, but this filter can change that
739
-                && apply_filters(
740
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
741
-                    true,
742
-                    $reg_step,
743
-                    $this->checkout
744
-                )
745
-            ) {
746
-                return true;
747
-            }
748
-
749
-            // instantiate step class using file path and class name
750
-            $reg_step_obj = EE_Registry::instance()->load_file(
751
-                $reg_step['file_path'],
752
-                $reg_step['class_name'],
753
-                'class',
754
-                [$this->checkout],
755
-                false
756
-            );
757
-            // did we get the goods ?
758
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
759
-                // set reg step order based on config
760
-                $reg_step_obj->set_order($order);
761
-                // add instantiated reg step object to the master reg steps array
762
-                $this->checkout->add_reg_step($reg_step_obj);
763
-            } else {
764
-                EE_Error::add_error(
765
-                    esc_html__('The current step could not be set.', 'event_espresso'),
766
-                    __FILE__,
767
-                    __FUNCTION__,
768
-                    __LINE__
769
-                );
770
-                return false;
771
-            }
772
-        } else {
773
-            if (WP_DEBUG) {
774
-                EE_Error::add_error(
775
-                    sprintf(
776
-                        esc_html__(
777
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
778
-                            'event_espresso'
779
-                        ),
780
-                        $reg_step['file_path'] ?? '',
781
-                        $reg_step['class_name'] ?? '',
782
-                        $reg_step['slug'] ?? '',
783
-                        '<ul>',
784
-                        '<li>',
785
-                        '</li>',
786
-                        '</ul>'
787
-                    ),
788
-                    __FILE__,
789
-                    __FUNCTION__,
790
-                    __LINE__
791
-                );
792
-            }
793
-            return false;
794
-        }
795
-        return true;
796
-    }
797
-
798
-
799
-    /**
800
-     * @return bool
801
-     * @throws EE_Error
802
-     * @throws ReflectionException
803
-     */
804
-    private function _verify_transaction_and_get_registrations(): bool
805
-    {
806
-        // was there already a valid transaction in the checkout from the session ?
807
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
808
-            // get transaction from db or session
809
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
810
-                ? $this->_get_transaction_and_cart_for_previous_visit()
811
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
812
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
813
-                EE_Error::add_error(
814
-                    esc_html__(
815
-                        'Your Registration and Transaction information could not be retrieved from the db.',
816
-                        'event_espresso'
817
-                    ),
818
-                    __FILE__,
819
-                    __FUNCTION__,
820
-                    __LINE__
821
-                );
822
-                $this->checkout->transaction = EE_Transaction::new_instance();
823
-                // add some style and make it dance
824
-                $this->add_styles_and_scripts($this);
825
-                EED_Single_Page_Checkout::$_initialized = true;
826
-                return false;
827
-            }
828
-            // and the registrations for the transaction
829
-            $this->_get_registrations($this->checkout->transaction);
830
-        }
831
-        return true;
832
-    }
833
-
834
-
835
-    /**
836
-     * @return EE_Transaction|null
837
-     * @throws EE_Error
838
-     * @throws ReflectionException
839
-     */
840
-    private function _get_transaction_and_cart_for_previous_visit(): ?EE_Transaction
841
-    {
842
-        /** @var $TXN_model EEM_Transaction */
843
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
844
-        // because the reg_url_link is present in the request,
845
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
846
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
847
-        // verify transaction
848
-        if ($transaction instanceof EE_Transaction) {
849
-            // and get the cart that was used for that transaction
850
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
851
-            return $transaction;
852
-        }
853
-        EE_Error::add_error(
854
-            esc_html__(
855
-                'Your Registration and Transaction information could not be retrieved from the db.',
856
-                'event_espresso'
857
-            ),
858
-            __FILE__,
859
-            __FUNCTION__,
860
-            __LINE__
861
-        );
862
-        return null;
863
-    }
864
-
865
-
866
-    /**
867
-     * @param EE_Transaction|null $transaction
868
-     * @return EE_Cart
869
-     */
870
-    private function _get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
871
-    {
872
-        return $this->checkout->get_cart_for_transaction($transaction);
873
-    }
874
-
875
-
876
-    /**
877
-     * @param EE_Transaction|null $transaction
878
-     * @return EE_Cart
879
-     */
880
-    public function get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
881
-    {
882
-        return $this->checkout->get_cart_for_transaction($transaction);
883
-    }
884
-
885
-
886
-    /**
887
-     * generates a new EE_Transaction object and adds it to the $_transaction property.
888
-     *
889
-     * @return EE_Transaction|null
890
-     * @throws EE_Error
891
-     * @throws ReflectionException
892
-     */
893
-    private function _get_cart_for_current_session_and_setup_new_transaction(): ?EE_Transaction
894
-    {
895
-        //  if there's no transaction, then this is the FIRST visit to SPCO
896
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
897
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
898
-        // and then create a new transaction
899
-        $transaction = $this->_initialize_transaction();
900
-        // verify transaction
901
-        if ($transaction instanceof EE_Transaction) {
902
-            // and save TXN data to the cart
903
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
904
-        } else {
905
-            EE_Error::add_error(
906
-                esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
907
-                __FILE__,
908
-                __FUNCTION__,
909
-                __LINE__
910
-            );
911
-        }
912
-        return $transaction;
913
-    }
914
-
915
-
916
-    /**
917
-     * generates a new EE_Transaction object and adds it to the $_transaction property.
918
-     *
919
-     * @return EE_Transaction|null
920
-     */
921
-    private function _initialize_transaction(): ?EE_Transaction
922
-    {
923
-        try {
924
-            // ensure cart totals have been calculated
925
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
926
-            // grab the cart grand total
927
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
928
-            // create new TXN
929
-            $transaction = EE_Transaction::new_instance(
930
-                [
931
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
932
-                    'TXN_total'     => max($cart_total, 0),
933
-                    'TXN_paid'      => 0,
934
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
935
-                ]
936
-            );
937
-            // save it so that we have an ID for other objects to use
938
-            $transaction->save();
939
-            // set cron job for following up on TXNs after their session has expired
940
-            EE_Cron_Tasks::schedule_expired_transaction_check(
941
-                EE_Registry::instance()->SSN->expiration() + 1,
942
-                $transaction->ID()
943
-            );
944
-            return $transaction;
945
-        } catch (Exception $e) {
946
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
947
-        }
948
-        return null;
949
-    }
950
-
951
-
952
-    /**
953
-     * _get_registrations
954
-     *
955
-     * @param EE_Transaction $transaction
956
-     * @return void
957
-     * @throws EE_Error
958
-     * @throws ReflectionException
959
-     */
960
-    private function _get_registrations(EE_Transaction $transaction)
961
-    {
962
-        // first step: grab the registrants  { : o
963
-        $registrations                      = $transaction->registrations($this->checkout->reg_cache_where_params);
964
-        $this->checkout->total_ticket_count = count($registrations);
965
-        // verify registrations have been set
966
-        if (empty($registrations)) {
967
-            // if no cached registrations, then check the db
968
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params);
969
-            // still nothing ? well as long as this isn't a revisit
970
-            if (empty($registrations) && ! $this->checkout->revisit) {
971
-                // generate new registrations from scratch
972
-                $registrations = $this->_initialize_registrations($transaction);
973
-            }
974
-        }
975
-        // sort by their original registration order
976
-        usort($registrations, ['EED_Single_Page_Checkout', 'sort_registrations_by_REG_count']);
977
-        // then loop thru the array
978
-        foreach ($registrations as $registration) {
979
-            // verify each registration
980
-            if ($registration instanceof EE_Registration) {
981
-                // we display all attendee info for the primary registrant
982
-                if (
983
-                    $this->checkout->reg_url_link === $registration->reg_url_link()
984
-                    && $registration->is_primary_registrant()
985
-                ) {
986
-                    $this->checkout->primary_revisit = true;
987
-                    break;
988
-                }
989
-                if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
990
-                    // but hide info if it doesn't belong to you
991
-                    $transaction->clear_cache('Registration', $registration->ID());
992
-                    $this->checkout->total_ticket_count--;
993
-                }
994
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
995
-            }
996
-        }
997
-    }
998
-
999
-
1000
-    /**
1001
-     * adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1002
-     *
1003
-     * @param EE_Transaction $transaction
1004
-     * @return array
1005
-     * @throws EE_Error
1006
-     * @throws ReflectionException
1007
-     */
1008
-    private function _initialize_registrations(EE_Transaction $transaction): array
1009
-    {
1010
-        $att_nmbr      = 0;
1011
-        $registrations = [];
1012
-        /** @type EE_Registration_Processor $registration_processor */
1013
-        $registration_processor             = EE_Registry::instance()->load_class('Registration_Processor');
1014
-        $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1015
-        // now let's add the cart items to the $transaction
1016
-        foreach ($this->checkout->cart->get_tickets() as $line_item) {
1017
-            // do the following for each ticket of this type they selected
1018
-            for ($x = 1; $x <= $line_item->quantity(); $x++) {
1019
-                $att_nmbr++;
1020
-                /** @var CreateRegistrationCommand $CreateRegistrationCommand */
1021
-                $CreateRegistrationCommand = EE_Registry::instance()->create(
1022
-                    CreateRegistrationCommand::class,
1023
-                    [
1024
-                        $transaction,
1025
-                        $line_item,
1026
-                        $att_nmbr,
1027
-                        $this->checkout->total_ticket_count,
1028
-                    ]
1029
-                );
1030
-                // override capabilities for frontend registrations
1031
-                if ($this->request->isFrontend()) {
1032
-                    $CreateRegistrationCommand->setCapCheck(
1033
-                        new PublicCapabilities('', 'create_new_registration')
1034
-                    );
1035
-                }
1036
-                $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1037
-                if (! $registration instanceof EE_Registration) {
1038
-                    throw new InvalidEntityException($registration, 'EE_Registration');
1039
-                }
1040
-                $registrations[ $registration->ID() ] = $registration;
1041
-            }
1042
-        }
1043
-        $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1044
-        return $registrations;
1045
-    }
1046
-
1047
-
1048
-    /**
1049
-     * @param EE_Registration $reg_A
1050
-     * @param EE_Registration $reg_B
1051
-     * @return int
1052
-     * @throws EE_Error
1053
-     * @throws ReflectionException
1054
-     */
1055
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B): int
1056
-    {
1057
-        // this shouldn't ever happen within the same TXN, but oh well
1058
-        if ($reg_A->count() === $reg_B->count()) {
1059
-            return 0;
1060
-        }
1061
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1062
-    }
1063
-
1064
-
1065
-    /**
1066
-     * just makes sure that everything is set up correctly before proceeding
1067
-     *
1068
-     * @return bool
1069
-     * @throws EE_Error
1070
-     * @throws ReflectionException
1071
-     */
1072
-    private function _final_verifications(): bool
1073
-    {
1074
-        // filter checkout
1075
-        $this->checkout = apply_filters(
1076
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1077
-            $this->checkout
1078
-        );
1079
-        // verify that current step is still set correctly
1080
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1081
-            EE_Error::add_error(
1082
-                esc_html__(
1083
-                    'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1084
-                    'event_espresso'
1085
-                ),
1086
-                __FILE__,
1087
-                __FUNCTION__,
1088
-                __LINE__
1089
-            );
1090
-            return false;
1091
-        }
1092
-        // if returning to SPCO, then verify that primary registrant is set
1093
-        if (! empty($this->checkout->reg_url_link)) {
1094
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1095
-            if (! $valid_registrant instanceof EE_Registration) {
1096
-                EE_Error::add_error(
1097
-                    esc_html__(
1098
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1099
-                        'event_espresso'
1100
-                    ),
1101
-                    __FILE__,
1102
-                    __FUNCTION__,
1103
-                    __LINE__
1104
-                );
1105
-                return false;
1106
-            }
1107
-            $valid_registrant = null;
1108
-            foreach (
1109
-                $this->checkout->transaction->registrations(
1110
-                    $this->checkout->reg_cache_where_params
1111
-                ) as $registration
1112
-            ) {
1113
-                if (
1114
-                    $registration instanceof EE_Registration
1115
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1116
-                ) {
1117
-                    $valid_registrant = $registration;
1118
-                }
1119
-            }
1120
-            if (! $valid_registrant instanceof EE_Registration) {
1121
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1122
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1123
-                    // clear the session, mark the checkout as unverified, and try again
1124
-                    EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1125
-                    EED_Single_Page_Checkout::$_initialized       = false;
1126
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1127
-                    $this->_initialize();
1128
-                    EE_Error::reset_notices();
1129
-                    return false;
1130
-                }
1131
-                EE_Error::add_error(
1132
-                    esc_html__(
1133
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1134
-                        'event_espresso'
1135
-                    ),
1136
-                    __FILE__,
1137
-                    __FUNCTION__,
1138
-                    __LINE__
1139
-                );
1140
-                return false;
1141
-            }
1142
-        }
1143
-        // now that things have been kinda sufficiently verified,
1144
-        // let's add the checkout to the session so that it's available to other systems
1145
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1146
-        return true;
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1152
-     * then loops thru all the active reg steps and calls the initialize_reg_step() method
1153
-     *
1154
-     * @param bool $reinitializing
1155
-     * @throws EE_Error
1156
-     */
1157
-    private function _initialize_reg_steps(bool $reinitializing = false)
1158
-    {
1159
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1160
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1161
-        foreach ($this->checkout->reg_steps as $reg_step) {
1162
-            if (! $reg_step->initialize_reg_step()) {
1163
-                // if not initialized then maybe this step is being removed...
1164
-                if (! $reinitializing && $reg_step->is_current_step()) {
1165
-                    // if it was the current step, then we need to start over here
1166
-                    $this->_initialize_reg_steps(true);
1167
-                    return;
1168
-                }
1169
-                continue;
1170
-            }
1171
-            // add css and JS for current step
1172
-            $this->add_styles_and_scripts($reg_step);
1173
-            if ($reg_step->is_current_step()) {
1174
-                // the text that appears on the reg step form submit button
1175
-                $reg_step->set_submit_button_text();
1176
-            }
1177
-        }
1178
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1179
-        do_action(
1180
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1181
-            $this->checkout->current_step
1182
-        );
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * @return boolean
1188
-     * @throws EE_Error
1189
-     * @throws ReflectionException
1190
-     */
1191
-    private function _check_form_submission(): bool
1192
-    {
1193
-        // does this request require the reg form to be generated ?
1194
-        if ($this->checkout->generate_reg_form) {
1195
-            // ever heard that song by Blue Rodeo ?
1196
-            try {
1197
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1198
-                // if not displaying a form, then check for form submission
1199
-                if (
1200
-                    $this->checkout->process_form_submission
1201
-                    && $this->checkout->current_step->reg_form->was_submitted()
1202
-                ) {
1203
-                    // clear out any old data in case this step is being run again
1204
-                    $this->checkout->current_step->set_valid_data([]);
1205
-                    // capture submitted form data
1206
-                    $request_data = $this->request->requestParams();
1207
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1208
-                        (array) apply_filters(
1209
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1210
-                            $request_data,
1211
-                            $this->checkout
1212
-                        )
1213
-                    );
1214
-                    // validate submitted form data
1215
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1216
-                        // thou shall not pass !!!
1217
-                        $this->checkout->continue_reg = false;
1218
-                        // any form validation errors?
1219
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1220
-                            EE_Error::add_error(
1221
-                                $this->checkout->current_step->reg_form->submission_error_message(),
1222
-                                __FILE__,
1223
-                                __FUNCTION__,
1224
-                                __LINE__
1225
-                            );
1226
-                        }
1227
-                        // well not really... what will happen is
1228
-                        // we'll just get redirected back to redo the current step
1229
-                        $this->go_to_next_step();
1230
-                        return false;
1231
-                    }
1232
-                }
1233
-            } catch (EE_Error $e) {
1234
-                $e->get_error();
1235
-            }
1236
-        }
1237
-        return true;
1238
-    }
1239
-
1240
-
1241
-    /**
1242
-     * @return void
1243
-     * @throws EE_Error
1244
-     * @throws ReflectionException
1245
-     */
1246
-    private function _process_form_action()
1247
-    {
1248
-        // what cha wanna do?
1249
-        switch ($this->checkout->action) {
1250
-            // AJAX next step reg form
1251
-            case 'display_spco_reg_step':
1252
-                $this->checkout->redirect = false;
1253
-                if ($this->request->isAjax()) {
1254
-                    $this->checkout->json_response->set_reg_step_html(
1255
-                        $this->checkout->current_step->display_reg_form()
1256
-                    );
1257
-                }
1258
-                break;
1259
-            default:
1260
-                // meh... do one of those other steps first
1261
-                if (
1262
-                    ! empty($this->checkout->action)
1263
-                    && is_callable([$this->checkout->current_step, $this->checkout->action])
1264
-                ) {
1265
-                    // dynamically creates hook point like:
1266
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1267
-                    do_action(
1268
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1269
-                        $this->checkout->current_step
1270
-                    );
1271
-                    $process_reg_step = apply_filters(
1272
-                        "AHEE__Single_Page_Checkout__process_reg_step__{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1273
-                        true,
1274
-                        $this->checkout->current_step,
1275
-                        $this
1276
-                    );
1277
-                    // call action on current step
1278
-                    if ($process_reg_step && call_user_func([$this->checkout->current_step, $this->checkout->action])) {
1279
-                        // good registrant, you get to proceed
1280
-                        if (
1281
-                            $this->checkout->current_step->success_message() !== ''
1282
-                            && apply_filters(
1283
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1284
-                                false
1285
-                            )
1286
-                        ) {
1287
-                            EE_Error::add_success(
1288
-                                $this->checkout->current_step->success_message()
1289
-                                . '<br />' . $this->checkout->next_step->_instructions()
1290
-                            );
1291
-                        }
1292
-                        // pack it up, pack it in...
1293
-                        $this->_setup_redirect();
1294
-                    }
1295
-                    // dynamically creates hook point like:
1296
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1297
-                    do_action(
1298
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1299
-                        $this->checkout->current_step
1300
-                    );
1301
-                } else {
1302
-                    EE_Error::add_error(
1303
-                        sprintf(
1304
-                            esc_html__(
1305
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1306
-                                'event_espresso'
1307
-                            ),
1308
-                            $this->checkout->action,
1309
-                            $this->checkout->current_step->name()
1310
-                        ),
1311
-                        __FILE__,
1312
-                        __FUNCTION__,
1313
-                        __LINE__
1314
-                    );
1315
-                }
1316
-            // end default
1317
-        }
1318
-        // store our progress so far
1319
-        $this->checkout->stash_transaction_and_checkout();
1320
-        // advance to the next step! If you pass GO, collect $200
1321
-        $this->go_to_next_step();
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target an object with the method `translate_js_strings` and
1327
-     *                                                          `enqueue_styles_and_scripts`.
1328
-     * @return void
1329
-     */
1330
-    public function add_styles_and_scripts($target)
1331
-    {
1332
-        // i18n
1333
-        $target->translate_js_strings();
1334
-        if ($this->checkout->admin_request) {
1335
-            add_action('admin_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1336
-        } else {
1337
-            add_action('wp_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1338
-        }
1339
-    }
1340
-
1341
-
1342
-    /**
1343
-     * @return void
1344
-     */
1345
-    public function translate_js_strings()
1346
-    {
1347
-        EE_Registry::$i18n_js_strings['revisit']                        = $this->checkout->revisit;
1348
-        EE_Registry::$i18n_js_strings['e_reg_url_link']                 = $this->checkout->reg_url_link;
1349
-        EE_Registry::$i18n_js_strings['server_error']                   = esc_html__(
1350
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1351
-            'event_espresso'
1352
-        );
1353
-        EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1354
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1355
-            'event_espresso'
1356
-        );
1357
-        EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1358
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1359
-            'event_espresso'
1360
-        );
1361
-        EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1362
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1363
-            'event_espresso'
1364
-        );
1365
-        EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1366
-            'This registration step could not be completed. Please refresh the page and try again.',
1367
-            'event_espresso'
1368
-        );
1369
-        EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1370
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1371
-            'event_espresso'
1372
-        );
1373
-        EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1374
-            esc_html__(
1375
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1376
-                'event_espresso'
1377
-            ),
1378
-            '<br/>',
1379
-            '<br/>'
1380
-        );
1381
-        EE_Registry::$i18n_js_strings['language']                       = get_bloginfo('language');
1382
-        EE_Registry::$i18n_js_strings['EESID']                          = EE_Registry::instance()->SSN->id();
1383
-        EE_Registry::$i18n_js_strings['currency']                       = EE_Registry::instance()->CFG->currency;
1384
-        EE_Registry::$i18n_js_strings['datepicker_yearRange']           = '-150:+20';
1385
-        EE_Registry::$i18n_js_strings['timer_years']                    = esc_html__('years', 'event_espresso');
1386
-        EE_Registry::$i18n_js_strings['timer_months']                   = esc_html__('months', 'event_espresso');
1387
-        EE_Registry::$i18n_js_strings['timer_weeks']                    = esc_html__('weeks', 'event_espresso');
1388
-        EE_Registry::$i18n_js_strings['timer_days']                     = esc_html__('days', 'event_espresso');
1389
-        EE_Registry::$i18n_js_strings['timer_hours']                    = esc_html__('hours', 'event_espresso');
1390
-        EE_Registry::$i18n_js_strings['timer_minutes']                  = esc_html__('minutes', 'event_espresso');
1391
-        EE_Registry::$i18n_js_strings['timer_seconds']                  = esc_html__('seconds', 'event_espresso');
1392
-        EE_Registry::$i18n_js_strings['timer_year']                     = esc_html__('year', 'event_espresso');
1393
-        EE_Registry::$i18n_js_strings['timer_month']                    = esc_html__('month', 'event_espresso');
1394
-        EE_Registry::$i18n_js_strings['timer_week']                     = esc_html__('week', 'event_espresso');
1395
-        EE_Registry::$i18n_js_strings['timer_day']                      = esc_html__('day', 'event_espresso');
1396
-        EE_Registry::$i18n_js_strings['timer_hour']                     = esc_html__('hour', 'event_espresso');
1397
-        EE_Registry::$i18n_js_strings['timer_minute']                   = esc_html__('minute', 'event_espresso');
1398
-        EE_Registry::$i18n_js_strings['timer_second']                   = esc_html__('second', 'event_espresso');
1399
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
1400
-            EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1401
-        EE_Registry::$i18n_js_strings['ajax_submit']                    = apply_filters(
1402
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1403
-            true
1404
-        );
1405
-        EE_Registry::$i18n_js_strings['session_extension']              = absint(
1406
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1407
-        );
1408
-        EE_Registry::$i18n_js_strings['session_expiration']             = gmdate(
1409
-            'M d, Y H:i:s',
1410
-            EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1411
-        );
1412
-    }
1413
-
1414
-
1415
-    /**
1416
-     * @return void
1417
-     * @throws EE_Error
1418
-     */
1419
-    public function enqueue_styles_and_scripts()
1420
-    {
1421
-        // load css
1422
-        wp_register_style(
1423
-            'single_page_checkout',
1424
-            SPCO_CSS_URL . 'single_page_checkout.css',
1425
-            ['espresso_default'],
1426
-            EVENT_ESPRESSO_VERSION
1427
-        );
1428
-        wp_enqueue_style('single_page_checkout');
1429
-        // load JS
1430
-        wp_register_script(
1431
-            'jquery_plugin',
1432
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1433
-            ['jquery'],
1434
-            '1.0.1',
1435
-            true
1436
-        );
1437
-        wp_register_script(
1438
-            'jquery_countdown',
1439
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1440
-            ['jquery_plugin'],
1441
-            '2.1.0',
1442
-            true
1443
-        );
1444
-        wp_register_script(
1445
-            'single_page_checkout',
1446
-            SPCO_JS_URL . 'single_page_checkout.js',
1447
-            ['espresso_core', 'underscore', 'ee_form_section_validation'],
1448
-            EVENT_ESPRESSO_VERSION,
1449
-            true
1450
-        );
1451
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1452
-            $this->checkout->registration_form->enqueue_js();
1453
-        }
1454
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1455
-            $this->checkout->current_step->reg_form->enqueue_js();
1456
-        }
1457
-        wp_enqueue_script('single_page_checkout');
1458
-        if (apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)) {
1459
-            wp_enqueue_script('jquery_countdown');
1460
-        }
1461
-        /**
1462
-         * global action hook for enqueueing styles and scripts with
1463
-         * spco calls.
1464
-         */
1465
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1466
-        /**
1467
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1468
-         * The hook will end up being something like:
1469
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1470
-         */
1471
-        do_action(
1472
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1473
-            $this
1474
-        );
1475
-    }
1476
-
1477
-
1478
-    /**
1479
-     * display the Registration Single Page Checkout Form
1480
-     *
1481
-     * @return void
1482
-     * @throws EE_Error
1483
-     * @throws ReflectionException
1484
-     */
1485
-    private function _display_spco_reg_form()
1486
-    {
1487
-        // if registering via the admin, just display the reg form for the current step
1488
-        if ($this->checkout->admin_request) {
1489
-            EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->current_step->display_reg_form());
1490
-        } else {
1491
-            // add powered by EE msg
1492
-            add_action('AHEE__SPCO__reg_form_footer', ['EED_Single_Page_Checkout', 'display_registration_footer']);
1493
-            $empty_cart                                 = count(
1494
-                    $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1495
-                ) < 1;
1496
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1497
-            $cookies_not_set_msg                        = '';
1498
-            if ($empty_cart) {
1499
-                $cookies_not_set_msg = apply_filters(
1500
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1501
-                    sprintf(
1502
-                        esc_html__(
1503
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1504
-                            'event_espresso'
1505
-                        ),
1506
-                        '<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1507
-                        '</div>',
1508
-                        '<h6 class="important-notice">',
1509
-                        '</h6>',
1510
-                        '<p>',
1511
-                        '</p>',
1512
-                        '<br />',
1513
-                        '<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
1514
-                        '</a>'
1515
-                    )
1516
-                );
1517
-            }
1518
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1519
-                [
1520
-                    'name'            => 'single-page-checkout',
1521
-                    'html_id'         => 'ee-single-page-checkout-dv',
1522
-                    'layout_strategy' =>
1523
-                        new EE_Template_Layout(
1524
-                            [
1525
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1526
-                                'template_args'        => [
1527
-                                    'empty_cart'              => $empty_cart,
1528
-                                    'revisit'                 => $this->checkout->revisit,
1529
-                                    'reg_steps'               => $this->checkout->reg_steps,
1530
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1531
-                                        ? $this->checkout->next_step->slug()
1532
-                                        : '',
1533
-                                    'empty_msg'               => apply_filters(
1534
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1535
-                                        sprintf(
1536
-                                            esc_html__(
1537
-                                                'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1538
-                                                'event_espresso'
1539
-                                            ),
1540
-                                            '<a href="'
1541
-                                            . get_post_type_archive_link('espresso_events')
1542
-                                            . '" title="',
1543
-                                            '">',
1544
-                                            '</a>'
1545
-                                        )
1546
-                                    ),
1547
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1548
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1549
-                                    'session_expiration'      => gmdate(
1550
-                                        'M d, Y H:i:s',
1551
-                                        EE_Registry::instance()->SSN->expiration()
1552
-                                        + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1553
-                                    ),
1554
-                                ],
1555
-                            ]
1556
-                        ),
1557
-                ]
1558
-            );
1559
-            // load template and add to output sent that gets filtered into the_content()
1560
-            EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->registration_form->get_html());
1561
-        }
1562
-    }
1563
-
1564
-
1565
-    /**
1566
-     * @param $next_step
1567
-     * @return void
1568
-     */
1569
-    public function add_extra_finalize_registration_inputs($next_step)
1570
-    {
1571
-        if ($next_step === 'finalize_registration') {
1572
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1573
-        }
1574
-    }
1575
-
1576
-
1577
-    /**
1578
-     * @return void
1579
-     */
1580
-    public static function display_registration_footer()
1581
-    {
1582
-        if (
1583
-            apply_filters(
1584
-                'FHEE__EE_Front__Controller__show_reg_footer',
1585
-                EE_Registry::instance()->CFG->admin->show_reg_footer
1586
-            )
1587
-        ) {
1588
-            add_filter(
1589
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1590
-                function ($url) {
1591
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1592
-                }
1593
-            );
1594
-            echo apply_filters(
1595
-                'FHEE__EE_Front_Controller__display_registration_footer',
1596
-                EEH_Template::powered_by_event_espresso(
1597
-                    '',
1598
-                    'espresso-registration-footer-dv',
1599
-                    ['utm_content' => 'registration_checkout']
1600
-                )
1601
-            );
1602
-        }
1603
-    }
1604
-
1605
-
1606
-    /**
1607
-     * @return void
1608
-     * @throws EE_Error
1609
-     * @throws ReflectionException
1610
-     */
1611
-    public function unlock_transaction()
1612
-    {
1613
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1614
-            $this->checkout->transaction->unlock();
1615
-        }
1616
-    }
1617
-
1618
-
1619
-    /**
1620
-     * @return void
1621
-     */
1622
-    private function _setup_redirect()
1623
-    {
1624
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1625
-            $this->checkout->redirect = true;
1626
-            if (empty($this->checkout->redirect_url)) {
1627
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1628
-            }
1629
-            $this->checkout->redirect_url = apply_filters(
1630
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1631
-                $this->checkout->redirect_url,
1632
-                $this->checkout
1633
-            );
1634
-        }
1635
-    }
1636
-
1637
-
1638
-    /**
1639
-     * handle ajax message responses and redirects
1640
-     *
1641
-     * @return void
1642
-     * @throws EE_Error
1643
-     * @throws ReflectionException
1644
-     */
1645
-    public function go_to_next_step()
1646
-    {
1647
-        if ($this->request->isAjax()) {
1648
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1649
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1650
-        }
1651
-        $this->unlock_transaction();
1652
-        // just return for these conditions
1653
-        if (
1654
-            $this->checkout->admin_request
1655
-            || $this->checkout->action === 'redirect_form'
1656
-            || $this->checkout->action === 'update_checkout'
1657
-        ) {
1658
-            return;
1659
-        }
1660
-        // AJAX response
1661
-        $this->_handle_json_response();
1662
-        // redirect to next step or the Thank-You page
1663
-        $this->_handle_html_redirects();
1664
-        // hmmm... must be something wrong, so let's just display the form again !
1665
-        $this->_display_spco_reg_form();
1666
-    }
1667
-
1668
-
1669
-    /**
1670
-     * @return void
1671
-     * @throws EE_Error
1672
-     */
1673
-    protected function _handle_json_response()
1674
-    {
1675
-        // if this is an ajax request
1676
-        if ($this->request->isAjax()) {
1677
-            $this->checkout->json_response->set_registration_time_limit(
1678
-                $this->checkout->get_registration_time_limit()
1679
-            );
1680
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1681
-            // just send the ajax (
1682
-            $json_response = apply_filters(
1683
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1684
-                $this->checkout->json_response
1685
-            );
1686
-            exit($json_response);
1687
-        }
1688
-    }
1689
-
1690
-
1691
-    /**
1692
-     * @return void
1693
-     */
1694
-    protected function _handle_html_redirects()
1695
-    {
1696
-        // going somewhere ?
1697
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1698
-            // store notices in a transient
1699
-            EE_Error::get_notices(false, true);
1700
-            wp_safe_redirect($this->checkout->redirect_url);
1701
-            exit();
1702
-        }
1703
-    }
1704
-
1705
-
1706
-    /**
1707
-     * @return void
1708
-     */
1709
-    public function set_checkout_anchor()
1710
-    {
1711
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1712
-    }
1713
-
1714
-
1715
-    /**
1716
-     * @return string
1717
-     * @since 4.9.59.p
1718
-     */
1719
-    public static function getRegistrationExpirationNotice(): string
1720
-    {
1721
-        return sprintf(
1722
-            esc_html__(
1723
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1724
-                'event_espresso'
1725
-            ),
1726
-            '<h4 class="important-notice">',
1727
-            '</h4>',
1728
-            '<br />',
1729
-            '<p>',
1730
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1731
-            '">',
1732
-            '</a>',
1733
-            '</p>'
1734
-        );
1735
-    }
22
+	/**
23
+	 * $_initialized - has the SPCO controller already been initialized ?
24
+	 */
25
+	private static bool $_initialized = false;
26
+
27
+
28
+	/**
29
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
30
+	 */
31
+	private static bool $_checkout_verified = true;
32
+
33
+	/**
34
+	 * $_reg_steps_array - holds initial array of reg steps
35
+	 *
36
+	 * @var array $_reg_steps_array
37
+	 */
38
+	private static array $_reg_steps_array = [];
39
+
40
+	/**
41
+	 * $checkout - EE_Checkout object for handling the properties of the current checkout process
42
+	 */
43
+	public ?EE_Checkout $checkout = null;
44
+
45
+	protected ?RequestInterface $request = null;
46
+
47
+	private bool $debug = false;    //  true    false
48
+
49
+
50
+	/**
51
+	 * @return EED_Single_Page_Checkout|EED_Module
52
+	 * @throws EE_Error
53
+	 * @throws ReflectionException
54
+	 */
55
+	public static function instance()
56
+	{
57
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
58
+		return parent::get_instance(__CLASS__);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @return EE_CART
64
+	 */
65
+	public function cart(): EE_CART
66
+	{
67
+		return $this->checkout->cart;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @return RequestInterface
73
+	 * @since   4.10.14.p
74
+	 */
75
+	public static function getRequest(): RequestInterface
76
+	{
77
+		return LoaderFactory::getLoader()->getShared(RequestInterface::class);
78
+	}
79
+
80
+
81
+	/**
82
+	 * @return EE_Transaction
83
+	 */
84
+	public function transaction(): EE_Transaction
85
+	{
86
+		return $this->checkout->transaction;
87
+	}
88
+
89
+
90
+	/**
91
+	 *    set_hooks - for hooking into EE Core, other modules, etc
92
+	 *
93
+	 * @return    void
94
+	 * @throws EE_Error
95
+	 */
96
+	public static function set_hooks()
97
+	{
98
+		EED_Single_Page_Checkout::set_definitions();
99
+	}
100
+
101
+
102
+	/**
103
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
104
+	 *
105
+	 * @return    void
106
+	 * @throws EE_Error
107
+	 */
108
+	public static function set_hooks_admin()
109
+	{
110
+		EED_Single_Page_Checkout::set_definitions();
111
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
112
+			return;
113
+		}
114
+		// going to start an output buffer in case anything gets accidentally output
115
+		// that might disrupt our JSON response
116
+		ob_start();
117
+		EED_Single_Page_Checkout::load_reg_steps();
118
+		// set ajax hooks
119
+		add_action('wp_ajax_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
120
+		add_action('wp_ajax_nopriv_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
121
+		add_action('wp_ajax_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
122
+		add_action('wp_ajax_nopriv_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
123
+		add_action('wp_ajax_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
124
+		add_action('wp_ajax_nopriv_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
125
+	}
126
+
127
+
128
+	/**
129
+	 *    process ajax request
130
+	 *
131
+	 * @param string $ajax_action
132
+	 * @throws EE_Error
133
+	 * @throws ReflectionException
134
+	 */
135
+	public static function process_ajax_request(string $ajax_action)
136
+	{
137
+		$request = EED_Single_Page_Checkout::getRequest();
138
+		$request->setRequestParam('action', $ajax_action);
139
+		EED_Single_Page_Checkout::instance()->_initialize();
140
+	}
141
+
142
+
143
+	/**
144
+	 * ajax display registration step
145
+	 *
146
+	 * @throws EE_Error
147
+	 * @throws ReflectionException
148
+	 */
149
+	public static function display_reg_step()
150
+	{
151
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
152
+	}
153
+
154
+
155
+	/**
156
+	 * ajax process registration step
157
+	 *
158
+	 * @throws EE_Error
159
+	 * @throws ReflectionException
160
+	 */
161
+	public static function process_reg_step()
162
+	{
163
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
164
+	}
165
+
166
+
167
+	/**
168
+	 * ajax process registration step
169
+	 *
170
+	 * @throws EE_Error
171
+	 * @throws ReflectionException
172
+	 */
173
+	public static function update_reg_step()
174
+	{
175
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
176
+	}
177
+
178
+
179
+	/**
180
+	 * update_checkout
181
+	 *
182
+	 * @return void
183
+	 * @throws ReflectionException
184
+	 * @throws EE_Error
185
+	 */
186
+	public static function update_checkout()
187
+	{
188
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
189
+	}
190
+
191
+
192
+	/**
193
+	 *    set_definitions
194
+	 *
195
+	 * @return    void
196
+	 * @throws EE_Error
197
+	 */
198
+	public static function set_definitions()
199
+	{
200
+		if (defined('SPCO_BASE_PATH')) {
201
+			return;
202
+		}
203
+		define(
204
+			'SPCO_BASE_PATH',
205
+			rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
206
+		);
207
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
208
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
209
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
210
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
211
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
212
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
213
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
214
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
215
+			EED_Single_Page_Checkout::getRegistrationExpirationNotice();
216
+	}
217
+
218
+
219
+	/**
220
+	 * load_reg_steps
221
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
222
+	 *
223
+	 * @throws EE_Error
224
+	 */
225
+	public static function load_reg_steps()
226
+	{
227
+		static $reg_steps_loaded = false;
228
+		if ($reg_steps_loaded) {
229
+			return;
230
+		}
231
+		// filter list of reg_steps
232
+		$reg_steps_to_load = (array) apply_filters(
233
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
234
+			EED_Single_Page_Checkout::get_reg_steps()
235
+		);
236
+		// sort by key (order)
237
+		ksort($reg_steps_to_load);
238
+		// loop through folders
239
+		foreach ($reg_steps_to_load as $order => $reg_step) {
240
+			// we need a
241
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
242
+				// copy over to the reg_steps_array
243
+				EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
244
+				// register custom key route for each reg step
245
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
246
+				EE_Config::register_route(
247
+					$reg_step['slug'],
248
+					'EED_Single_Page_Checkout',
249
+					'run',
250
+					'step'
251
+				);
252
+				// add AJAX or other hooks
253
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
254
+					// setup autoloaders if necessary
255
+					if (! class_exists($reg_step['class_name'])) {
256
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
257
+							$reg_step['file_path'],
258
+							true
259
+						);
260
+					}
261
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
262
+						call_user_func([$reg_step['class_name'], 'set_hooks']);
263
+					}
264
+				}
265
+			}
266
+		}
267
+		$reg_steps_loaded = true;
268
+	}
269
+
270
+
271
+	/**
272
+	 *    get_reg_steps
273
+	 *
274
+	 * @return    array
275
+	 */
276
+	public static function get_reg_steps(): array
277
+	{
278
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
279
+		if (empty($reg_steps)) {
280
+			$reg_steps = [
281
+				10  => [
282
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
283
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
284
+					'slug'       => 'attendee_information',
285
+					'has_hooks'  => false,
286
+				],
287
+				30  => [
288
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
289
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
290
+					'slug'       => 'payment_options',
291
+					'has_hooks'  => true,
292
+				],
293
+				999 => [
294
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
295
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
296
+					'slug'       => 'finalize_registration',
297
+					'has_hooks'  => false,
298
+				],
299
+			];
300
+		}
301
+		return $reg_steps;
302
+	}
303
+
304
+
305
+	/**
306
+	 * @return array|string
307
+	 * @throws EE_Error
308
+	 * @throws ReflectionException
309
+	 */
310
+	public static function registration_checkout_for_admin()
311
+	{
312
+		$request = EED_Single_Page_Checkout::getRequest();
313
+		$request->setRequestParam('step', 'attendee_information');
314
+		$request->setRequestParam('action', 'display_spco_reg_step');
315
+		$request->setRequestParam('process_form_submission', false);
316
+		EED_Single_Page_Checkout::instance()->_initialize();
317
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
318
+		return EED_Single_Page_Checkout::getResponse()->getOutput();
319
+	}
320
+
321
+
322
+	/**
323
+	 * @return EE_Transaction|null
324
+	 * @throws EE_Error
325
+	 * @throws ReflectionException
326
+	 */
327
+	public static function process_registration_from_admin(): ?EE_Transaction
328
+	{
329
+		$request = EED_Single_Page_Checkout::getRequest();
330
+		$request->setRequestParam('step', 'attendee_information');
331
+		$request->setRequestParam('action', 'process_reg_step');
332
+		$request->setRequestParam('process_form_submission', true);
333
+		EED_Single_Page_Checkout::instance()->_initialize();
334
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
335
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
336
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
337
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
338
+				if ($final_reg_step->process_reg_step()) {
339
+					$final_reg_step->set_completed();
340
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
341
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
342
+				}
343
+			}
344
+		}
345
+		return null;
346
+	}
347
+
348
+
349
+	/**
350
+	 *    run
351
+	 *
352
+	 * @param WP_Query|null $WP_Query
353
+	 * @return    void
354
+	 */
355
+	public function run($WP_Query)
356
+	{
357
+		if (
358
+			$WP_Query instanceof WP_Query
359
+			&& $WP_Query->is_main_query()
360
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
361
+			&& $this->_is_reg_checkout()
362
+		) {
363
+			$this->_initialize();
364
+		}
365
+	}
366
+
367
+
368
+	/**
369
+	 * determines whether current url matches reg page url
370
+	 *
371
+	 * @return bool
372
+	 */
373
+	protected function _is_reg_checkout(): bool
374
+	{
375
+		// get current permalink for reg page without any extra query args
376
+		$reg_page_url = get_permalink(EE_Config::instance()->core->reg_page_id);
377
+		// get request URI for current request, but without the scheme or host
378
+		$current_request_uri = EEH_URL::filter_input_server_url();
379
+		$current_request_uri = html_entity_decode($current_request_uri);
380
+		// get array of query args from the current request URI
381
+		$query_args = EEH_URL::get_query_string($current_request_uri);
382
+		// grab page id if it is set
383
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
384
+		// and remove the page id from the query args (we will re-add it later)
385
+		unset($query_args['page_id']);
386
+		// now strip all query args from current request URI
387
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
388
+		// and re-add the page id if it was set
389
+		if ($page_id) {
390
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
391
+		}
392
+		// remove slashes and ?
393
+		$current_request_uri = trim($current_request_uri, '?/');
394
+		// is current request URI part of the known full reg page URL ?
395
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
396
+	}
397
+
398
+
399
+	/**
400
+	 * @param WP_Query $wp_query
401
+	 * @return    void
402
+	 * @throws EE_Error
403
+	 * @throws ReflectionException
404
+	 */
405
+	public static function init(WP_Query $wp_query)
406
+	{
407
+		EED_Single_Page_Checkout::instance()->run($wp_query);
408
+	}
409
+
410
+
411
+	/**
412
+	 * @return void
413
+	 */
414
+	private function _initialize()
415
+	{
416
+		// ensure SPCO doesn't run twice
417
+		if (EED_Single_Page_Checkout::$_initialized) {
418
+			return;
419
+		}
420
+		try {
421
+			$this->request = EED_Single_Page_Checkout::getRequest();
422
+			EED_Single_Page_Checkout::load_reg_steps();
423
+			$this->_verify_session();
424
+			// set up the EE_Checkout object
425
+			$this->checkout = $this->_initialize_checkout();
426
+			// filter checkout
427
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
428
+			// get the $_GET
429
+			$this->_get_request_vars();
430
+			if ($this->_block_bots()) {
431
+				return;
432
+			}
433
+			// filter continue_reg
434
+			$this->checkout->continue_reg = apply_filters(
435
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
436
+				true,
437
+				$this->checkout
438
+			);
439
+			// load the reg steps array
440
+			if (! $this->_load_and_instantiate_reg_steps()) {
441
+				EED_Single_Page_Checkout::$_initialized = true;
442
+				return;
443
+			}
444
+			// set the current step
445
+			$this->checkout->set_current_step($this->checkout->step);
446
+			// and the next step
447
+			$this->checkout->set_next_step();
448
+			// verify that everything has been set up correctly
449
+			if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
450
+				EED_Single_Page_Checkout::$_initialized = true;
451
+				return;
452
+			}
453
+			do_action('AHEE__Single_Page_Checkout___initialize__after_final_verifications', $this->checkout);
454
+			// lock the transaction
455
+			$this->checkout->transaction->lock();
456
+			// make sure all of our cached objects are added to their respective model entity mappers
457
+			$this->checkout->refresh_all_entities();
458
+			// set amount owing
459
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
460
+			// initialize each reg step, which gives them the chance to potentially alter the process
461
+			$this->_initialize_reg_steps();
462
+			// DEBUG LOG
463
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
464
+			// get reg form
465
+			if (! $this->_check_form_submission()) {
466
+				EED_Single_Page_Checkout::$_initialized = true;
467
+				return;
468
+			}
469
+			// checkout the action!!!
470
+			$this->_process_form_action();
471
+			// add some style and make it dance
472
+			$this->add_styles_and_scripts($this);
473
+			// kk... SPCO has successfully run
474
+			EED_Single_Page_Checkout::$_initialized = true;
475
+			// set no cache headers and constants
476
+			EE_System::do_not_cache();
477
+			// add anchor
478
+			add_action('loop_start', [$this, 'set_checkout_anchor'], 1);
479
+			// remove transaction lock
480
+			add_action('shutdown', [$this, 'unlock_transaction'], 1);
481
+		} catch (Exception $e) {
482
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
483
+		}
484
+	}
485
+
486
+
487
+	/**
488
+	 * checks that the session is valid and not expired
489
+	 *
490
+	 * @throws EE_Error
491
+	 * @throws ReflectionException
492
+	 */
493
+	private function _verify_session()
494
+	{
495
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
496
+			throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
497
+		}
498
+		$clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
499
+		// is session still valid ?
500
+		if (
501
+			$clear_session_requested
502
+			|| (
503
+				EE_Registry::instance()->SSN->expired()
504
+				&& $this->request->getRequestParam('e_reg_url_link') === ''
505
+			)
506
+		) {
507
+			$this->checkout = new EE_Checkout();
508
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
509
+			// EE_Registry::instance()->SSN->reset_cart();
510
+			// EE_Registry::instance()->SSN->reset_checkout();
511
+			// EE_Registry::instance()->SSN->reset_transaction();
512
+			if (! $clear_session_requested) {
513
+				EE_Error::add_attention(
514
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
515
+					__FILE__,
516
+					__FUNCTION__,
517
+					__LINE__
518
+				);
519
+			}
520
+			// EE_Registry::instance()->SSN->reset_expired();
521
+		}
522
+	}
523
+
524
+
525
+	/**
526
+	 * loads and instantiates EE_Checkout
527
+	 *
528
+	 * @return EE_Checkout
529
+	 * @throws EE_Error
530
+	 * @throws ReflectionException
531
+	 */
532
+	private function _initialize_checkout(): EE_Checkout
533
+	{
534
+		// look in session for existing checkout
535
+		/** @type EE_Checkout $checkout */
536
+		$checkout = EE_Registry::instance()->SSN->checkout();
537
+		// verify
538
+		if (! $checkout instanceof EE_Checkout) {
539
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
540
+			$checkout = EE_Registry::instance()->load_file(
541
+				SPCO_INC_PATH,
542
+				'EE_Checkout',
543
+				'class',
544
+				[],
545
+				false
546
+			);
547
+		} else {
548
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
549
+				$this->unlock_transaction();
550
+				wp_safe_redirect($checkout->redirect_url);
551
+				exit();
552
+			}
553
+		}
554
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
555
+		// verify again
556
+		if (! $checkout instanceof EE_Checkout) {
557
+			throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
558
+		}
559
+		// reset anything that needs a clean slate for each request
560
+		$checkout->reset_for_current_request();
561
+		return $checkout;
562
+	}
563
+
564
+
565
+	/**
566
+	 * @return void
567
+	 */
568
+	private function _get_request_vars()
569
+	{
570
+		// make sure this request is marked as belonging to EE
571
+		/** @var CurrentPage $current_page */
572
+		$current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class);
573
+		$current_page->setEspressoPage(true);
574
+		// which step is being requested ?
575
+		$this->checkout->step = $this->request->getRequestParam('step', $this->_get_first_step());
576
+		// which step is being edited ?
577
+		$this->checkout->edit_step = $this->request->getRequestParam('edit_step');
578
+		// and what we're doing on the current step
579
+		$this->checkout->action = $this->request->getRequestParam('action', 'display_spco_reg_step');
580
+		// timestamp
581
+		$this->checkout->uts = $this->request->getRequestParam('uts', 0, 'int');
582
+		// returning to edit ?
583
+		$this->checkout->reg_url_link = $this->request->getRequestParam('e_reg_url_link');
584
+		// add reg url link to registration query params
585
+		if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
586
+			$this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
587
+		}
588
+		// or some other kind of revisit ?
589
+		$this->checkout->revisit = $this->request->getRequestParam('revisit', false, 'bool');
590
+		// and whether to generate a reg form for this request
591
+		$this->checkout->generate_reg_form = $this->request->getRequestParam('generate_reg_form', true, 'bool');
592
+		// and whether to process a reg form submission for this request
593
+		$this->checkout->process_form_submission = $this->request->getRequestParam(
594
+			'process_form_submission',
595
+			$this->checkout->action === 'process_reg_step',
596
+			'bool'
597
+		);
598
+		$this->checkout->process_form_submission = filter_var(
599
+			$this->checkout->action !== 'display_spco_reg_step'
600
+				? $this->checkout->process_form_submission
601
+				: false,
602
+			FILTER_VALIDATE_BOOLEAN
603
+		);
604
+		$this->_display_request_vars();
605
+	}
606
+
607
+
608
+	/**
609
+	 * @return void
610
+	 */
611
+	protected function _display_request_vars()
612
+	{
613
+		if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
614
+			return;
615
+		}
616
+		EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
617
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
618
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
619
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
620
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
621
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
622
+		EEH_Debug_Tools::printr(
623
+			$this->checkout->generate_reg_form,
624
+			'$this->checkout->generate_reg_form',
625
+			__FILE__,
626
+			__LINE__
627
+		);
628
+		EEH_Debug_Tools::printr(
629
+			$this->checkout->process_form_submission,
630
+			'$this->checkout->process_form_submission',
631
+			__FILE__,
632
+			__LINE__
633
+		);
634
+	}
635
+
636
+
637
+	/**
638
+	 * _block_bots
639
+	 * checks that the incoming request has either of the following set:
640
+	 *  a UTS (unix timestamp) which indicates that the request was redirected from the Ticket Selector
641
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
642
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
643
+	 * then where you coming from man?
644
+	 *
645
+	 * @return boolean
646
+	 */
647
+	private function _block_bots(): bool
648
+	{
649
+		return EED_Invalid_Checkout_Access::getInvalidCheckoutAccess()->checkoutAccessIsInvalid($this->checkout);
650
+	}
651
+
652
+
653
+	/**
654
+	 *  gets slug for first step in $_reg_steps_array
655
+	 *
656
+	 * @return string
657
+	 */
658
+	private function _get_first_step(): string
659
+	{
660
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
661
+		return $first_step['slug'] ?? 'attendee_information';
662
+	}
663
+
664
+
665
+	/**
666
+	 * instantiates each reg step based on the loaded reg_steps array
667
+	 *
668
+	 * @return bool
669
+	 * @throws EE_Error
670
+	 * @throws InvalidArgumentException
671
+	 * @throws InvalidDataTypeException
672
+	 * @throws InvalidInterfaceException
673
+	 * @throws ReflectionException
674
+	 */
675
+	private function _load_and_instantiate_reg_steps(): bool
676
+	{
677
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
678
+		// have reg_steps already been instantiated ?
679
+		if (
680
+			empty($this->checkout->reg_steps)
681
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
682
+		) {
683
+			// if not, then loop through raw reg steps array
684
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
685
+				if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
686
+					return false;
687
+				}
688
+			}
689
+			if (isset($this->checkout->reg_steps['registration_confirmation'])) {
690
+				// skip the registration_confirmation page ?
691
+				// just remove it from the reg steps array
692
+				$this->checkout->remove_reg_step('registration_confirmation', false);
693
+			}
694
+			// filter the array for good luck
695
+			$this->checkout->reg_steps = apply_filters(
696
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
697
+				$this->checkout->reg_steps
698
+			);
699
+			// finally re-sort based on the reg step class order properties
700
+			$this->checkout->sort_reg_steps();
701
+		} else {
702
+			foreach ($this->checkout->reg_steps as $reg_step) {
703
+				// set all current step stati to FALSE
704
+				$reg_step->set_is_current_step(false);
705
+			}
706
+		}
707
+		if (empty($this->checkout->reg_steps)) {
708
+			EE_Error::add_error(
709
+				esc_html__('No Reg Steps were loaded..', 'event_espresso'),
710
+				__FILE__,
711
+				__FUNCTION__,
712
+				__LINE__
713
+			);
714
+			return false;
715
+		}
716
+		// make reg step details available to JS
717
+		$this->checkout->set_reg_step_JSON_info();
718
+		return true;
719
+	}
720
+
721
+
722
+	/**
723
+	 * @param array $reg_step
724
+	 * @param int   $order
725
+	 * @return bool
726
+	 * @throws EE_Error
727
+	 * @throws ReflectionException
728
+	 */
729
+	private function _load_and_instantiate_reg_step(array $reg_step = [], int $order = 0): bool
730
+	{
731
+		// we need a file_path, class_name, and slug to add a reg step
732
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
733
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
734
+			if (
735
+				$this->checkout->reg_url_link
736
+				&& $this->checkout->step !== $reg_step['slug']
737
+				&& $reg_step['slug'] !== 'finalize_registration'
738
+				// normally at this point we would NOT load the reg step, but this filter can change that
739
+				&& apply_filters(
740
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
741
+					true,
742
+					$reg_step,
743
+					$this->checkout
744
+				)
745
+			) {
746
+				return true;
747
+			}
748
+
749
+			// instantiate step class using file path and class name
750
+			$reg_step_obj = EE_Registry::instance()->load_file(
751
+				$reg_step['file_path'],
752
+				$reg_step['class_name'],
753
+				'class',
754
+				[$this->checkout],
755
+				false
756
+			);
757
+			// did we get the goods ?
758
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
759
+				// set reg step order based on config
760
+				$reg_step_obj->set_order($order);
761
+				// add instantiated reg step object to the master reg steps array
762
+				$this->checkout->add_reg_step($reg_step_obj);
763
+			} else {
764
+				EE_Error::add_error(
765
+					esc_html__('The current step could not be set.', 'event_espresso'),
766
+					__FILE__,
767
+					__FUNCTION__,
768
+					__LINE__
769
+				);
770
+				return false;
771
+			}
772
+		} else {
773
+			if (WP_DEBUG) {
774
+				EE_Error::add_error(
775
+					sprintf(
776
+						esc_html__(
777
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
778
+							'event_espresso'
779
+						),
780
+						$reg_step['file_path'] ?? '',
781
+						$reg_step['class_name'] ?? '',
782
+						$reg_step['slug'] ?? '',
783
+						'<ul>',
784
+						'<li>',
785
+						'</li>',
786
+						'</ul>'
787
+					),
788
+					__FILE__,
789
+					__FUNCTION__,
790
+					__LINE__
791
+				);
792
+			}
793
+			return false;
794
+		}
795
+		return true;
796
+	}
797
+
798
+
799
+	/**
800
+	 * @return bool
801
+	 * @throws EE_Error
802
+	 * @throws ReflectionException
803
+	 */
804
+	private function _verify_transaction_and_get_registrations(): bool
805
+	{
806
+		// was there already a valid transaction in the checkout from the session ?
807
+		if (! $this->checkout->transaction instanceof EE_Transaction) {
808
+			// get transaction from db or session
809
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
810
+				? $this->_get_transaction_and_cart_for_previous_visit()
811
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
812
+			if (! $this->checkout->transaction instanceof EE_Transaction) {
813
+				EE_Error::add_error(
814
+					esc_html__(
815
+						'Your Registration and Transaction information could not be retrieved from the db.',
816
+						'event_espresso'
817
+					),
818
+					__FILE__,
819
+					__FUNCTION__,
820
+					__LINE__
821
+				);
822
+				$this->checkout->transaction = EE_Transaction::new_instance();
823
+				// add some style and make it dance
824
+				$this->add_styles_and_scripts($this);
825
+				EED_Single_Page_Checkout::$_initialized = true;
826
+				return false;
827
+			}
828
+			// and the registrations for the transaction
829
+			$this->_get_registrations($this->checkout->transaction);
830
+		}
831
+		return true;
832
+	}
833
+
834
+
835
+	/**
836
+	 * @return EE_Transaction|null
837
+	 * @throws EE_Error
838
+	 * @throws ReflectionException
839
+	 */
840
+	private function _get_transaction_and_cart_for_previous_visit(): ?EE_Transaction
841
+	{
842
+		/** @var $TXN_model EEM_Transaction */
843
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
844
+		// because the reg_url_link is present in the request,
845
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
846
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
847
+		// verify transaction
848
+		if ($transaction instanceof EE_Transaction) {
849
+			// and get the cart that was used for that transaction
850
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
851
+			return $transaction;
852
+		}
853
+		EE_Error::add_error(
854
+			esc_html__(
855
+				'Your Registration and Transaction information could not be retrieved from the db.',
856
+				'event_espresso'
857
+			),
858
+			__FILE__,
859
+			__FUNCTION__,
860
+			__LINE__
861
+		);
862
+		return null;
863
+	}
864
+
865
+
866
+	/**
867
+	 * @param EE_Transaction|null $transaction
868
+	 * @return EE_Cart
869
+	 */
870
+	private function _get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
871
+	{
872
+		return $this->checkout->get_cart_for_transaction($transaction);
873
+	}
874
+
875
+
876
+	/**
877
+	 * @param EE_Transaction|null $transaction
878
+	 * @return EE_Cart
879
+	 */
880
+	public function get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
881
+	{
882
+		return $this->checkout->get_cart_for_transaction($transaction);
883
+	}
884
+
885
+
886
+	/**
887
+	 * generates a new EE_Transaction object and adds it to the $_transaction property.
888
+	 *
889
+	 * @return EE_Transaction|null
890
+	 * @throws EE_Error
891
+	 * @throws ReflectionException
892
+	 */
893
+	private function _get_cart_for_current_session_and_setup_new_transaction(): ?EE_Transaction
894
+	{
895
+		//  if there's no transaction, then this is the FIRST visit to SPCO
896
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
897
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
898
+		// and then create a new transaction
899
+		$transaction = $this->_initialize_transaction();
900
+		// verify transaction
901
+		if ($transaction instanceof EE_Transaction) {
902
+			// and save TXN data to the cart
903
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
904
+		} else {
905
+			EE_Error::add_error(
906
+				esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
907
+				__FILE__,
908
+				__FUNCTION__,
909
+				__LINE__
910
+			);
911
+		}
912
+		return $transaction;
913
+	}
914
+
915
+
916
+	/**
917
+	 * generates a new EE_Transaction object and adds it to the $_transaction property.
918
+	 *
919
+	 * @return EE_Transaction|null
920
+	 */
921
+	private function _initialize_transaction(): ?EE_Transaction
922
+	{
923
+		try {
924
+			// ensure cart totals have been calculated
925
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
926
+			// grab the cart grand total
927
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
928
+			// create new TXN
929
+			$transaction = EE_Transaction::new_instance(
930
+				[
931
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
932
+					'TXN_total'     => max($cart_total, 0),
933
+					'TXN_paid'      => 0,
934
+					'STS_ID'        => EEM_Transaction::failed_status_code,
935
+				]
936
+			);
937
+			// save it so that we have an ID for other objects to use
938
+			$transaction->save();
939
+			// set cron job for following up on TXNs after their session has expired
940
+			EE_Cron_Tasks::schedule_expired_transaction_check(
941
+				EE_Registry::instance()->SSN->expiration() + 1,
942
+				$transaction->ID()
943
+			);
944
+			return $transaction;
945
+		} catch (Exception $e) {
946
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
947
+		}
948
+		return null;
949
+	}
950
+
951
+
952
+	/**
953
+	 * _get_registrations
954
+	 *
955
+	 * @param EE_Transaction $transaction
956
+	 * @return void
957
+	 * @throws EE_Error
958
+	 * @throws ReflectionException
959
+	 */
960
+	private function _get_registrations(EE_Transaction $transaction)
961
+	{
962
+		// first step: grab the registrants  { : o
963
+		$registrations                      = $transaction->registrations($this->checkout->reg_cache_where_params);
964
+		$this->checkout->total_ticket_count = count($registrations);
965
+		// verify registrations have been set
966
+		if (empty($registrations)) {
967
+			// if no cached registrations, then check the db
968
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params);
969
+			// still nothing ? well as long as this isn't a revisit
970
+			if (empty($registrations) && ! $this->checkout->revisit) {
971
+				// generate new registrations from scratch
972
+				$registrations = $this->_initialize_registrations($transaction);
973
+			}
974
+		}
975
+		// sort by their original registration order
976
+		usort($registrations, ['EED_Single_Page_Checkout', 'sort_registrations_by_REG_count']);
977
+		// then loop thru the array
978
+		foreach ($registrations as $registration) {
979
+			// verify each registration
980
+			if ($registration instanceof EE_Registration) {
981
+				// we display all attendee info for the primary registrant
982
+				if (
983
+					$this->checkout->reg_url_link === $registration->reg_url_link()
984
+					&& $registration->is_primary_registrant()
985
+				) {
986
+					$this->checkout->primary_revisit = true;
987
+					break;
988
+				}
989
+				if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
990
+					// but hide info if it doesn't belong to you
991
+					$transaction->clear_cache('Registration', $registration->ID());
992
+					$this->checkout->total_ticket_count--;
993
+				}
994
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
995
+			}
996
+		}
997
+	}
998
+
999
+
1000
+	/**
1001
+	 * adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1002
+	 *
1003
+	 * @param EE_Transaction $transaction
1004
+	 * @return array
1005
+	 * @throws EE_Error
1006
+	 * @throws ReflectionException
1007
+	 */
1008
+	private function _initialize_registrations(EE_Transaction $transaction): array
1009
+	{
1010
+		$att_nmbr      = 0;
1011
+		$registrations = [];
1012
+		/** @type EE_Registration_Processor $registration_processor */
1013
+		$registration_processor             = EE_Registry::instance()->load_class('Registration_Processor');
1014
+		$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1015
+		// now let's add the cart items to the $transaction
1016
+		foreach ($this->checkout->cart->get_tickets() as $line_item) {
1017
+			// do the following for each ticket of this type they selected
1018
+			for ($x = 1; $x <= $line_item->quantity(); $x++) {
1019
+				$att_nmbr++;
1020
+				/** @var CreateRegistrationCommand $CreateRegistrationCommand */
1021
+				$CreateRegistrationCommand = EE_Registry::instance()->create(
1022
+					CreateRegistrationCommand::class,
1023
+					[
1024
+						$transaction,
1025
+						$line_item,
1026
+						$att_nmbr,
1027
+						$this->checkout->total_ticket_count,
1028
+					]
1029
+				);
1030
+				// override capabilities for frontend registrations
1031
+				if ($this->request->isFrontend()) {
1032
+					$CreateRegistrationCommand->setCapCheck(
1033
+						new PublicCapabilities('', 'create_new_registration')
1034
+					);
1035
+				}
1036
+				$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1037
+				if (! $registration instanceof EE_Registration) {
1038
+					throw new InvalidEntityException($registration, 'EE_Registration');
1039
+				}
1040
+				$registrations[ $registration->ID() ] = $registration;
1041
+			}
1042
+		}
1043
+		$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1044
+		return $registrations;
1045
+	}
1046
+
1047
+
1048
+	/**
1049
+	 * @param EE_Registration $reg_A
1050
+	 * @param EE_Registration $reg_B
1051
+	 * @return int
1052
+	 * @throws EE_Error
1053
+	 * @throws ReflectionException
1054
+	 */
1055
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B): int
1056
+	{
1057
+		// this shouldn't ever happen within the same TXN, but oh well
1058
+		if ($reg_A->count() === $reg_B->count()) {
1059
+			return 0;
1060
+		}
1061
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1062
+	}
1063
+
1064
+
1065
+	/**
1066
+	 * just makes sure that everything is set up correctly before proceeding
1067
+	 *
1068
+	 * @return bool
1069
+	 * @throws EE_Error
1070
+	 * @throws ReflectionException
1071
+	 */
1072
+	private function _final_verifications(): bool
1073
+	{
1074
+		// filter checkout
1075
+		$this->checkout = apply_filters(
1076
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1077
+			$this->checkout
1078
+		);
1079
+		// verify that current step is still set correctly
1080
+		if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1081
+			EE_Error::add_error(
1082
+				esc_html__(
1083
+					'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1084
+					'event_espresso'
1085
+				),
1086
+				__FILE__,
1087
+				__FUNCTION__,
1088
+				__LINE__
1089
+			);
1090
+			return false;
1091
+		}
1092
+		// if returning to SPCO, then verify that primary registrant is set
1093
+		if (! empty($this->checkout->reg_url_link)) {
1094
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1095
+			if (! $valid_registrant instanceof EE_Registration) {
1096
+				EE_Error::add_error(
1097
+					esc_html__(
1098
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1099
+						'event_espresso'
1100
+					),
1101
+					__FILE__,
1102
+					__FUNCTION__,
1103
+					__LINE__
1104
+				);
1105
+				return false;
1106
+			}
1107
+			$valid_registrant = null;
1108
+			foreach (
1109
+				$this->checkout->transaction->registrations(
1110
+					$this->checkout->reg_cache_where_params
1111
+				) as $registration
1112
+			) {
1113
+				if (
1114
+					$registration instanceof EE_Registration
1115
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1116
+				) {
1117
+					$valid_registrant = $registration;
1118
+				}
1119
+			}
1120
+			if (! $valid_registrant instanceof EE_Registration) {
1121
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1122
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1123
+					// clear the session, mark the checkout as unverified, and try again
1124
+					EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1125
+					EED_Single_Page_Checkout::$_initialized       = false;
1126
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1127
+					$this->_initialize();
1128
+					EE_Error::reset_notices();
1129
+					return false;
1130
+				}
1131
+				EE_Error::add_error(
1132
+					esc_html__(
1133
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1134
+						'event_espresso'
1135
+					),
1136
+					__FILE__,
1137
+					__FUNCTION__,
1138
+					__LINE__
1139
+				);
1140
+				return false;
1141
+			}
1142
+		}
1143
+		// now that things have been kinda sufficiently verified,
1144
+		// let's add the checkout to the session so that it's available to other systems
1145
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1146
+		return true;
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1152
+	 * then loops thru all the active reg steps and calls the initialize_reg_step() method
1153
+	 *
1154
+	 * @param bool $reinitializing
1155
+	 * @throws EE_Error
1156
+	 */
1157
+	private function _initialize_reg_steps(bool $reinitializing = false)
1158
+	{
1159
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1160
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1161
+		foreach ($this->checkout->reg_steps as $reg_step) {
1162
+			if (! $reg_step->initialize_reg_step()) {
1163
+				// if not initialized then maybe this step is being removed...
1164
+				if (! $reinitializing && $reg_step->is_current_step()) {
1165
+					// if it was the current step, then we need to start over here
1166
+					$this->_initialize_reg_steps(true);
1167
+					return;
1168
+				}
1169
+				continue;
1170
+			}
1171
+			// add css and JS for current step
1172
+			$this->add_styles_and_scripts($reg_step);
1173
+			if ($reg_step->is_current_step()) {
1174
+				// the text that appears on the reg step form submit button
1175
+				$reg_step->set_submit_button_text();
1176
+			}
1177
+		}
1178
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1179
+		do_action(
1180
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1181
+			$this->checkout->current_step
1182
+		);
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * @return boolean
1188
+	 * @throws EE_Error
1189
+	 * @throws ReflectionException
1190
+	 */
1191
+	private function _check_form_submission(): bool
1192
+	{
1193
+		// does this request require the reg form to be generated ?
1194
+		if ($this->checkout->generate_reg_form) {
1195
+			// ever heard that song by Blue Rodeo ?
1196
+			try {
1197
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1198
+				// if not displaying a form, then check for form submission
1199
+				if (
1200
+					$this->checkout->process_form_submission
1201
+					&& $this->checkout->current_step->reg_form->was_submitted()
1202
+				) {
1203
+					// clear out any old data in case this step is being run again
1204
+					$this->checkout->current_step->set_valid_data([]);
1205
+					// capture submitted form data
1206
+					$request_data = $this->request->requestParams();
1207
+					$this->checkout->current_step->reg_form->receive_form_submission(
1208
+						(array) apply_filters(
1209
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1210
+							$request_data,
1211
+							$this->checkout
1212
+						)
1213
+					);
1214
+					// validate submitted form data
1215
+					if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1216
+						// thou shall not pass !!!
1217
+						$this->checkout->continue_reg = false;
1218
+						// any form validation errors?
1219
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1220
+							EE_Error::add_error(
1221
+								$this->checkout->current_step->reg_form->submission_error_message(),
1222
+								__FILE__,
1223
+								__FUNCTION__,
1224
+								__LINE__
1225
+							);
1226
+						}
1227
+						// well not really... what will happen is
1228
+						// we'll just get redirected back to redo the current step
1229
+						$this->go_to_next_step();
1230
+						return false;
1231
+					}
1232
+				}
1233
+			} catch (EE_Error $e) {
1234
+				$e->get_error();
1235
+			}
1236
+		}
1237
+		return true;
1238
+	}
1239
+
1240
+
1241
+	/**
1242
+	 * @return void
1243
+	 * @throws EE_Error
1244
+	 * @throws ReflectionException
1245
+	 */
1246
+	private function _process_form_action()
1247
+	{
1248
+		// what cha wanna do?
1249
+		switch ($this->checkout->action) {
1250
+			// AJAX next step reg form
1251
+			case 'display_spco_reg_step':
1252
+				$this->checkout->redirect = false;
1253
+				if ($this->request->isAjax()) {
1254
+					$this->checkout->json_response->set_reg_step_html(
1255
+						$this->checkout->current_step->display_reg_form()
1256
+					);
1257
+				}
1258
+				break;
1259
+			default:
1260
+				// meh... do one of those other steps first
1261
+				if (
1262
+					! empty($this->checkout->action)
1263
+					&& is_callable([$this->checkout->current_step, $this->checkout->action])
1264
+				) {
1265
+					// dynamically creates hook point like:
1266
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1267
+					do_action(
1268
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1269
+						$this->checkout->current_step
1270
+					);
1271
+					$process_reg_step = apply_filters(
1272
+						"AHEE__Single_Page_Checkout__process_reg_step__{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1273
+						true,
1274
+						$this->checkout->current_step,
1275
+						$this
1276
+					);
1277
+					// call action on current step
1278
+					if ($process_reg_step && call_user_func([$this->checkout->current_step, $this->checkout->action])) {
1279
+						// good registrant, you get to proceed
1280
+						if (
1281
+							$this->checkout->current_step->success_message() !== ''
1282
+							&& apply_filters(
1283
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1284
+								false
1285
+							)
1286
+						) {
1287
+							EE_Error::add_success(
1288
+								$this->checkout->current_step->success_message()
1289
+								. '<br />' . $this->checkout->next_step->_instructions()
1290
+							);
1291
+						}
1292
+						// pack it up, pack it in...
1293
+						$this->_setup_redirect();
1294
+					}
1295
+					// dynamically creates hook point like:
1296
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1297
+					do_action(
1298
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1299
+						$this->checkout->current_step
1300
+					);
1301
+				} else {
1302
+					EE_Error::add_error(
1303
+						sprintf(
1304
+							esc_html__(
1305
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1306
+								'event_espresso'
1307
+							),
1308
+							$this->checkout->action,
1309
+							$this->checkout->current_step->name()
1310
+						),
1311
+						__FILE__,
1312
+						__FUNCTION__,
1313
+						__LINE__
1314
+					);
1315
+				}
1316
+			// end default
1317
+		}
1318
+		// store our progress so far
1319
+		$this->checkout->stash_transaction_and_checkout();
1320
+		// advance to the next step! If you pass GO, collect $200
1321
+		$this->go_to_next_step();
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target an object with the method `translate_js_strings` and
1327
+	 *                                                          `enqueue_styles_and_scripts`.
1328
+	 * @return void
1329
+	 */
1330
+	public function add_styles_and_scripts($target)
1331
+	{
1332
+		// i18n
1333
+		$target->translate_js_strings();
1334
+		if ($this->checkout->admin_request) {
1335
+			add_action('admin_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1336
+		} else {
1337
+			add_action('wp_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1338
+		}
1339
+	}
1340
+
1341
+
1342
+	/**
1343
+	 * @return void
1344
+	 */
1345
+	public function translate_js_strings()
1346
+	{
1347
+		EE_Registry::$i18n_js_strings['revisit']                        = $this->checkout->revisit;
1348
+		EE_Registry::$i18n_js_strings['e_reg_url_link']                 = $this->checkout->reg_url_link;
1349
+		EE_Registry::$i18n_js_strings['server_error']                   = esc_html__(
1350
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1351
+			'event_espresso'
1352
+		);
1353
+		EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1354
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1355
+			'event_espresso'
1356
+		);
1357
+		EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1358
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1359
+			'event_espresso'
1360
+		);
1361
+		EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1362
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1363
+			'event_espresso'
1364
+		);
1365
+		EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1366
+			'This registration step could not be completed. Please refresh the page and try again.',
1367
+			'event_espresso'
1368
+		);
1369
+		EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1370
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1371
+			'event_espresso'
1372
+		);
1373
+		EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1374
+			esc_html__(
1375
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1376
+				'event_espresso'
1377
+			),
1378
+			'<br/>',
1379
+			'<br/>'
1380
+		);
1381
+		EE_Registry::$i18n_js_strings['language']                       = get_bloginfo('language');
1382
+		EE_Registry::$i18n_js_strings['EESID']                          = EE_Registry::instance()->SSN->id();
1383
+		EE_Registry::$i18n_js_strings['currency']                       = EE_Registry::instance()->CFG->currency;
1384
+		EE_Registry::$i18n_js_strings['datepicker_yearRange']           = '-150:+20';
1385
+		EE_Registry::$i18n_js_strings['timer_years']                    = esc_html__('years', 'event_espresso');
1386
+		EE_Registry::$i18n_js_strings['timer_months']                   = esc_html__('months', 'event_espresso');
1387
+		EE_Registry::$i18n_js_strings['timer_weeks']                    = esc_html__('weeks', 'event_espresso');
1388
+		EE_Registry::$i18n_js_strings['timer_days']                     = esc_html__('days', 'event_espresso');
1389
+		EE_Registry::$i18n_js_strings['timer_hours']                    = esc_html__('hours', 'event_espresso');
1390
+		EE_Registry::$i18n_js_strings['timer_minutes']                  = esc_html__('minutes', 'event_espresso');
1391
+		EE_Registry::$i18n_js_strings['timer_seconds']                  = esc_html__('seconds', 'event_espresso');
1392
+		EE_Registry::$i18n_js_strings['timer_year']                     = esc_html__('year', 'event_espresso');
1393
+		EE_Registry::$i18n_js_strings['timer_month']                    = esc_html__('month', 'event_espresso');
1394
+		EE_Registry::$i18n_js_strings['timer_week']                     = esc_html__('week', 'event_espresso');
1395
+		EE_Registry::$i18n_js_strings['timer_day']                      = esc_html__('day', 'event_espresso');
1396
+		EE_Registry::$i18n_js_strings['timer_hour']                     = esc_html__('hour', 'event_espresso');
1397
+		EE_Registry::$i18n_js_strings['timer_minute']                   = esc_html__('minute', 'event_espresso');
1398
+		EE_Registry::$i18n_js_strings['timer_second']                   = esc_html__('second', 'event_espresso');
1399
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
1400
+			EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1401
+		EE_Registry::$i18n_js_strings['ajax_submit']                    = apply_filters(
1402
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1403
+			true
1404
+		);
1405
+		EE_Registry::$i18n_js_strings['session_extension']              = absint(
1406
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1407
+		);
1408
+		EE_Registry::$i18n_js_strings['session_expiration']             = gmdate(
1409
+			'M d, Y H:i:s',
1410
+			EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1411
+		);
1412
+	}
1413
+
1414
+
1415
+	/**
1416
+	 * @return void
1417
+	 * @throws EE_Error
1418
+	 */
1419
+	public function enqueue_styles_and_scripts()
1420
+	{
1421
+		// load css
1422
+		wp_register_style(
1423
+			'single_page_checkout',
1424
+			SPCO_CSS_URL . 'single_page_checkout.css',
1425
+			['espresso_default'],
1426
+			EVENT_ESPRESSO_VERSION
1427
+		);
1428
+		wp_enqueue_style('single_page_checkout');
1429
+		// load JS
1430
+		wp_register_script(
1431
+			'jquery_plugin',
1432
+			EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1433
+			['jquery'],
1434
+			'1.0.1',
1435
+			true
1436
+		);
1437
+		wp_register_script(
1438
+			'jquery_countdown',
1439
+			EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1440
+			['jquery_plugin'],
1441
+			'2.1.0',
1442
+			true
1443
+		);
1444
+		wp_register_script(
1445
+			'single_page_checkout',
1446
+			SPCO_JS_URL . 'single_page_checkout.js',
1447
+			['espresso_core', 'underscore', 'ee_form_section_validation'],
1448
+			EVENT_ESPRESSO_VERSION,
1449
+			true
1450
+		);
1451
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1452
+			$this->checkout->registration_form->enqueue_js();
1453
+		}
1454
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1455
+			$this->checkout->current_step->reg_form->enqueue_js();
1456
+		}
1457
+		wp_enqueue_script('single_page_checkout');
1458
+		if (apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)) {
1459
+			wp_enqueue_script('jquery_countdown');
1460
+		}
1461
+		/**
1462
+		 * global action hook for enqueueing styles and scripts with
1463
+		 * spco calls.
1464
+		 */
1465
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1466
+		/**
1467
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1468
+		 * The hook will end up being something like:
1469
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1470
+		 */
1471
+		do_action(
1472
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1473
+			$this
1474
+		);
1475
+	}
1476
+
1477
+
1478
+	/**
1479
+	 * display the Registration Single Page Checkout Form
1480
+	 *
1481
+	 * @return void
1482
+	 * @throws EE_Error
1483
+	 * @throws ReflectionException
1484
+	 */
1485
+	private function _display_spco_reg_form()
1486
+	{
1487
+		// if registering via the admin, just display the reg form for the current step
1488
+		if ($this->checkout->admin_request) {
1489
+			EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->current_step->display_reg_form());
1490
+		} else {
1491
+			// add powered by EE msg
1492
+			add_action('AHEE__SPCO__reg_form_footer', ['EED_Single_Page_Checkout', 'display_registration_footer']);
1493
+			$empty_cart                                 = count(
1494
+					$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1495
+				) < 1;
1496
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1497
+			$cookies_not_set_msg                        = '';
1498
+			if ($empty_cart) {
1499
+				$cookies_not_set_msg = apply_filters(
1500
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1501
+					sprintf(
1502
+						esc_html__(
1503
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1504
+							'event_espresso'
1505
+						),
1506
+						'<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1507
+						'</div>',
1508
+						'<h6 class="important-notice">',
1509
+						'</h6>',
1510
+						'<p>',
1511
+						'</p>',
1512
+						'<br />',
1513
+						'<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
1514
+						'</a>'
1515
+					)
1516
+				);
1517
+			}
1518
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1519
+				[
1520
+					'name'            => 'single-page-checkout',
1521
+					'html_id'         => 'ee-single-page-checkout-dv',
1522
+					'layout_strategy' =>
1523
+						new EE_Template_Layout(
1524
+							[
1525
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1526
+								'template_args'        => [
1527
+									'empty_cart'              => $empty_cart,
1528
+									'revisit'                 => $this->checkout->revisit,
1529
+									'reg_steps'               => $this->checkout->reg_steps,
1530
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1531
+										? $this->checkout->next_step->slug()
1532
+										: '',
1533
+									'empty_msg'               => apply_filters(
1534
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1535
+										sprintf(
1536
+											esc_html__(
1537
+												'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1538
+												'event_espresso'
1539
+											),
1540
+											'<a href="'
1541
+											. get_post_type_archive_link('espresso_events')
1542
+											. '" title="',
1543
+											'">',
1544
+											'</a>'
1545
+										)
1546
+									),
1547
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1548
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1549
+									'session_expiration'      => gmdate(
1550
+										'M d, Y H:i:s',
1551
+										EE_Registry::instance()->SSN->expiration()
1552
+										+ (get_option('gmt_offset') * HOUR_IN_SECONDS)
1553
+									),
1554
+								],
1555
+							]
1556
+						),
1557
+				]
1558
+			);
1559
+			// load template and add to output sent that gets filtered into the_content()
1560
+			EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->registration_form->get_html());
1561
+		}
1562
+	}
1563
+
1564
+
1565
+	/**
1566
+	 * @param $next_step
1567
+	 * @return void
1568
+	 */
1569
+	public function add_extra_finalize_registration_inputs($next_step)
1570
+	{
1571
+		if ($next_step === 'finalize_registration') {
1572
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1573
+		}
1574
+	}
1575
+
1576
+
1577
+	/**
1578
+	 * @return void
1579
+	 */
1580
+	public static function display_registration_footer()
1581
+	{
1582
+		if (
1583
+			apply_filters(
1584
+				'FHEE__EE_Front__Controller__show_reg_footer',
1585
+				EE_Registry::instance()->CFG->admin->show_reg_footer
1586
+			)
1587
+		) {
1588
+			add_filter(
1589
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1590
+				function ($url) {
1591
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1592
+				}
1593
+			);
1594
+			echo apply_filters(
1595
+				'FHEE__EE_Front_Controller__display_registration_footer',
1596
+				EEH_Template::powered_by_event_espresso(
1597
+					'',
1598
+					'espresso-registration-footer-dv',
1599
+					['utm_content' => 'registration_checkout']
1600
+				)
1601
+			);
1602
+		}
1603
+	}
1604
+
1605
+
1606
+	/**
1607
+	 * @return void
1608
+	 * @throws EE_Error
1609
+	 * @throws ReflectionException
1610
+	 */
1611
+	public function unlock_transaction()
1612
+	{
1613
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1614
+			$this->checkout->transaction->unlock();
1615
+		}
1616
+	}
1617
+
1618
+
1619
+	/**
1620
+	 * @return void
1621
+	 */
1622
+	private function _setup_redirect()
1623
+	{
1624
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1625
+			$this->checkout->redirect = true;
1626
+			if (empty($this->checkout->redirect_url)) {
1627
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1628
+			}
1629
+			$this->checkout->redirect_url = apply_filters(
1630
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1631
+				$this->checkout->redirect_url,
1632
+				$this->checkout
1633
+			);
1634
+		}
1635
+	}
1636
+
1637
+
1638
+	/**
1639
+	 * handle ajax message responses and redirects
1640
+	 *
1641
+	 * @return void
1642
+	 * @throws EE_Error
1643
+	 * @throws ReflectionException
1644
+	 */
1645
+	public function go_to_next_step()
1646
+	{
1647
+		if ($this->request->isAjax()) {
1648
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1649
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1650
+		}
1651
+		$this->unlock_transaction();
1652
+		// just return for these conditions
1653
+		if (
1654
+			$this->checkout->admin_request
1655
+			|| $this->checkout->action === 'redirect_form'
1656
+			|| $this->checkout->action === 'update_checkout'
1657
+		) {
1658
+			return;
1659
+		}
1660
+		// AJAX response
1661
+		$this->_handle_json_response();
1662
+		// redirect to next step or the Thank-You page
1663
+		$this->_handle_html_redirects();
1664
+		// hmmm... must be something wrong, so let's just display the form again !
1665
+		$this->_display_spco_reg_form();
1666
+	}
1667
+
1668
+
1669
+	/**
1670
+	 * @return void
1671
+	 * @throws EE_Error
1672
+	 */
1673
+	protected function _handle_json_response()
1674
+	{
1675
+		// if this is an ajax request
1676
+		if ($this->request->isAjax()) {
1677
+			$this->checkout->json_response->set_registration_time_limit(
1678
+				$this->checkout->get_registration_time_limit()
1679
+			);
1680
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1681
+			// just send the ajax (
1682
+			$json_response = apply_filters(
1683
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1684
+				$this->checkout->json_response
1685
+			);
1686
+			exit($json_response);
1687
+		}
1688
+	}
1689
+
1690
+
1691
+	/**
1692
+	 * @return void
1693
+	 */
1694
+	protected function _handle_html_redirects()
1695
+	{
1696
+		// going somewhere ?
1697
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1698
+			// store notices in a transient
1699
+			EE_Error::get_notices(false, true);
1700
+			wp_safe_redirect($this->checkout->redirect_url);
1701
+			exit();
1702
+		}
1703
+	}
1704
+
1705
+
1706
+	/**
1707
+	 * @return void
1708
+	 */
1709
+	public function set_checkout_anchor()
1710
+	{
1711
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1712
+	}
1713
+
1714
+
1715
+	/**
1716
+	 * @return string
1717
+	 * @since 4.9.59.p
1718
+	 */
1719
+	public static function getRegistrationExpirationNotice(): string
1720
+	{
1721
+		return sprintf(
1722
+			esc_html__(
1723
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1724
+				'event_espresso'
1725
+			),
1726
+			'<h4 class="important-notice">',
1727
+			'</h4>',
1728
+			'<br />',
1729
+			'<p>',
1730
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1731
+			'">',
1732
+			'</a>',
1733
+			'</p>'
1734
+		);
1735
+	}
1736 1736
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -44,7 +44,7 @@  discard block
 block discarded – undo
44 44
 
45 45
     protected ?RequestInterface $request = null;
46 46
 
47
-    private bool $debug = false;    //  true    false
47
+    private bool $debug = false; //  true    false
48 48
 
49 49
 
50 50
     /**
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
     public static function set_hooks_admin()
109 109
     {
110 110
         EED_Single_Page_Checkout::set_definitions();
111
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
111
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
112 112
             return;
113 113
         }
114 114
         // going to start an output buffer in case anything gets accidentally output
@@ -202,14 +202,14 @@  discard block
 block discarded – undo
202 202
         }
203 203
         define(
204 204
             'SPCO_BASE_PATH',
205
-            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
205
+            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/').'/'
206 206
         );
207
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
208
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
209
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
210
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
211
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
212
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
207
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css/');
208
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img/');
209
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js/');
210
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc/');
211
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps/');
212
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates/');
213 213
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
214 214
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
215 215
             EED_Single_Page_Checkout::getRegistrationExpirationNotice();
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
             // we need a
241 241
             if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
242 242
                 // copy over to the reg_steps_array
243
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
243
+                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
244 244
                 // register custom key route for each reg step
245 245
                 // ie: step=>"slug" - this is the entire reason we load the reg steps array now
246 246
                 EE_Config::register_route(
@@ -252,7 +252,7 @@  discard block
 block discarded – undo
252 252
                 // add AJAX or other hooks
253 253
                 if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
254 254
                     // setup autoloaders if necessary
255
-                    if (! class_exists($reg_step['class_name'])) {
255
+                    if ( ! class_exists($reg_step['class_name'])) {
256 256
                         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
257 257
                             $reg_step['file_path'],
258 258
                             true
@@ -279,19 +279,19 @@  discard block
 block discarded – undo
279 279
         if (empty($reg_steps)) {
280 280
             $reg_steps = [
281 281
                 10  => [
282
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
282
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
283 283
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
284 284
                     'slug'       => 'attendee_information',
285 285
                     'has_hooks'  => false,
286 286
                 ],
287 287
                 30  => [
288
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
288
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
289 289
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
290 290
                     'slug'       => 'payment_options',
291 291
                     'has_hooks'  => true,
292 292
                 ],
293 293
                 999 => [
294
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
294
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
295 295
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
296 296
                     'slug'       => 'finalize_registration',
297 297
                     'has_hooks'  => false,
@@ -437,7 +437,7 @@  discard block
 block discarded – undo
437 437
                 $this->checkout
438 438
             );
439 439
             // load the reg steps array
440
-            if (! $this->_load_and_instantiate_reg_steps()) {
440
+            if ( ! $this->_load_and_instantiate_reg_steps()) {
441 441
                 EED_Single_Page_Checkout::$_initialized = true;
442 442
                 return;
443 443
             }
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
             // and the next step
447 447
             $this->checkout->set_next_step();
448 448
             // verify that everything has been set up correctly
449
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
449
+            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
450 450
                 EED_Single_Page_Checkout::$_initialized = true;
451 451
                 return;
452 452
             }
@@ -462,7 +462,7 @@  discard block
 block discarded – undo
462 462
             // DEBUG LOG
463 463
             // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
464 464
             // get reg form
465
-            if (! $this->_check_form_submission()) {
465
+            if ( ! $this->_check_form_submission()) {
466 466
                 EED_Single_Page_Checkout::$_initialized = true;
467 467
                 return;
468 468
             }
@@ -492,7 +492,7 @@  discard block
 block discarded – undo
492 492
      */
493 493
     private function _verify_session()
494 494
     {
495
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
495
+        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
496 496
             throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
497 497
         }
498 498
         $clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
@@ -509,7 +509,7 @@  discard block
 block discarded – undo
509 509
             // EE_Registry::instance()->SSN->reset_cart();
510 510
             // EE_Registry::instance()->SSN->reset_checkout();
511 511
             // EE_Registry::instance()->SSN->reset_transaction();
512
-            if (! $clear_session_requested) {
512
+            if ( ! $clear_session_requested) {
513 513
                 EE_Error::add_attention(
514 514
                     EE_Registry::$i18n_js_strings['registration_expiration_notice'],
515 515
                     __FILE__,
@@ -535,7 +535,7 @@  discard block
 block discarded – undo
535 535
         /** @type EE_Checkout $checkout */
536 536
         $checkout = EE_Registry::instance()->SSN->checkout();
537 537
         // verify
538
-        if (! $checkout instanceof EE_Checkout) {
538
+        if ( ! $checkout instanceof EE_Checkout) {
539 539
             // instantiate EE_Checkout object for handling the properties of the current checkout process
540 540
             $checkout = EE_Registry::instance()->load_file(
541 541
                 SPCO_INC_PATH,
@@ -553,7 +553,7 @@  discard block
 block discarded – undo
553 553
         }
554 554
         $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
555 555
         // verify again
556
-        if (! $checkout instanceof EE_Checkout) {
556
+        if ( ! $checkout instanceof EE_Checkout) {
557 557
             throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
558 558
         }
559 559
         // reset anything that needs a clean slate for each request
@@ -610,7 +610,7 @@  discard block
 block discarded – undo
610 610
      */
611 611
     protected function _display_request_vars()
612 612
     {
613
-        if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
613
+        if ( ! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
614 614
             return;
615 615
         }
616 616
         EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
@@ -682,7 +682,7 @@  discard block
 block discarded – undo
682 682
         ) {
683 683
             // if not, then loop through raw reg steps array
684 684
             foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
685
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
685
+                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
686 686
                     return false;
687 687
                 }
688 688
             }
@@ -804,12 +804,12 @@  discard block
 block discarded – undo
804 804
     private function _verify_transaction_and_get_registrations(): bool
805 805
     {
806 806
         // was there already a valid transaction in the checkout from the session ?
807
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
807
+        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
808 808
             // get transaction from db or session
809 809
             $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
810 810
                 ? $this->_get_transaction_and_cart_for_previous_visit()
811 811
                 : $this->_get_cart_for_current_session_and_setup_new_transaction();
812
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
812
+            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
813 813
                 EE_Error::add_error(
814 814
                     esc_html__(
815 815
                         'Your Registration and Transaction information could not be retrieved from the db.',
@@ -1034,10 +1034,10 @@  discard block
 block discarded – undo
1034 1034
                     );
1035 1035
                 }
1036 1036
                 $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1037
-                if (! $registration instanceof EE_Registration) {
1037
+                if ( ! $registration instanceof EE_Registration) {
1038 1038
                     throw new InvalidEntityException($registration, 'EE_Registration');
1039 1039
                 }
1040
-                $registrations[ $registration->ID() ] = $registration;
1040
+                $registrations[$registration->ID()] = $registration;
1041 1041
             }
1042 1042
         }
1043 1043
         $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
             $this->checkout
1078 1078
         );
1079 1079
         // verify that current step is still set correctly
1080
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1080
+        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1081 1081
             EE_Error::add_error(
1082 1082
                 esc_html__(
1083 1083
                     'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
@@ -1090,9 +1090,9 @@  discard block
 block discarded – undo
1090 1090
             return false;
1091 1091
         }
1092 1092
         // if returning to SPCO, then verify that primary registrant is set
1093
-        if (! empty($this->checkout->reg_url_link)) {
1093
+        if ( ! empty($this->checkout->reg_url_link)) {
1094 1094
             $valid_registrant = $this->checkout->transaction->primary_registration();
1095
-            if (! $valid_registrant instanceof EE_Registration) {
1095
+            if ( ! $valid_registrant instanceof EE_Registration) {
1096 1096
                 EE_Error::add_error(
1097 1097
                     esc_html__(
1098 1098
                         'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
@@ -1117,7 +1117,7 @@  discard block
 block discarded – undo
1117 1117
                     $valid_registrant = $registration;
1118 1118
                 }
1119 1119
             }
1120
-            if (! $valid_registrant instanceof EE_Registration) {
1120
+            if ( ! $valid_registrant instanceof EE_Registration) {
1121 1121
                 // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1122 1122
                 if (EED_Single_Page_Checkout::$_checkout_verified) {
1123 1123
                     // clear the session, mark the checkout as unverified, and try again
@@ -1159,9 +1159,9 @@  discard block
 block discarded – undo
1159 1159
         $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1160 1160
         // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1161 1161
         foreach ($this->checkout->reg_steps as $reg_step) {
1162
-            if (! $reg_step->initialize_reg_step()) {
1162
+            if ( ! $reg_step->initialize_reg_step()) {
1163 1163
                 // if not initialized then maybe this step is being removed...
1164
-                if (! $reinitializing && $reg_step->is_current_step()) {
1164
+                if ( ! $reinitializing && $reg_step->is_current_step()) {
1165 1165
                     // if it was the current step, then we need to start over here
1166 1166
                     $this->_initialize_reg_steps(true);
1167 1167
                     return;
@@ -1212,7 +1212,7 @@  discard block
 block discarded – undo
1212 1212
                         )
1213 1213
                     );
1214 1214
                     // validate submitted form data
1215
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1215
+                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1216 1216
                         // thou shall not pass !!!
1217 1217
                         $this->checkout->continue_reg = false;
1218 1218
                         // any form validation errors?
@@ -1286,7 +1286,7 @@  discard block
 block discarded – undo
1286 1286
                         ) {
1287 1287
                             EE_Error::add_success(
1288 1288
                                 $this->checkout->current_step->success_message()
1289
-                                . '<br />' . $this->checkout->next_step->_instructions()
1289
+                                . '<br />'.$this->checkout->next_step->_instructions()
1290 1290
                             );
1291 1291
                         }
1292 1292
                         // pack it up, pack it in...
@@ -1350,27 +1350,27 @@  discard block
 block discarded – undo
1350 1350
             'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1351 1351
             'event_espresso'
1352 1352
         );
1353
-        EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1353
+        EE_Registry::$i18n_js_strings['invalid_json_response'] = esc_html__(
1354 1354
             'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1355 1355
             'event_espresso'
1356 1356
         );
1357
-        EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1357
+        EE_Registry::$i18n_js_strings['validation_error'] = esc_html__(
1358 1358
             'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1359 1359
             'event_espresso'
1360 1360
         );
1361
-        EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1361
+        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
1362 1362
             'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1363 1363
             'event_espresso'
1364 1364
         );
1365
-        EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1365
+        EE_Registry::$i18n_js_strings['reg_step_error'] = esc_html__(
1366 1366
             'This registration step could not be completed. Please refresh the page and try again.',
1367 1367
             'event_espresso'
1368 1368
         );
1369
-        EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1369
+        EE_Registry::$i18n_js_strings['invalid_coupon'] = esc_html__(
1370 1370
             'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1371 1371
             'event_espresso'
1372 1372
         );
1373
-        EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1373
+        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1374 1374
             esc_html__(
1375 1375
                 'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1376 1376
                 'event_espresso'
@@ -1421,7 +1421,7 @@  discard block
 block discarded – undo
1421 1421
         // load css
1422 1422
         wp_register_style(
1423 1423
             'single_page_checkout',
1424
-            SPCO_CSS_URL . 'single_page_checkout.css',
1424
+            SPCO_CSS_URL.'single_page_checkout.css',
1425 1425
             ['espresso_default'],
1426 1426
             EVENT_ESPRESSO_VERSION
1427 1427
         );
@@ -1429,21 +1429,21 @@  discard block
 block discarded – undo
1429 1429
         // load JS
1430 1430
         wp_register_script(
1431 1431
             'jquery_plugin',
1432
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1432
+            EE_THIRD_PARTY_URL.'jquery	.plugin.min.js',
1433 1433
             ['jquery'],
1434 1434
             '1.0.1',
1435 1435
             true
1436 1436
         );
1437 1437
         wp_register_script(
1438 1438
             'jquery_countdown',
1439
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1439
+            EE_THIRD_PARTY_URL.'jquery	.countdown.min.js',
1440 1440
             ['jquery_plugin'],
1441 1441
             '2.1.0',
1442 1442
             true
1443 1443
         );
1444 1444
         wp_register_script(
1445 1445
             'single_page_checkout',
1446
-            SPCO_JS_URL . 'single_page_checkout.js',
1446
+            SPCO_JS_URL.'single_page_checkout.js',
1447 1447
             ['espresso_core', 'underscore', 'ee_form_section_validation'],
1448 1448
             EVENT_ESPRESSO_VERSION,
1449 1449
             true
@@ -1469,7 +1469,7 @@  discard block
 block discarded – undo
1469 1469
          *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1470 1470
          */
1471 1471
         do_action(
1472
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1472
+            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(),
1473 1473
             $this
1474 1474
         );
1475 1475
     }
@@ -1522,7 +1522,7 @@  discard block
 block discarded – undo
1522 1522
                     'layout_strategy' =>
1523 1523
                         new EE_Template_Layout(
1524 1524
                             [
1525
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1525
+                                'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
1526 1526
                                 'template_args'        => [
1527 1527
                                     'empty_cart'              => $empty_cart,
1528 1528
                                     'revisit'                 => $this->checkout->revisit,
@@ -1587,7 +1587,7 @@  discard block
 block discarded – undo
1587 1587
         ) {
1588 1588
             add_filter(
1589 1589
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1590
-                function ($url) {
1590
+                function($url) {
1591 1591
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1592 1592
                 }
1593 1593
             );
@@ -1727,7 +1727,7 @@  discard block
 block discarded – undo
1727 1727
             '</h4>',
1728 1728
             '<br />',
1729 1729
             '<p>',
1730
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1730
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
1731 1731
             '">',
1732 1732
             '</a>',
1733 1733
             '</p>'
Please login to merge, or discard this patch.
modules/single_page_checkout/inc/EE_Checkout.class.php 2 patches
Indentation   +1417 added lines, -1417 removed lines patch added patch discarded remove patch
@@ -14,1422 +14,1422 @@
 block discarded – undo
14 14
  */
15 15
 class EE_Checkout
16 16
 {
17
-    /**
18
-     *    whether current request originated from the EE admin
19
-     *
20
-     * @var bool
21
-     */
22
-    public $admin_request = false;
23
-
24
-    /**
25
-     * whether returning to edit attendee information or to retry a payment
26
-     *
27
-     * @var bool
28
-     */
29
-    public $revisit = false;
30
-
31
-    /**
32
-     * whether the primary registrant is returning to edit attendee information or to retry a payment
33
-     *
34
-     * @var bool
35
-     */
36
-    public $primary_revisit = false;
37
-
38
-    /**
39
-     * is registration allowed to progress or halted for some reason such as failing to pass recaptcha?
40
-     *
41
-     * @var bool
42
-     */
43
-    public $continue_reg = true;
44
-
45
-    /**
46
-     * redirect to thank you page ?
47
-     *
48
-     * @var bool
49
-     */
50
-    public $redirect = false;
51
-
52
-    /**
53
-     * generate the reg form or not ?
54
-     *
55
-     * @var bool
56
-     */
57
-    public $generate_reg_form = true;
58
-
59
-    /**
60
-     * process a reg form submission or not ?
61
-     *
62
-     * @var bool
63
-     */
64
-    public $process_form_submission = false;
65
-
66
-    /**
67
-     * tracks whether the TXN status modified during this checkout
68
-     *
69
-     * @var bool
70
-     */
71
-    public $txn_status_updated = false;
72
-
73
-    /**
74
-     * only triggered to true after absolutely everything has finished.
75
-     *
76
-     * @var bool
77
-     */
78
-    protected $exit_spco = false;
79
-
80
-    /**
81
-     * tracks whether any of the TXN's Registrations statuses modified during this checkout
82
-     * indexed by registration ID
83
-     *
84
-     * @var array
85
-     */
86
-    protected $reg_status_updated = array();
87
-
88
-    /**
89
-     * timestamp when redirected from Ticket Selector to the checkout
90
-     *
91
-     * @var int
92
-     */
93
-    public $uts = 0;
94
-
95
-    /**
96
-     * total number of tickets that were in the cart
97
-     *
98
-     * @var int
99
-     */
100
-    public $total_ticket_count = 0;
101
-
102
-    /**
103
-     * corresponds loosely to EE_Transaction::remaining()
104
-     * but can be modified by SPCO
105
-     *
106
-     * @var float
107
-     */
108
-    public $amount_owing = 0;
109
-
110
-    /**
111
-     * the reg step slug from the incoming request
112
-     *
113
-     * @var string
114
-     */
115
-    public $step = '';
116
-
117
-    /**
118
-     * the reg step slug for a step being edited
119
-     *
120
-     * @var string
121
-     */
122
-    public $edit_step = '';
123
-
124
-    /**
125
-     * the action being performed on the current step
126
-     *
127
-     * @var string
128
-     */
129
-    public $action = '';
130
-
131
-    /**
132
-     * reg_url_link for a previously saved registration
133
-     *
134
-     * @var string
135
-     */
136
-    public $reg_url_link = '';
137
-
138
-    /**
139
-     * string slug for the payment method that was selected during the payment options step
140
-     *
141
-     * @var string
142
-     */
143
-    public $selected_method_of_payment = '';
144
-
145
-    /**
146
-     * base url for the site's registration checkout page - additional url params will be added to this
147
-     *
148
-     * @var string
149
-     */
150
-    public $reg_page_base_url = '';
151
-
152
-    /**
153
-     * base url for the site's registration cancelled page - additional url params will be added to this
154
-     *
155
-     * @var string
156
-     */
157
-    public $cancel_page_url = '';
158
-
159
-    /**
160
-     * base url for the site's thank you page - additional url params will be added to this
161
-     *
162
-     * @var string
163
-     */
164
-    public $thank_you_page_url = '';
165
-
166
-    /**
167
-     * base url for any redirects - additional url params will be added to this
168
-     *
169
-     * @var string
170
-     */
171
-    public $redirect_url = '';
172
-
173
-    /**
174
-     * form of POST data for use with off-site gateways
175
-     *
176
-     * @var string
177
-     */
178
-    public $redirect_form = '';
179
-
180
-    /**
181
-     * array of query where params to use when retrieving cached registrations from $this->checkout->transaction
182
-     *
183
-     * @var array
184
-     */
185
-    public $reg_cache_where_params = array();
186
-
187
-    /**
188
-     * a class for managing and creating the JSON encoded array of data that gets passed back to the client during AJAX
189
-     * requests
190
-     *
191
-     * @var EE_SPCO_JSON_Response
192
-     */
193
-    public $json_response;
194
-
195
-    /**
196
-     * where we are going next in the reg process
197
-     *
198
-     * @var EE_SPCO_Reg_Step
199
-     */
200
-    public $next_step;
201
-
202
-    /**
203
-     * where we are in the reg process
204
-     *
205
-     * @var EE_SPCO_Reg_Step
206
-     */
207
-    public $current_step;
208
-
209
-    /**
210
-     *    $_cart - the current cart object
211
-     *
212
-     * @var EE_CART
213
-     */
214
-    public $cart;
215
-
216
-    /**
217
-     *    $_transaction - the current transaction object
218
-     *
219
-     * @var EE_Transaction
220
-     */
221
-    public $transaction;
222
-
223
-    /**
224
-     *    the related attendee object for the primary registrant
225
-     *
226
-     * @var EE_Attendee
227
-     */
228
-    public $primary_attendee_obj;
229
-
230
-    /**
231
-     *    $payment_method - the payment method object for the selected method of payment
232
-     *
233
-     * @var EE_Payment_Method
234
-     */
235
-    public $payment_method;
236
-
237
-    /**
238
-     *    $payment - if a payment was successfully made during the reg process,
239
-     *    then here it is !!!
240
-     *
241
-     * @var EE_Payment
242
-     */
243
-    public $payment;
244
-
245
-    /**
246
-     *    if a payment method was selected that uses an on-site gateway, then this is the billing form
247
-     *
248
-     * @var EE_Billing_Info_Form|EE_Billing_Attendee_Info_Form
249
-     */
250
-    public $billing_form;
251
-
252
-    /**
253
-     *    the entire registration form composed of ALL of the subsections generated by the various reg steps
254
-     *
255
-     * @var EE_Form_Section_Proper
256
-     */
257
-    public $registration_form;
258
-
259
-    /**
260
-     * array of EE_SPCO_Reg_Step objects
261
-     *
262
-     * @var EE_SPCO_Reg_Step[]
263
-     */
264
-    public $reg_steps = array();
265
-
266
-    /**
267
-     * array of EE_Payment_Method objects
268
-     *
269
-     * @var EE_Payment_Method[]
270
-     */
271
-    public $available_payment_methods = array();
272
-
273
-
274
-    /**
275
-     *    class constructor
276
-     *
277
-     * @access    public
278
-     */
279
-    public function __construct()
280
-    {
281
-        $this->reg_page_base_url = EE_Registry::instance()->CFG->core->reg_page_url();
282
-        $this->thank_you_page_url = EE_Registry::instance()->CFG->core->thank_you_page_url();
283
-        $this->cancel_page_url = EE_Registry::instance()->CFG->core->cancel_page_url();
284
-        $this->continue_reg = apply_filters('FHEE__EE_Checkout___construct___continue_reg', true);
285
-
286
-        $this->admin_request = is_admin() && ! EED_Single_Page_Checkout::getRequest()->isAjax();
287
-        $this->reg_cache_where_params = array(
288
-            0          => array('REG_deleted' => false),
289
-            'order_by' => array('REG_count' => 'ASC'),
290
-        );
291
-    }
292
-
293
-
294
-    /**
295
-     * returns true if ANY reg status was updated during checkout
296
-     *
297
-     * @return boolean
298
-     */
299
-    public function any_reg_status_updated()
300
-    {
301
-        foreach ($this->reg_status_updated as $reg_status) {
302
-            if ($reg_status) {
303
-                return true;
304
-            }
305
-        }
306
-        return false;
307
-    }
308
-
309
-
310
-    /**
311
-     * @param $REG_ID
312
-     * @return boolean
313
-     */
314
-    public function reg_status_updated($REG_ID)
315
-    {
316
-        return isset($this->reg_status_updated[ $REG_ID ]) ? $this->reg_status_updated[ $REG_ID ] : false;
317
-    }
318
-
319
-
320
-    /**
321
-     * @param $REG_ID
322
-     * @param $reg_status
323
-     */
324
-    public function set_reg_status_updated($REG_ID, $reg_status)
325
-    {
326
-        $this->reg_status_updated[ $REG_ID ] = filter_var($reg_status, FILTER_VALIDATE_BOOLEAN);
327
-    }
328
-
329
-
330
-    /**
331
-     * exit_spco
332
-     *
333
-     * @return bool
334
-     */
335
-    public function exit_spco()
336
-    {
337
-        return $this->exit_spco;
338
-    }
339
-
340
-
341
-    /**
342
-     * set_exit_spco
343
-     * can ONLY be set by the  Finalize_Registration reg step
344
-     */
345
-    public function set_exit_spco()
346
-    {
347
-        if ($this->current_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
348
-            $this->exit_spco = true;
349
-        }
350
-    }
351
-
352
-
353
-    /**
354
-     *    reset_for_current_request
355
-     *
356
-     * @access    public
357
-     * @return    void
358
-     */
359
-    public function reset_for_current_request()
360
-    {
361
-        $this->process_form_submission = false;
362
-        $this->continue_reg = apply_filters('FHEE__EE_Checkout___construct___continue_reg', true);
363
-        $this->admin_request = is_admin() && ! EED_Single_Page_Checkout::getRequest()->isFrontAjax();
364
-        $this->continue_reg = true;
365
-        $this->redirect = false;
366
-        // don't reset the cached redirect form if we're about to be asked to display it !!!
367
-        $action = EED_Single_Page_Checkout::getRequest()->getRequestParam('action', 'display_spco_reg_step');
368
-        if ($action !== 'redirect_form') {
369
-            $this->redirect_form = '';
370
-        }
371
-        $this->redirect_url = '';
372
-        $this->json_response = new EE_SPCO_JSON_Response();
373
-        EE_Form_Section_Proper::reset_js_localization();
374
-    }
375
-
376
-
377
-    /**
378
-     *    add_reg_step
379
-     *
380
-     * @access    public
381
-     * @param EE_SPCO_Reg_Step $reg_step_obj
382
-     * @return    void
383
-     */
384
-    public function add_reg_step(EE_SPCO_Reg_Step $reg_step_obj)
385
-    {
386
-        $this->reg_steps[ $reg_step_obj->slug() ] = $reg_step_obj;
387
-    }
388
-
389
-
390
-    /**
391
-     * skip_reg_step
392
-     * if the current reg step does not need to run for some reason,
393
-     * then this will advance SPCO to the next reg step,
394
-     * and mark the skipped step as completed
395
-     *
396
-     * @access    public
397
-     * @param string $reg_step_slug
398
-     * @return    void
399
-     * @throws \EE_Error
400
-     */
401
-    public function skip_reg_step($reg_step_slug = '')
402
-    {
403
-        $step_to_skip = $this->find_reg_step($reg_step_slug);
404
-        if ($step_to_skip instanceof EE_SPCO_Reg_Step && $step_to_skip->is_current_step()) {
405
-            $step_to_skip->set_is_current_step(false);
406
-            $step_to_skip->set_completed();
407
-            // advance to the next step
408
-            $this->set_current_step($this->next_step->slug());
409
-            // also reset the step param in the request in case any other code references that directly
410
-            EED_Single_Page_Checkout::getRequest()->setRequestParam('step', $this->current_step->slug());
411
-            // since we are skipping a step and setting the current step to be what was previously the next step,
412
-            // we need to check that the next step is now correct, and not still set to the current step.
413
-            if ($this->current_step->slug() === $this->next_step->slug()) {
414
-                // correctly setup the next step
415
-                $this->set_next_step();
416
-            }
417
-            $this->set_reg_step_initiated($this->current_step);
418
-        }
419
-    }
420
-
421
-
422
-    /**
423
-     *    remove_reg_step
424
-     *
425
-     * @access    public
426
-     * @param string $reg_step_slug
427
-     * @param bool   $reset whether to reset reg steps after removal
428
-     * @throws EE_Error
429
-     */
430
-    public function remove_reg_step($reg_step_slug = '', $reset = true)
431
-    {
432
-        unset($this->reg_steps[ $reg_step_slug ]);
433
-        if ($this->transaction instanceof EE_Transaction) {
434
-            // now remove reg step from TXN and save
435
-            $this->transaction->remove_reg_step($reg_step_slug);
436
-            $this->transaction->save();
437
-        }
438
-        if ($reset) {
439
-            $this->reset_reg_steps();
440
-        }
441
-    }
442
-
443
-
444
-    /**
445
-     *    set_reg_step_order
446
-     *
447
-     * @access    public
448
-     * @param string $reg_step_slug
449
-     * @param int    $order
450
-     * @return    void
451
-     */
452
-    public function set_reg_step_order($reg_step_slug = '', $order = 100)
453
-    {
454
-        if (isset($this->reg_steps[ $reg_step_slug ])) {
455
-            $this->reg_steps[ $reg_step_slug ]->set_order($order);
456
-        }
457
-    }
458
-
459
-
460
-    /**
461
-     * @param string $current_step
462
-     * @return void
463
-     */
464
-    public function set_current_step(string $current_step)
465
-    {
466
-        // grab what step we're on
467
-        $this->current_step = $this->reg_steps[ $current_step ] ?? reset($this->reg_steps);
468
-        // verify instance
469
-        if (! $this->current_step instanceof EE_SPCO_Reg_Step)  {
470
-            EE_Error::add_error(
471
-                esc_html__('The current step could not be set.', 'event_espresso'),
472
-                __FILE__,
473
-                __FUNCTION__,
474
-                __LINE__
475
-            );
476
-        }
477
-        // we don't want to repeat completed steps if this is the first time through SPCO
478
-        if ($this->continue_reg && ! $this->revisit && $this->current_step->completed()) {
479
-            // so advance to the next step
480
-            $this->set_next_step();
481
-            if ($this->next_step instanceof EE_SPCO_Reg_Step) {
482
-                // and attempt to set it as the current step
483
-                $this->set_current_step($this->next_step->slug());
484
-            }
485
-            return;
486
-        }
487
-        $this->current_step->set_is_current_step(true);
488
-        $this->current_step->setRequest(EED_Single_Page_Checkout::getRequest());
489
-    }
490
-
491
-
492
-    /**
493
-     *    set_next_step
494
-     * advances the reg_steps array pointer and sets the next step, then reverses pointer back to the current step
495
-     *
496
-     * @access    public
497
-     * @return    void
498
-     */
499
-    public function set_next_step()
500
-    {
501
-        // set pointer to start of array
502
-        reset($this->reg_steps);
503
-        // if there is more than one step
504
-        if (count($this->reg_steps) > 1) {
505
-            // advance to the current step and set pointer
506
-            while (key($this->reg_steps) !== $this->current_step->slug() && key($this->reg_steps) !== '') {
507
-                next($this->reg_steps);
508
-            }
509
-        }
510
-        // advance one more spot ( if it exists )
511
-        $this->next_step = next($this->reg_steps);
512
-        // verify instance
513
-        $this->next_step = $this->next_step instanceof EE_SPCO_Reg_Step ? $this->next_step : null;
514
-        // then back to current step to reset
515
-        prev($this->reg_steps);
516
-    }
517
-
518
-
519
-    /**
520
-     *    get_next_reg_step
521
-     *    this simply returns the next step from reg_steps array
522
-     *
523
-     * @access    public
524
-     * @return    EE_SPCO_Reg_Step | null
525
-     */
526
-    public function get_next_reg_step()
527
-    {
528
-        $next = next($this->reg_steps);
529
-        prev($this->reg_steps);
530
-        return $next instanceof EE_SPCO_Reg_Step ? $next : null;
531
-    }
532
-
533
-
534
-    /**
535
-     * get_prev_reg_step
536
-     *    this simply returns the previous step from reg_steps array
537
-     *
538
-     * @access    public
539
-     * @return    EE_SPCO_Reg_Step | null
540
-     */
541
-    public function get_prev_reg_step()
542
-    {
543
-        $prev = prev($this->reg_steps);
544
-        next($this->reg_steps);
545
-        return $prev instanceof EE_SPCO_Reg_Step ? $prev : null;
546
-    }
547
-
548
-
549
-    /**
550
-     * sort_reg_steps
551
-     *
552
-     * @access public
553
-     * @return void
554
-     */
555
-    public function sort_reg_steps()
556
-    {
557
-        $reg_step_sorting_callback = apply_filters(
558
-            'FHEE__EE_Checkout__sort_reg_steps__reg_step_sorting_callback',
559
-            'reg_step_sorting_callback'
560
-        );
561
-        uasort($this->reg_steps, array($this, $reg_step_sorting_callback));
562
-    }
563
-
564
-
565
-    /**
566
-     * find_reg_step
567
-     * finds a reg step by the given slug
568
-     *
569
-     * @access    public
570
-     * @param string $reg_step_slug
571
-     * @return EE_SPCO_Reg_Step|null
572
-     */
573
-    public function find_reg_step($reg_step_slug = '')
574
-    {
575
-        if (! empty($reg_step_slug)) {
576
-            // copy reg step array
577
-            $reg_steps = $this->reg_steps;
578
-            // set pointer to start of array
579
-            reset($reg_steps);
580
-            // if there is more than one step
581
-            if (count($reg_steps) > 1) {
582
-                // advance to the current step and set pointer
583
-                while (key($reg_steps) !== $reg_step_slug && key($reg_steps) !== '') {
584
-                    next($reg_steps);
585
-                }
586
-                return current($reg_steps);
587
-            }
588
-        }
589
-        return null;
590
-    }
591
-
592
-
593
-    /**
594
-     * reg_step_sorting_callback
595
-     *
596
-     * @access public
597
-     * @param EE_SPCO_Reg_Step $reg_step_A
598
-     * @param EE_SPCO_Reg_Step $reg_step_B
599
-     * @return int
600
-     */
601
-    public function reg_step_sorting_callback(EE_SPCO_Reg_Step $reg_step_A, EE_SPCO_Reg_Step $reg_step_B)
602
-    {
603
-        // send finalize_registration step to the end of the array
604
-        if ($reg_step_A->slug() === 'finalize_registration') {
605
-            return 1;
606
-        } elseif ($reg_step_B->slug() === 'finalize_registration') {
607
-            return -1;
608
-        }
609
-        if ($reg_step_A->order() === $reg_step_B->order()) {
610
-            return 0;
611
-        }
612
-        return ($reg_step_A->order() > $reg_step_B->order()) ? 1 : -1;
613
-    }
614
-
615
-
616
-    /**
617
-     * set_reg_step_initiated
618
-     *
619
-     * @access    public
620
-     * @param    EE_SPCO_Reg_Step $reg_step
621
-     * @throws \EE_Error
622
-     */
623
-    public function set_reg_step_initiated(EE_SPCO_Reg_Step $reg_step)
624
-    {
625
-        // call set_reg_step_initiated ???
626
-        if (
17
+	/**
18
+	 *    whether current request originated from the EE admin
19
+	 *
20
+	 * @var bool
21
+	 */
22
+	public $admin_request = false;
23
+
24
+	/**
25
+	 * whether returning to edit attendee information or to retry a payment
26
+	 *
27
+	 * @var bool
28
+	 */
29
+	public $revisit = false;
30
+
31
+	/**
32
+	 * whether the primary registrant is returning to edit attendee information or to retry a payment
33
+	 *
34
+	 * @var bool
35
+	 */
36
+	public $primary_revisit = false;
37
+
38
+	/**
39
+	 * is registration allowed to progress or halted for some reason such as failing to pass recaptcha?
40
+	 *
41
+	 * @var bool
42
+	 */
43
+	public $continue_reg = true;
44
+
45
+	/**
46
+	 * redirect to thank you page ?
47
+	 *
48
+	 * @var bool
49
+	 */
50
+	public $redirect = false;
51
+
52
+	/**
53
+	 * generate the reg form or not ?
54
+	 *
55
+	 * @var bool
56
+	 */
57
+	public $generate_reg_form = true;
58
+
59
+	/**
60
+	 * process a reg form submission or not ?
61
+	 *
62
+	 * @var bool
63
+	 */
64
+	public $process_form_submission = false;
65
+
66
+	/**
67
+	 * tracks whether the TXN status modified during this checkout
68
+	 *
69
+	 * @var bool
70
+	 */
71
+	public $txn_status_updated = false;
72
+
73
+	/**
74
+	 * only triggered to true after absolutely everything has finished.
75
+	 *
76
+	 * @var bool
77
+	 */
78
+	protected $exit_spco = false;
79
+
80
+	/**
81
+	 * tracks whether any of the TXN's Registrations statuses modified during this checkout
82
+	 * indexed by registration ID
83
+	 *
84
+	 * @var array
85
+	 */
86
+	protected $reg_status_updated = array();
87
+
88
+	/**
89
+	 * timestamp when redirected from Ticket Selector to the checkout
90
+	 *
91
+	 * @var int
92
+	 */
93
+	public $uts = 0;
94
+
95
+	/**
96
+	 * total number of tickets that were in the cart
97
+	 *
98
+	 * @var int
99
+	 */
100
+	public $total_ticket_count = 0;
101
+
102
+	/**
103
+	 * corresponds loosely to EE_Transaction::remaining()
104
+	 * but can be modified by SPCO
105
+	 *
106
+	 * @var float
107
+	 */
108
+	public $amount_owing = 0;
109
+
110
+	/**
111
+	 * the reg step slug from the incoming request
112
+	 *
113
+	 * @var string
114
+	 */
115
+	public $step = '';
116
+
117
+	/**
118
+	 * the reg step slug for a step being edited
119
+	 *
120
+	 * @var string
121
+	 */
122
+	public $edit_step = '';
123
+
124
+	/**
125
+	 * the action being performed on the current step
126
+	 *
127
+	 * @var string
128
+	 */
129
+	public $action = '';
130
+
131
+	/**
132
+	 * reg_url_link for a previously saved registration
133
+	 *
134
+	 * @var string
135
+	 */
136
+	public $reg_url_link = '';
137
+
138
+	/**
139
+	 * string slug for the payment method that was selected during the payment options step
140
+	 *
141
+	 * @var string
142
+	 */
143
+	public $selected_method_of_payment = '';
144
+
145
+	/**
146
+	 * base url for the site's registration checkout page - additional url params will be added to this
147
+	 *
148
+	 * @var string
149
+	 */
150
+	public $reg_page_base_url = '';
151
+
152
+	/**
153
+	 * base url for the site's registration cancelled page - additional url params will be added to this
154
+	 *
155
+	 * @var string
156
+	 */
157
+	public $cancel_page_url = '';
158
+
159
+	/**
160
+	 * base url for the site's thank you page - additional url params will be added to this
161
+	 *
162
+	 * @var string
163
+	 */
164
+	public $thank_you_page_url = '';
165
+
166
+	/**
167
+	 * base url for any redirects - additional url params will be added to this
168
+	 *
169
+	 * @var string
170
+	 */
171
+	public $redirect_url = '';
172
+
173
+	/**
174
+	 * form of POST data for use with off-site gateways
175
+	 *
176
+	 * @var string
177
+	 */
178
+	public $redirect_form = '';
179
+
180
+	/**
181
+	 * array of query where params to use when retrieving cached registrations from $this->checkout->transaction
182
+	 *
183
+	 * @var array
184
+	 */
185
+	public $reg_cache_where_params = array();
186
+
187
+	/**
188
+	 * a class for managing and creating the JSON encoded array of data that gets passed back to the client during AJAX
189
+	 * requests
190
+	 *
191
+	 * @var EE_SPCO_JSON_Response
192
+	 */
193
+	public $json_response;
194
+
195
+	/**
196
+	 * where we are going next in the reg process
197
+	 *
198
+	 * @var EE_SPCO_Reg_Step
199
+	 */
200
+	public $next_step;
201
+
202
+	/**
203
+	 * where we are in the reg process
204
+	 *
205
+	 * @var EE_SPCO_Reg_Step
206
+	 */
207
+	public $current_step;
208
+
209
+	/**
210
+	 *    $_cart - the current cart object
211
+	 *
212
+	 * @var EE_CART
213
+	 */
214
+	public $cart;
215
+
216
+	/**
217
+	 *    $_transaction - the current transaction object
218
+	 *
219
+	 * @var EE_Transaction
220
+	 */
221
+	public $transaction;
222
+
223
+	/**
224
+	 *    the related attendee object for the primary registrant
225
+	 *
226
+	 * @var EE_Attendee
227
+	 */
228
+	public $primary_attendee_obj;
229
+
230
+	/**
231
+	 *    $payment_method - the payment method object for the selected method of payment
232
+	 *
233
+	 * @var EE_Payment_Method
234
+	 */
235
+	public $payment_method;
236
+
237
+	/**
238
+	 *    $payment - if a payment was successfully made during the reg process,
239
+	 *    then here it is !!!
240
+	 *
241
+	 * @var EE_Payment
242
+	 */
243
+	public $payment;
244
+
245
+	/**
246
+	 *    if a payment method was selected that uses an on-site gateway, then this is the billing form
247
+	 *
248
+	 * @var EE_Billing_Info_Form|EE_Billing_Attendee_Info_Form
249
+	 */
250
+	public $billing_form;
251
+
252
+	/**
253
+	 *    the entire registration form composed of ALL of the subsections generated by the various reg steps
254
+	 *
255
+	 * @var EE_Form_Section_Proper
256
+	 */
257
+	public $registration_form;
258
+
259
+	/**
260
+	 * array of EE_SPCO_Reg_Step objects
261
+	 *
262
+	 * @var EE_SPCO_Reg_Step[]
263
+	 */
264
+	public $reg_steps = array();
265
+
266
+	/**
267
+	 * array of EE_Payment_Method objects
268
+	 *
269
+	 * @var EE_Payment_Method[]
270
+	 */
271
+	public $available_payment_methods = array();
272
+
273
+
274
+	/**
275
+	 *    class constructor
276
+	 *
277
+	 * @access    public
278
+	 */
279
+	public function __construct()
280
+	{
281
+		$this->reg_page_base_url = EE_Registry::instance()->CFG->core->reg_page_url();
282
+		$this->thank_you_page_url = EE_Registry::instance()->CFG->core->thank_you_page_url();
283
+		$this->cancel_page_url = EE_Registry::instance()->CFG->core->cancel_page_url();
284
+		$this->continue_reg = apply_filters('FHEE__EE_Checkout___construct___continue_reg', true);
285
+
286
+		$this->admin_request = is_admin() && ! EED_Single_Page_Checkout::getRequest()->isAjax();
287
+		$this->reg_cache_where_params = array(
288
+			0          => array('REG_deleted' => false),
289
+			'order_by' => array('REG_count' => 'ASC'),
290
+		);
291
+	}
292
+
293
+
294
+	/**
295
+	 * returns true if ANY reg status was updated during checkout
296
+	 *
297
+	 * @return boolean
298
+	 */
299
+	public function any_reg_status_updated()
300
+	{
301
+		foreach ($this->reg_status_updated as $reg_status) {
302
+			if ($reg_status) {
303
+				return true;
304
+			}
305
+		}
306
+		return false;
307
+	}
308
+
309
+
310
+	/**
311
+	 * @param $REG_ID
312
+	 * @return boolean
313
+	 */
314
+	public function reg_status_updated($REG_ID)
315
+	{
316
+		return isset($this->reg_status_updated[ $REG_ID ]) ? $this->reg_status_updated[ $REG_ID ] : false;
317
+	}
318
+
319
+
320
+	/**
321
+	 * @param $REG_ID
322
+	 * @param $reg_status
323
+	 */
324
+	public function set_reg_status_updated($REG_ID, $reg_status)
325
+	{
326
+		$this->reg_status_updated[ $REG_ID ] = filter_var($reg_status, FILTER_VALIDATE_BOOLEAN);
327
+	}
328
+
329
+
330
+	/**
331
+	 * exit_spco
332
+	 *
333
+	 * @return bool
334
+	 */
335
+	public function exit_spco()
336
+	{
337
+		return $this->exit_spco;
338
+	}
339
+
340
+
341
+	/**
342
+	 * set_exit_spco
343
+	 * can ONLY be set by the  Finalize_Registration reg step
344
+	 */
345
+	public function set_exit_spco()
346
+	{
347
+		if ($this->current_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
348
+			$this->exit_spco = true;
349
+		}
350
+	}
351
+
352
+
353
+	/**
354
+	 *    reset_for_current_request
355
+	 *
356
+	 * @access    public
357
+	 * @return    void
358
+	 */
359
+	public function reset_for_current_request()
360
+	{
361
+		$this->process_form_submission = false;
362
+		$this->continue_reg = apply_filters('FHEE__EE_Checkout___construct___continue_reg', true);
363
+		$this->admin_request = is_admin() && ! EED_Single_Page_Checkout::getRequest()->isFrontAjax();
364
+		$this->continue_reg = true;
365
+		$this->redirect = false;
366
+		// don't reset the cached redirect form if we're about to be asked to display it !!!
367
+		$action = EED_Single_Page_Checkout::getRequest()->getRequestParam('action', 'display_spco_reg_step');
368
+		if ($action !== 'redirect_form') {
369
+			$this->redirect_form = '';
370
+		}
371
+		$this->redirect_url = '';
372
+		$this->json_response = new EE_SPCO_JSON_Response();
373
+		EE_Form_Section_Proper::reset_js_localization();
374
+	}
375
+
376
+
377
+	/**
378
+	 *    add_reg_step
379
+	 *
380
+	 * @access    public
381
+	 * @param EE_SPCO_Reg_Step $reg_step_obj
382
+	 * @return    void
383
+	 */
384
+	public function add_reg_step(EE_SPCO_Reg_Step $reg_step_obj)
385
+	{
386
+		$this->reg_steps[ $reg_step_obj->slug() ] = $reg_step_obj;
387
+	}
388
+
389
+
390
+	/**
391
+	 * skip_reg_step
392
+	 * if the current reg step does not need to run for some reason,
393
+	 * then this will advance SPCO to the next reg step,
394
+	 * and mark the skipped step as completed
395
+	 *
396
+	 * @access    public
397
+	 * @param string $reg_step_slug
398
+	 * @return    void
399
+	 * @throws \EE_Error
400
+	 */
401
+	public function skip_reg_step($reg_step_slug = '')
402
+	{
403
+		$step_to_skip = $this->find_reg_step($reg_step_slug);
404
+		if ($step_to_skip instanceof EE_SPCO_Reg_Step && $step_to_skip->is_current_step()) {
405
+			$step_to_skip->set_is_current_step(false);
406
+			$step_to_skip->set_completed();
407
+			// advance to the next step
408
+			$this->set_current_step($this->next_step->slug());
409
+			// also reset the step param in the request in case any other code references that directly
410
+			EED_Single_Page_Checkout::getRequest()->setRequestParam('step', $this->current_step->slug());
411
+			// since we are skipping a step and setting the current step to be what was previously the next step,
412
+			// we need to check that the next step is now correct, and not still set to the current step.
413
+			if ($this->current_step->slug() === $this->next_step->slug()) {
414
+				// correctly setup the next step
415
+				$this->set_next_step();
416
+			}
417
+			$this->set_reg_step_initiated($this->current_step);
418
+		}
419
+	}
420
+
421
+
422
+	/**
423
+	 *    remove_reg_step
424
+	 *
425
+	 * @access    public
426
+	 * @param string $reg_step_slug
427
+	 * @param bool   $reset whether to reset reg steps after removal
428
+	 * @throws EE_Error
429
+	 */
430
+	public function remove_reg_step($reg_step_slug = '', $reset = true)
431
+	{
432
+		unset($this->reg_steps[ $reg_step_slug ]);
433
+		if ($this->transaction instanceof EE_Transaction) {
434
+			// now remove reg step from TXN and save
435
+			$this->transaction->remove_reg_step($reg_step_slug);
436
+			$this->transaction->save();
437
+		}
438
+		if ($reset) {
439
+			$this->reset_reg_steps();
440
+		}
441
+	}
442
+
443
+
444
+	/**
445
+	 *    set_reg_step_order
446
+	 *
447
+	 * @access    public
448
+	 * @param string $reg_step_slug
449
+	 * @param int    $order
450
+	 * @return    void
451
+	 */
452
+	public function set_reg_step_order($reg_step_slug = '', $order = 100)
453
+	{
454
+		if (isset($this->reg_steps[ $reg_step_slug ])) {
455
+			$this->reg_steps[ $reg_step_slug ]->set_order($order);
456
+		}
457
+	}
458
+
459
+
460
+	/**
461
+	 * @param string $current_step
462
+	 * @return void
463
+	 */
464
+	public function set_current_step(string $current_step)
465
+	{
466
+		// grab what step we're on
467
+		$this->current_step = $this->reg_steps[ $current_step ] ?? reset($this->reg_steps);
468
+		// verify instance
469
+		if (! $this->current_step instanceof EE_SPCO_Reg_Step)  {
470
+			EE_Error::add_error(
471
+				esc_html__('The current step could not be set.', 'event_espresso'),
472
+				__FILE__,
473
+				__FUNCTION__,
474
+				__LINE__
475
+			);
476
+		}
477
+		// we don't want to repeat completed steps if this is the first time through SPCO
478
+		if ($this->continue_reg && ! $this->revisit && $this->current_step->completed()) {
479
+			// so advance to the next step
480
+			$this->set_next_step();
481
+			if ($this->next_step instanceof EE_SPCO_Reg_Step) {
482
+				// and attempt to set it as the current step
483
+				$this->set_current_step($this->next_step->slug());
484
+			}
485
+			return;
486
+		}
487
+		$this->current_step->set_is_current_step(true);
488
+		$this->current_step->setRequest(EED_Single_Page_Checkout::getRequest());
489
+	}
490
+
491
+
492
+	/**
493
+	 *    set_next_step
494
+	 * advances the reg_steps array pointer and sets the next step, then reverses pointer back to the current step
495
+	 *
496
+	 * @access    public
497
+	 * @return    void
498
+	 */
499
+	public function set_next_step()
500
+	{
501
+		// set pointer to start of array
502
+		reset($this->reg_steps);
503
+		// if there is more than one step
504
+		if (count($this->reg_steps) > 1) {
505
+			// advance to the current step and set pointer
506
+			while (key($this->reg_steps) !== $this->current_step->slug() && key($this->reg_steps) !== '') {
507
+				next($this->reg_steps);
508
+			}
509
+		}
510
+		// advance one more spot ( if it exists )
511
+		$this->next_step = next($this->reg_steps);
512
+		// verify instance
513
+		$this->next_step = $this->next_step instanceof EE_SPCO_Reg_Step ? $this->next_step : null;
514
+		// then back to current step to reset
515
+		prev($this->reg_steps);
516
+	}
517
+
518
+
519
+	/**
520
+	 *    get_next_reg_step
521
+	 *    this simply returns the next step from reg_steps array
522
+	 *
523
+	 * @access    public
524
+	 * @return    EE_SPCO_Reg_Step | null
525
+	 */
526
+	public function get_next_reg_step()
527
+	{
528
+		$next = next($this->reg_steps);
529
+		prev($this->reg_steps);
530
+		return $next instanceof EE_SPCO_Reg_Step ? $next : null;
531
+	}
532
+
533
+
534
+	/**
535
+	 * get_prev_reg_step
536
+	 *    this simply returns the previous step from reg_steps array
537
+	 *
538
+	 * @access    public
539
+	 * @return    EE_SPCO_Reg_Step | null
540
+	 */
541
+	public function get_prev_reg_step()
542
+	{
543
+		$prev = prev($this->reg_steps);
544
+		next($this->reg_steps);
545
+		return $prev instanceof EE_SPCO_Reg_Step ? $prev : null;
546
+	}
547
+
548
+
549
+	/**
550
+	 * sort_reg_steps
551
+	 *
552
+	 * @access public
553
+	 * @return void
554
+	 */
555
+	public function sort_reg_steps()
556
+	{
557
+		$reg_step_sorting_callback = apply_filters(
558
+			'FHEE__EE_Checkout__sort_reg_steps__reg_step_sorting_callback',
559
+			'reg_step_sorting_callback'
560
+		);
561
+		uasort($this->reg_steps, array($this, $reg_step_sorting_callback));
562
+	}
563
+
564
+
565
+	/**
566
+	 * find_reg_step
567
+	 * finds a reg step by the given slug
568
+	 *
569
+	 * @access    public
570
+	 * @param string $reg_step_slug
571
+	 * @return EE_SPCO_Reg_Step|null
572
+	 */
573
+	public function find_reg_step($reg_step_slug = '')
574
+	{
575
+		if (! empty($reg_step_slug)) {
576
+			// copy reg step array
577
+			$reg_steps = $this->reg_steps;
578
+			// set pointer to start of array
579
+			reset($reg_steps);
580
+			// if there is more than one step
581
+			if (count($reg_steps) > 1) {
582
+				// advance to the current step and set pointer
583
+				while (key($reg_steps) !== $reg_step_slug && key($reg_steps) !== '') {
584
+					next($reg_steps);
585
+				}
586
+				return current($reg_steps);
587
+			}
588
+		}
589
+		return null;
590
+	}
591
+
592
+
593
+	/**
594
+	 * reg_step_sorting_callback
595
+	 *
596
+	 * @access public
597
+	 * @param EE_SPCO_Reg_Step $reg_step_A
598
+	 * @param EE_SPCO_Reg_Step $reg_step_B
599
+	 * @return int
600
+	 */
601
+	public function reg_step_sorting_callback(EE_SPCO_Reg_Step $reg_step_A, EE_SPCO_Reg_Step $reg_step_B)
602
+	{
603
+		// send finalize_registration step to the end of the array
604
+		if ($reg_step_A->slug() === 'finalize_registration') {
605
+			return 1;
606
+		} elseif ($reg_step_B->slug() === 'finalize_registration') {
607
+			return -1;
608
+		}
609
+		if ($reg_step_A->order() === $reg_step_B->order()) {
610
+			return 0;
611
+		}
612
+		return ($reg_step_A->order() > $reg_step_B->order()) ? 1 : -1;
613
+	}
614
+
615
+
616
+	/**
617
+	 * set_reg_step_initiated
618
+	 *
619
+	 * @access    public
620
+	 * @param    EE_SPCO_Reg_Step $reg_step
621
+	 * @throws \EE_Error
622
+	 */
623
+	public function set_reg_step_initiated(EE_SPCO_Reg_Step $reg_step)
624
+	{
625
+		// call set_reg_step_initiated ???
626
+		if (
627 627
 // first time visiting SPCO ?
628
-            ! $this->revisit
629
-            && (
630
-                // and displaying the reg step form for the first time ?
631
-                $this->action === 'display_spco_reg_step'
632
-                // or initializing the final step
633
-                || $reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration
634
-            )
635
-        ) {
636
-            // set the start time for this reg step
637
-            if (! $this->transaction->set_reg_step_initiated($reg_step->slug())) {
638
-                if (WP_DEBUG) {
639
-                    EE_Error::add_error(
640
-                        sprintf(
641
-                            esc_html__('The "%1$s" registration step was not initialized properly.', 'event_espresso'),
642
-                            $reg_step->name()
643
-                        ),
644
-                        __FILE__,
645
-                        __FUNCTION__,
646
-                        __LINE__
647
-                    );
648
-                }
649
-            }
650
-        }
651
-    }
652
-
653
-
654
-    /**
655
-     *    set_reg_step_JSON_info
656
-     *
657
-     * @access public
658
-     * @return    void
659
-     */
660
-    public function set_reg_step_JSON_info()
661
-    {
662
-        EE_Registry::$i18n_js_strings['reg_steps'] = array();
663
-        // pass basic reg step data to JS
664
-        foreach ($this->reg_steps as $reg_step) {
665
-            EE_Registry::$i18n_js_strings['reg_steps'][] = $reg_step->slug();
666
-        }
667
-        // reset reg step html
668
-        // $this->json_response->set_reg_step_html('');
669
-    }
670
-
671
-
672
-    /**
673
-     *    reset_reg_steps
674
-     *
675
-     * @access public
676
-     * @return void
677
-     */
678
-    public function reset_reg_steps()
679
-    {
680
-        $this->sort_reg_steps();
681
-        $this->set_current_step(EED_Single_Page_Checkout::getRequest()->getRequestParam('step'));
682
-        $this->set_next_step();
683
-        // the text that appears on the reg step form submit button
684
-        $this->current_step->set_submit_button_text();
685
-        $this->set_reg_step_JSON_info();
686
-    }
687
-
688
-
689
-    /**
690
-     *    get_registration_time_limit
691
-     *
692
-     * @access    public
693
-     * @return        string
694
-     */
695
-    public function get_registration_time_limit()
696
-    {
697
-        $registration_time_limit = (float) (EE_Registry::instance()->SSN->expiration() - time());
698
-        $time_limit_format = $registration_time_limit > 60 * MINUTE_IN_SECONDS ? 'H:i:s' : 'i:s';
699
-        $registration_time_limit = date($time_limit_format, $registration_time_limit);
700
-        return apply_filters(
701
-            'FHEE__EE_Checkout__get_registration_time_limit__registration_time_limit',
702
-            $registration_time_limit
703
-        );
704
-    }
705
-
706
-
707
-    /**
708
-     * payment_required
709
-     *
710
-     * @return boolean
711
-     */
712
-    public function payment_required()
713
-    {
714
-        // if NOT:
715
-        //     registration via admin
716
-        //      completed TXN
717
-        //      overpaid TXN
718
-        //      free TXN(total = 0.00)
719
-        //      then payment required is TRUE
720
-        return ! ($this->admin_request
721
-                  || $this->transaction->is_completed()
722
-                  || $this->transaction->is_overpaid()
723
-                  || $this->transaction->is_free()) ? true : false;
724
-    }
725
-
726
-
727
-    /**
728
-     * get_cart_for_transaction
729
-     *
730
-     * @access public
731
-     * @param EE_Transaction $transaction
732
-     * @return EE_Cart
733
-     */
734
-    public function get_cart_for_transaction($transaction)
735
-    {
736
-        $session = EE_Registry::instance()->load_core('Session');
737
-        $cart = $transaction instanceof EE_Transaction ? EE_Cart::get_cart_from_txn($transaction, $session) : null;
738
-        // verify cart
739
-        if (! $cart instanceof EE_Cart) {
740
-            $cart = EE_Registry::instance()->load_core('Cart');
741
-        }
742
-
743
-        return $cart;
744
-    }
745
-
746
-
747
-    /**
748
-     *    initialize_txn_reg_steps_array
749
-     *
750
-     * @access public
751
-     * @return    array
752
-     */
753
-    public function initialize_txn_reg_steps_array()
754
-    {
755
-        $txn_reg_steps_array = array();
756
-        foreach ($this->reg_steps as $reg_step) {
757
-            $txn_reg_steps_array[ $reg_step->slug() ] = false;
758
-        }
759
-        return $txn_reg_steps_array;
760
-    }
761
-
762
-
763
-    /**
764
-     *    update_txn_reg_steps_array
765
-     *
766
-     * @access public
767
-     * @return    bool
768
-     * @throws \EE_Error
769
-     */
770
-    public function update_txn_reg_steps_array()
771
-    {
772
-        $updated = false;
773
-        foreach ($this->reg_steps as $reg_step) {
774
-            if ($reg_step->completed()) {
775
-                $updated = $this->transaction->set_reg_step_completed($reg_step->slug())
776
-                    ? true
777
-                    : $updated;
778
-            }
779
-        }
780
-        if ($updated) {
781
-            $this->transaction->save();
782
-        }
783
-        return $updated;
784
-    }
785
-
786
-
787
-    /**
788
-     *    stash_transaction_and_checkout
789
-     *
790
-     * @access public
791
-     * @return    void
792
-     * @throws \EE_Error
793
-     */
794
-    public function stash_transaction_and_checkout()
795
-    {
796
-        if (! $this->revisit) {
797
-            $this->update_txn_reg_steps_array();
798
-        }
799
-        $this->track_transaction_and_registration_status_updates();
800
-        // save all data to the db, but suppress errors
801
-        // $this->save_all_data( FALSE );
802
-        // cache the checkout in the session
803
-        EE_Registry::instance()->SSN->set_checkout($this);
804
-    }
805
-
806
-
807
-    /**
808
-     *    track_transaction_and_registration_status_updates
809
-     *    stores whether any updates were made to the TXN or it's related registrations
810
-     *
811
-     * @access public
812
-     * @return void
813
-     * @throws \EE_Error
814
-     */
815
-    public function track_transaction_and_registration_status_updates()
816
-    {
817
-        // verify the transaction
818
-        if ($this->transaction instanceof EE_Transaction) {
819
-            // has there been a TXN status change during this checkout?
820
-            $this->txn_status_updated = $this->transaction->txn_status_updated();
821
-            /** @type EE_Registration_Processor $registration_processor */
822
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
823
-            // grab the saved registrations from the transaction
824
-            foreach ($this->transaction->registrations($this->reg_cache_where_params) as $registration) {
825
-                if ($registration_processor->reg_status_updated($registration->ID())) {
826
-                    $this->set_reg_status_updated($registration->ID(), true);
827
-                }
828
-            }
829
-        }
830
-    }
831
-
832
-
833
-    /**
834
-     *    visit_allows_processing_of_this_registration
835
-     *    determines if the current SPCO visit should allow the passed EE_Registration to be used in processing.
836
-     *    one of the following conditions must be met:
837
-     *        EITHER:    A) first time thru SPCO -> process ALL registrations ( NOT a revisit )
838
-     *        OR :        B) primary registrant is editing info -> process ALL registrations ( primary_revisit )
839
-     *        OR :        C) another registrant is editing info -> ONLY process their registration ( revisit AND their
840
-     *        reg_url_link matches )
841
-     *
842
-     * @access public
843
-     * @param    EE_Registration $registration
844
-     * @return    bool
845
-     * @throws \EE_Error
846
-     */
847
-    public function visit_allows_processing_of_this_registration(EE_Registration $registration)
848
-    {
849
-        return ! $this->revisit
850
-               || $this->primary_revisit
851
-               || (
852
-                   $this->revisit && $this->reg_url_link === $registration->reg_url_link()
853
-               )
854
-            ? true
855
-            : false;
856
-    }
857
-
858
-
859
-    /**
860
-     *    _transaction_has_primary_registration
861
-     *
862
-     * @access        private
863
-     * @return        bool
864
-     */
865
-    public function transaction_has_primary_registrant()
866
-    {
867
-        return $this->primary_attendee_obj instanceof EE_Attendee ? true : false;
868
-    }
869
-
870
-
871
-    /**
872
-     *    save_all_data
873
-     *    simply loops through the current transaction and saves all data for each registration
874
-     *
875
-     * @access public
876
-     * @param bool $show_errors
877
-     * @return bool
878
-     * @throws \EE_Error
879
-     */
880
-    public function save_all_data($show_errors = true)
881
-    {
882
-        // verify the transaction
883
-        if ($this->transaction instanceof EE_Transaction) {
884
-            // save to ensure that TXN has ID
885
-            $this->transaction->save();
886
-            // grab the saved registrations from the transaction
887
-            foreach ($this->transaction->registrations($this->reg_cache_where_params) as $registration) {
888
-                $this->_save_registration($registration, $show_errors);
889
-            }
890
-        } else {
891
-            if ($show_errors) {
892
-                EE_Error::add_error(
893
-                    esc_html__(
894
-                        'A valid Transaction was not found when attempting to save your registration information.',
895
-                        'event_espresso'
896
-                    ),
897
-                    __FILE__,
898
-                    __FUNCTION__,
899
-                    __LINE__
900
-                );
901
-            }
902
-            return false;
903
-        }
904
-        return true;
905
-    }
906
-
907
-
908
-    /**
909
-     * _save_registration_attendee
910
-     *
911
-     * @param    EE_Registration $registration
912
-     * @param bool               $show_errors
913
-     * @return void
914
-     * @throws \EE_Error
915
-     */
916
-    private function _save_registration($registration, $show_errors = true)
917
-    {
918
-        // verify object
919
-        if ($registration instanceof EE_Registration) {
920
-            // should this registration be processed during this visit ?
921
-            if ($this->visit_allows_processing_of_this_registration($registration)) {
922
-                // set TXN ID
923
-                if (! $registration->transaction_ID()) {
924
-                    $registration->set_transaction_id($this->transaction->ID());
925
-                }
926
-                // verify and save the attendee
927
-                $this->_save_registration_attendee($registration, $show_errors);
928
-                // save answers to reg form questions
929
-                $this->_save_registration_answers($registration, $show_errors);
930
-                // save changes
931
-                $registration->save();
932
-                // update txn cache
933
-                if (! $this->transaction->update_cache_after_object_save('Registration', $registration)) {
934
-                    if ($show_errors) {
935
-                        EE_Error::add_error(
936
-                            esc_html__(
937
-                                'The newly saved Registration object could not be cached on the Transaction.',
938
-                                'event_espresso'
939
-                            ),
940
-                            __FILE__,
941
-                            __FUNCTION__,
942
-                            __LINE__
943
-                        );
944
-                    }
945
-                }
946
-            }
947
-        } else {
948
-            if ($show_errors) {
949
-                EE_Error::add_error(
950
-                    esc_html__(
951
-                        'An invalid Registration object was discovered when attempting to save your registration information.',
952
-                        'event_espresso'
953
-                    ),
954
-                    __FILE__,
955
-                    __FUNCTION__,
956
-                    __LINE__
957
-                );
958
-            }
959
-        }
960
-    }
961
-
962
-
963
-    /**
964
-     * _save_registration_attendee
965
-     *
966
-     * @param    EE_Registration $registration
967
-     * @param bool               $show_errors
968
-     * @return void
969
-     * @throws \EE_Error
970
-     */
971
-    private function _save_registration_attendee($registration, $show_errors = true)
972
-    {
973
-        if ($registration->attendee() instanceof EE_Attendee) {
974
-            // save so that ATT has ID
975
-            $registration->attendee()->save();
976
-            if (! $registration->update_cache_after_object_save('Attendee', $registration->attendee())) {
977
-                if ($show_errors) {
978
-                    EE_Error::add_error(
979
-                        esc_html__(
980
-                            'The newly saved Attendee object could not be cached on the registration.',
981
-                            'event_espresso'
982
-                        ),
983
-                        __FILE__,
984
-                        __FUNCTION__,
985
-                        __LINE__
986
-                    );
987
-                }
988
-            }
989
-        } else {
990
-            if ($show_errors) {
991
-                EE_Error::add_error(
992
-                    sprintf(
993
-                        '%1$s||%1$s $attendee = %2$s',
994
-                        esc_html__(
995
-                            'Either no Attendee information was found, or an invalid Attendee object was discovered when attempting to save your registration information.',
996
-                            'event_espresso'
997
-                        ),
998
-                        var_export($registration->attendee(), true)
999
-                    ),
1000
-                    __FILE__,
1001
-                    __FUNCTION__,
1002
-                    __LINE__
1003
-                );
1004
-            }
1005
-        }
1006
-    }
1007
-
1008
-
1009
-    /**
1010
-     * _save_question_answers
1011
-     *
1012
-     * @param    EE_Registration $registration
1013
-     * @param bool               $show_errors
1014
-     * @return void
1015
-     * @throws \EE_Error
1016
-     */
1017
-    private function _save_registration_answers($registration, $show_errors = true)
1018
-    {
1019
-        // now save the answers
1020
-        foreach ($registration->answers() as $cache_key => $answer) {
1021
-            // verify object
1022
-            if ($answer instanceof EE_Answer) {
1023
-                $answer->set_registration($registration->ID());
1024
-                $answer->save();
1025
-                if (! $registration->update_cache_after_object_save('Answer', $answer, $cache_key)) {
1026
-                    if ($show_errors) {
1027
-                        EE_Error::add_error(
1028
-                            esc_html__(
1029
-                                'The newly saved Answer object could not be cached on the registration.',
1030
-                                'event_espresso'
1031
-                            ),
1032
-                            __FILE__,
1033
-                            __FUNCTION__,
1034
-                            __LINE__
1035
-                        );
1036
-                    }
1037
-                }
1038
-            } else {
1039
-                if ($show_errors) {
1040
-                    EE_Error::add_error(
1041
-                        esc_html__(
1042
-                            'An invalid Answer object was discovered when attempting to save your registration information.',
1043
-                            'event_espresso'
1044
-                        ),
1045
-                        __FILE__,
1046
-                        __FUNCTION__,
1047
-                        __LINE__
1048
-                    );
1049
-                }
1050
-            }
1051
-        }
1052
-    }
1053
-
1054
-
1055
-    /**
1056
-     *    refresh_all_entities
1057
-     *   will either refresh the entity map with objects form the db or from the checkout cache
1058
-     *
1059
-     * @access public
1060
-     * @param bool $from_db
1061
-     * @return bool
1062
-     * @throws \EE_Error
1063
-     */
1064
-    public function refresh_all_entities($from_db = false)
1065
-    {
1066
-        $this->current_step->setRequest(EED_Single_Page_Checkout::getRequest());
1067
-        $from_db = $this->current_step->is_final_step() || $this->action === 'process_gateway_response'
1068
-            ? true
1069
-            : $from_db;
1070
-        // $this->log(
1071
-        //     __CLASS__,
1072
-        //     __FUNCTION__,
1073
-        //     __LINE__,
1074
-        //     array('from_db' => $from_db)
1075
-        // );
1076
-        return $from_db ? $this->refresh_from_db() : $this->refresh_entity_map();
1077
-    }
1078
-
1079
-
1080
-    /**
1081
-     *  refresh_entity_map
1082
-     *  simply loops through the current transaction and updates each
1083
-     *  model's entity map using EEM_Base::refresh_entity_map_from_db()
1084
-     *
1085
-     * @access public
1086
-     * @return bool
1087
-     * @throws \EE_Error
1088
-     */
1089
-    protected function refresh_from_db()
1090
-    {
1091
-        // verify the transaction
1092
-        if ($this->transaction instanceof EE_Transaction && $this->transaction->ID()) {
1093
-            // pull fresh TXN data from the db
1094
-            $this->transaction = $this->transaction->get_model()->refresh_entity_map_from_db($this->transaction->ID());
1095
-            // update EE_Checkout's cached primary_attendee object
1096
-            $this->primary_attendee_obj = $this->_refresh_primary_attendee_obj_from_db($this->transaction);
1097
-            // update EE_Checkout's cached payment object
1098
-            $payment = $this->transaction->last_payment();
1099
-            $this->payment = $payment instanceof EE_Payment ? $payment : $this->payment;
1100
-            // update EE_Checkout's cached payment_method object
1101
-            $payment_method = $this->payment instanceof EE_Payment ? $this->payment->payment_method() : null;
1102
-            $this->payment_method = $payment_method instanceof EE_Payment_Method ? $payment_method
1103
-                : $this->payment_method;
1104
-            // now refresh the cart, based on the TXN
1105
-            $this->cart = $this->get_cart_for_transaction($this->transaction);
1106
-        } else {
1107
-            EE_Error::add_error(
1108
-                esc_html__(
1109
-                    'A valid Transaction was not found when attempting to update the model entity mapper.',
1110
-                    'event_espresso'
1111
-                ),
1112
-                __FILE__,
1113
-                __FUNCTION__,
1114
-                __LINE__
1115
-            );
1116
-            return false;
1117
-        }
1118
-        return true;
1119
-    }
1120
-
1121
-
1122
-    /**
1123
-     * _refresh_primary_attendee_obj_from_db
1124
-     *
1125
-     * @param   EE_Transaction $transaction
1126
-     * @return  EE_Attendee | null
1127
-     * @throws \EE_Error
1128
-     */
1129
-    protected function _refresh_primary_attendee_obj_from_db(EE_Transaction $transaction)
1130
-    {
1131
-        $primary_attendee_obj = null;
1132
-        // grab the saved registrations from the transaction
1133
-        foreach ($transaction->registrations($this->reg_cache_where_params, true) as $registration) {
1134
-            // verify object
1135
-            if ($registration instanceof EE_Registration) {
1136
-                $attendee = $registration->attendee();
1137
-                // verify object && maybe cache primary_attendee_obj ?
1138
-                if ($attendee instanceof EE_Attendee && $registration->is_primary_registrant()) {
1139
-                    $primary_attendee_obj = $attendee;
1140
-                }
1141
-            } else {
1142
-                EE_Error::add_error(
1143
-                    esc_html__(
1144
-                        'An invalid Registration object was discovered when attempting to update the model entity mapper.',
1145
-                        'event_espresso'
1146
-                    ),
1147
-                    __FILE__,
1148
-                    __FUNCTION__,
1149
-                    __LINE__
1150
-                );
1151
-            }
1152
-        }
1153
-        return $primary_attendee_obj;
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     *  refresh_entity_map
1159
-     *  simply loops through the current transaction and updates
1160
-     *  each model's entity map using EEM_Base::refresh_entity_map_with()
1161
-     *
1162
-     * @access public
1163
-     * @return bool
1164
-     * @throws \EE_Error
1165
-     */
1166
-    protected function refresh_entity_map()
1167
-    {
1168
-        // verify the transaction
1169
-        if ($this->transaction instanceof EE_Transaction && $this->transaction->ID()) {
1170
-            // never cache payment info
1171
-            $this->transaction->clear_cache('Payment');
1172
-            // is the Payment Options Reg Step completed ?
1173
-            if ($this->transaction->reg_step_completed('payment_options')) {
1174
-                // then check for payments and update TXN accordingly
1175
-                /** @type EE_Transaction_Payments $transaction_payments */
1176
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1177
-                $transaction_payments->calculate_total_payments_and_update_status($this->transaction);
1178
-            }
1179
-            // grab the saved registrations from the transaction
1180
-            foreach ($this->transaction->registrations($this->reg_cache_where_params) as $reg_cache_ID => $registration) {
1181
-                $this->_refresh_registration($reg_cache_ID, $registration);
1182
-            }
1183
-            // make sure our cached TXN is added to the model entity mapper
1184
-            $this->transaction = $this->transaction->get_model()->refresh_entity_map_with(
1185
-                $this->transaction->ID(),
1186
-                $this->transaction
1187
-            );
1188
-        } else {
1189
-            EE_Error::add_error(
1190
-                esc_html__(
1191
-                    'A valid Transaction was not found when attempting to update the model entity mapper.',
1192
-                    'event_espresso'
1193
-                ),
1194
-                __FILE__,
1195
-                __FUNCTION__,
1196
-                __LINE__
1197
-            );
1198
-            return false;
1199
-        }
1200
-        // verify and update the cart because inaccurate totals are not so much fun
1201
-        if ($this->cart instanceof EE_Cart) {
1202
-            $grand_total = $this->cart->get_grand_total();
1203
-            if ($grand_total instanceof EE_Line_Item && $grand_total->ID()) {
1204
-                $grand_total->recalculate_total_including_taxes();
1205
-                $grand_total = $grand_total->get_model()->refresh_entity_map_with(
1206
-                    $this->cart->get_grand_total()->ID(),
1207
-                    $this->cart->get_grand_total()
1208
-                );
1209
-            }
1210
-            if ($grand_total instanceof EE_Line_Item) {
1211
-                $this->cart = EE_Cart::instance($grand_total);
1212
-            } else {
1213
-                EE_Error::add_error(
1214
-                    esc_html__(
1215
-                        'A valid Cart was not found when attempting to update the model entity mapper.',
1216
-                        'event_espresso'
1217
-                    ),
1218
-                    __FILE__,
1219
-                    __FUNCTION__,
1220
-                    __LINE__
1221
-                );
1222
-                return false;
1223
-            }
1224
-        }
1225
-        return true;
1226
-    }
1227
-
1228
-
1229
-    /**
1230
-     * _refresh_registration
1231
-     *
1232
-     * @param    string | int    $reg_cache_ID
1233
-     * @param    EE_Registration $registration
1234
-     * @return void
1235
-     * @throws \EE_Error
1236
-     */
1237
-    protected function _refresh_registration($reg_cache_ID, $registration)
1238
-    {
1239
-
1240
-        // verify object
1241
-        if ($registration instanceof EE_Registration) {
1242
-            // update the entity mapper attendee
1243
-            $this->_refresh_registration_attendee($registration);
1244
-            // update the entity mapper answers for reg form questions
1245
-            $this->_refresh_registration_answers($registration);
1246
-            // make sure the cached registration is added to the model entity mapper
1247
-            $registration->get_model()->refresh_entity_map_with($reg_cache_ID, $registration);
1248
-        } else {
1249
-            EE_Error::add_error(
1250
-                esc_html__(
1251
-                    'An invalid Registration object was discovered when attempting to update the model entity mapper.',
1252
-                    'event_espresso'
1253
-                ),
1254
-                __FILE__,
1255
-                __FUNCTION__,
1256
-                __LINE__
1257
-            );
1258
-        }
1259
-    }
1260
-
1261
-
1262
-    /**
1263
-     * _save_registration_attendee
1264
-     *
1265
-     * @param    EE_Registration $registration
1266
-     * @return void
1267
-     * @throws \EE_Error
1268
-     */
1269
-    protected function _refresh_registration_attendee($registration)
1270
-    {
1271
-        $attendee = $registration->attendee();
1272
-        // verify object
1273
-        if ($attendee instanceof EE_Attendee && $attendee->ID()) {
1274
-            // make sure the cached attendee is added to the model entity mapper
1275
-            $registration->attendee()->get_model()->refresh_entity_map_with($attendee->ID(), $attendee);
1276
-            // maybe cache primary_attendee_obj ?
1277
-            if ($registration->is_primary_registrant()) {
1278
-                $this->primary_attendee_obj = $attendee;
1279
-            }
1280
-        }
1281
-    }
1282
-
1283
-
1284
-    /**
1285
-     * _refresh_registration_answers
1286
-     *
1287
-     * @param    EE_Registration $registration
1288
-     * @return void
1289
-     * @throws \EE_Error
1290
-     */
1291
-    protected function _refresh_registration_answers($registration)
1292
-    {
1293
-
1294
-        // now update the answers
1295
-        foreach ($registration->answers() as $cache_key => $answer) {
1296
-            // verify object
1297
-            if ($answer instanceof EE_Answer) {
1298
-                if ($answer->ID()) {
1299
-                    // make sure the cached answer is added to the model entity mapper
1300
-                    $answer->get_model()->refresh_entity_map_with($answer->ID(), $answer);
1301
-                }
1302
-            } else {
1303
-                EE_Error::add_error(
1304
-                    esc_html__(
1305
-                        'An invalid Answer object was discovered when attempting to update the model entity mapper.',
1306
-                        'event_espresso'
1307
-                    ),
1308
-                    __FILE__,
1309
-                    __FUNCTION__,
1310
-                    __LINE__
1311
-                );
1312
-            }
1313
-        }
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     *    __sleep
1319
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
1320
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
1321
-     * reg form, because if needed, it will be regenerated anyways
1322
-     *
1323
-     * @return array
1324
-     * @throws \EE_Error
1325
-     */
1326
-    public function __sleep()
1327
-    {
1328
-        if ($this->primary_attendee_obj instanceof EE_Attendee && $this->primary_attendee_obj->ID()) {
1329
-            $this->primary_attendee_obj = $this->primary_attendee_obj->ID();
1330
-        }        // remove the reg form and the checkout
1331
-        if ($this->transaction instanceof EE_Transaction && $this->transaction->ID()) {
1332
-            $this->transaction = $this->transaction->ID();
1333
-        }        // remove the reg form and the checkout
1334
-        return array_diff(array_keys(get_object_vars($this)), array('billing_form', 'registration_form'));
1335
-    }
1336
-
1337
-
1338
-    /**
1339
-     *    __wakeup
1340
-     * to conserve db space, we are removing the EE_Checkout object from EE_SPCO_Reg_Step objects upon serialization
1341
-     * this will reinstate the EE_Checkout object on each EE_SPCO_Reg_Step object
1342
-     */
1343
-    public function __wakeup()
1344
-    {
1345
-        if (! $this->primary_attendee_obj instanceof EE_Attendee && absint($this->primary_attendee_obj) !== 0) {
1346
-            // $this->primary_attendee_obj is actually just an ID, so use it to get the object from the db
1347
-            $this->primary_attendee_obj = EEM_Attendee::instance()->get_one_by_ID($this->primary_attendee_obj);
1348
-        }
1349
-        if (! $this->transaction instanceof EE_Transaction && absint($this->transaction) !== 0) {
1350
-            // $this->transaction is actually just an ID, so use it to get the object from the db
1351
-            $this->transaction = EEM_Transaction::instance()->get_one_by_ID($this->transaction);
1352
-        }
1353
-        foreach ($this->reg_steps as $reg_step) {
1354
-            $reg_step->checkout = $this;
1355
-        }
1356
-    }
1357
-
1358
-
1359
-    /**
1360
-     * debug
1361
-     *
1362
-     * @param string $class
1363
-     * @param string $func
1364
-     * @param string $line
1365
-     * @param array  $info
1366
-     * @param bool   $display_request
1367
-     * @throws \EE_Error
1368
-     */
1369
-    public function log($class = '', $func = '', $line = '', $info = array(), $display_request = false)
1370
-    {
1371
-        $disabled = true;
1372
-        if (WP_DEBUG && ! $disabled) {
1373
-            $debug_data = get_option('EE_DEBUG_SPCO_' . EE_Session::instance()->id(), array());
1374
-            $default_data = array(
1375
-                $class                    => $func . '() : ' . $line,
1376
-                'request->step'           => $this->step,
1377
-                'request->action'         => $this->action,
1378
-                'current_step->slug'      => $this->current_step instanceof EE_SPCO_Reg_Step ?
1379
-                    $this->current_step->slug() : '',
1380
-                'current_step->completed' => $this->current_step instanceof EE_SPCO_Reg_Step ?
1381
-                    $this->current_step->completed() : '',
1382
-                'txn_status_updated'      => $this->transaction->txn_status_updated(),
1383
-                'reg_status_updated'      => $this->reg_status_updated,
1384
-                'reg_url_link'            => $this->reg_url_link,
1385
-            );
1386
-            if ($this->transaction instanceof EE_Transaction) {
1387
-                $default_data['TXN_status'] = $this->transaction->status_ID();
1388
-                $default_data['TXN_reg_steps'] = $this->transaction->reg_steps();
1389
-                foreach ($this->transaction->registrations($this->reg_cache_where_params) as $REG_ID => $registration) {
1390
-                    $default_data['registrations'][ $REG_ID ] = $registration->status_ID();
1391
-                }
1392
-                if ($this->transaction->ID()) {
1393
-                    $TXN_ID = 'EE_Transaction: ' . $this->transaction->ID();
1394
-                    // don't serialize objects
1395
-                    $info = $this->_strip_objects($info);
1396
-                    if (! isset($debug_data[ $TXN_ID ])) {
1397
-                        $debug_data[ $TXN_ID ] = array();
1398
-                    }
1399
-                    $debug_data[ $TXN_ID ][ microtime() ] = array_merge(
1400
-                        $default_data,
1401
-                        $info
1402
-                    );
1403
-                    update_option('EE_DEBUG_SPCO_' . EE_Session::instance()->id(), $debug_data);
1404
-                }
1405
-            }
1406
-        }
1407
-    }
1408
-
1409
-
1410
-    /**
1411
-     * _strip_objects
1412
-     *
1413
-     * @param array $info
1414
-     * @return array
1415
-     */
1416
-    public function _strip_objects($info = array())
1417
-    {
1418
-        foreach ((array) $info as $key => $value) {
1419
-            if (is_array($value)) {
1420
-                $info[ $key ] = $this->_strip_objects($value);
1421
-            } elseif (is_object($value)) {
1422
-                $object_class = get_class($value);
1423
-                $info[ $object_class ] = array();
1424
-                $info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : 0;
1425
-                if (method_exists($value, 'status')) {
1426
-                    $info[ $object_class ]['status'] = $value->status();
1427
-                } elseif (method_exists($value, 'status_ID')) {
1428
-                    $info[ $object_class ]['status'] = $value->status_ID();
1429
-                }
1430
-                unset($info[ $key ]);
1431
-            }
1432
-        }
1433
-        return (array) $info;
1434
-    }
628
+			! $this->revisit
629
+			&& (
630
+				// and displaying the reg step form for the first time ?
631
+				$this->action === 'display_spco_reg_step'
632
+				// or initializing the final step
633
+				|| $reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration
634
+			)
635
+		) {
636
+			// set the start time for this reg step
637
+			if (! $this->transaction->set_reg_step_initiated($reg_step->slug())) {
638
+				if (WP_DEBUG) {
639
+					EE_Error::add_error(
640
+						sprintf(
641
+							esc_html__('The "%1$s" registration step was not initialized properly.', 'event_espresso'),
642
+							$reg_step->name()
643
+						),
644
+						__FILE__,
645
+						__FUNCTION__,
646
+						__LINE__
647
+					);
648
+				}
649
+			}
650
+		}
651
+	}
652
+
653
+
654
+	/**
655
+	 *    set_reg_step_JSON_info
656
+	 *
657
+	 * @access public
658
+	 * @return    void
659
+	 */
660
+	public function set_reg_step_JSON_info()
661
+	{
662
+		EE_Registry::$i18n_js_strings['reg_steps'] = array();
663
+		// pass basic reg step data to JS
664
+		foreach ($this->reg_steps as $reg_step) {
665
+			EE_Registry::$i18n_js_strings['reg_steps'][] = $reg_step->slug();
666
+		}
667
+		// reset reg step html
668
+		// $this->json_response->set_reg_step_html('');
669
+	}
670
+
671
+
672
+	/**
673
+	 *    reset_reg_steps
674
+	 *
675
+	 * @access public
676
+	 * @return void
677
+	 */
678
+	public function reset_reg_steps()
679
+	{
680
+		$this->sort_reg_steps();
681
+		$this->set_current_step(EED_Single_Page_Checkout::getRequest()->getRequestParam('step'));
682
+		$this->set_next_step();
683
+		// the text that appears on the reg step form submit button
684
+		$this->current_step->set_submit_button_text();
685
+		$this->set_reg_step_JSON_info();
686
+	}
687
+
688
+
689
+	/**
690
+	 *    get_registration_time_limit
691
+	 *
692
+	 * @access    public
693
+	 * @return        string
694
+	 */
695
+	public function get_registration_time_limit()
696
+	{
697
+		$registration_time_limit = (float) (EE_Registry::instance()->SSN->expiration() - time());
698
+		$time_limit_format = $registration_time_limit > 60 * MINUTE_IN_SECONDS ? 'H:i:s' : 'i:s';
699
+		$registration_time_limit = date($time_limit_format, $registration_time_limit);
700
+		return apply_filters(
701
+			'FHEE__EE_Checkout__get_registration_time_limit__registration_time_limit',
702
+			$registration_time_limit
703
+		);
704
+	}
705
+
706
+
707
+	/**
708
+	 * payment_required
709
+	 *
710
+	 * @return boolean
711
+	 */
712
+	public function payment_required()
713
+	{
714
+		// if NOT:
715
+		//     registration via admin
716
+		//      completed TXN
717
+		//      overpaid TXN
718
+		//      free TXN(total = 0.00)
719
+		//      then payment required is TRUE
720
+		return ! ($this->admin_request
721
+				  || $this->transaction->is_completed()
722
+				  || $this->transaction->is_overpaid()
723
+				  || $this->transaction->is_free()) ? true : false;
724
+	}
725
+
726
+
727
+	/**
728
+	 * get_cart_for_transaction
729
+	 *
730
+	 * @access public
731
+	 * @param EE_Transaction $transaction
732
+	 * @return EE_Cart
733
+	 */
734
+	public function get_cart_for_transaction($transaction)
735
+	{
736
+		$session = EE_Registry::instance()->load_core('Session');
737
+		$cart = $transaction instanceof EE_Transaction ? EE_Cart::get_cart_from_txn($transaction, $session) : null;
738
+		// verify cart
739
+		if (! $cart instanceof EE_Cart) {
740
+			$cart = EE_Registry::instance()->load_core('Cart');
741
+		}
742
+
743
+		return $cart;
744
+	}
745
+
746
+
747
+	/**
748
+	 *    initialize_txn_reg_steps_array
749
+	 *
750
+	 * @access public
751
+	 * @return    array
752
+	 */
753
+	public function initialize_txn_reg_steps_array()
754
+	{
755
+		$txn_reg_steps_array = array();
756
+		foreach ($this->reg_steps as $reg_step) {
757
+			$txn_reg_steps_array[ $reg_step->slug() ] = false;
758
+		}
759
+		return $txn_reg_steps_array;
760
+	}
761
+
762
+
763
+	/**
764
+	 *    update_txn_reg_steps_array
765
+	 *
766
+	 * @access public
767
+	 * @return    bool
768
+	 * @throws \EE_Error
769
+	 */
770
+	public function update_txn_reg_steps_array()
771
+	{
772
+		$updated = false;
773
+		foreach ($this->reg_steps as $reg_step) {
774
+			if ($reg_step->completed()) {
775
+				$updated = $this->transaction->set_reg_step_completed($reg_step->slug())
776
+					? true
777
+					: $updated;
778
+			}
779
+		}
780
+		if ($updated) {
781
+			$this->transaction->save();
782
+		}
783
+		return $updated;
784
+	}
785
+
786
+
787
+	/**
788
+	 *    stash_transaction_and_checkout
789
+	 *
790
+	 * @access public
791
+	 * @return    void
792
+	 * @throws \EE_Error
793
+	 */
794
+	public function stash_transaction_and_checkout()
795
+	{
796
+		if (! $this->revisit) {
797
+			$this->update_txn_reg_steps_array();
798
+		}
799
+		$this->track_transaction_and_registration_status_updates();
800
+		// save all data to the db, but suppress errors
801
+		// $this->save_all_data( FALSE );
802
+		// cache the checkout in the session
803
+		EE_Registry::instance()->SSN->set_checkout($this);
804
+	}
805
+
806
+
807
+	/**
808
+	 *    track_transaction_and_registration_status_updates
809
+	 *    stores whether any updates were made to the TXN or it's related registrations
810
+	 *
811
+	 * @access public
812
+	 * @return void
813
+	 * @throws \EE_Error
814
+	 */
815
+	public function track_transaction_and_registration_status_updates()
816
+	{
817
+		// verify the transaction
818
+		if ($this->transaction instanceof EE_Transaction) {
819
+			// has there been a TXN status change during this checkout?
820
+			$this->txn_status_updated = $this->transaction->txn_status_updated();
821
+			/** @type EE_Registration_Processor $registration_processor */
822
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
823
+			// grab the saved registrations from the transaction
824
+			foreach ($this->transaction->registrations($this->reg_cache_where_params) as $registration) {
825
+				if ($registration_processor->reg_status_updated($registration->ID())) {
826
+					$this->set_reg_status_updated($registration->ID(), true);
827
+				}
828
+			}
829
+		}
830
+	}
831
+
832
+
833
+	/**
834
+	 *    visit_allows_processing_of_this_registration
835
+	 *    determines if the current SPCO visit should allow the passed EE_Registration to be used in processing.
836
+	 *    one of the following conditions must be met:
837
+	 *        EITHER:    A) first time thru SPCO -> process ALL registrations ( NOT a revisit )
838
+	 *        OR :        B) primary registrant is editing info -> process ALL registrations ( primary_revisit )
839
+	 *        OR :        C) another registrant is editing info -> ONLY process their registration ( revisit AND their
840
+	 *        reg_url_link matches )
841
+	 *
842
+	 * @access public
843
+	 * @param    EE_Registration $registration
844
+	 * @return    bool
845
+	 * @throws \EE_Error
846
+	 */
847
+	public function visit_allows_processing_of_this_registration(EE_Registration $registration)
848
+	{
849
+		return ! $this->revisit
850
+			   || $this->primary_revisit
851
+			   || (
852
+				   $this->revisit && $this->reg_url_link === $registration->reg_url_link()
853
+			   )
854
+			? true
855
+			: false;
856
+	}
857
+
858
+
859
+	/**
860
+	 *    _transaction_has_primary_registration
861
+	 *
862
+	 * @access        private
863
+	 * @return        bool
864
+	 */
865
+	public function transaction_has_primary_registrant()
866
+	{
867
+		return $this->primary_attendee_obj instanceof EE_Attendee ? true : false;
868
+	}
869
+
870
+
871
+	/**
872
+	 *    save_all_data
873
+	 *    simply loops through the current transaction and saves all data for each registration
874
+	 *
875
+	 * @access public
876
+	 * @param bool $show_errors
877
+	 * @return bool
878
+	 * @throws \EE_Error
879
+	 */
880
+	public function save_all_data($show_errors = true)
881
+	{
882
+		// verify the transaction
883
+		if ($this->transaction instanceof EE_Transaction) {
884
+			// save to ensure that TXN has ID
885
+			$this->transaction->save();
886
+			// grab the saved registrations from the transaction
887
+			foreach ($this->transaction->registrations($this->reg_cache_where_params) as $registration) {
888
+				$this->_save_registration($registration, $show_errors);
889
+			}
890
+		} else {
891
+			if ($show_errors) {
892
+				EE_Error::add_error(
893
+					esc_html__(
894
+						'A valid Transaction was not found when attempting to save your registration information.',
895
+						'event_espresso'
896
+					),
897
+					__FILE__,
898
+					__FUNCTION__,
899
+					__LINE__
900
+				);
901
+			}
902
+			return false;
903
+		}
904
+		return true;
905
+	}
906
+
907
+
908
+	/**
909
+	 * _save_registration_attendee
910
+	 *
911
+	 * @param    EE_Registration $registration
912
+	 * @param bool               $show_errors
913
+	 * @return void
914
+	 * @throws \EE_Error
915
+	 */
916
+	private function _save_registration($registration, $show_errors = true)
917
+	{
918
+		// verify object
919
+		if ($registration instanceof EE_Registration) {
920
+			// should this registration be processed during this visit ?
921
+			if ($this->visit_allows_processing_of_this_registration($registration)) {
922
+				// set TXN ID
923
+				if (! $registration->transaction_ID()) {
924
+					$registration->set_transaction_id($this->transaction->ID());
925
+				}
926
+				// verify and save the attendee
927
+				$this->_save_registration_attendee($registration, $show_errors);
928
+				// save answers to reg form questions
929
+				$this->_save_registration_answers($registration, $show_errors);
930
+				// save changes
931
+				$registration->save();
932
+				// update txn cache
933
+				if (! $this->transaction->update_cache_after_object_save('Registration', $registration)) {
934
+					if ($show_errors) {
935
+						EE_Error::add_error(
936
+							esc_html__(
937
+								'The newly saved Registration object could not be cached on the Transaction.',
938
+								'event_espresso'
939
+							),
940
+							__FILE__,
941
+							__FUNCTION__,
942
+							__LINE__
943
+						);
944
+					}
945
+				}
946
+			}
947
+		} else {
948
+			if ($show_errors) {
949
+				EE_Error::add_error(
950
+					esc_html__(
951
+						'An invalid Registration object was discovered when attempting to save your registration information.',
952
+						'event_espresso'
953
+					),
954
+					__FILE__,
955
+					__FUNCTION__,
956
+					__LINE__
957
+				);
958
+			}
959
+		}
960
+	}
961
+
962
+
963
+	/**
964
+	 * _save_registration_attendee
965
+	 *
966
+	 * @param    EE_Registration $registration
967
+	 * @param bool               $show_errors
968
+	 * @return void
969
+	 * @throws \EE_Error
970
+	 */
971
+	private function _save_registration_attendee($registration, $show_errors = true)
972
+	{
973
+		if ($registration->attendee() instanceof EE_Attendee) {
974
+			// save so that ATT has ID
975
+			$registration->attendee()->save();
976
+			if (! $registration->update_cache_after_object_save('Attendee', $registration->attendee())) {
977
+				if ($show_errors) {
978
+					EE_Error::add_error(
979
+						esc_html__(
980
+							'The newly saved Attendee object could not be cached on the registration.',
981
+							'event_espresso'
982
+						),
983
+						__FILE__,
984
+						__FUNCTION__,
985
+						__LINE__
986
+					);
987
+				}
988
+			}
989
+		} else {
990
+			if ($show_errors) {
991
+				EE_Error::add_error(
992
+					sprintf(
993
+						'%1$s||%1$s $attendee = %2$s',
994
+						esc_html__(
995
+							'Either no Attendee information was found, or an invalid Attendee object was discovered when attempting to save your registration information.',
996
+							'event_espresso'
997
+						),
998
+						var_export($registration->attendee(), true)
999
+					),
1000
+					__FILE__,
1001
+					__FUNCTION__,
1002
+					__LINE__
1003
+				);
1004
+			}
1005
+		}
1006
+	}
1007
+
1008
+
1009
+	/**
1010
+	 * _save_question_answers
1011
+	 *
1012
+	 * @param    EE_Registration $registration
1013
+	 * @param bool               $show_errors
1014
+	 * @return void
1015
+	 * @throws \EE_Error
1016
+	 */
1017
+	private function _save_registration_answers($registration, $show_errors = true)
1018
+	{
1019
+		// now save the answers
1020
+		foreach ($registration->answers() as $cache_key => $answer) {
1021
+			// verify object
1022
+			if ($answer instanceof EE_Answer) {
1023
+				$answer->set_registration($registration->ID());
1024
+				$answer->save();
1025
+				if (! $registration->update_cache_after_object_save('Answer', $answer, $cache_key)) {
1026
+					if ($show_errors) {
1027
+						EE_Error::add_error(
1028
+							esc_html__(
1029
+								'The newly saved Answer object could not be cached on the registration.',
1030
+								'event_espresso'
1031
+							),
1032
+							__FILE__,
1033
+							__FUNCTION__,
1034
+							__LINE__
1035
+						);
1036
+					}
1037
+				}
1038
+			} else {
1039
+				if ($show_errors) {
1040
+					EE_Error::add_error(
1041
+						esc_html__(
1042
+							'An invalid Answer object was discovered when attempting to save your registration information.',
1043
+							'event_espresso'
1044
+						),
1045
+						__FILE__,
1046
+						__FUNCTION__,
1047
+						__LINE__
1048
+					);
1049
+				}
1050
+			}
1051
+		}
1052
+	}
1053
+
1054
+
1055
+	/**
1056
+	 *    refresh_all_entities
1057
+	 *   will either refresh the entity map with objects form the db or from the checkout cache
1058
+	 *
1059
+	 * @access public
1060
+	 * @param bool $from_db
1061
+	 * @return bool
1062
+	 * @throws \EE_Error
1063
+	 */
1064
+	public function refresh_all_entities($from_db = false)
1065
+	{
1066
+		$this->current_step->setRequest(EED_Single_Page_Checkout::getRequest());
1067
+		$from_db = $this->current_step->is_final_step() || $this->action === 'process_gateway_response'
1068
+			? true
1069
+			: $from_db;
1070
+		// $this->log(
1071
+		//     __CLASS__,
1072
+		//     __FUNCTION__,
1073
+		//     __LINE__,
1074
+		//     array('from_db' => $from_db)
1075
+		// );
1076
+		return $from_db ? $this->refresh_from_db() : $this->refresh_entity_map();
1077
+	}
1078
+
1079
+
1080
+	/**
1081
+	 *  refresh_entity_map
1082
+	 *  simply loops through the current transaction and updates each
1083
+	 *  model's entity map using EEM_Base::refresh_entity_map_from_db()
1084
+	 *
1085
+	 * @access public
1086
+	 * @return bool
1087
+	 * @throws \EE_Error
1088
+	 */
1089
+	protected function refresh_from_db()
1090
+	{
1091
+		// verify the transaction
1092
+		if ($this->transaction instanceof EE_Transaction && $this->transaction->ID()) {
1093
+			// pull fresh TXN data from the db
1094
+			$this->transaction = $this->transaction->get_model()->refresh_entity_map_from_db($this->transaction->ID());
1095
+			// update EE_Checkout's cached primary_attendee object
1096
+			$this->primary_attendee_obj = $this->_refresh_primary_attendee_obj_from_db($this->transaction);
1097
+			// update EE_Checkout's cached payment object
1098
+			$payment = $this->transaction->last_payment();
1099
+			$this->payment = $payment instanceof EE_Payment ? $payment : $this->payment;
1100
+			// update EE_Checkout's cached payment_method object
1101
+			$payment_method = $this->payment instanceof EE_Payment ? $this->payment->payment_method() : null;
1102
+			$this->payment_method = $payment_method instanceof EE_Payment_Method ? $payment_method
1103
+				: $this->payment_method;
1104
+			// now refresh the cart, based on the TXN
1105
+			$this->cart = $this->get_cart_for_transaction($this->transaction);
1106
+		} else {
1107
+			EE_Error::add_error(
1108
+				esc_html__(
1109
+					'A valid Transaction was not found when attempting to update the model entity mapper.',
1110
+					'event_espresso'
1111
+				),
1112
+				__FILE__,
1113
+				__FUNCTION__,
1114
+				__LINE__
1115
+			);
1116
+			return false;
1117
+		}
1118
+		return true;
1119
+	}
1120
+
1121
+
1122
+	/**
1123
+	 * _refresh_primary_attendee_obj_from_db
1124
+	 *
1125
+	 * @param   EE_Transaction $transaction
1126
+	 * @return  EE_Attendee | null
1127
+	 * @throws \EE_Error
1128
+	 */
1129
+	protected function _refresh_primary_attendee_obj_from_db(EE_Transaction $transaction)
1130
+	{
1131
+		$primary_attendee_obj = null;
1132
+		// grab the saved registrations from the transaction
1133
+		foreach ($transaction->registrations($this->reg_cache_where_params, true) as $registration) {
1134
+			// verify object
1135
+			if ($registration instanceof EE_Registration) {
1136
+				$attendee = $registration->attendee();
1137
+				// verify object && maybe cache primary_attendee_obj ?
1138
+				if ($attendee instanceof EE_Attendee && $registration->is_primary_registrant()) {
1139
+					$primary_attendee_obj = $attendee;
1140
+				}
1141
+			} else {
1142
+				EE_Error::add_error(
1143
+					esc_html__(
1144
+						'An invalid Registration object was discovered when attempting to update the model entity mapper.',
1145
+						'event_espresso'
1146
+					),
1147
+					__FILE__,
1148
+					__FUNCTION__,
1149
+					__LINE__
1150
+				);
1151
+			}
1152
+		}
1153
+		return $primary_attendee_obj;
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 *  refresh_entity_map
1159
+	 *  simply loops through the current transaction and updates
1160
+	 *  each model's entity map using EEM_Base::refresh_entity_map_with()
1161
+	 *
1162
+	 * @access public
1163
+	 * @return bool
1164
+	 * @throws \EE_Error
1165
+	 */
1166
+	protected function refresh_entity_map()
1167
+	{
1168
+		// verify the transaction
1169
+		if ($this->transaction instanceof EE_Transaction && $this->transaction->ID()) {
1170
+			// never cache payment info
1171
+			$this->transaction->clear_cache('Payment');
1172
+			// is the Payment Options Reg Step completed ?
1173
+			if ($this->transaction->reg_step_completed('payment_options')) {
1174
+				// then check for payments and update TXN accordingly
1175
+				/** @type EE_Transaction_Payments $transaction_payments */
1176
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1177
+				$transaction_payments->calculate_total_payments_and_update_status($this->transaction);
1178
+			}
1179
+			// grab the saved registrations from the transaction
1180
+			foreach ($this->transaction->registrations($this->reg_cache_where_params) as $reg_cache_ID => $registration) {
1181
+				$this->_refresh_registration($reg_cache_ID, $registration);
1182
+			}
1183
+			// make sure our cached TXN is added to the model entity mapper
1184
+			$this->transaction = $this->transaction->get_model()->refresh_entity_map_with(
1185
+				$this->transaction->ID(),
1186
+				$this->transaction
1187
+			);
1188
+		} else {
1189
+			EE_Error::add_error(
1190
+				esc_html__(
1191
+					'A valid Transaction was not found when attempting to update the model entity mapper.',
1192
+					'event_espresso'
1193
+				),
1194
+				__FILE__,
1195
+				__FUNCTION__,
1196
+				__LINE__
1197
+			);
1198
+			return false;
1199
+		}
1200
+		// verify and update the cart because inaccurate totals are not so much fun
1201
+		if ($this->cart instanceof EE_Cart) {
1202
+			$grand_total = $this->cart->get_grand_total();
1203
+			if ($grand_total instanceof EE_Line_Item && $grand_total->ID()) {
1204
+				$grand_total->recalculate_total_including_taxes();
1205
+				$grand_total = $grand_total->get_model()->refresh_entity_map_with(
1206
+					$this->cart->get_grand_total()->ID(),
1207
+					$this->cart->get_grand_total()
1208
+				);
1209
+			}
1210
+			if ($grand_total instanceof EE_Line_Item) {
1211
+				$this->cart = EE_Cart::instance($grand_total);
1212
+			} else {
1213
+				EE_Error::add_error(
1214
+					esc_html__(
1215
+						'A valid Cart was not found when attempting to update the model entity mapper.',
1216
+						'event_espresso'
1217
+					),
1218
+					__FILE__,
1219
+					__FUNCTION__,
1220
+					__LINE__
1221
+				);
1222
+				return false;
1223
+			}
1224
+		}
1225
+		return true;
1226
+	}
1227
+
1228
+
1229
+	/**
1230
+	 * _refresh_registration
1231
+	 *
1232
+	 * @param    string | int    $reg_cache_ID
1233
+	 * @param    EE_Registration $registration
1234
+	 * @return void
1235
+	 * @throws \EE_Error
1236
+	 */
1237
+	protected function _refresh_registration($reg_cache_ID, $registration)
1238
+	{
1239
+
1240
+		// verify object
1241
+		if ($registration instanceof EE_Registration) {
1242
+			// update the entity mapper attendee
1243
+			$this->_refresh_registration_attendee($registration);
1244
+			// update the entity mapper answers for reg form questions
1245
+			$this->_refresh_registration_answers($registration);
1246
+			// make sure the cached registration is added to the model entity mapper
1247
+			$registration->get_model()->refresh_entity_map_with($reg_cache_ID, $registration);
1248
+		} else {
1249
+			EE_Error::add_error(
1250
+				esc_html__(
1251
+					'An invalid Registration object was discovered when attempting to update the model entity mapper.',
1252
+					'event_espresso'
1253
+				),
1254
+				__FILE__,
1255
+				__FUNCTION__,
1256
+				__LINE__
1257
+			);
1258
+		}
1259
+	}
1260
+
1261
+
1262
+	/**
1263
+	 * _save_registration_attendee
1264
+	 *
1265
+	 * @param    EE_Registration $registration
1266
+	 * @return void
1267
+	 * @throws \EE_Error
1268
+	 */
1269
+	protected function _refresh_registration_attendee($registration)
1270
+	{
1271
+		$attendee = $registration->attendee();
1272
+		// verify object
1273
+		if ($attendee instanceof EE_Attendee && $attendee->ID()) {
1274
+			// make sure the cached attendee is added to the model entity mapper
1275
+			$registration->attendee()->get_model()->refresh_entity_map_with($attendee->ID(), $attendee);
1276
+			// maybe cache primary_attendee_obj ?
1277
+			if ($registration->is_primary_registrant()) {
1278
+				$this->primary_attendee_obj = $attendee;
1279
+			}
1280
+		}
1281
+	}
1282
+
1283
+
1284
+	/**
1285
+	 * _refresh_registration_answers
1286
+	 *
1287
+	 * @param    EE_Registration $registration
1288
+	 * @return void
1289
+	 * @throws \EE_Error
1290
+	 */
1291
+	protected function _refresh_registration_answers($registration)
1292
+	{
1293
+
1294
+		// now update the answers
1295
+		foreach ($registration->answers() as $cache_key => $answer) {
1296
+			// verify object
1297
+			if ($answer instanceof EE_Answer) {
1298
+				if ($answer->ID()) {
1299
+					// make sure the cached answer is added to the model entity mapper
1300
+					$answer->get_model()->refresh_entity_map_with($answer->ID(), $answer);
1301
+				}
1302
+			} else {
1303
+				EE_Error::add_error(
1304
+					esc_html__(
1305
+						'An invalid Answer object was discovered when attempting to update the model entity mapper.',
1306
+						'event_espresso'
1307
+					),
1308
+					__FILE__,
1309
+					__FUNCTION__,
1310
+					__LINE__
1311
+				);
1312
+			}
1313
+		}
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 *    __sleep
1319
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
1320
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
1321
+	 * reg form, because if needed, it will be regenerated anyways
1322
+	 *
1323
+	 * @return array
1324
+	 * @throws \EE_Error
1325
+	 */
1326
+	public function __sleep()
1327
+	{
1328
+		if ($this->primary_attendee_obj instanceof EE_Attendee && $this->primary_attendee_obj->ID()) {
1329
+			$this->primary_attendee_obj = $this->primary_attendee_obj->ID();
1330
+		}        // remove the reg form and the checkout
1331
+		if ($this->transaction instanceof EE_Transaction && $this->transaction->ID()) {
1332
+			$this->transaction = $this->transaction->ID();
1333
+		}        // remove the reg form and the checkout
1334
+		return array_diff(array_keys(get_object_vars($this)), array('billing_form', 'registration_form'));
1335
+	}
1336
+
1337
+
1338
+	/**
1339
+	 *    __wakeup
1340
+	 * to conserve db space, we are removing the EE_Checkout object from EE_SPCO_Reg_Step objects upon serialization
1341
+	 * this will reinstate the EE_Checkout object on each EE_SPCO_Reg_Step object
1342
+	 */
1343
+	public function __wakeup()
1344
+	{
1345
+		if (! $this->primary_attendee_obj instanceof EE_Attendee && absint($this->primary_attendee_obj) !== 0) {
1346
+			// $this->primary_attendee_obj is actually just an ID, so use it to get the object from the db
1347
+			$this->primary_attendee_obj = EEM_Attendee::instance()->get_one_by_ID($this->primary_attendee_obj);
1348
+		}
1349
+		if (! $this->transaction instanceof EE_Transaction && absint($this->transaction) !== 0) {
1350
+			// $this->transaction is actually just an ID, so use it to get the object from the db
1351
+			$this->transaction = EEM_Transaction::instance()->get_one_by_ID($this->transaction);
1352
+		}
1353
+		foreach ($this->reg_steps as $reg_step) {
1354
+			$reg_step->checkout = $this;
1355
+		}
1356
+	}
1357
+
1358
+
1359
+	/**
1360
+	 * debug
1361
+	 *
1362
+	 * @param string $class
1363
+	 * @param string $func
1364
+	 * @param string $line
1365
+	 * @param array  $info
1366
+	 * @param bool   $display_request
1367
+	 * @throws \EE_Error
1368
+	 */
1369
+	public function log($class = '', $func = '', $line = '', $info = array(), $display_request = false)
1370
+	{
1371
+		$disabled = true;
1372
+		if (WP_DEBUG && ! $disabled) {
1373
+			$debug_data = get_option('EE_DEBUG_SPCO_' . EE_Session::instance()->id(), array());
1374
+			$default_data = array(
1375
+				$class                    => $func . '() : ' . $line,
1376
+				'request->step'           => $this->step,
1377
+				'request->action'         => $this->action,
1378
+				'current_step->slug'      => $this->current_step instanceof EE_SPCO_Reg_Step ?
1379
+					$this->current_step->slug() : '',
1380
+				'current_step->completed' => $this->current_step instanceof EE_SPCO_Reg_Step ?
1381
+					$this->current_step->completed() : '',
1382
+				'txn_status_updated'      => $this->transaction->txn_status_updated(),
1383
+				'reg_status_updated'      => $this->reg_status_updated,
1384
+				'reg_url_link'            => $this->reg_url_link,
1385
+			);
1386
+			if ($this->transaction instanceof EE_Transaction) {
1387
+				$default_data['TXN_status'] = $this->transaction->status_ID();
1388
+				$default_data['TXN_reg_steps'] = $this->transaction->reg_steps();
1389
+				foreach ($this->transaction->registrations($this->reg_cache_where_params) as $REG_ID => $registration) {
1390
+					$default_data['registrations'][ $REG_ID ] = $registration->status_ID();
1391
+				}
1392
+				if ($this->transaction->ID()) {
1393
+					$TXN_ID = 'EE_Transaction: ' . $this->transaction->ID();
1394
+					// don't serialize objects
1395
+					$info = $this->_strip_objects($info);
1396
+					if (! isset($debug_data[ $TXN_ID ])) {
1397
+						$debug_data[ $TXN_ID ] = array();
1398
+					}
1399
+					$debug_data[ $TXN_ID ][ microtime() ] = array_merge(
1400
+						$default_data,
1401
+						$info
1402
+					);
1403
+					update_option('EE_DEBUG_SPCO_' . EE_Session::instance()->id(), $debug_data);
1404
+				}
1405
+			}
1406
+		}
1407
+	}
1408
+
1409
+
1410
+	/**
1411
+	 * _strip_objects
1412
+	 *
1413
+	 * @param array $info
1414
+	 * @return array
1415
+	 */
1416
+	public function _strip_objects($info = array())
1417
+	{
1418
+		foreach ((array) $info as $key => $value) {
1419
+			if (is_array($value)) {
1420
+				$info[ $key ] = $this->_strip_objects($value);
1421
+			} elseif (is_object($value)) {
1422
+				$object_class = get_class($value);
1423
+				$info[ $object_class ] = array();
1424
+				$info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : 0;
1425
+				if (method_exists($value, 'status')) {
1426
+					$info[ $object_class ]['status'] = $value->status();
1427
+				} elseif (method_exists($value, 'status_ID')) {
1428
+					$info[ $object_class ]['status'] = $value->status_ID();
1429
+				}
1430
+				unset($info[ $key ]);
1431
+			}
1432
+		}
1433
+		return (array) $info;
1434
+	}
1435 1435
 }
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
      */
314 314
     public function reg_status_updated($REG_ID)
315 315
     {
316
-        return isset($this->reg_status_updated[ $REG_ID ]) ? $this->reg_status_updated[ $REG_ID ] : false;
316
+        return isset($this->reg_status_updated[$REG_ID]) ? $this->reg_status_updated[$REG_ID] : false;
317 317
     }
318 318
 
319 319
 
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
      */
324 324
     public function set_reg_status_updated($REG_ID, $reg_status)
325 325
     {
326
-        $this->reg_status_updated[ $REG_ID ] = filter_var($reg_status, FILTER_VALIDATE_BOOLEAN);
326
+        $this->reg_status_updated[$REG_ID] = filter_var($reg_status, FILTER_VALIDATE_BOOLEAN);
327 327
     }
328 328
 
329 329
 
@@ -383,7 +383,7 @@  discard block
 block discarded – undo
383 383
      */
384 384
     public function add_reg_step(EE_SPCO_Reg_Step $reg_step_obj)
385 385
     {
386
-        $this->reg_steps[ $reg_step_obj->slug() ] = $reg_step_obj;
386
+        $this->reg_steps[$reg_step_obj->slug()] = $reg_step_obj;
387 387
     }
388 388
 
389 389
 
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
      */
430 430
     public function remove_reg_step($reg_step_slug = '', $reset = true)
431 431
     {
432
-        unset($this->reg_steps[ $reg_step_slug ]);
432
+        unset($this->reg_steps[$reg_step_slug]);
433 433
         if ($this->transaction instanceof EE_Transaction) {
434 434
             // now remove reg step from TXN and save
435 435
             $this->transaction->remove_reg_step($reg_step_slug);
@@ -451,8 +451,8 @@  discard block
 block discarded – undo
451 451
      */
452 452
     public function set_reg_step_order($reg_step_slug = '', $order = 100)
453 453
     {
454
-        if (isset($this->reg_steps[ $reg_step_slug ])) {
455
-            $this->reg_steps[ $reg_step_slug ]->set_order($order);
454
+        if (isset($this->reg_steps[$reg_step_slug])) {
455
+            $this->reg_steps[$reg_step_slug]->set_order($order);
456 456
         }
457 457
     }
458 458
 
@@ -464,9 +464,9 @@  discard block
 block discarded – undo
464 464
     public function set_current_step(string $current_step)
465 465
     {
466 466
         // grab what step we're on
467
-        $this->current_step = $this->reg_steps[ $current_step ] ?? reset($this->reg_steps);
467
+        $this->current_step = $this->reg_steps[$current_step] ?? reset($this->reg_steps);
468 468
         // verify instance
469
-        if (! $this->current_step instanceof EE_SPCO_Reg_Step)  {
469
+        if ( ! $this->current_step instanceof EE_SPCO_Reg_Step) {
470 470
             EE_Error::add_error(
471 471
                 esc_html__('The current step could not be set.', 'event_espresso'),
472 472
                 __FILE__,
@@ -572,7 +572,7 @@  discard block
 block discarded – undo
572 572
      */
573 573
     public function find_reg_step($reg_step_slug = '')
574 574
     {
575
-        if (! empty($reg_step_slug)) {
575
+        if ( ! empty($reg_step_slug)) {
576 576
             // copy reg step array
577 577
             $reg_steps = $this->reg_steps;
578 578
             // set pointer to start of array
@@ -634,7 +634,7 @@  discard block
 block discarded – undo
634 634
             )
635 635
         ) {
636 636
             // set the start time for this reg step
637
-            if (! $this->transaction->set_reg_step_initiated($reg_step->slug())) {
637
+            if ( ! $this->transaction->set_reg_step_initiated($reg_step->slug())) {
638 638
                 if (WP_DEBUG) {
639 639
                     EE_Error::add_error(
640 640
                         sprintf(
@@ -736,7 +736,7 @@  discard block
 block discarded – undo
736 736
         $session = EE_Registry::instance()->load_core('Session');
737 737
         $cart = $transaction instanceof EE_Transaction ? EE_Cart::get_cart_from_txn($transaction, $session) : null;
738 738
         // verify cart
739
-        if (! $cart instanceof EE_Cart) {
739
+        if ( ! $cart instanceof EE_Cart) {
740 740
             $cart = EE_Registry::instance()->load_core('Cart');
741 741
         }
742 742
 
@@ -754,7 +754,7 @@  discard block
 block discarded – undo
754 754
     {
755 755
         $txn_reg_steps_array = array();
756 756
         foreach ($this->reg_steps as $reg_step) {
757
-            $txn_reg_steps_array[ $reg_step->slug() ] = false;
757
+            $txn_reg_steps_array[$reg_step->slug()] = false;
758 758
         }
759 759
         return $txn_reg_steps_array;
760 760
     }
@@ -793,7 +793,7 @@  discard block
 block discarded – undo
793 793
      */
794 794
     public function stash_transaction_and_checkout()
795 795
     {
796
-        if (! $this->revisit) {
796
+        if ( ! $this->revisit) {
797 797
             $this->update_txn_reg_steps_array();
798 798
         }
799 799
         $this->track_transaction_and_registration_status_updates();
@@ -920,7 +920,7 @@  discard block
 block discarded – undo
920 920
             // should this registration be processed during this visit ?
921 921
             if ($this->visit_allows_processing_of_this_registration($registration)) {
922 922
                 // set TXN ID
923
-                if (! $registration->transaction_ID()) {
923
+                if ( ! $registration->transaction_ID()) {
924 924
                     $registration->set_transaction_id($this->transaction->ID());
925 925
                 }
926 926
                 // verify and save the attendee
@@ -930,7 +930,7 @@  discard block
 block discarded – undo
930 930
                 // save changes
931 931
                 $registration->save();
932 932
                 // update txn cache
933
-                if (! $this->transaction->update_cache_after_object_save('Registration', $registration)) {
933
+                if ( ! $this->transaction->update_cache_after_object_save('Registration', $registration)) {
934 934
                     if ($show_errors) {
935 935
                         EE_Error::add_error(
936 936
                             esc_html__(
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
         if ($registration->attendee() instanceof EE_Attendee) {
974 974
             // save so that ATT has ID
975 975
             $registration->attendee()->save();
976
-            if (! $registration->update_cache_after_object_save('Attendee', $registration->attendee())) {
976
+            if ( ! $registration->update_cache_after_object_save('Attendee', $registration->attendee())) {
977 977
                 if ($show_errors) {
978 978
                     EE_Error::add_error(
979 979
                         esc_html__(
@@ -1022,7 +1022,7 @@  discard block
 block discarded – undo
1022 1022
             if ($answer instanceof EE_Answer) {
1023 1023
                 $answer->set_registration($registration->ID());
1024 1024
                 $answer->save();
1025
-                if (! $registration->update_cache_after_object_save('Answer', $answer, $cache_key)) {
1025
+                if ( ! $registration->update_cache_after_object_save('Answer', $answer, $cache_key)) {
1026 1026
                     if ($show_errors) {
1027 1027
                         EE_Error::add_error(
1028 1028
                             esc_html__(
@@ -1342,11 +1342,11 @@  discard block
 block discarded – undo
1342 1342
      */
1343 1343
     public function __wakeup()
1344 1344
     {
1345
-        if (! $this->primary_attendee_obj instanceof EE_Attendee && absint($this->primary_attendee_obj) !== 0) {
1345
+        if ( ! $this->primary_attendee_obj instanceof EE_Attendee && absint($this->primary_attendee_obj) !== 0) {
1346 1346
             // $this->primary_attendee_obj is actually just an ID, so use it to get the object from the db
1347 1347
             $this->primary_attendee_obj = EEM_Attendee::instance()->get_one_by_ID($this->primary_attendee_obj);
1348 1348
         }
1349
-        if (! $this->transaction instanceof EE_Transaction && absint($this->transaction) !== 0) {
1349
+        if ( ! $this->transaction instanceof EE_Transaction && absint($this->transaction) !== 0) {
1350 1350
             // $this->transaction is actually just an ID, so use it to get the object from the db
1351 1351
             $this->transaction = EEM_Transaction::instance()->get_one_by_ID($this->transaction);
1352 1352
         }
@@ -1370,9 +1370,9 @@  discard block
 block discarded – undo
1370 1370
     {
1371 1371
         $disabled = true;
1372 1372
         if (WP_DEBUG && ! $disabled) {
1373
-            $debug_data = get_option('EE_DEBUG_SPCO_' . EE_Session::instance()->id(), array());
1373
+            $debug_data = get_option('EE_DEBUG_SPCO_'.EE_Session::instance()->id(), array());
1374 1374
             $default_data = array(
1375
-                $class                    => $func . '() : ' . $line,
1375
+                $class                    => $func.'() : '.$line,
1376 1376
                 'request->step'           => $this->step,
1377 1377
                 'request->action'         => $this->action,
1378 1378
                 'current_step->slug'      => $this->current_step instanceof EE_SPCO_Reg_Step ?
@@ -1387,20 +1387,20 @@  discard block
 block discarded – undo
1387 1387
                 $default_data['TXN_status'] = $this->transaction->status_ID();
1388 1388
                 $default_data['TXN_reg_steps'] = $this->transaction->reg_steps();
1389 1389
                 foreach ($this->transaction->registrations($this->reg_cache_where_params) as $REG_ID => $registration) {
1390
-                    $default_data['registrations'][ $REG_ID ] = $registration->status_ID();
1390
+                    $default_data['registrations'][$REG_ID] = $registration->status_ID();
1391 1391
                 }
1392 1392
                 if ($this->transaction->ID()) {
1393
-                    $TXN_ID = 'EE_Transaction: ' . $this->transaction->ID();
1393
+                    $TXN_ID = 'EE_Transaction: '.$this->transaction->ID();
1394 1394
                     // don't serialize objects
1395 1395
                     $info = $this->_strip_objects($info);
1396
-                    if (! isset($debug_data[ $TXN_ID ])) {
1397
-                        $debug_data[ $TXN_ID ] = array();
1396
+                    if ( ! isset($debug_data[$TXN_ID])) {
1397
+                        $debug_data[$TXN_ID] = array();
1398 1398
                     }
1399
-                    $debug_data[ $TXN_ID ][ microtime() ] = array_merge(
1399
+                    $debug_data[$TXN_ID][microtime()] = array_merge(
1400 1400
                         $default_data,
1401 1401
                         $info
1402 1402
                     );
1403
-                    update_option('EE_DEBUG_SPCO_' . EE_Session::instance()->id(), $debug_data);
1403
+                    update_option('EE_DEBUG_SPCO_'.EE_Session::instance()->id(), $debug_data);
1404 1404
                 }
1405 1405
             }
1406 1406
         }
@@ -1417,17 +1417,17 @@  discard block
 block discarded – undo
1417 1417
     {
1418 1418
         foreach ((array) $info as $key => $value) {
1419 1419
             if (is_array($value)) {
1420
-                $info[ $key ] = $this->_strip_objects($value);
1420
+                $info[$key] = $this->_strip_objects($value);
1421 1421
             } elseif (is_object($value)) {
1422 1422
                 $object_class = get_class($value);
1423
-                $info[ $object_class ] = array();
1424
-                $info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : 0;
1423
+                $info[$object_class] = array();
1424
+                $info[$object_class]['ID'] = method_exists($value, 'ID') ? $value->ID() : 0;
1425 1425
                 if (method_exists($value, 'status')) {
1426
-                    $info[ $object_class ]['status'] = $value->status();
1426
+                    $info[$object_class]['status'] = $value->status();
1427 1427
                 } elseif (method_exists($value, 'status_ID')) {
1428
-                    $info[ $object_class ]['status'] = $value->status_ID();
1428
+                    $info[$object_class]['status'] = $value->status_ID();
1429 1429
                 }
1430
-                unset($info[ $key ]);
1430
+                unset($info[$key]);
1431 1431
             }
1432 1432
         }
1433 1433
         return (array) $info;
Please login to merge, or discard this patch.
modules/invalid_checkout_access/EED_Invalid_Checkout_Access.module.php 2 patches
Indentation   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -13,84 +13,84 @@
 block discarded – undo
13 13
  */
14 14
 class EED_Invalid_Checkout_Access extends EED_Module
15 15
 {
16
-    /**
17
-     * @var InvalidCheckoutAccess $invalid_checkout_access_form
18
-     */
19
-    private static $invalid_checkout_access_form;
16
+	/**
17
+	 * @var InvalidCheckoutAccess $invalid_checkout_access_form
18
+	 */
19
+	private static $invalid_checkout_access_form;
20 20
 
21
-    /**
22
-     * set_hooks - for hooking into EE Core, other modules, etc
23
-     */
24
-    public static function set_hooks()
25
-    {
26
-    }
21
+	/**
22
+	 * set_hooks - for hooking into EE Core, other modules, etc
23
+	 */
24
+	public static function set_hooks()
25
+	{
26
+	}
27 27
 
28 28
 
29
-    /**
30
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
31
-     */
32
-    public static function set_hooks_admin()
33
-    {
34
-        add_action(
35
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
36
-            array('EED_Invalid_Checkout_Access', 'display_invalid_checkout_access_form'),
37
-            15
38
-        );
39
-        add_filter(
40
-            'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
41
-            array('EED_Invalid_Checkout_Access', 'process_invalid_checkout_access_form')
42
-        );
43
-    }
29
+	/**
30
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
31
+	 */
32
+	public static function set_hooks_admin()
33
+	{
34
+		add_action(
35
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
36
+			array('EED_Invalid_Checkout_Access', 'display_invalid_checkout_access_form'),
37
+			15
38
+		);
39
+		add_filter(
40
+			'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
41
+			array('EED_Invalid_Checkout_Access', 'process_invalid_checkout_access_form')
42
+		);
43
+	}
44 44
 
45 45
 
46
-    /**
47
-     * run - initial module setup
48
-     * this method is primarily used for activating resources in the EE_Front_Controller thru the use of filters
49
-     *
50
-     * @var WP $WP
51
-     */
52
-    public function run($WP)
53
-    {
54
-        // TODO: Implement run() method.
55
-    }
46
+	/**
47
+	 * run - initial module setup
48
+	 * this method is primarily used for activating resources in the EE_Front_Controller thru the use of filters
49
+	 *
50
+	 * @var WP $WP
51
+	 */
52
+	public function run($WP)
53
+	{
54
+		// TODO: Implement run() method.
55
+	}
56 56
 
57 57
 
58
-    /**
59
-     * @return InvalidCheckoutAccess
60
-     */
61
-    public static function getInvalidCheckoutAccess(): InvalidCheckoutAccess
62
-    {
63
-        if (! self::$invalid_checkout_access_form instanceof InvalidCheckoutAccess) {
64
-            self::$invalid_checkout_access_form = new InvalidCheckoutAccess();
65
-        }
66
-        return self::$invalid_checkout_access_form;
67
-    }
58
+	/**
59
+	 * @return InvalidCheckoutAccess
60
+	 */
61
+	public static function getInvalidCheckoutAccess(): InvalidCheckoutAccess
62
+	{
63
+		if (! self::$invalid_checkout_access_form instanceof InvalidCheckoutAccess) {
64
+			self::$invalid_checkout_access_form = new InvalidCheckoutAccess();
65
+		}
66
+		return self::$invalid_checkout_access_form;
67
+	}
68 68
 
69 69
 
70
-    /**
71
-     * email_validation_settings_form
72
-     *
73
-     * @return    void
74
-     * @throws EE_Error
75
-     */
76
-    public static function display_invalid_checkout_access_form()
77
-    {
78
-        $invalid_checkout_access_form = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
79
-        echo wp_kses($invalid_checkout_access_form->getForm()->get_html(), AllowedTags::getWithFormTags());
80
-    }
70
+	/**
71
+	 * email_validation_settings_form
72
+	 *
73
+	 * @return    void
74
+	 * @throws EE_Error
75
+	 */
76
+	public static function display_invalid_checkout_access_form()
77
+	{
78
+		$invalid_checkout_access_form = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
79
+		echo wp_kses($invalid_checkout_access_form->getForm()->get_html(), AllowedTags::getWithFormTags());
80
+	}
81 81
 
82 82
 
83
-    /**
84
-     * email_validation_settings_form
85
-     *
86
-     * @param EE_Registration_Config $EE_Registration_Config
87
-     * @return EE_Registration_Config
88
-     * @throws EE_Error
89
-     * @throws ReflectionException
90
-     */
91
-    public static function process_invalid_checkout_access_form(EE_Registration_Config $EE_Registration_Config)
92
-    {
93
-        $invalid_checkout_access_form = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
94
-        return $invalid_checkout_access_form->processForm($EE_Registration_Config);
95
-    }
83
+	/**
84
+	 * email_validation_settings_form
85
+	 *
86
+	 * @param EE_Registration_Config $EE_Registration_Config
87
+	 * @return EE_Registration_Config
88
+	 * @throws EE_Error
89
+	 * @throws ReflectionException
90
+	 */
91
+	public static function process_invalid_checkout_access_form(EE_Registration_Config $EE_Registration_Config)
92
+	{
93
+		$invalid_checkout_access_form = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
94
+		return $invalid_checkout_access_form->processForm($EE_Registration_Config);
95
+	}
96 96
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -60,7 +60,7 @@
 block discarded – undo
60 60
      */
61 61
     public static function getInvalidCheckoutAccess(): InvalidCheckoutAccess
62 62
     {
63
-        if (! self::$invalid_checkout_access_form instanceof InvalidCheckoutAccess) {
63
+        if ( ! self::$invalid_checkout_access_form instanceof InvalidCheckoutAccess) {
64 64
             self::$invalid_checkout_access_form = new InvalidCheckoutAccess();
65 65
         }
66 66
         return self::$invalid_checkout_access_form;
Please login to merge, or discard this patch.