Completed
Branch master (59af22)
by
unknown
07:35 queued 03:06
created
PaymentMethods/PayPalCommerce/modules/EED_PayPalCommerce.module.php 2 patches
Indentation   +486 added lines, -486 removed lines patch added patch discarded remove patch
@@ -22,490 +22,490 @@
 block discarded – undo
22 22
  */
23 23
 class EED_PayPalCommerce extends EED_Module
24 24
 {
25
-    /**
26
-     * @return EED_Module
27
-     * @throws EE_Error
28
-     * @throws ReflectionException
29
-     */
30
-    public static function instance(): EED_Module
31
-    {
32
-        return parent::get_instance(__CLASS__);
33
-    }
34
-
35
-
36
-    /**
37
-     * Run - initial module setup.
38
-     *
39
-     * @param WP $WP
40
-     * @return void
41
-     */
42
-    public function run($WP)
43
-    {
44
-    }
45
-
46
-
47
-    /**
48
-     * For hooking into EE Core and other modules.
49
-     *
50
-     * @return void
51
-     */
52
-    public static function set_hooks(): void
53
-    {
54
-        if (DbStatus::isOnline()) {
55
-            // Don't load PM on the front-end if not Connected.
56
-            add_filter(
57
-                'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
58
-                [__CLASS__, 'filterPaymentMethods'],
59
-                100
60
-            );
61
-        }
62
-    }
63
-
64
-
65
-    /**
66
-     * For hooking into EE Core and other modules Admin.
67
-     *
68
-     * @return void
69
-     */
70
-    public static function set_hooks_admin(): void
71
-    {
72
-        if (DbStatus::isOnline()) {
73
-            // Create an Order.
74
-            add_action('wp_ajax_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
75
-            add_action('wp_ajax_nopriv_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
76
-            // Capture the Order.
77
-            add_action('wp_ajax_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
78
-            add_action('wp_ajax_nopriv_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
79
-            // Log errors from the JS side.
80
-            add_action('wp_ajax_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
81
-            add_action('wp_ajax_nopriv_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
82
-            // Don't load PM in the admin if not Connected.
83
-            add_filter(
84
-                'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
85
-                [__CLASS__, 'filterPaymentMethods'],
86
-                100
87
-            );
88
-        }
89
-    }
90
-
91
-
92
-    /**
93
-     * Create the order and return its data as JSON.
94
-     * (AJAX)
95
-     *
96
-     * @return void
97
-     * @throws EE_Error
98
-     * @throws ReflectionException
99
-     */
100
-    public static function createOrderRequest(): void
101
-    {
102
-        $paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
103
-        $post_params = EED_Module::getRequest()->postParams();
104
-        if (! $paypal_pm instanceof EE_Payment_Method) {
105
-            PayPalLogger::errorLogAndExit(
106
-                esc_html__('Related payment method not found (create Order).', 'event_espresso'),
107
-                $post_params
108
-            );
109
-        }
110
-        $transaction  = EED_PayPalCommerce::getTransaction();
111
-        $billing_info = $post_params['billing_info'] ?? [];
112
-        if ($billing_info) {
113
-            $billing_info_decoded = json_decode(stripslashes($billing_info), true);
114
-            $billing_info         = is_array($billing_info_decoded) ? $billing_info_decoded : [];
115
-        }
116
-        if (! $transaction) {
117
-            PayPalLogger::errorLogAndExit(
118
-                esc_html__('Transaction info not found.', 'event_espresso'),
119
-                $post_params,
120
-                $paypal_pm
121
-            );
122
-        }
123
-        $order_data = EED_PayPalCommerce::createOrder($transaction, $billing_info, $paypal_pm);
124
-        wp_send_json($order_data);
125
-    }
126
-
127
-
128
-    /**
129
-     * Capture the order and return status in JSON.
130
-     * (AJAX)
131
-     *
132
-     * @return void
133
-     */
134
-    public static function captureOrderRequest(): void
135
-    {
136
-        $error_message = false;
137
-        $paypal_pm     = EED_PayPalCommerce::getPaymentMethod();
138
-        if (! $paypal_pm instanceof EE_Payment_Method) {
139
-            $error_message = esc_html__(
140
-                'Payment method could not be found while trying to capture the Order.',
141
-                'event_espresso'
142
-            );
143
-        }
144
-        $transaction = EED_PayPalCommerce::getTransaction();
145
-        if (! $transaction) {
146
-            $error_message = esc_html__(
147
-                'Could not process this payment because it has no associated transaction.',
148
-                'event_espresso'
149
-            );
150
-        }
151
-        $order_id = EED_Module::getRequest()->getRequestParam('order_id');
152
-        if (! $order_id) {
153
-            $error_message = esc_html__('Order ID missing.', 'event_espresso');
154
-        }
155
-        // Check for the payment nonce.
156
-        // $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
157
-        // $order_nonce = $request->getRequestParam('pp_order_nonce');
158
-        // if (empty($order_nonce) || ! wp_verify_nonce($order_nonce, Domain::CAPTURE_ORDER_NONCE_NAME)) {
159
-        //     $error_message = esc_html__('No or incorrect order capture nonce provided !', 'event_espresso');
160
-        //     return EEG_PayPalCheckout::updatePaymentStatus($payment, $failed_status, $request->postParams(), $error_message);
161
-        // }
162
-        $billing_info         = EED_Module::getRequest()->getRequestParam('billing_info');
163
-        $billing_info_decoded = json_decode(stripslashes($billing_info), true);
164
-        $billing_info         = is_array($billing_info_decoded) ? $billing_info_decoded : [];
165
-        if (! $billing_info) {
166
-            $error_message = esc_html__('Billing info missing.', 'event_espresso');
167
-        }
168
-        // We had an error. Log and EXIT.
169
-        if ($error_message) {
170
-            PayPalLogger::errorLogAndExit($error_message, EED_Module::getRequest()->postParams(), $paypal_pm);
171
-        }
172
-        try {
173
-            $capture_response = EED_PayPalCommerce::captureOrder($transaction, $paypal_pm, $order_id, $billing_info);
174
-        } catch (Exception $e) {
175
-            $capture_response = [
176
-                'error'   => 'CAPTURE_ORDER_ERROR',
177
-                'message' => $e->getMessage(),
178
-            ];
179
-        }
180
-        wp_send_json($capture_response);
181
-    }
182
-
183
-
184
-    /**
185
-     * Create a new Order using the PP API.
186
-     *
187
-     * @param EE_Transaction    $transaction
188
-     * @param array             $billing_info
189
-     * @param EE_Payment_Method $paypal_pm
190
-     * @return array
191
-     * @throws EE_Error
192
-     * @throws ReflectionException
193
-     */
194
-    public static function createOrder(
195
-        EE_Transaction $transaction,
196
-        array $billing_info,
197
-        EE_Payment_Method $paypal_pm
198
-    ): array {
199
-        $create_order_api = EED_PayPalCommerce::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
200
-        if (! $create_order_api instanceof CreateOrder) {
201
-            return [
202
-                'error'   => 'CREATE_ORDER_API_FAULT',
203
-                'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
204
-            ];
205
-        }
206
-        $payment = EEG_PayPalCheckout::createPayment($transaction, $paypal_pm);
207
-        $order   = $create_order_api->create();
208
-        if (isset($order['error'])) {
209
-            EEG_PayPalCheckout::updatePaymentStatus($payment, EEM_Payment::status_id_failed, $order, $order['error']);
210
-            return [
211
-                'error'   => 'CREATE_ORDER_API_RESPONSE_ERROR',
212
-                'message' => $order['message'],
213
-            ];
214
-        }
215
-        return [
216
-            'pp_order_id' => $order['id'],
217
-        ];
218
-    }
219
-
220
-
221
-    /**
222
-     * Create a new Order using the PP API.
223
-     *
224
-     * @param EE_Transaction    $transaction
225
-     * @param EE_Payment_Method $paypal_pm
226
-     * @param string            $order_id
227
-     * @param array             $billing_info
228
-     * @return array
229
-     * @throws EE_Error
230
-     * @throws ReflectionException
231
-     */
232
-    public static function captureOrder(
233
-        EE_Transaction $transaction,
234
-        EE_Payment_Method $paypal_pm,
235
-        string            $order_id,
236
-        array             $billing_info
237
-    ): array {
238
-        $capture_order_api = EED_PayPalCommerce::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
239
-        if (! $capture_order_api instanceof CaptureOrder) {
240
-            return [
241
-                'error'   => 'CAPTURE_ORDER_API_FAULT',
242
-                'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
243
-            ];
244
-        }
245
-        $payment = $transaction->last_payment() ?? EEG_PayPalCheckout::createPayment($transaction, $paypal_pm);
246
-        $order   = $capture_order_api->capture();
247
-        if (isset($order['error'])) {
248
-            EEG_PayPalCheckout::updatePaymentStatus($payment, EEM_Payment::status_id_failed, $order, $order['error']);
249
-            return $order;
250
-        }
251
-        // Attach the transaction ID to this order.
252
-        try {
253
-            $order['ee_txn_id'] = $transaction->ID();
254
-        } catch (Exception $e) {
255
-            // Just don't set the txn id.
256
-        }
257
-        $order_status = EEG_PayPalCheckout::isOrderCompleted($order);
258
-        if ($order_status['completed']) {
259
-            // Order captured, so payment was successful.
260
-            $update_message = esc_html__('Order captured successfully.', 'event_espresso');
261
-            EEG_PayPalCheckout::updatePaymentStatus($payment, EEM_Payment::status_id_approved, $order, $update_message);
262
-        } else {
263
-            EEG_PayPalCheckout::updatePaymentStatus(
264
-                $payment,
265
-                EEM_Payment::status_id_failed,
266
-                $order,
267
-                $order_status['message']
268
-            );
269
-        }
270
-        EEG_PayPalCheckout::saveBillingDetails($payment, $transaction, $order, $billing_info);
271
-        $nonce = wp_create_nonce(Domain::CAPTURE_ORDER_NONCE_NAME);
272
-        return [
273
-            'pp_order_nonce'  => $nonce,
274
-            'pp_order_id'     => $order['id'],
275
-            'pp_order_status' => $order['purchase_units'][0]['payments']['captures'][0]['status'] ?? 'ORDER_STATUS_UNKNOWN',
276
-            'pp_order_amount' => $order['purchase_units'][0]['payments']['captures'][0]['amount']['value'] ?? '',
277
-        ];
278
-    }
279
-
280
-
281
-    /**
282
-     * Create an Order for this transaction.
283
-     *
284
-     * @param EE_Transaction    $transaction
285
-     * @param array             $billing_info
286
-     * @param EE_Payment_Method $paypal_pm
287
-     * @return CreateOrder|null
288
-     * @throws EE_Error
289
-     * @throws ReflectionException
290
-     */
291
-    public static function getCreateOrderApi(
292
-        EE_Transaction $transaction,
293
-        array $billing_info,
294
-        EE_Payment_Method $paypal_pm
295
-    ): ?CreateOrder {
296
-        $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
297
-        if (! $paypal_api instanceof PayPalApi) {
298
-            return null;
299
-        }
300
-        return LoaderFactory::getNew(CreateOrder::class, [$paypal_api, $transaction, $billing_info]);
301
-    }
302
-
303
-
304
-    /**
305
-     * Create an Order for this transaction.
306
-     *
307
-     * @param EE_Transaction    $transaction
308
-     * @param EE_Payment_Method $paypal_pm
309
-     * @param string            $order_id
310
-     * @return CaptureOrder|null
311
-     * @throws EE_Error
312
-     * @throws ReflectionException
313
-     */
314
-    public static function getCaptureOrderApi(
315
-        EE_Transaction $transaction,
316
-        EE_Payment_Method $paypal_pm,
317
-        string $order_id
318
-    ): ?CaptureOrder {
319
-        $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
320
-        if (! $paypal_api instanceof PayPalApi) {
321
-            return null;
322
-        }
323
-        return LoaderFactory::getNew(CaptureOrder::class, [$paypal_api, $transaction, $order_id]);
324
-    }
325
-
326
-
327
-    /**
328
-     * Return a PayPal API object, or false on failure.
329
-     *
330
-     * @param EE_Payment_Method $paypal_pm
331
-     * @return PayPalApi|null
332
-     * @throws EE_Error
333
-     * @throws ReflectionException
334
-     */
335
-    public static function getPayPalApi(EE_Payment_Method $paypal_pm): ?PayPalApi
336
-    {
337
-        // Try getting the first party credentials to determine if this is a first party integration that's active.
338
-        $client_id     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_ID);
339
-        $client_secret = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_SECRET);
340
-        $bn_code       = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
341
-        if ($client_id && $client_secret) {
342
-            return new FirstPartyPayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
343
-        }
344
-        // Third party integration credentials:
345
-        $access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
346
-        if (! $access_token || ! $bn_code) {
347
-            return null;
348
-        }
349
-        $partner_client_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_CLIENT_ID) ?: '';
350
-        $payer_id          = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_MERCHANT_ID) ?: '';
351
-        return new ThirdPartyPayPalApi(
352
-            $access_token, $bn_code, $partner_client_id, $payer_id, $paypal_pm->debug_mode()
353
-        );
354
-    }
355
-
356
-
357
-    /**
358
-     * Requests a client token.
359
-     *
360
-     * @param EE_Payment_Method $paypal_pm
361
-     * @return array
362
-     * @throws EE_Error
363
-     * @throws ReflectionException
364
-     */
365
-    public static function requestClientToken(EE_Payment_Method $paypal_pm): array
366
-    {
367
-        $error      = ['error' => 'GET_CLIENT_TOKEN_FAULT'];
368
-        $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
369
-        if (! $paypal_api instanceof PayPalApi) {
370
-            $error['message'] = esc_html__('Got an error while trying to get the client token.', 'event_espresso');
371
-            return $error;
372
-        }
373
-        $client_token_api = new ClientToken($paypal_api, $paypal_pm->debug_mode());
374
-        $client_token     = $client_token_api->getToken();
375
-        if (isset($client_token['error'])) {
376
-            return $client_token;
377
-        }
378
-        if (empty($client_token)) {
379
-            $error['message'] = esc_html__('Client token not valid.', 'event_espresso');
380
-            return $error;
381
-        }
382
-        return $client_token;
383
-    }
384
-
385
-
386
-    /**
387
-     * Retrieve the payment method from the provided data.
388
-     *
389
-     * @return EE_Transaction|null
390
-     */
391
-    public static function getTransaction(): ?EE_Transaction
392
-    {
393
-        try {
394
-            $txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
395
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
396
-            if (! $transaction instanceof EE_Transaction) {
397
-                PayPalLogger::errorLog(
398
-                    esc_html__('No transaction found by ID:', 'event_espresso'),
399
-                    EED_Module::getRequest()->postParams()
400
-                );
401
-                return null;
402
-            }
403
-        } catch (Exception $e) {
404
-            return null;
405
-        }
406
-        return $transaction;
407
-    }
408
-
409
-
410
-    /**
411
-     * Return a PayPal API object, or false on failure.
412
-     *
413
-     * @param EE_Payment_Method $paypal_pm
414
-     * @return bool
415
-     * @throws EE_Error
416
-     * @throws ReflectionException
417
-     */
418
-    public static function isThirdParty(EE_Payment_Method $paypal_pm): bool
419
-    {
420
-        $pp_meta_data = PayPalExtraMetaManager::getAllData($paypal_pm);
421
-        return ! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
422
-            && ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ]);
423
-    }
424
-
425
-
426
-    /**
427
-     * Retrieve the payment method from the provided data.
428
-     *
429
-     * @return EE_Payment_Method|null
430
-     */
431
-    public static function getPaymentMethod(): ?EE_Payment_Method
432
-    {
433
-        try {
434
-            // Check if all required parameters are present.
435
-            $pm_slug        = EED_Module::getRequest()->getRequestParam('payment_method');
436
-            $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_slug);
437
-            if ($payment_method instanceof EE_Payment_Method) {
438
-                return $payment_method;
439
-            }
440
-        } catch (Exception $e) {
441
-            return null;
442
-        }
443
-        return null;
444
-    }
445
-
446
-
447
-    /**
448
-     * Log JS error.
449
-     *
450
-     * @return void
451
-     */
452
-    public static function logJsError(): void
453
-    {
454
-        // Default to the "first" PayPal checkout PM.
455
-        $request        = EED_Module::getRequest();
456
-        $pm_slug        = $request->getRequestParam('pm_slug', Domain::PM_SLUG);
457
-        $payment_method = null;
458
-        $txn_id         = 'unknown';
459
-        try {
460
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pm_slug);
461
-            $txn_id         = sanitize_text_field($request->getRequestParam('txn_id', '-'));
462
-        } catch (Exception $e) {
463
-            // Don't throw out anything, log at least something.
464
-        }
465
-        PayPalLogger::errorLog("JS Error on transaction: $txn_id", $request->postParams(), $payment_method);
466
-    }
467
-
468
-
469
-    /**
470
-     * Filter the Payment Methods list.
471
-     * if needed, this filter can also supply the $transaction and $scope parameters.
472
-     *
473
-     * @param EE_Payment_Method[] $payment_methods
474
-     * @return array
475
-     * @throws EE_Error
476
-     * @throws ReflectionException
477
-     */
478
-    public static function filterPaymentMethods(array $payment_methods): array
479
-    {
480
-        // Don't allow this PM on the checkout page if not Connected.
481
-        foreach ($payment_methods as $key => $pm) {
482
-            // It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
483
-            if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
484
-                unset($payment_methods[ $key ]);
485
-            }
486
-        }
487
-        return $payment_methods;
488
-    }
489
-
490
-
491
-    /**
492
-     *  Get all active states.
493
-     *
494
-     * @return array
495
-     * @throws EE_Error
496
-     * @throws ReflectionException
497
-     */
498
-    public static function getActiveStates(): array
499
-    {
500
-        $state_options = [];
501
-        $states        = EEM_State::instance()->get_all_active_states();
502
-        if (! empty($states)) {
503
-            foreach ($states as $numeral => $state) {
504
-                if ($state instanceof EE_State) {
505
-                    $state_options[ $numeral ] = $state->abbrev();
506
-                }
507
-            }
508
-        }
509
-        return $state_options;
510
-    }
25
+	/**
26
+	 * @return EED_Module
27
+	 * @throws EE_Error
28
+	 * @throws ReflectionException
29
+	 */
30
+	public static function instance(): EED_Module
31
+	{
32
+		return parent::get_instance(__CLASS__);
33
+	}
34
+
35
+
36
+	/**
37
+	 * Run - initial module setup.
38
+	 *
39
+	 * @param WP $WP
40
+	 * @return void
41
+	 */
42
+	public function run($WP)
43
+	{
44
+	}
45
+
46
+
47
+	/**
48
+	 * For hooking into EE Core and other modules.
49
+	 *
50
+	 * @return void
51
+	 */
52
+	public static function set_hooks(): void
53
+	{
54
+		if (DbStatus::isOnline()) {
55
+			// Don't load PM on the front-end if not Connected.
56
+			add_filter(
57
+				'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
58
+				[__CLASS__, 'filterPaymentMethods'],
59
+				100
60
+			);
61
+		}
62
+	}
63
+
64
+
65
+	/**
66
+	 * For hooking into EE Core and other modules Admin.
67
+	 *
68
+	 * @return void
69
+	 */
70
+	public static function set_hooks_admin(): void
71
+	{
72
+		if (DbStatus::isOnline()) {
73
+			// Create an Order.
74
+			add_action('wp_ajax_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
75
+			add_action('wp_ajax_nopriv_eeaPPCCreateOrder', [__CLASS__, 'createOrderRequest']);
76
+			// Capture the Order.
77
+			add_action('wp_ajax_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
78
+			add_action('wp_ajax_nopriv_eeaPPCCaptureOrder', [__CLASS__, 'captureOrderRequest']);
79
+			// Log errors from the JS side.
80
+			add_action('wp_ajax_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
81
+			add_action('wp_ajax_nopriv_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
82
+			// Don't load PM in the admin if not Connected.
83
+			add_filter(
84
+				'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
85
+				[__CLASS__, 'filterPaymentMethods'],
86
+				100
87
+			);
88
+		}
89
+	}
90
+
91
+
92
+	/**
93
+	 * Create the order and return its data as JSON.
94
+	 * (AJAX)
95
+	 *
96
+	 * @return void
97
+	 * @throws EE_Error
98
+	 * @throws ReflectionException
99
+	 */
100
+	public static function createOrderRequest(): void
101
+	{
102
+		$paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
103
+		$post_params = EED_Module::getRequest()->postParams();
104
+		if (! $paypal_pm instanceof EE_Payment_Method) {
105
+			PayPalLogger::errorLogAndExit(
106
+				esc_html__('Related payment method not found (create Order).', 'event_espresso'),
107
+				$post_params
108
+			);
109
+		}
110
+		$transaction  = EED_PayPalCommerce::getTransaction();
111
+		$billing_info = $post_params['billing_info'] ?? [];
112
+		if ($billing_info) {
113
+			$billing_info_decoded = json_decode(stripslashes($billing_info), true);
114
+			$billing_info         = is_array($billing_info_decoded) ? $billing_info_decoded : [];
115
+		}
116
+		if (! $transaction) {
117
+			PayPalLogger::errorLogAndExit(
118
+				esc_html__('Transaction info not found.', 'event_espresso'),
119
+				$post_params,
120
+				$paypal_pm
121
+			);
122
+		}
123
+		$order_data = EED_PayPalCommerce::createOrder($transaction, $billing_info, $paypal_pm);
124
+		wp_send_json($order_data);
125
+	}
126
+
127
+
128
+	/**
129
+	 * Capture the order and return status in JSON.
130
+	 * (AJAX)
131
+	 *
132
+	 * @return void
133
+	 */
134
+	public static function captureOrderRequest(): void
135
+	{
136
+		$error_message = false;
137
+		$paypal_pm     = EED_PayPalCommerce::getPaymentMethod();
138
+		if (! $paypal_pm instanceof EE_Payment_Method) {
139
+			$error_message = esc_html__(
140
+				'Payment method could not be found while trying to capture the Order.',
141
+				'event_espresso'
142
+			);
143
+		}
144
+		$transaction = EED_PayPalCommerce::getTransaction();
145
+		if (! $transaction) {
146
+			$error_message = esc_html__(
147
+				'Could not process this payment because it has no associated transaction.',
148
+				'event_espresso'
149
+			);
150
+		}
151
+		$order_id = EED_Module::getRequest()->getRequestParam('order_id');
152
+		if (! $order_id) {
153
+			$error_message = esc_html__('Order ID missing.', 'event_espresso');
154
+		}
155
+		// Check for the payment nonce.
156
+		// $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
157
+		// $order_nonce = $request->getRequestParam('pp_order_nonce');
158
+		// if (empty($order_nonce) || ! wp_verify_nonce($order_nonce, Domain::CAPTURE_ORDER_NONCE_NAME)) {
159
+		//     $error_message = esc_html__('No or incorrect order capture nonce provided !', 'event_espresso');
160
+		//     return EEG_PayPalCheckout::updatePaymentStatus($payment, $failed_status, $request->postParams(), $error_message);
161
+		// }
162
+		$billing_info         = EED_Module::getRequest()->getRequestParam('billing_info');
163
+		$billing_info_decoded = json_decode(stripslashes($billing_info), true);
164
+		$billing_info         = is_array($billing_info_decoded) ? $billing_info_decoded : [];
165
+		if (! $billing_info) {
166
+			$error_message = esc_html__('Billing info missing.', 'event_espresso');
167
+		}
168
+		// We had an error. Log and EXIT.
169
+		if ($error_message) {
170
+			PayPalLogger::errorLogAndExit($error_message, EED_Module::getRequest()->postParams(), $paypal_pm);
171
+		}
172
+		try {
173
+			$capture_response = EED_PayPalCommerce::captureOrder($transaction, $paypal_pm, $order_id, $billing_info);
174
+		} catch (Exception $e) {
175
+			$capture_response = [
176
+				'error'   => 'CAPTURE_ORDER_ERROR',
177
+				'message' => $e->getMessage(),
178
+			];
179
+		}
180
+		wp_send_json($capture_response);
181
+	}
182
+
183
+
184
+	/**
185
+	 * Create a new Order using the PP API.
186
+	 *
187
+	 * @param EE_Transaction    $transaction
188
+	 * @param array             $billing_info
189
+	 * @param EE_Payment_Method $paypal_pm
190
+	 * @return array
191
+	 * @throws EE_Error
192
+	 * @throws ReflectionException
193
+	 */
194
+	public static function createOrder(
195
+		EE_Transaction $transaction,
196
+		array $billing_info,
197
+		EE_Payment_Method $paypal_pm
198
+	): array {
199
+		$create_order_api = EED_PayPalCommerce::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
200
+		if (! $create_order_api instanceof CreateOrder) {
201
+			return [
202
+				'error'   => 'CREATE_ORDER_API_FAULT',
203
+				'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
204
+			];
205
+		}
206
+		$payment = EEG_PayPalCheckout::createPayment($transaction, $paypal_pm);
207
+		$order   = $create_order_api->create();
208
+		if (isset($order['error'])) {
209
+			EEG_PayPalCheckout::updatePaymentStatus($payment, EEM_Payment::status_id_failed, $order, $order['error']);
210
+			return [
211
+				'error'   => 'CREATE_ORDER_API_RESPONSE_ERROR',
212
+				'message' => $order['message'],
213
+			];
214
+		}
215
+		return [
216
+			'pp_order_id' => $order['id'],
217
+		];
218
+	}
219
+
220
+
221
+	/**
222
+	 * Create a new Order using the PP API.
223
+	 *
224
+	 * @param EE_Transaction    $transaction
225
+	 * @param EE_Payment_Method $paypal_pm
226
+	 * @param string            $order_id
227
+	 * @param array             $billing_info
228
+	 * @return array
229
+	 * @throws EE_Error
230
+	 * @throws ReflectionException
231
+	 */
232
+	public static function captureOrder(
233
+		EE_Transaction $transaction,
234
+		EE_Payment_Method $paypal_pm,
235
+		string            $order_id,
236
+		array             $billing_info
237
+	): array {
238
+		$capture_order_api = EED_PayPalCommerce::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
239
+		if (! $capture_order_api instanceof CaptureOrder) {
240
+			return [
241
+				'error'   => 'CAPTURE_ORDER_API_FAULT',
242
+				'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
243
+			];
244
+		}
245
+		$payment = $transaction->last_payment() ?? EEG_PayPalCheckout::createPayment($transaction, $paypal_pm);
246
+		$order   = $capture_order_api->capture();
247
+		if (isset($order['error'])) {
248
+			EEG_PayPalCheckout::updatePaymentStatus($payment, EEM_Payment::status_id_failed, $order, $order['error']);
249
+			return $order;
250
+		}
251
+		// Attach the transaction ID to this order.
252
+		try {
253
+			$order['ee_txn_id'] = $transaction->ID();
254
+		} catch (Exception $e) {
255
+			// Just don't set the txn id.
256
+		}
257
+		$order_status = EEG_PayPalCheckout::isOrderCompleted($order);
258
+		if ($order_status['completed']) {
259
+			// Order captured, so payment was successful.
260
+			$update_message = esc_html__('Order captured successfully.', 'event_espresso');
261
+			EEG_PayPalCheckout::updatePaymentStatus($payment, EEM_Payment::status_id_approved, $order, $update_message);
262
+		} else {
263
+			EEG_PayPalCheckout::updatePaymentStatus(
264
+				$payment,
265
+				EEM_Payment::status_id_failed,
266
+				$order,
267
+				$order_status['message']
268
+			);
269
+		}
270
+		EEG_PayPalCheckout::saveBillingDetails($payment, $transaction, $order, $billing_info);
271
+		$nonce = wp_create_nonce(Domain::CAPTURE_ORDER_NONCE_NAME);
272
+		return [
273
+			'pp_order_nonce'  => $nonce,
274
+			'pp_order_id'     => $order['id'],
275
+			'pp_order_status' => $order['purchase_units'][0]['payments']['captures'][0]['status'] ?? 'ORDER_STATUS_UNKNOWN',
276
+			'pp_order_amount' => $order['purchase_units'][0]['payments']['captures'][0]['amount']['value'] ?? '',
277
+		];
278
+	}
279
+
280
+
281
+	/**
282
+	 * Create an Order for this transaction.
283
+	 *
284
+	 * @param EE_Transaction    $transaction
285
+	 * @param array             $billing_info
286
+	 * @param EE_Payment_Method $paypal_pm
287
+	 * @return CreateOrder|null
288
+	 * @throws EE_Error
289
+	 * @throws ReflectionException
290
+	 */
291
+	public static function getCreateOrderApi(
292
+		EE_Transaction $transaction,
293
+		array $billing_info,
294
+		EE_Payment_Method $paypal_pm
295
+	): ?CreateOrder {
296
+		$paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
297
+		if (! $paypal_api instanceof PayPalApi) {
298
+			return null;
299
+		}
300
+		return LoaderFactory::getNew(CreateOrder::class, [$paypal_api, $transaction, $billing_info]);
301
+	}
302
+
303
+
304
+	/**
305
+	 * Create an Order for this transaction.
306
+	 *
307
+	 * @param EE_Transaction    $transaction
308
+	 * @param EE_Payment_Method $paypal_pm
309
+	 * @param string            $order_id
310
+	 * @return CaptureOrder|null
311
+	 * @throws EE_Error
312
+	 * @throws ReflectionException
313
+	 */
314
+	public static function getCaptureOrderApi(
315
+		EE_Transaction $transaction,
316
+		EE_Payment_Method $paypal_pm,
317
+		string $order_id
318
+	): ?CaptureOrder {
319
+		$paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
320
+		if (! $paypal_api instanceof PayPalApi) {
321
+			return null;
322
+		}
323
+		return LoaderFactory::getNew(CaptureOrder::class, [$paypal_api, $transaction, $order_id]);
324
+	}
325
+
326
+
327
+	/**
328
+	 * Return a PayPal API object, or false on failure.
329
+	 *
330
+	 * @param EE_Payment_Method $paypal_pm
331
+	 * @return PayPalApi|null
332
+	 * @throws EE_Error
333
+	 * @throws ReflectionException
334
+	 */
335
+	public static function getPayPalApi(EE_Payment_Method $paypal_pm): ?PayPalApi
336
+	{
337
+		// Try getting the first party credentials to determine if this is a first party integration that's active.
338
+		$client_id     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_ID);
339
+		$client_secret = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_SECRET);
340
+		$bn_code       = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
341
+		if ($client_id && $client_secret) {
342
+			return new FirstPartyPayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
343
+		}
344
+		// Third party integration credentials:
345
+		$access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
346
+		if (! $access_token || ! $bn_code) {
347
+			return null;
348
+		}
349
+		$partner_client_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_CLIENT_ID) ?: '';
350
+		$payer_id          = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_MERCHANT_ID) ?: '';
351
+		return new ThirdPartyPayPalApi(
352
+			$access_token, $bn_code, $partner_client_id, $payer_id, $paypal_pm->debug_mode()
353
+		);
354
+	}
355
+
356
+
357
+	/**
358
+	 * Requests a client token.
359
+	 *
360
+	 * @param EE_Payment_Method $paypal_pm
361
+	 * @return array
362
+	 * @throws EE_Error
363
+	 * @throws ReflectionException
364
+	 */
365
+	public static function requestClientToken(EE_Payment_Method $paypal_pm): array
366
+	{
367
+		$error      = ['error' => 'GET_CLIENT_TOKEN_FAULT'];
368
+		$paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
369
+		if (! $paypal_api instanceof PayPalApi) {
370
+			$error['message'] = esc_html__('Got an error while trying to get the client token.', 'event_espresso');
371
+			return $error;
372
+		}
373
+		$client_token_api = new ClientToken($paypal_api, $paypal_pm->debug_mode());
374
+		$client_token     = $client_token_api->getToken();
375
+		if (isset($client_token['error'])) {
376
+			return $client_token;
377
+		}
378
+		if (empty($client_token)) {
379
+			$error['message'] = esc_html__('Client token not valid.', 'event_espresso');
380
+			return $error;
381
+		}
382
+		return $client_token;
383
+	}
384
+
385
+
386
+	/**
387
+	 * Retrieve the payment method from the provided data.
388
+	 *
389
+	 * @return EE_Transaction|null
390
+	 */
391
+	public static function getTransaction(): ?EE_Transaction
392
+	{
393
+		try {
394
+			$txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
395
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
396
+			if (! $transaction instanceof EE_Transaction) {
397
+				PayPalLogger::errorLog(
398
+					esc_html__('No transaction found by ID:', 'event_espresso'),
399
+					EED_Module::getRequest()->postParams()
400
+				);
401
+				return null;
402
+			}
403
+		} catch (Exception $e) {
404
+			return null;
405
+		}
406
+		return $transaction;
407
+	}
408
+
409
+
410
+	/**
411
+	 * Return a PayPal API object, or false on failure.
412
+	 *
413
+	 * @param EE_Payment_Method $paypal_pm
414
+	 * @return bool
415
+	 * @throws EE_Error
416
+	 * @throws ReflectionException
417
+	 */
418
+	public static function isThirdParty(EE_Payment_Method $paypal_pm): bool
419
+	{
420
+		$pp_meta_data = PayPalExtraMetaManager::getAllData($paypal_pm);
421
+		return ! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
422
+			&& ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ]);
423
+	}
424
+
425
+
426
+	/**
427
+	 * Retrieve the payment method from the provided data.
428
+	 *
429
+	 * @return EE_Payment_Method|null
430
+	 */
431
+	public static function getPaymentMethod(): ?EE_Payment_Method
432
+	{
433
+		try {
434
+			// Check if all required parameters are present.
435
+			$pm_slug        = EED_Module::getRequest()->getRequestParam('payment_method');
436
+			$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_slug);
437
+			if ($payment_method instanceof EE_Payment_Method) {
438
+				return $payment_method;
439
+			}
440
+		} catch (Exception $e) {
441
+			return null;
442
+		}
443
+		return null;
444
+	}
445
+
446
+
447
+	/**
448
+	 * Log JS error.
449
+	 *
450
+	 * @return void
451
+	 */
452
+	public static function logJsError(): void
453
+	{
454
+		// Default to the "first" PayPal checkout PM.
455
+		$request        = EED_Module::getRequest();
456
+		$pm_slug        = $request->getRequestParam('pm_slug', Domain::PM_SLUG);
457
+		$payment_method = null;
458
+		$txn_id         = 'unknown';
459
+		try {
460
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pm_slug);
461
+			$txn_id         = sanitize_text_field($request->getRequestParam('txn_id', '-'));
462
+		} catch (Exception $e) {
463
+			// Don't throw out anything, log at least something.
464
+		}
465
+		PayPalLogger::errorLog("JS Error on transaction: $txn_id", $request->postParams(), $payment_method);
466
+	}
467
+
468
+
469
+	/**
470
+	 * Filter the Payment Methods list.
471
+	 * if needed, this filter can also supply the $transaction and $scope parameters.
472
+	 *
473
+	 * @param EE_Payment_Method[] $payment_methods
474
+	 * @return array
475
+	 * @throws EE_Error
476
+	 * @throws ReflectionException
477
+	 */
478
+	public static function filterPaymentMethods(array $payment_methods): array
479
+	{
480
+		// Don't allow this PM on the checkout page if not Connected.
481
+		foreach ($payment_methods as $key => $pm) {
482
+			// It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
483
+			if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
484
+				unset($payment_methods[ $key ]);
485
+			}
486
+		}
487
+		return $payment_methods;
488
+	}
489
+
490
+
491
+	/**
492
+	 *  Get all active states.
493
+	 *
494
+	 * @return array
495
+	 * @throws EE_Error
496
+	 * @throws ReflectionException
497
+	 */
498
+	public static function getActiveStates(): array
499
+	{
500
+		$state_options = [];
501
+		$states        = EEM_State::instance()->get_all_active_states();
502
+		if (! empty($states)) {
503
+			foreach ($states as $numeral => $state) {
504
+				if ($state instanceof EE_State) {
505
+					$state_options[ $numeral ] = $state->abbrev();
506
+				}
507
+			}
508
+		}
509
+		return $state_options;
510
+	}
511 511
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -101,7 +101,7 @@  discard block
 block discarded – undo
101 101
     {
102 102
         $paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
103 103
         $post_params = EED_Module::getRequest()->postParams();
104
-        if (! $paypal_pm instanceof EE_Payment_Method) {
104
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
105 105
             PayPalLogger::errorLogAndExit(
106 106
                 esc_html__('Related payment method not found (create Order).', 'event_espresso'),
107 107
                 $post_params
@@ -113,7 +113,7 @@  discard block
 block discarded – undo
113 113
             $billing_info_decoded = json_decode(stripslashes($billing_info), true);
114 114
             $billing_info         = is_array($billing_info_decoded) ? $billing_info_decoded : [];
115 115
         }
116
-        if (! $transaction) {
116
+        if ( ! $transaction) {
117 117
             PayPalLogger::errorLogAndExit(
118 118
                 esc_html__('Transaction info not found.', 'event_espresso'),
119 119
                 $post_params,
@@ -135,21 +135,21 @@  discard block
 block discarded – undo
135 135
     {
136 136
         $error_message = false;
137 137
         $paypal_pm     = EED_PayPalCommerce::getPaymentMethod();
138
-        if (! $paypal_pm instanceof EE_Payment_Method) {
138
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
139 139
             $error_message = esc_html__(
140 140
                 'Payment method could not be found while trying to capture the Order.',
141 141
                 'event_espresso'
142 142
             );
143 143
         }
144 144
         $transaction = EED_PayPalCommerce::getTransaction();
145
-        if (! $transaction) {
145
+        if ( ! $transaction) {
146 146
             $error_message = esc_html__(
147 147
                 'Could not process this payment because it has no associated transaction.',
148 148
                 'event_espresso'
149 149
             );
150 150
         }
151 151
         $order_id = EED_Module::getRequest()->getRequestParam('order_id');
152
-        if (! $order_id) {
152
+        if ( ! $order_id) {
153 153
             $error_message = esc_html__('Order ID missing.', 'event_espresso');
154 154
         }
155 155
         // Check for the payment nonce.
@@ -162,7 +162,7 @@  discard block
 block discarded – undo
162 162
         $billing_info         = EED_Module::getRequest()->getRequestParam('billing_info');
163 163
         $billing_info_decoded = json_decode(stripslashes($billing_info), true);
164 164
         $billing_info         = is_array($billing_info_decoded) ? $billing_info_decoded : [];
165
-        if (! $billing_info) {
165
+        if ( ! $billing_info) {
166 166
             $error_message = esc_html__('Billing info missing.', 'event_espresso');
167 167
         }
168 168
         // We had an error. Log and EXIT.
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
         EE_Payment_Method $paypal_pm
198 198
     ): array {
199 199
         $create_order_api = EED_PayPalCommerce::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
200
-        if (! $create_order_api instanceof CreateOrder) {
200
+        if ( ! $create_order_api instanceof CreateOrder) {
201 201
             return [
202 202
                 'error'   => 'CREATE_ORDER_API_FAULT',
203 203
                 'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
@@ -236,7 +236,7 @@  discard block
 block discarded – undo
236 236
         array             $billing_info
237 237
     ): array {
238 238
         $capture_order_api = EED_PayPalCommerce::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
239
-        if (! $capture_order_api instanceof CaptureOrder) {
239
+        if ( ! $capture_order_api instanceof CaptureOrder) {
240 240
             return [
241 241
                 'error'   => 'CAPTURE_ORDER_API_FAULT',
242 242
                 'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
         EE_Payment_Method $paypal_pm
295 295
     ): ?CreateOrder {
296 296
         $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
297
-        if (! $paypal_api instanceof PayPalApi) {
297
+        if ( ! $paypal_api instanceof PayPalApi) {
298 298
             return null;
299 299
         }
300 300
         return LoaderFactory::getNew(CreateOrder::class, [$paypal_api, $transaction, $billing_info]);
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
         string $order_id
318 318
     ): ?CaptureOrder {
319 319
         $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
320
-        if (! $paypal_api instanceof PayPalApi) {
320
+        if ( ! $paypal_api instanceof PayPalApi) {
321 321
             return null;
322 322
         }
323 323
         return LoaderFactory::getNew(CaptureOrder::class, [$paypal_api, $transaction, $order_id]);
@@ -343,7 +343,7 @@  discard block
 block discarded – undo
343 343
         }
344 344
         // Third party integration credentials:
345 345
         $access_token = EED_PayPalOnboard::getPartnerAccessToken($paypal_pm);
346
-        if (! $access_token || ! $bn_code) {
346
+        if ( ! $access_token || ! $bn_code) {
347 347
             return null;
348 348
         }
349 349
         $partner_client_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_CLIENT_ID) ?: '';
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
     {
367 367
         $error      = ['error' => 'GET_CLIENT_TOKEN_FAULT'];
368 368
         $paypal_api = EED_PayPalCommerce::getPayPalApi($paypal_pm);
369
-        if (! $paypal_api instanceof PayPalApi) {
369
+        if ( ! $paypal_api instanceof PayPalApi) {
370 370
             $error['message'] = esc_html__('Got an error while trying to get the client token.', 'event_espresso');
371 371
             return $error;
372 372
         }
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
         try {
394 394
             $txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
395 395
             $transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
396
-            if (! $transaction instanceof EE_Transaction) {
396
+            if ( ! $transaction instanceof EE_Transaction) {
397 397
                 PayPalLogger::errorLog(
398 398
                     esc_html__('No transaction found by ID:', 'event_espresso'),
399 399
                     EED_Module::getRequest()->postParams()
@@ -418,8 +418,8 @@  discard block
 block discarded – undo
418 418
     public static function isThirdParty(EE_Payment_Method $paypal_pm): bool
419 419
     {
420 420
         $pp_meta_data = PayPalExtraMetaManager::getAllData($paypal_pm);
421
-        return ! empty($pp_meta_data[ Domain::META_KEY_SELLER_MERCHANT_ID ])
422
-            && ! empty($pp_meta_data[ Domain::META_KEY_ACCESS_TOKEN ]);
421
+        return ! empty($pp_meta_data[Domain::META_KEY_SELLER_MERCHANT_ID])
422
+            && ! empty($pp_meta_data[Domain::META_KEY_ACCESS_TOKEN]);
423 423
     }
424 424
 
425 425
 
@@ -481,7 +481,7 @@  discard block
 block discarded – undo
481 481
         foreach ($payment_methods as $key => $pm) {
482 482
             // It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
483 483
             if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
484
-                unset($payment_methods[ $key ]);
484
+                unset($payment_methods[$key]);
485 485
             }
486 486
         }
487 487
         return $payment_methods;
@@ -499,10 +499,10 @@  discard block
 block discarded – undo
499 499
     {
500 500
         $state_options = [];
501 501
         $states        = EEM_State::instance()->get_all_active_states();
502
-        if (! empty($states)) {
502
+        if ( ! empty($states)) {
503 503
             foreach ($states as $numeral => $state) {
504 504
                 if ($state instanceof EE_State) {
505
-                    $state_options[ $numeral ] = $state->abbrev();
505
+                    $state_options[$numeral] = $state->abbrev();
506 506
                 }
507 507
             }
508 508
         }
Please login to merge, or discard this patch.
admin_pages/general_settings/General_Settings_Admin_Page.core.php 2 patches
Indentation   +1463 added lines, -1463 removed lines patch added patch discarded remove patch
@@ -22,1480 +22,1480 @@
 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'   => ' ',
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
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1013
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1014
-        }
1015
-
1016
-        $success = true;
1017
-        $CNT_ISO = $this->getCountryISO('');
1018
-        if (! $CNT_ISO) {
1019
-            EE_Error::add_error(
1020
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1021
-                __FILE__,
1022
-                __FUNCTION__,
1023
-                __LINE__
1024
-            );
1025
-            $success = false;
1026
-        }
1027
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1028
-        if (! $STA_abbrev) {
1029
-            EE_Error::add_error(
1030
-                esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1031
-                __FILE__,
1032
-                __FUNCTION__,
1033
-                __LINE__
1034
-            );
1035
-            $success = false;
1036
-        }
1037
-        $STA_name = $this->request->getRequestParam('STA_name');
1038
-        if (! $STA_name) {
1039
-            EE_Error::add_error(
1040
-                esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1041
-                __FILE__,
1042
-                __FUNCTION__,
1043
-                __LINE__
1044
-            );
1045
-            $success = false;
1046
-        }
1047
-
1048
-        if ($success) {
1049
-            $cols_n_values = [
1050
-                'CNT_ISO'    => $CNT_ISO,
1051
-                'STA_abbrev' => $STA_abbrev,
1052
-                'STA_name'   => $STA_name,
1053
-                'STA_active' => true,
1054
-            ];
1055
-            $success       = EEM_State::instance()->insert($cols_n_values);
1056
-            EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1057
-        }
1058
-
1059
-        if (defined('DOING_AJAX')) {
1060
-            $notices = EE_Error::get_notices(false, false, false);
1061
-            echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1062
-            die();
1063
-        }
1064
-        $this->_redirect_after_action(
1065
-            $success,
1066
-            esc_html__('State', 'event_espresso'),
1067
-            'added',
1068
-            ['action' => 'country_settings']
1069
-        );
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     * @return void
1075
-     * @throws EE_Error
1076
-     * @throws InvalidArgumentException
1077
-     * @throws InvalidDataTypeException
1078
-     * @throws InvalidInterfaceException
1079
-     * @throws ReflectionException
1080
-     */
1081
-    public function delete_state()
1082
-    {
1083
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1084
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1085
-        }
1086
-
1087
-        $CNT_ISO    = $this->getCountryISO();
1088
-        $STA_ID     = $this->request->getRequestParam('STA_ID');
1089
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1090
-
1091
-        if (! $STA_ID) {
1092
-            EE_Error::add_error(
1093
-                esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1094
-                __FILE__,
1095
-                __FUNCTION__,
1096
-                __LINE__
1097
-            );
1098
-            return;
1099
-        }
1100
-
1101
-        $success = EEM_State::instance()->delete_by_ID($STA_ID);
1102
-        if ($success !== false) {
1103
-            do_action(
1104
-                'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1105
-                $CNT_ISO,
1106
-                $STA_ID,
1107
-                ['STA_abbrev' => $STA_abbrev]
1108
-            );
1109
-            EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1110
-        }
1111
-        if (defined('DOING_AJAX')) {
1112
-            $notices                = EE_Error::get_notices(false);
1113
-            $notices['return_data'] = true;
1114
-            echo wp_json_encode($notices);
1115
-            die();
1116
-        }
1117
-        $this->_redirect_after_action(
1118
-            $success,
1119
-            esc_html__('State', 'event_espresso'),
1120
-            'deleted',
1121
-            ['action' => 'country_settings']
1122
-        );
1123
-    }
1124
-
1125
-
1126
-    /**
1127
-     * @return void
1128
-     * @throws EE_Error
1129
-     * @throws InvalidArgumentException
1130
-     * @throws InvalidDataTypeException
1131
-     * @throws InvalidInterfaceException
1132
-     * @throws ReflectionException
1133
-     */
1134
-    protected function _update_country_settings()
1135
-    {
1136
-        $CNT_ISO = $this->getCountryISO();
1137
-        if (! $CNT_ISO) {
1138
-            EE_Error::add_error(
1139
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1140
-                __FILE__,
1141
-                __FUNCTION__,
1142
-                __LINE__
1143
-            );
1144
-            return;
1145
-        }
1146
-
1147
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1148
-
1149
-        $cols_n_values                    = [];
1150
-        $cols_n_values['CNT_ISO3']        = strtoupper(
1151
-            $this->request->getRequestParam(
1152
-                "cntry[$CNT_ISO][CNT_ISO3]",
1153
-                $country->ISO3()
1154
-            )
1155
-        );
1156
-        $cols_n_values['CNT_name']        = $this->request->getRequestParam(
1157
-            "cntry[$CNT_ISO][CNT_name]",
1158
-            $country->name()
1159
-        );
1160
-        $cols_n_values['CNT_cur_code']    = strtoupper(
1161
-            $this->request->getRequestParam(
1162
-                "cntry[$CNT_ISO][CNT_cur_code]",
1163
-                $country->currency_code()
1164
-            )
1165
-        );
1166
-        $cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1167
-            "cntry[$CNT_ISO][CNT_cur_single]",
1168
-            $country->currency_name_single()
1169
-        );
1170
-        $cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1171
-            "cntry[$CNT_ISO][CNT_cur_plural]",
1172
-            $country->currency_name_plural()
1173
-        );
1174
-        $cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1175
-            "cntry[$CNT_ISO][CNT_cur_sign]",
1176
-            $country->currency_sign()
1177
-        );
1178
-        $cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1179
-            "cntry[$CNT_ISO][CNT_cur_sign_b4]",
1180
-            $country->currency_sign_before(),
1181
-            DataType::BOOL
1182
-        );
1183
-        $cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1184
-            "cntry[$CNT_ISO][CNT_cur_dec_plc]",
1185
-            $country->currency_decimal_places()
1186
-        );
1187
-        $cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1188
-            "cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1189
-            $country->currency_decimal_mark()
1190
-        );
1191
-        $cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1192
-            "cntry[$CNT_ISO][CNT_cur_thsnds]",
1193
-            $country->currency_thousands_separator()
1194
-        );
1195
-        $cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1196
-            "cntry[$CNT_ISO][CNT_tel_code]",
1197
-            $country->telephoneCode()
1198
-        );
1199
-        $cols_n_values['CNT_active']      = $this->request->getRequestParam(
1200
-            "cntry[$CNT_ISO][CNT_active]",
1201
-            $country->isActive(),
1202
-            DataType::BOOL
1203
-        );
1204
-        $cols_n_values['CNT_is_EU']      = $this->request->getRequestParam(
1205
-            "cntry[$CNT_ISO][CNT_is_EU]",
1206
-            $country->isEU(),
1207
-            DataType::BOOL
1208
-        );
1209
-
1210
-        // allow filtering of country data
1211
-        $cols_n_values = apply_filters(
1212
-            'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1213
-            $cols_n_values
1214
-        );
1215
-
1216
-        // where values
1217
-        $where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1218
-        // run the update
1219
-        $success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1220
-
1221
-        // allow filtering of states data
1222
-        $states = apply_filters(
1223
-            'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1224
-            $this->request->getRequestParam('states', [], DataType::STRING, true)
1225
-        );
1226
-
1227
-        if (! empty($states) && $success !== false) {
1228
-            // loop thru state data ( looks like : states[75][STA_name] )
1229
-            foreach ($states as $STA_ID => $state) {
1230
-                $cols_n_values = [
1231
-                    'CNT_ISO'    => $CNT_ISO,
1232
-                    'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1233
-                    'STA_name'   => sanitize_text_field($state['STA_name']),
1234
-                    'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1235
-                ];
1236
-                // where values
1237
-                $where_cols_n_values = [['STA_ID' => $STA_ID]];
1238
-                // run the update
1239
-                $success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1240
-                if ($success !== false) {
1241
-                    do_action(
1242
-                        'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1243
-                        $CNT_ISO,
1244
-                        $STA_ID,
1245
-                        $cols_n_values
1246
-                    );
1247
-                }
1248
-            }
1249
-        }
1250
-        // check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1251
-        if (
1252
-            isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1253
-            && $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1254
-        ) {
1255
-            EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1256
-            EE_Registry::instance()->CFG->update_espresso_config();
1257
-        }
1258
-
1259
-        if ($success !== false) {
1260
-            EE_Error::add_success(
1261
-                esc_html__('Country Settings updated successfully.', 'event_espresso')
1262
-            );
1263
-        }
1264
-        $this->_redirect_after_action(
1265
-            $success,
1266
-            '',
1267
-            '',
1268
-            ['action' => 'country_settings', 'country' => $CNT_ISO],
1269
-            true
1270
-        );
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * form_form_field_label_wrap
1276
-     *
1277
-     * @param string $label
1278
-     * @return string
1279
-     */
1280
-    public function country_form_field_label_wrap(string $label): string
1281
-    {
1282
-        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'   => ' ',
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
+		if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1013
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1014
+		}
1015
+
1016
+		$success = true;
1017
+		$CNT_ISO = $this->getCountryISO('');
1018
+		if (! $CNT_ISO) {
1019
+			EE_Error::add_error(
1020
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1021
+				__FILE__,
1022
+				__FUNCTION__,
1023
+				__LINE__
1024
+			);
1025
+			$success = false;
1026
+		}
1027
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1028
+		if (! $STA_abbrev) {
1029
+			EE_Error::add_error(
1030
+				esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1031
+				__FILE__,
1032
+				__FUNCTION__,
1033
+				__LINE__
1034
+			);
1035
+			$success = false;
1036
+		}
1037
+		$STA_name = $this->request->getRequestParam('STA_name');
1038
+		if (! $STA_name) {
1039
+			EE_Error::add_error(
1040
+				esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1041
+				__FILE__,
1042
+				__FUNCTION__,
1043
+				__LINE__
1044
+			);
1045
+			$success = false;
1046
+		}
1047
+
1048
+		if ($success) {
1049
+			$cols_n_values = [
1050
+				'CNT_ISO'    => $CNT_ISO,
1051
+				'STA_abbrev' => $STA_abbrev,
1052
+				'STA_name'   => $STA_name,
1053
+				'STA_active' => true,
1054
+			];
1055
+			$success       = EEM_State::instance()->insert($cols_n_values);
1056
+			EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1057
+		}
1058
+
1059
+		if (defined('DOING_AJAX')) {
1060
+			$notices = EE_Error::get_notices(false, false, false);
1061
+			echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1062
+			die();
1063
+		}
1064
+		$this->_redirect_after_action(
1065
+			$success,
1066
+			esc_html__('State', 'event_espresso'),
1067
+			'added',
1068
+			['action' => 'country_settings']
1069
+		);
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 * @return void
1075
+	 * @throws EE_Error
1076
+	 * @throws InvalidArgumentException
1077
+	 * @throws InvalidDataTypeException
1078
+	 * @throws InvalidInterfaceException
1079
+	 * @throws ReflectionException
1080
+	 */
1081
+	public function delete_state()
1082
+	{
1083
+		if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1084
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1085
+		}
1086
+
1087
+		$CNT_ISO    = $this->getCountryISO();
1088
+		$STA_ID     = $this->request->getRequestParam('STA_ID');
1089
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1090
+
1091
+		if (! $STA_ID) {
1092
+			EE_Error::add_error(
1093
+				esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1094
+				__FILE__,
1095
+				__FUNCTION__,
1096
+				__LINE__
1097
+			);
1098
+			return;
1099
+		}
1100
+
1101
+		$success = EEM_State::instance()->delete_by_ID($STA_ID);
1102
+		if ($success !== false) {
1103
+			do_action(
1104
+				'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1105
+				$CNT_ISO,
1106
+				$STA_ID,
1107
+				['STA_abbrev' => $STA_abbrev]
1108
+			);
1109
+			EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1110
+		}
1111
+		if (defined('DOING_AJAX')) {
1112
+			$notices                = EE_Error::get_notices(false);
1113
+			$notices['return_data'] = true;
1114
+			echo wp_json_encode($notices);
1115
+			die();
1116
+		}
1117
+		$this->_redirect_after_action(
1118
+			$success,
1119
+			esc_html__('State', 'event_espresso'),
1120
+			'deleted',
1121
+			['action' => 'country_settings']
1122
+		);
1123
+	}
1124
+
1125
+
1126
+	/**
1127
+	 * @return void
1128
+	 * @throws EE_Error
1129
+	 * @throws InvalidArgumentException
1130
+	 * @throws InvalidDataTypeException
1131
+	 * @throws InvalidInterfaceException
1132
+	 * @throws ReflectionException
1133
+	 */
1134
+	protected function _update_country_settings()
1135
+	{
1136
+		$CNT_ISO = $this->getCountryISO();
1137
+		if (! $CNT_ISO) {
1138
+			EE_Error::add_error(
1139
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1140
+				__FILE__,
1141
+				__FUNCTION__,
1142
+				__LINE__
1143
+			);
1144
+			return;
1145
+		}
1146
+
1147
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1148
+
1149
+		$cols_n_values                    = [];
1150
+		$cols_n_values['CNT_ISO3']        = strtoupper(
1151
+			$this->request->getRequestParam(
1152
+				"cntry[$CNT_ISO][CNT_ISO3]",
1153
+				$country->ISO3()
1154
+			)
1155
+		);
1156
+		$cols_n_values['CNT_name']        = $this->request->getRequestParam(
1157
+			"cntry[$CNT_ISO][CNT_name]",
1158
+			$country->name()
1159
+		);
1160
+		$cols_n_values['CNT_cur_code']    = strtoupper(
1161
+			$this->request->getRequestParam(
1162
+				"cntry[$CNT_ISO][CNT_cur_code]",
1163
+				$country->currency_code()
1164
+			)
1165
+		);
1166
+		$cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1167
+			"cntry[$CNT_ISO][CNT_cur_single]",
1168
+			$country->currency_name_single()
1169
+		);
1170
+		$cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1171
+			"cntry[$CNT_ISO][CNT_cur_plural]",
1172
+			$country->currency_name_plural()
1173
+		);
1174
+		$cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1175
+			"cntry[$CNT_ISO][CNT_cur_sign]",
1176
+			$country->currency_sign()
1177
+		);
1178
+		$cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1179
+			"cntry[$CNT_ISO][CNT_cur_sign_b4]",
1180
+			$country->currency_sign_before(),
1181
+			DataType::BOOL
1182
+		);
1183
+		$cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1184
+			"cntry[$CNT_ISO][CNT_cur_dec_plc]",
1185
+			$country->currency_decimal_places()
1186
+		);
1187
+		$cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1188
+			"cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1189
+			$country->currency_decimal_mark()
1190
+		);
1191
+		$cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1192
+			"cntry[$CNT_ISO][CNT_cur_thsnds]",
1193
+			$country->currency_thousands_separator()
1194
+		);
1195
+		$cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1196
+			"cntry[$CNT_ISO][CNT_tel_code]",
1197
+			$country->telephoneCode()
1198
+		);
1199
+		$cols_n_values['CNT_active']      = $this->request->getRequestParam(
1200
+			"cntry[$CNT_ISO][CNT_active]",
1201
+			$country->isActive(),
1202
+			DataType::BOOL
1203
+		);
1204
+		$cols_n_values['CNT_is_EU']      = $this->request->getRequestParam(
1205
+			"cntry[$CNT_ISO][CNT_is_EU]",
1206
+			$country->isEU(),
1207
+			DataType::BOOL
1208
+		);
1209
+
1210
+		// allow filtering of country data
1211
+		$cols_n_values = apply_filters(
1212
+			'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1213
+			$cols_n_values
1214
+		);
1215
+
1216
+		// where values
1217
+		$where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1218
+		// run the update
1219
+		$success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1220
+
1221
+		// allow filtering of states data
1222
+		$states = apply_filters(
1223
+			'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1224
+			$this->request->getRequestParam('states', [], DataType::STRING, true)
1225
+		);
1226
+
1227
+		if (! empty($states) && $success !== false) {
1228
+			// loop thru state data ( looks like : states[75][STA_name] )
1229
+			foreach ($states as $STA_ID => $state) {
1230
+				$cols_n_values = [
1231
+					'CNT_ISO'    => $CNT_ISO,
1232
+					'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1233
+					'STA_name'   => sanitize_text_field($state['STA_name']),
1234
+					'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1235
+				];
1236
+				// where values
1237
+				$where_cols_n_values = [['STA_ID' => $STA_ID]];
1238
+				// run the update
1239
+				$success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1240
+				if ($success !== false) {
1241
+					do_action(
1242
+						'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1243
+						$CNT_ISO,
1244
+						$STA_ID,
1245
+						$cols_n_values
1246
+					);
1247
+				}
1248
+			}
1249
+		}
1250
+		// check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1251
+		if (
1252
+			isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1253
+			&& $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1254
+		) {
1255
+			EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1256
+			EE_Registry::instance()->CFG->update_espresso_config();
1257
+		}
1258
+
1259
+		if ($success !== false) {
1260
+			EE_Error::add_success(
1261
+				esc_html__('Country Settings updated successfully.', 'event_espresso')
1262
+			);
1263
+		}
1264
+		$this->_redirect_after_action(
1265
+			$success,
1266
+			'',
1267
+			'',
1268
+			['action' => 'country_settings', 'country' => $CNT_ISO],
1269
+			true
1270
+		);
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * form_form_field_label_wrap
1276
+	 *
1277
+	 * @param string $label
1278
+	 * @return string
1279
+	 */
1280
+	public function country_form_field_label_wrap(string $label): string
1281
+	{
1282
+		return '
1283 1283
 			<tr>
1284 1284
 				<th>
1285 1285
 					' . $label . '
1286 1286
 				</th>';
1287
-    }
1288
-
1289
-
1290
-    /**
1291
-     * form_form_field_input__wrap
1292
-     *
1293
-     * @param string $input
1294
-     * @return string
1295
-     */
1296
-    public function country_form_field_input__wrap(string $input): string
1297
-    {
1298
-        return '
1287
+	}
1288
+
1289
+
1290
+	/**
1291
+	 * form_form_field_input__wrap
1292
+	 *
1293
+	 * @param string $input
1294
+	 * @return string
1295
+	 */
1296
+	public function country_form_field_input__wrap(string $input): string
1297
+	{
1298
+		return '
1299 1299
 				<td class="general-settings-country-input-td">
1300 1300
 					' . $input . '
1301 1301
 				</td>
1302 1302
 			</tr>';
1303
-    }
1304
-
1305
-
1306
-    /**
1307
-     * form_form_field_label_wrap
1308
-     *
1309
-     * @param string $label
1310
-     * @param string $required_text
1311
-     * @return string
1312
-     */
1313
-    public function state_form_field_label_wrap(string $label, string $required_text): string
1314
-    {
1315
-        return $required_text;
1316
-    }
1317
-
1318
-
1319
-    /**
1320
-     * form_form_field_input__wrap
1321
-     *
1322
-     * @param string $input
1323
-     * @return string
1324
-     */
1325
-    public function state_form_field_input__wrap(string $input): string
1326
-    {
1327
-        return '
1303
+	}
1304
+
1305
+
1306
+	/**
1307
+	 * form_form_field_label_wrap
1308
+	 *
1309
+	 * @param string $label
1310
+	 * @param string $required_text
1311
+	 * @return string
1312
+	 */
1313
+	public function state_form_field_label_wrap(string $label, string $required_text): string
1314
+	{
1315
+		return $required_text;
1316
+	}
1317
+
1318
+
1319
+	/**
1320
+	 * form_form_field_input__wrap
1321
+	 *
1322
+	 * @param string $input
1323
+	 * @return string
1324
+	 */
1325
+	public function state_form_field_input__wrap(string $input): string
1326
+	{
1327
+		return '
1328 1328
 				<td class="general-settings-country-state-input-td">
1329 1329
 					' . $input . '
1330 1330
 				</td>';
1331
-    }
1332
-
1333
-
1334
-    /***********/
1335
-
1336
-
1337
-    /**
1338
-     * displays edit and view links for critical EE pages
1339
-     *
1340
-     * @param int $ee_page_id
1341
-     * @return string
1342
-     */
1343
-    public static function edit_view_links(int $ee_page_id): string
1344
-    {
1345
-        $edit_url = add_query_arg(
1346
-            ['post' => $ee_page_id, 'action' => 'edit'],
1347
-            admin_url('post.php')
1348
-        );
1349
-        $links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1350
-        $links    .= ' &nbsp;|&nbsp; ';
1351
-        $links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1352
-
1353
-        return $links;
1354
-    }
1355
-
1356
-
1357
-    /**
1358
-     * displays page and shortcode status for critical EE pages
1359
-     *
1360
-     * @param WP_Post $ee_page
1361
-     * @param string  $shortcode
1362
-     * @return string
1363
-     */
1364
-    public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1365
-    {
1366
-        // page status
1367
-        if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1368
-            $pg_class  = 'ee-status-bg--success';
1369
-            $pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1370
-        } else {
1371
-            $pg_class  = 'ee-status-bg--error';
1372
-            $pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1373
-        }
1374
-
1375
-        // shortcode status
1376
-        if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1377
-            $sc_class  = 'ee-status-bg--success';
1378
-            $sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1379
-        } else {
1380
-            $sc_class  = 'ee-status-bg--error';
1381
-            $sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1382
-        }
1383
-
1384
-        return '
1331
+	}
1332
+
1333
+
1334
+	/***********/
1335
+
1336
+
1337
+	/**
1338
+	 * displays edit and view links for critical EE pages
1339
+	 *
1340
+	 * @param int $ee_page_id
1341
+	 * @return string
1342
+	 */
1343
+	public static function edit_view_links(int $ee_page_id): string
1344
+	{
1345
+		$edit_url = add_query_arg(
1346
+			['post' => $ee_page_id, 'action' => 'edit'],
1347
+			admin_url('post.php')
1348
+		);
1349
+		$links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1350
+		$links    .= ' &nbsp;|&nbsp; ';
1351
+		$links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1352
+
1353
+		return $links;
1354
+	}
1355
+
1356
+
1357
+	/**
1358
+	 * displays page and shortcode status for critical EE pages
1359
+	 *
1360
+	 * @param WP_Post $ee_page
1361
+	 * @param string  $shortcode
1362
+	 * @return string
1363
+	 */
1364
+	public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1365
+	{
1366
+		// page status
1367
+		if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1368
+			$pg_class  = 'ee-status-bg--success';
1369
+			$pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1370
+		} else {
1371
+			$pg_class  = 'ee-status-bg--error';
1372
+			$pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1373
+		}
1374
+
1375
+		// shortcode status
1376
+		if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1377
+			$sc_class  = 'ee-status-bg--success';
1378
+			$sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1379
+		} else {
1380
+			$sc_class  = 'ee-status-bg--error';
1381
+			$sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1382
+		}
1383
+
1384
+		return '
1385 1385
         <span class="ee-page-status ' . $pg_class . '"><strong>' . $pg_status . '</strong></span>
1386 1386
         <span class="ee-page-status ' . $sc_class . '"><strong>' . $sc_status . '</strong></span>';
1387
-    }
1388
-
1389
-
1390
-    /**
1391
-     * generates a dropdown of all parent pages - copied from WP core
1392
-     *
1393
-     * @param int  $default
1394
-     * @param int  $parent
1395
-     * @param int  $level
1396
-     * @param bool $echo
1397
-     * @return string;
1398
-     */
1399
-    public static function page_settings_dropdown(
1400
-        int $default = 0,
1401
-        int $parent = 0,
1402
-        int $level = 0,
1403
-        bool $echo = true
1404
-    ): string {
1405
-        global $wpdb;
1406
-        $items  = $wpdb->get_results(
1407
-            $wpdb->prepare(
1408
-                "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",
1409
-                $parent
1410
-            )
1411
-        );
1412
-        $output = '';
1413
-
1414
-        if ($items) {
1415
-            $level = absint($level);
1416
-            foreach ($items as $item) {
1417
-                $ID         = absint($item->ID);
1418
-                $post_title = wp_strip_all_tags($item->post_title);
1419
-                $pad        = str_repeat('&nbsp;', $level * 3);
1420
-                $option     = "\n\t";
1421
-                $option     .= '<option class="level-' . $level . '" ';
1422
-                $option     .= 'value="' . $ID . '" ';
1423
-                $option     .= $ID === absint($default) ? ' selected' : '';
1424
-                $option     .= '>';
1425
-                $option     .= "$pad {$post_title}";
1426
-                $option     .= '</option>';
1427
-                $output     .= $option;
1428
-                ob_start();
1429
-                parent_dropdown($default, $item->ID, $level + 1);
1430
-                $output .= ob_get_clean();
1431
-            }
1432
-        }
1433
-        if ($echo) {
1434
-            echo wp_kses($output, AllowedTags::getWithFormTags());
1435
-            return '';
1436
-        }
1437
-        return $output;
1438
-    }
1439
-
1440
-
1441
-    /**
1442
-     * Loads the scripts for the privacy settings form
1443
-     */
1444
-    public function load_scripts_styles_privacy_settings()
1445
-    {
1446
-        $form_handler = $this->loader->getShared(
1447
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1448
-        );
1449
-        $form_handler->enqueueStylesAndScripts();
1450
-    }
1451
-
1452
-
1453
-    /**
1454
-     * display the privacy settings form
1455
-     *
1456
-     * @throws EE_Error
1457
-     */
1458
-    public function privacySettings()
1459
-    {
1460
-        $this->_set_add_edit_form_tags('update_privacy_settings');
1461
-        $this->_set_publish_post_box_vars();
1462
-        $form_handler                               = $this->loader->getShared(
1463
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1464
-        );
1465
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
1466
-            $form_handler->display(),
1467
-            '',
1468
-            'padding'
1469
-        );
1470
-        $this->display_admin_page_with_sidebar();
1471
-    }
1472
-
1473
-
1474
-    /**
1475
-     * Update the privacy settings from form data
1476
-     *
1477
-     * @throws EE_Error
1478
-     */
1479
-    public function updatePrivacySettings()
1480
-    {
1481
-        $form_handler = $this->loader->getShared(
1482
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1483
-        );
1484
-        $success      = $form_handler->process($this->get_request_data());
1485
-        $this->_redirect_after_action(
1486
-            $success,
1487
-            esc_html__('Registration Form Options', 'event_espresso'),
1488
-            'updated',
1489
-            ['action' => 'privacy_settings']
1490
-        );
1491
-    }
1492
-
1493
-
1494
-    public function setFontSize()
1495
-    {
1496
-        AdminFontSize::setAdminFontSize(
1497
-            $this->request->getRequestParam('font_size', AdminFontSize::FONT_SIZE_DEFAULT)
1498
-        );
1499
-        wp_safe_redirect($this->request->getServerParam('HTTP_REFERER'));
1500
-    }
1387
+	}
1388
+
1389
+
1390
+	/**
1391
+	 * generates a dropdown of all parent pages - copied from WP core
1392
+	 *
1393
+	 * @param int  $default
1394
+	 * @param int  $parent
1395
+	 * @param int  $level
1396
+	 * @param bool $echo
1397
+	 * @return string;
1398
+	 */
1399
+	public static function page_settings_dropdown(
1400
+		int $default = 0,
1401
+		int $parent = 0,
1402
+		int $level = 0,
1403
+		bool $echo = true
1404
+	): string {
1405
+		global $wpdb;
1406
+		$items  = $wpdb->get_results(
1407
+			$wpdb->prepare(
1408
+				"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",
1409
+				$parent
1410
+			)
1411
+		);
1412
+		$output = '';
1413
+
1414
+		if ($items) {
1415
+			$level = absint($level);
1416
+			foreach ($items as $item) {
1417
+				$ID         = absint($item->ID);
1418
+				$post_title = wp_strip_all_tags($item->post_title);
1419
+				$pad        = str_repeat('&nbsp;', $level * 3);
1420
+				$option     = "\n\t";
1421
+				$option     .= '<option class="level-' . $level . '" ';
1422
+				$option     .= 'value="' . $ID . '" ';
1423
+				$option     .= $ID === absint($default) ? ' selected' : '';
1424
+				$option     .= '>';
1425
+				$option     .= "$pad {$post_title}";
1426
+				$option     .= '</option>';
1427
+				$output     .= $option;
1428
+				ob_start();
1429
+				parent_dropdown($default, $item->ID, $level + 1);
1430
+				$output .= ob_get_clean();
1431
+			}
1432
+		}
1433
+		if ($echo) {
1434
+			echo wp_kses($output, AllowedTags::getWithFormTags());
1435
+			return '';
1436
+		}
1437
+		return $output;
1438
+	}
1439
+
1440
+
1441
+	/**
1442
+	 * Loads the scripts for the privacy settings form
1443
+	 */
1444
+	public function load_scripts_styles_privacy_settings()
1445
+	{
1446
+		$form_handler = $this->loader->getShared(
1447
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1448
+		);
1449
+		$form_handler->enqueueStylesAndScripts();
1450
+	}
1451
+
1452
+
1453
+	/**
1454
+	 * display the privacy settings form
1455
+	 *
1456
+	 * @throws EE_Error
1457
+	 */
1458
+	public function privacySettings()
1459
+	{
1460
+		$this->_set_add_edit_form_tags('update_privacy_settings');
1461
+		$this->_set_publish_post_box_vars();
1462
+		$form_handler                               = $this->loader->getShared(
1463
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1464
+		);
1465
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
1466
+			$form_handler->display(),
1467
+			'',
1468
+			'padding'
1469
+		);
1470
+		$this->display_admin_page_with_sidebar();
1471
+	}
1472
+
1473
+
1474
+	/**
1475
+	 * Update the privacy settings from form data
1476
+	 *
1477
+	 * @throws EE_Error
1478
+	 */
1479
+	public function updatePrivacySettings()
1480
+	{
1481
+		$form_handler = $this->loader->getShared(
1482
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1483
+		);
1484
+		$success      = $form_handler->process($this->get_request_data());
1485
+		$this->_redirect_after_action(
1486
+			$success,
1487
+			esc_html__('Registration Form Options', 'event_espresso'),
1488
+			'updated',
1489
+			['action' => 'privacy_settings']
1490
+		);
1491
+	}
1492
+
1493
+
1494
+	public function setFontSize()
1495
+	{
1496
+		AdminFontSize::setAdminFontSize(
1497
+			$this->request->getRequestParam('font_size', AdminFontSize::FONT_SIZE_DEFAULT)
1498
+		);
1499
+		wp_safe_redirect($this->request->getServerParam('HTTP_REFERER'));
1500
+	}
1501 1501
 }
Please login to merge, or discard this patch.
Spacing   +50 added lines, -50 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
         );
@@ -1009,13 +1009,13 @@  discard block
 block discarded – undo
1009 1009
      */
1010 1010
     public function add_new_state()
1011 1011
     {
1012
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1012
+        if ( ! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1013 1013
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1014 1014
         }
1015 1015
 
1016 1016
         $success = true;
1017 1017
         $CNT_ISO = $this->getCountryISO('');
1018
-        if (! $CNT_ISO) {
1018
+        if ( ! $CNT_ISO) {
1019 1019
             EE_Error::add_error(
1020 1020
                 esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1021 1021
                 __FILE__,
@@ -1025,7 +1025,7 @@  discard block
 block discarded – undo
1025 1025
             $success = false;
1026 1026
         }
1027 1027
         $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1028
-        if (! $STA_abbrev) {
1028
+        if ( ! $STA_abbrev) {
1029 1029
             EE_Error::add_error(
1030 1030
                 esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1031 1031
                 __FILE__,
@@ -1035,7 +1035,7 @@  discard block
 block discarded – undo
1035 1035
             $success = false;
1036 1036
         }
1037 1037
         $STA_name = $this->request->getRequestParam('STA_name');
1038
-        if (! $STA_name) {
1038
+        if ( ! $STA_name) {
1039 1039
             EE_Error::add_error(
1040 1040
                 esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1041 1041
                 __FILE__,
@@ -1052,7 +1052,7 @@  discard block
 block discarded – undo
1052 1052
                 'STA_name'   => $STA_name,
1053 1053
                 'STA_active' => true,
1054 1054
             ];
1055
-            $success       = EEM_State::instance()->insert($cols_n_values);
1055
+            $success = EEM_State::instance()->insert($cols_n_values);
1056 1056
             EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1057 1057
         }
1058 1058
 
@@ -1080,7 +1080,7 @@  discard block
 block discarded – undo
1080 1080
      */
1081 1081
     public function delete_state()
1082 1082
     {
1083
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1083
+        if ( ! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
1084 1084
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1085 1085
         }
1086 1086
 
@@ -1088,7 +1088,7 @@  discard block
 block discarded – undo
1088 1088
         $STA_ID     = $this->request->getRequestParam('STA_ID');
1089 1089
         $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1090 1090
 
1091
-        if (! $STA_ID) {
1091
+        if ( ! $STA_ID) {
1092 1092
             EE_Error::add_error(
1093 1093
                 esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1094 1094
                 __FILE__,
@@ -1134,7 +1134,7 @@  discard block
 block discarded – undo
1134 1134
     protected function _update_country_settings()
1135 1135
     {
1136 1136
         $CNT_ISO = $this->getCountryISO();
1137
-        if (! $CNT_ISO) {
1137
+        if ( ! $CNT_ISO) {
1138 1138
             EE_Error::add_error(
1139 1139
                 esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1140 1140
                 __FILE__,
@@ -1153,25 +1153,25 @@  discard block
 block discarded – undo
1153 1153
                 $country->ISO3()
1154 1154
             )
1155 1155
         );
1156
-        $cols_n_values['CNT_name']        = $this->request->getRequestParam(
1156
+        $cols_n_values['CNT_name'] = $this->request->getRequestParam(
1157 1157
             "cntry[$CNT_ISO][CNT_name]",
1158 1158
             $country->name()
1159 1159
         );
1160
-        $cols_n_values['CNT_cur_code']    = strtoupper(
1160
+        $cols_n_values['CNT_cur_code'] = strtoupper(
1161 1161
             $this->request->getRequestParam(
1162 1162
                 "cntry[$CNT_ISO][CNT_cur_code]",
1163 1163
                 $country->currency_code()
1164 1164
             )
1165 1165
         );
1166
-        $cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1166
+        $cols_n_values['CNT_cur_single'] = $this->request->getRequestParam(
1167 1167
             "cntry[$CNT_ISO][CNT_cur_single]",
1168 1168
             $country->currency_name_single()
1169 1169
         );
1170
-        $cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1170
+        $cols_n_values['CNT_cur_plural'] = $this->request->getRequestParam(
1171 1171
             "cntry[$CNT_ISO][CNT_cur_plural]",
1172 1172
             $country->currency_name_plural()
1173 1173
         );
1174
-        $cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1174
+        $cols_n_values['CNT_cur_sign'] = $this->request->getRequestParam(
1175 1175
             "cntry[$CNT_ISO][CNT_cur_sign]",
1176 1176
             $country->currency_sign()
1177 1177
         );
@@ -1188,20 +1188,20 @@  discard block
 block discarded – undo
1188 1188
             "cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1189 1189
             $country->currency_decimal_mark()
1190 1190
         );
1191
-        $cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1191
+        $cols_n_values['CNT_cur_thsnds'] = $this->request->getRequestParam(
1192 1192
             "cntry[$CNT_ISO][CNT_cur_thsnds]",
1193 1193
             $country->currency_thousands_separator()
1194 1194
         );
1195
-        $cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1195
+        $cols_n_values['CNT_tel_code'] = $this->request->getRequestParam(
1196 1196
             "cntry[$CNT_ISO][CNT_tel_code]",
1197 1197
             $country->telephoneCode()
1198 1198
         );
1199
-        $cols_n_values['CNT_active']      = $this->request->getRequestParam(
1199
+        $cols_n_values['CNT_active'] = $this->request->getRequestParam(
1200 1200
             "cntry[$CNT_ISO][CNT_active]",
1201 1201
             $country->isActive(),
1202 1202
             DataType::BOOL
1203 1203
         );
1204
-        $cols_n_values['CNT_is_EU']      = $this->request->getRequestParam(
1204
+        $cols_n_values['CNT_is_EU'] = $this->request->getRequestParam(
1205 1205
             "cntry[$CNT_ISO][CNT_is_EU]",
1206 1206
             $country->isEU(),
1207 1207
             DataType::BOOL
@@ -1224,7 +1224,7 @@  discard block
 block discarded – undo
1224 1224
             $this->request->getRequestParam('states', [], DataType::STRING, true)
1225 1225
         );
1226 1226
 
1227
-        if (! empty($states) && $success !== false) {
1227
+        if ( ! empty($states) && $success !== false) {
1228 1228
             // loop thru state data ( looks like : states[75][STA_name] )
1229 1229
             foreach ($states as $STA_ID => $state) {
1230 1230
                 $cols_n_values = [
@@ -1282,7 +1282,7 @@  discard block
 block discarded – undo
1282 1282
         return '
1283 1283
 			<tr>
1284 1284
 				<th>
1285
-					' . $label . '
1285
+					' . $label.'
1286 1286
 				</th>';
1287 1287
     }
1288 1288
 
@@ -1297,7 +1297,7 @@  discard block
 block discarded – undo
1297 1297
     {
1298 1298
         return '
1299 1299
 				<td class="general-settings-country-input-td">
1300
-					' . $input . '
1300
+					' . $input.'
1301 1301
 				</td>
1302 1302
 			</tr>';
1303 1303
     }
@@ -1326,7 +1326,7 @@  discard block
 block discarded – undo
1326 1326
     {
1327 1327
         return '
1328 1328
 				<td class="general-settings-country-state-input-td">
1329
-					' . $input . '
1329
+					' . $input.'
1330 1330
 				</td>';
1331 1331
     }
1332 1332
 
@@ -1346,9 +1346,9 @@  discard block
 block discarded – undo
1346 1346
             ['post' => $ee_page_id, 'action' => 'edit'],
1347 1347
             admin_url('post.php')
1348 1348
         );
1349
-        $links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1349
+        $links = '<a href="'.esc_url_raw($edit_url).'" >'.esc_html__('Edit', 'event_espresso').'</a>';
1350 1350
         $links    .= ' &nbsp;|&nbsp; ';
1351
-        $links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1351
+        $links    .= '<a href="'.get_permalink($ee_page_id).'" >'.esc_html__('View', 'event_espresso').'</a>';
1352 1352
 
1353 1353
         return $links;
1354 1354
     }
@@ -1382,8 +1382,8 @@  discard block
 block discarded – undo
1382 1382
         }
1383 1383
 
1384 1384
         return '
1385
-        <span class="ee-page-status ' . $pg_class . '"><strong>' . $pg_status . '</strong></span>
1386
-        <span class="ee-page-status ' . $sc_class . '"><strong>' . $sc_status . '</strong></span>';
1385
+        <span class="ee-page-status ' . $pg_class.'"><strong>'.$pg_status.'</strong></span>
1386
+        <span class="ee-page-status ' . $sc_class.'"><strong>'.$sc_status.'</strong></span>';
1387 1387
     }
1388 1388
 
1389 1389
 
@@ -1403,7 +1403,7 @@  discard block
 block discarded – undo
1403 1403
         bool $echo = true
1404 1404
     ): string {
1405 1405
         global $wpdb;
1406
-        $items  = $wpdb->get_results(
1406
+        $items = $wpdb->get_results(
1407 1407
             $wpdb->prepare(
1408 1408
                 "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",
1409 1409
                 $parent
@@ -1418,8 +1418,8 @@  discard block
 block discarded – undo
1418 1418
                 $post_title = wp_strip_all_tags($item->post_title);
1419 1419
                 $pad        = str_repeat('&nbsp;', $level * 3);
1420 1420
                 $option     = "\n\t";
1421
-                $option     .= '<option class="level-' . $level . '" ';
1422
-                $option     .= 'value="' . $ID . '" ';
1421
+                $option     .= '<option class="level-'.$level.'" ';
1422
+                $option     .= 'value="'.$ID.'" ';
1423 1423
                 $option     .= $ID === absint($default) ? ' selected' : '';
1424 1424
                 $option     .= '>';
1425 1425
                 $option     .= "$pad {$post_title}";
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +2549 added lines, -2549 removed lines patch added patch discarded remove patch
@@ -16,2553 +16,2553 @@
 block discarded – undo
16 16
  */
17 17
 class Transactions_Admin_Page extends EE_Admin_Page
18 18
 {
19
-    /**
20
-     * @var EE_Transaction
21
-     */
22
-    private $_transaction;
23
-
24
-    /**
25
-     * @var EE_Session
26
-     */
27
-    private $_session;
28
-
29
-    /**
30
-     * @var array $_txn_status
31
-     */
32
-    private static $_txn_status;
33
-
34
-    /**
35
-     * @var array $_pay_status
36
-     */
37
-    private static $_pay_status;
38
-
39
-    /**
40
-     * @var array $_existing_reg_payment_REG_IDs
41
-     */
42
-    protected $_existing_reg_payment_REG_IDs;
43
-
44
-
45
-    /**
46
-     *    _init_page_props
47
-     *
48
-     * @return void
49
-     */
50
-    protected function _init_page_props()
51
-    {
52
-        $this->page_slug        = TXN_PG_SLUG;
53
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
54
-        $this->_admin_base_url  = TXN_ADMIN_URL;
55
-        $this->_admin_base_path = TXN_ADMIN;
56
-    }
57
-
58
-
59
-    /**
60
-     *    _ajax_hooks
61
-     *
62
-     * @return void
63
-     */
64
-    protected function _ajax_hooks()
65
-    {
66
-    }
67
-
68
-
69
-    /**
70
-     *    _define_page_props
71
-     *
72
-     * @return void
73
-     */
74
-    protected function _define_page_props()
75
-    {
76
-        $this->_admin_page_title = $this->page_label;
77
-        $this->_labels           = [
78
-            'buttons' => [
79
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
-            ],
83
-        ];
84
-    }
85
-
86
-
87
-    /**
88
-     *        grab url requests and route them
89
-     *
90
-     * @access private
91
-     * @return void
92
-     * @throws EE_Error
93
-     * @throws InvalidArgumentException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidInterfaceException
96
-     * @throws ReflectionException
97
-     */
98
-    public function _set_page_routes()
99
-    {
100
-        $this->_set_transaction_status_array();
101
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
102
-
103
-        $this->_page_routes = [
104
-
105
-            'default' => [
106
-                'func'       => '_transactions_overview_list_table',
107
-                'capability' => 'ee_read_transactions',
108
-            ],
109
-
110
-            'view_transaction' => [
111
-                'func'       => '_transaction_details',
112
-                'capability' => 'ee_read_transaction',
113
-                'obj_id'     => $TXN_ID,
114
-            ],
115
-
116
-            'send_payment_reminder' => [
117
-                'func'       => '_send_payment_reminder',
118
-                'noheader'   => true,
119
-                'capability' => 'ee_send_message',
120
-            ],
121
-
122
-            'espresso_apply_payment' => [
123
-                'func'       => [$this, 'apply_payments_or_refunds'],
124
-                'noheader'   => true,
125
-                'capability' => 'ee_edit_payments',
126
-            ],
127
-
128
-            'espresso_apply_refund' => [
129
-                'func'       => [$this, 'apply_payments_or_refunds'],
130
-                'noheader'   => true,
131
-                'capability' => 'ee_edit_payments',
132
-            ],
133
-
134
-            'espresso_delete_payment' => [
135
-                'func'       => [$this, 'delete_payment'],
136
-                'noheader'   => true,
137
-                'capability' => 'ee_delete_payments',
138
-            ],
139
-
140
-            'espresso_recalculate_line_items' => [
141
-                'func'       => 'recalculateLineItems',
142
-                'noheader'   => true,
143
-                'capability' => 'ee_edit_payments',
144
-            ],
145
-
146
-        ];
147
-    }
148
-
149
-
150
-    protected function _set_page_config()
151
-    {
152
-        $TXN_ID             = $this->request->getRequestParam('TXN_ID', 0, 'int');
153
-        $this->_page_config = [
154
-            'default'          => [
155
-                'nav'           => [
156
-                    'label' => esc_html__('Overview', 'event_espresso'),
157
-                    'icon'  => 'dashicons-list-view',
158
-                    'order' => 10,
159
-                ],
160
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
161
-                'help_tabs'     => [
162
-                    'transactions_overview_help_tab'                       => [
163
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
164
-                        'filename' => 'transactions_overview',
165
-                    ],
166
-                    'transactions_overview_table_column_headings_help_tab' => [
167
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
168
-                        'filename' => 'transactions_overview_table_column_headings',
169
-                    ],
170
-                    'transactions_overview_views_filters_help_tab'         => [
171
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
172
-                        'filename' => 'transactions_overview_views_filters_search',
173
-                    ],
174
-                ],
175
-                'require_nonce' => false,
176
-            ],
177
-            'view_transaction' => [
178
-                'nav'       => [
179
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
180
-                    'icon'       => 'dashicons-cart',
181
-                    'order'      => 5,
182
-                    'url'        => $TXN_ID
183
-                        ? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
184
-                        : $this->_admin_base_url,
185
-                    'persistent' => false,
186
-                ],
187
-                'help_tabs' => [
188
-                    'transactions_view_transaction_help_tab'                                              => [
189
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
190
-                        'filename' => 'transactions_view_transaction',
191
-                    ],
192
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => [
193
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
194
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
195
-                    ],
196
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => [
197
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
198
-                        'filename' => 'transactions_view_transaction_attendees_registered',
199
-                    ],
200
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
201
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
202
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
203
-                    ],
204
-                ],
205
-                'qtips'     => ['Transaction_Details_Tips'],
206
-                'metaboxes' => ['_transaction_details_metaboxes'],
207
-
208
-                'require_nonce' => false,
209
-            ],
210
-        ];
211
-    }
212
-
213
-
214
-    /**
215
-     * The below methods aren't used by this class currently
216
-     */
217
-    protected function _add_screen_options()
218
-    {
219
-        // noop
220
-    }
221
-
222
-
223
-    protected function _add_feature_pointers()
224
-    {
225
-        // noop
226
-    }
227
-
228
-
229
-    public function admin_init()
230
-    {
231
-        $EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
232
-        $event_name    = $this->request->getRequestParam('event_name');
233
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
234
-        // IF a registration was JUST added via the admin...
235
-        if ($EVT_ID && $event_name && $redirect_from) {
236
-            // then set a cookie so that we can block any attempts to use
237
-            // the back button as a way to enter another registration.
238
-            setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
239
-            // and update the global
240
-            $_COOKIE['ee_registration_added'] = $EVT_ID;
241
-        }
242
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
243
-            '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.',
244
-            'event_espresso'
245
-        );
246
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
247
-            'An error occurred! Please refresh the page and try again.',
248
-            'event_espresso'
249
-        );
250
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
251
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
252
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
253
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
254
-            'This transaction has been overpaid ! Payments Total',
255
-            'event_espresso'
256
-        );
257
-    }
258
-
259
-
260
-    public function admin_notices()
261
-    {
262
-        // noop
263
-    }
264
-
265
-
266
-    public function admin_footer_scripts()
267
-    {
268
-        // noop
269
-    }
270
-
271
-
272
-    /**
273
-     * _set_transaction_status_array
274
-     * sets list of transaction statuses
275
-     *
276
-     * @access private
277
-     * @return void
278
-     * @throws EE_Error
279
-     * @throws InvalidArgumentException
280
-     * @throws InvalidDataTypeException
281
-     * @throws InvalidInterfaceException
282
-     * @throws ReflectionException
283
-     */
284
-    private function _set_transaction_status_array()
285
-    {
286
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
287
-    }
288
-
289
-
290
-    /**
291
-     * get_transaction_status_array
292
-     * return the transaction status array for wp_list_table
293
-     *
294
-     * @access public
295
-     * @return array
296
-     */
297
-    public function get_transaction_status_array()
298
-    {
299
-        return self::$_txn_status;
300
-    }
301
-
302
-
303
-    /**
304
-     *    get list of payment statuses
305
-     *
306
-     * @access private
307
-     * @return void
308
-     * @throws EE_Error
309
-     * @throws InvalidArgumentException
310
-     * @throws InvalidDataTypeException
311
-     * @throws InvalidInterfaceException
312
-     * @throws ReflectionException
313
-     */
314
-    private function _get_payment_status_array()
315
-    {
316
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
317
-        $this->_template_args['payment_status'] = self::$_pay_status;
318
-    }
319
-
320
-
321
-    /**
322
-     *    _add_screen_options_default
323
-     *
324
-     * @access protected
325
-     * @return void
326
-     * @throws InvalidArgumentException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     */
330
-    protected function _add_screen_options_default()
331
-    {
332
-        $this->_per_page_screen_option();
333
-    }
334
-
335
-
336
-    /**
337
-     * load_scripts_styles
338
-     *
339
-     * @access public
340
-     * @return void
341
-     */
342
-    public function load_scripts_styles()
343
-    {
344
-        // enqueue style
345
-        wp_register_style(
346
-            'espresso_txn',
347
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
348
-            [],
349
-            EVENT_ESPRESSO_VERSION
350
-        );
351
-        wp_enqueue_style('espresso_txn');
352
-        // scripts
353
-        wp_register_script(
354
-            'espresso_txn',
355
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
356
-            [
357
-                'ee_admin_js',
358
-                'ee-datepicker',
359
-                'jquery-ui-datepicker',
360
-                'jquery-ui-draggable',
361
-                'ee-dialog',
362
-                'ee-accounting',
363
-                'ee-serialize-full-array',
364
-            ],
365
-            EVENT_ESPRESSO_VERSION,
366
-            true
367
-        );
368
-        wp_enqueue_script('espresso_txn');
369
-    }
370
-
371
-
372
-    /**
373
-     *    load_scripts_styles_view_transaction
374
-     *
375
-     * @access public
376
-     * @return void
377
-     */
378
-    public function load_scripts_styles_view_transaction()
379
-    {
380
-        // styles
381
-        wp_enqueue_style('espresso-ui-theme');
382
-    }
383
-
384
-
385
-    /**
386
-     *    load_scripts_styles_default
387
-     *
388
-     * @access public
389
-     * @return void
390
-     */
391
-    public function load_scripts_styles_default()
392
-    {
393
-        // styles
394
-        wp_enqueue_style('espresso-ui-theme');
395
-    }
396
-
397
-
398
-    /**
399
-     *    _set_list_table_views_default
400
-     *
401
-     * @access protected
402
-     * @return void
403
-     */
404
-    protected function _set_list_table_views_default()
405
-    {
406
-        $this->_views = [
407
-            'all'        => [
408
-                'slug'  => 'all',
409
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
410
-                'count' => 0,
411
-            ],
412
-            'abandoned'  => [
413
-                'slug'  => 'abandoned',
414
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
415
-                'count' => 0,
416
-            ],
417
-            'incomplete' => [
418
-                'slug'  => 'incomplete',
419
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
420
-                'count' => 0,
421
-            ],
422
-        ];
423
-        if (
424
-            /**
425
-             * Filters whether a link to the "Failed Transactions" list table
426
-             * appears on the Transactions Admin Page list table.
427
-             * List display can be turned back on via the following:
428
-             * add_filter(
429
-             *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
430
-             *     '__return_true'
431
-             * );
432
-             *
433
-             * @param boolean                 $display_failed_txns_list
434
-             * @param Transactions_Admin_Page $this
435
-             * @since 4.9.70.p
436
-             */
437
-        apply_filters(
438
-            'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
439
-            false,
440
-            $this
441
-        )
442
-        ) {
443
-            $this->_views['failed'] = [
444
-                'slug'  => 'failed',
445
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
446
-                'count' => 0,
447
-            ];
448
-        }
449
-    }
450
-
451
-
452
-    /**
453
-     * _set_transaction_object
454
-     * This sets the _transaction property for the transaction details screen
455
-     *
456
-     * @access private
457
-     * @return void
458
-     * @throws EE_Error
459
-     * @throws InvalidArgumentException
460
-     * @throws RuntimeException
461
-     * @throws InvalidDataTypeException
462
-     * @throws InvalidInterfaceException
463
-     * @throws ReflectionException
464
-     */
465
-    private function _set_transaction_object()
466
-    {
467
-        if ($this->_transaction instanceof EE_Transaction) {
468
-            return;
469
-        } //get out we've already set the object
470
-
471
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
472
-
473
-        // get transaction object
474
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
475
-        $this->_session     = $this->_transaction instanceof EE_Transaction
476
-            ? $this->_transaction->session_data()
477
-            : null;
478
-        if ($this->_transaction instanceof EE_Transaction) {
479
-            $this->_transaction->verify_abandoned_transaction_status();
480
-        }
481
-
482
-        if (! $this->_transaction instanceof EE_Transaction) {
483
-            $error_msg = sprintf(
484
-                esc_html__(
485
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
486
-                    'event_espresso'
487
-                ),
488
-                $TXN_ID
489
-            );
490
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
491
-        }
492
-    }
493
-
494
-
495
-    /**
496
-     *    _transaction_legend_items
497
-     *
498
-     * @access protected
499
-     * @return array
500
-     * @throws EE_Error
501
-     * @throws InvalidArgumentException
502
-     * @throws ReflectionException
503
-     * @throws InvalidDataTypeException
504
-     * @throws InvalidInterfaceException
505
-     */
506
-    protected function _transaction_legend_items()
507
-    {
508
-        EE_Registry::instance()->load_helper('MSG_Template');
509
-        $items = [];
510
-
511
-        if (
512
-            $this->capabilities->current_user_can(
513
-                'ee_read_global_messages',
514
-                'view_filtered_messages'
515
-            )
516
-        ) {
517
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
518
-            if (
519
-                is_array($related_for_icon)
520
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
521
-            ) {
522
-                $items['view_related_messages'] = [
523
-                    'class' => $related_for_icon['css_class'],
524
-                    'desc'  => $related_for_icon['label'],
525
-                ];
526
-            }
527
-        }
528
-
529
-        $items = apply_filters(
530
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
531
-            array_merge(
532
-                $items,
533
-                [
534
-                    'view_details'          => [
535
-                        'class' => 'dashicons dashicons-cart',
536
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
537
-                    ],
538
-                    'view_invoice'          => [
539
-                        'class' => 'dashicons dashicons-media-spreadsheet',
540
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
541
-                    ],
542
-                    'view_receipt'          => [
543
-                        'class' => 'dashicons dashicons-text-page',
544
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
545
-                    ],
546
-                    'view_registration'     => [
547
-                        'class' => 'dashicons dashicons-clipboard',
548
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
549
-                    ],
550
-                    'payment_overview_link' => [
551
-                        'class' => 'dashicons dashicons-money',
552
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
553
-                    ],
554
-                ]
555
-            )
556
-        );
557
-
558
-        if (
559
-            EEH_MSG_Template::is_mt_active('payment_reminder')
560
-            && $this->capabilities->current_user_can(
561
-                'ee_send_message',
562
-                'espresso_transactions_send_payment_reminder'
563
-            )
564
-        ) {
565
-            $items['send_payment_reminder'] = [
566
-                'class' => 'dashicons dashicons-email-alt',
567
-                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
568
-            ];
569
-        } else {
570
-            $items['blank*'] = [
571
-                'class' => '',
572
-                'desc'  => '',
573
-            ];
574
-        }
575
-        $more_items = apply_filters(
576
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
577
-            [
578
-                'overpaid'   => [
579
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
580
-                    'desc'  => EEH_Template::pretty_status(
581
-                        EEM_Transaction::overpaid_status_code,
582
-                        false,
583
-                        'sentence'
584
-                    ),
585
-                ],
586
-                'complete'   => [
587
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
588
-                    'desc'  => EEH_Template::pretty_status(
589
-                        EEM_Transaction::complete_status_code,
590
-                        false,
591
-                        'sentence'
592
-                    ),
593
-                ],
594
-                'incomplete' => [
595
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
596
-                    'desc'  => EEH_Template::pretty_status(
597
-                        EEM_Transaction::incomplete_status_code,
598
-                        false,
599
-                        'sentence'
600
-                    ),
601
-                ],
602
-                'abandoned'  => [
603
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
604
-                    'desc'  => EEH_Template::pretty_status(
605
-                        EEM_Transaction::abandoned_status_code,
606
-                        false,
607
-                        'sentence'
608
-                    ),
609
-                ],
610
-                'failed'     => [
611
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
612
-                    'desc'  => EEH_Template::pretty_status(
613
-                        EEM_Transaction::failed_status_code,
614
-                        false,
615
-                        'sentence'
616
-                    ),
617
-                ],
618
-            ]
619
-        );
620
-
621
-        return array_merge($items, $more_items);
622
-    }
623
-
624
-
625
-    /**
626
-     *    _transactions_overview_list_table
627
-     *
628
-     * @access protected
629
-     * @return void
630
-     * @throws DomainException
631
-     * @throws EE_Error
632
-     * @throws InvalidArgumentException
633
-     * @throws InvalidDataTypeException
634
-     * @throws InvalidInterfaceException
635
-     * @throws ReflectionException
636
-     */
637
-    protected function _transactions_overview_list_table()
638
-    {
639
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
640
-
641
-        $EVT_ID                                    = $this->request->getRequestParam('EVT_ID', 0, 'int');
642
-        $event                                     = EEM_Event::instance()->get_one_by_ID($EVT_ID);
643
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
644
-            ? sprintf(
645
-                esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
646
-                '<h3>',
647
-                '<a href="'
648
-                . EE_Admin_Page::add_query_args_and_nonce(
649
-                    ['action' => 'edit', 'post' => $event->ID()],
650
-                    EVENTS_ADMIN_URL
651
-                )
652
-                . '" aria-label="'
653
-                . esc_attr__('Click to Edit event', 'event_espresso')
654
-                . '">' . $event->name() . '</a>',
655
-                '</h3>'
656
-            )
657
-            : '';
658
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
659
-        $this->display_admin_list_table_page_with_no_sidebar();
660
-    }
661
-
662
-
663
-    /**
664
-     *    _transaction_details
665
-     * generates HTML for the View Transaction Details Admin page
666
-     *
667
-     * @access protected
668
-     * @return void
669
-     * @throws DomainException
670
-     * @throws EE_Error
671
-     * @throws InvalidArgumentException
672
-     * @throws InvalidDataTypeException
673
-     * @throws InvalidInterfaceException
674
-     * @throws RuntimeException
675
-     * @throws ReflectionException
676
-     */
677
-    protected function _transaction_details()
678
-    {
679
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
680
-
681
-        $this->_set_transaction_status_array();
682
-
683
-        $this->_template_args                      = [];
684
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
685
-
686
-        $this->_set_transaction_object();
687
-
688
-        if (! $this->_transaction instanceof EE_Transaction) {
689
-            return;
690
-        }
691
-
692
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
693
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
694
-
695
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
696
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
697
-
698
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
699
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
700
-        $this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
701
-
702
-        $txn_total  = $this->_transaction->total();
703
-        $total_paid = $this->_transaction->paid();
704
-        $amount_due = $txn_total - $total_paid;
705
-
706
-        $this->_template_args['grand_total'] = $txn_total;
707
-        $this->_template_args['total_paid']  = $total_paid;
708
-
709
-        $this->_template_args['amount_due']     = EEH_Template::format_currency($amount_due, false, false);
710
-        $this->_template_args['amount_due_raw'] = $amount_due;
711
-
712
-        $this->_template_args['amount_due_class'] = '';
713
-
714
-        if ($txn_total === (float) 0) {
715
-            // free event
716
-            $this->_template_args['amount_due'] = false;
717
-        } elseif ($amount_due < (float) 0) {
718
-            // overpaid
719
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
720
-        } elseif ($amount_due > (float) 0) {
721
-            // monies owing
722
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
723
-        } elseif ($total_paid === (float) 0) {
724
-            // no payments made yet
725
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
726
-        }
727
-
728
-        $payment_method = $this->_transaction->payment_method();
729
-
730
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
731
-            ? $payment_method->admin_name()
732
-            : esc_html__('Unknown', 'event_espresso');
733
-
734
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
735
-        // link back to overview
736
-        $this->_template_args['txn_overview_url'] = $this->request->getServerParam(
737
-            'HTTP_REFERER',
738
-            TXN_ADMIN_URL
739
-        );
740
-
741
-
742
-        // next link
743
-        $next_txn                                 = $this->_transaction->next(
744
-            null,
745
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
746
-            'TXN_ID'
747
-        );
748
-        $this->_template_args['next_transaction'] = $next_txn
749
-            ? $this->_next_link(
750
-                EE_Admin_Page::add_query_args_and_nonce(
751
-                    ['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
752
-                    TXN_ADMIN_URL
753
-                ),
754
-                'dashicons dashicons-arrow-right ee-icon-size-22'
755
-            )
756
-            : '';
757
-        // previous link
758
-        $previous_txn                                 = $this->_transaction->previous(
759
-            null,
760
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
761
-            'TXN_ID'
762
-        );
763
-        $this->_template_args['previous_transaction'] = $previous_txn
764
-            ? $this->_previous_link(
765
-                EE_Admin_Page::add_query_args_and_nonce(
766
-                    ['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
767
-                    TXN_ADMIN_URL
768
-                ),
769
-                'dashicons dashicons-arrow-left ee-icon-size-22'
770
-            )
771
-            : '';
772
-
773
-        $EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
774
-        $event_name    = $this->request->getRequestParam('event_name');
775
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
776
-
777
-        // were we just redirected here after adding a new registration ???
778
-        if ($EVT_ID && $event_name && $redirect_from) {
779
-            if (
780
-                $this->capabilities->current_user_can(
781
-                    'ee_edit_registrations',
782
-                    'espresso_registrations_new_registration',
783
-                    $EVT_ID
784
-                )
785
-            ) {
786
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
787
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
788
-                    [
789
-                        'page'     => 'espresso_registrations',
790
-                        'action'   => 'new_registration',
791
-                        'return'   => 'default',
792
-                        'TXN_ID'   => $this->_transaction->ID(),
793
-                        'event_id' => $EVT_ID,
794
-                    ],
795
-                    REG_ADMIN_URL
796
-                );
797
-                $this->_admin_page_title .= '">';
798
-
799
-                $this->_admin_page_title .= sprintf(
800
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
801
-                    htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
802
-                );
803
-                $this->_admin_page_title .= '</a>';
804
-            }
805
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
806
-        }
807
-        // grab messages at the last second
808
-        $this->_template_args['notices'] = EE_Error::get_notices();
809
-        // path to template
810
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
811
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
812
-            $template_path,
813
-            $this->_template_args,
814
-            true
815
-        );
816
-
817
-        // the details template wrapper
818
-        $this->display_admin_page_with_sidebar();
819
-    }
820
-
821
-
822
-    /**
823
-     *        _transaction_details_metaboxes
824
-     *
825
-     * @access protected
826
-     * @return void
827
-     * @throws EE_Error
828
-     * @throws InvalidArgumentException
829
-     * @throws InvalidDataTypeException
830
-     * @throws InvalidInterfaceException
831
-     * @throws RuntimeException
832
-     * @throws ReflectionException
833
-     */
834
-    protected function _transaction_details_metaboxes()
835
-    {
836
-        $this->_set_transaction_object();
837
-
838
-        if (! $this->_transaction instanceof EE_Transaction) {
839
-            return;
840
-        }
841
-        $this->addMetaBox(
842
-            'edit-txn-details-mbox',
843
-            '<span>' . esc_html__('Transaction Details', 'event_espresso')
844
-            . '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
845
-            [$this, 'txn_details_meta_box'],
846
-            $this->_wp_page_slug
847
-        );
848
-        $this->addMetaBox(
849
-            'edit-txn-attendees-mbox',
850
-            '<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
851
-            . '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
852
-            [$this, 'txn_attendees_meta_box'],
853
-            $this->_wp_page_slug,
854
-            'normal',
855
-            'high',
856
-            ['TXN_ID' => $this->_transaction->ID()]
857
-        );
858
-        $this->addMetaBox(
859
-            'edit-txn-registrant-mbox',
860
-            esc_html__('Primary Contact', 'event_espresso'),
861
-            [$this, 'txn_registrant_side_meta_box'],
862
-            $this->_wp_page_slug,
863
-            'side'
864
-        );
865
-        $this->addMetaBox(
866
-            'edit-txn-billing-info-mbox',
867
-            esc_html__('Billing Information', 'event_espresso'),
868
-            [$this, 'txn_billing_info_side_meta_box'],
869
-            $this->_wp_page_slug,
870
-            'side'
871
-        );
872
-    }
873
-
874
-
875
-    /**
876
-     * Callback for transaction actions metabox.
877
-     *
878
-     * @param EE_Transaction|null $transaction
879
-     * @return string
880
-     * @throws DomainException
881
-     * @throws EE_Error
882
-     * @throws InvalidArgumentException
883
-     * @throws InvalidDataTypeException
884
-     * @throws InvalidInterfaceException
885
-     * @throws ReflectionException
886
-     * @throws RuntimeException
887
-     */
888
-    public function getActionButtons(EE_Transaction $transaction = null)
889
-    {
890
-        $content = '';
891
-        $actions = [];
892
-        if (! $transaction instanceof EE_Transaction) {
893
-            return $content;
894
-        }
895
-        /** @var EE_Registration $primary_registration */
896
-        $primary_registration = $transaction->primary_registration();
897
-        $attendee             = $primary_registration instanceof EE_Registration
898
-            ? $primary_registration->attendee()
899
-            : null;
900
-
901
-        if (
902
-            $attendee instanceof EE_Attendee
903
-            && $this->capabilities->current_user_can(
904
-                'ee_send_message',
905
-                'espresso_transactions_send_payment_reminder'
906
-            )
907
-        ) {
908
-            $actions['payment_reminder'] =
909
-                EEH_MSG_Template::is_mt_active('payment_reminder')
910
-                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
911
-                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
912
-                    ? EEH_Template::get_button_or_link(
913
-                    EE_Admin_Page::add_query_args_and_nonce(
914
-                        [
915
-                            'action'      => 'send_payment_reminder',
916
-                            'TXN_ID'      => $this->_transaction->ID(),
917
-                            'redirect_to' => 'view_transaction',
918
-                        ],
919
-                        TXN_ADMIN_URL
920
-                    ),
921
-                    esc_html__(' Send Payment Reminder', 'event_espresso'),
922
-                    'button button--secondary',
923
-                    'dashicons dashicons-email-alt'
924
-                )
925
-                    : '';
926
-        }
927
-
928
-        if (
929
-            $this->capabilities->current_user_can(
930
-                'ee_edit_payments',
931
-                'espresso_transactions_recalculate_line_items'
932
-            )
933
-        ) {
934
-            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
935
-                EE_Admin_Page::add_query_args_and_nonce(
936
-                    [
937
-                        'action'      => 'espresso_recalculate_line_items',
938
-                        'TXN_ID'      => $this->_transaction->ID(),
939
-                        'redirect_to' => 'view_transaction',
940
-                    ],
941
-                    TXN_ADMIN_URL
942
-                ),
943
-                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
944
-                'button button--secondary',
945
-                'dashicons dashicons-update'
946
-            );
947
-        }
948
-
949
-        if (
950
-            $primary_registration instanceof EE_Registration
951
-            && EEH_MSG_Template::is_mt_active('receipt')
952
-        ) {
953
-            $actions['receipt'] = EEH_Template::get_button_or_link(
954
-                $primary_registration->receipt_url(),
955
-                esc_html__('View Receipt', 'event_espresso'),
956
-                'button button--secondary',
957
-                'dashicons dashicons-text-page'
958
-            );
959
-        }
960
-
961
-        if (
962
-            $primary_registration instanceof EE_Registration
963
-            && EEH_MSG_Template::is_mt_active('invoice')
964
-        ) {
965
-            $actions['invoice'] = EEH_Template::get_button_or_link(
966
-                $primary_registration->invoice_url(),
967
-                esc_html__('View Invoice', 'event_espresso'),
968
-                'button button--secondary',
969
-                'dashicons dashicons-media-spreadsheet'
970
-            );
971
-        }
972
-        $actions = array_filter(
973
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
974
-        );
975
-        if ($actions) {
976
-            $content .= implode('', $actions);
977
-        }
978
-        return $content;
979
-    }
980
-
981
-
982
-    /**
983
-     * txn_details_meta_box
984
-     * generates HTML for the Transaction main meta box
985
-     *
986
-     * @return void
987
-     * @throws DomainException
988
-     * @throws EE_Error
989
-     * @throws InvalidArgumentException
990
-     * @throws InvalidDataTypeException
991
-     * @throws InvalidInterfaceException
992
-     * @throws RuntimeException
993
-     * @throws ReflectionException
994
-     */
995
-    public function txn_details_meta_box()
996
-    {
997
-        $this->_set_transaction_object();
998
-        $this->_template_args['TXN_ID']              = $this->_transaction->ID();
999
-        $this->_template_args['attendee']            =
1000
-            $this->_transaction->primary_registration() instanceof EE_Registration
1001
-                ? $this->_transaction->primary_registration()->attendee()
1002
-                : null;
1003
-        $this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1004
-            'ee_edit_payments',
1005
-            'apply_payment_or_refund_from_registration_details'
1006
-        );
1007
-        $this->_template_args['can_delete_payments'] = $this->capabilities->current_user_can(
1008
-            'ee_delete_payments',
1009
-            'delete_payment_from_registration_details'
1010
-        );
1011
-
1012
-        // get line table
1013
-        EEH_Autoloader::register_line_item_display_autoloaders();
1014
-        $Line_Item_Display                       = new EE_Line_Item_Display(
1015
-            'admin_table',
1016
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1017
-        );
1018
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1019
-            $this->_transaction->total_line_item()
1020
-        );
1021
-        $this->_template_args['REG_code']        =
1022
-            $this->_transaction->primary_registration() instanceof EE_Registration
1023
-                ? $this->_transaction->primary_registration()->reg_code()
1024
-                : null;
1025
-        // process taxes
1026
-        $taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1027
-        $this->_template_args['taxes'] = ! empty($taxes)
1028
-            ? $taxes
1029
-            : false;
1030
-
1031
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1032
-            $this->_transaction->total(),
1033
-            false,
1034
-            false
1035
-        );
1036
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1037
-        $this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1038
-
1039
-        // process payment details
1040
-        $payments = $this->_transaction->payments();
1041
-        if (! empty($payments)) {
1042
-            $this->_template_args['payments']              = $payments;
1043
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1044
-        } else {
1045
-            $this->_template_args['payments']              = false;
1046
-            $this->_template_args['existing_reg_payments'] = [];
1047
-        }
1048
-
1049
-        $this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1050
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1051
-            ['action' => 'espresso_delete_payment'],
1052
-            TXN_ADMIN_URL
1053
-        );
1054
-
1055
-        if (isset($txn_details['invoice_number'])) {
1056
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1057
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1058
-                'Invoice Number',
1059
-                'event_espresso'
1060
-            );
1061
-        }
1062
-
1063
-        $this->_template_args['txn_details']['registration_session']['value'] =
1064
-            $this->_transaction->primary_registration() instanceof EE_Registration
1065
-                ? $this->_transaction->primary_registration()->session_ID()
1066
-                : null;
1067
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1068
-            'Registration Session',
1069
-            'event_espresso'
1070
-        );
1071
-
1072
-        $this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1073
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1074
-            'Transaction placed from IP',
1075
-            'event_espresso'
1076
-        );
1077
-
1078
-        $this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1079
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1080
-            'Registrant User Agent',
1081
-            'event_espresso'
1082
-        );
1083
-
1084
-        $reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1085
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1086
-            if ($reg_step_status === true) {
1087
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1088
-                              . sprintf(
1089
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1090
-                                  ucwords(str_replace('_', ' ', $reg_step))
1091
-                              )
1092
-                              . '</div>';
1093
-            } elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1094
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1095
-                              . sprintf(
1096
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1097
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1098
-                                  date(
1099
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1100
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1101
-                                  )
1102
-                              )
1103
-                              . '</div>';
1104
-            } else {
1105
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1106
-                              . sprintf(
1107
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1108
-                                  ucwords(str_replace('_', ' ', $reg_step))
1109
-                              )
1110
-                              . '</div>';
1111
-            }
1112
-        }
1113
-        $reg_steps                                                 .= '</ul>';
1114
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1115
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1116
-            'Registration Step Progress',
1117
-            'event_espresso'
1118
-        );
1119
-
1120
-
1121
-        $this->_get_registrations_to_apply_payment_to();
1122
-        $this->_get_payment_methods($payments);
1123
-        $this->_get_payment_status_array();
1124
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1125
-
1126
-        $this->_template_args['transaction_form_url']    = add_query_arg(
1127
-            [
1128
-                'action'  => 'edit_transaction',
1129
-                'process' => 'transaction',
1130
-            ],
1131
-            TXN_ADMIN_URL
1132
-        );
1133
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(
1134
-            [
1135
-                'page'   => 'espresso_transactions',
1136
-                'action' => 'espresso_apply_payment',
1137
-            ],
1138
-            TXN_ADMIN_URL
1139
-        );
1140
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1141
-            [
1142
-                'page'   => 'espresso_transactions',
1143
-                'action' => 'espresso_delete_payment',
1144
-            ],
1145
-            TXN_ADMIN_URL
1146
-        );
1147
-
1148
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1149
-
1150
-        // 'espresso_delete_payment_nonce'
1151
-
1152
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1153
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * _get_registration_payment_IDs
1159
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1160
-     *
1161
-     * @access protected
1162
-     * @param EE_Payment[] $payments
1163
-     * @return array
1164
-     * @throws EE_Error
1165
-     * @throws InvalidArgumentException
1166
-     * @throws InvalidDataTypeException
1167
-     * @throws InvalidInterfaceException
1168
-     * @throws ReflectionException
1169
-     */
1170
-    protected function _get_registration_payment_IDs($payments = [])
1171
-    {
1172
-        $existing_reg_payments = [];
1173
-        // get all reg payments for these payments
1174
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1175
-            [
1176
-                [
1177
-                    'PAY_ID' => [
1178
-                        'IN',
1179
-                        array_keys($payments),
1180
-                    ],
1181
-                ],
1182
-            ]
1183
-        );
1184
-        if (! empty($reg_payments)) {
1185
-            foreach ($payments as $payment) {
1186
-                if (! $payment instanceof EE_Payment) {
1187
-                    continue;
1188
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1189
-                    $existing_reg_payments[ $payment->ID() ] = [];
1190
-                }
1191
-                foreach ($reg_payments as $reg_payment) {
1192
-                    if (
1193
-                        $reg_payment instanceof EE_Registration_Payment
1194
-                        && $reg_payment->payment_ID() === $payment->ID()
1195
-                    ) {
1196
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1197
-                    }
1198
-                }
1199
-            }
1200
-        }
1201
-
1202
-        return $existing_reg_payments;
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * _get_registrations_to_apply_payment_to
1208
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1209
-     * which allows the admin to only apply the payment to the specific registrations
1210
-     *
1211
-     * @access protected
1212
-     * @return void
1213
-     * @throws EE_Error
1214
-     * @throws InvalidArgumentException
1215
-     * @throws InvalidDataTypeException
1216
-     * @throws InvalidInterfaceException
1217
-     * @throws ReflectionException
1218
-     */
1219
-    protected function _get_registrations_to_apply_payment_to()
1220
-    {
1221
-        // we want any registration with an active status (ie: not deleted or cancelled)
1222
-        $query_params                      = [
1223
-            [
1224
-                'STS_ID' => [
1225
-                    'IN',
1226
-                    [
1227
-                        RegStatus::APPROVED,
1228
-                        RegStatus::PENDING_PAYMENT,
1229
-                        RegStatus::AWAITING_REVIEW,
1230
-                    ],
1231
-                ],
1232
-            ],
1233
-        ];
1234
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1235
-                '',
1236
-                'txn-admin-apply-payment-to-registrations-dv',
1237
-                '',
1238
-                'clear: both; margin: 1.5em 0 0; display: none;'
1239
-            );
1240
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1241
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1242
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1243
-            EEH_HTML::tr(
1244
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1245
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1246
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1247
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1248
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1249
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1250
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1251
-            )
1252
-        );
1253
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1254
-        // get registrations for TXN
1255
-        $registrations         = $this->_transaction->registrations($query_params);
1256
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1257
-        foreach ($registrations as $registration) {
1258
-            if ($registration instanceof EE_Registration) {
1259
-                $attendee_name                     = $registration->attendee() instanceof EE_Attendee
1260
-                    ? $registration->attendee()->full_name()
1261
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1262
-                $owing                             = $registration->final_price() - $registration->paid();
1263
-                $taxable                           = $registration->ticket()->taxable()
1264
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1265
-                    : '';
1266
-                $checked                           = empty($existing_reg_payments)
1267
-                                                     || in_array($registration->ID(), $existing_reg_payments, true)
1268
-                    ? ' checked'
1269
-                    : '';
1270
-                $disabled                          = $registration->final_price() > 0
1271
-                    ? ''
1272
-                    : ' disabled';
1273
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1274
-                    EEH_HTML::td($registration->ID()) .
1275
-                    EEH_HTML::td($attendee_name) .
1276
-                    EEH_HTML::td(
1277
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1278
-                    ) .
1279
-                    EEH_HTML::td($registration->event_name()) .
1280
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1281
-                    EEH_HTML::td(
1282
-                        EEH_Template::format_currency($owing),
1283
-                        '',
1284
-                        'txn-admin-payment-owing-td jst-cntr'
1285
-                    ) .
1286
-                    EEH_HTML::td(
1287
-                        '<input type="checkbox" value="' . $registration->ID()
1288
-                        . '" name="txn_admin_payment[registrations]"'
1289
-                        . $checked . $disabled . '>',
1290
-                        '',
1291
-                        'jst-cntr'
1292
-                    ),
1293
-                    'apply-payment-registration-row-' . $registration->ID()
1294
-                );
1295
-            }
1296
-        }
1297
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1298
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1299
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1300
-        $registrations_to_apply_payment_to                         .= EEH_HTML::p(
1301
-            esc_html__(
1302
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1303
-                'event_espresso'
1304
-            ),
1305
-            '',
1306
-            'clear description'
1307
-        );
1308
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1309
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1310
-    }
1311
-
1312
-
1313
-    /**
1314
-     * _get_reg_status_selection
1315
-     *
1316
-     * @return void
1317
-     * @throws EE_Error
1318
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1319
-     *         instead of events.
1320
-     * @access protected
1321
-     */
1322
-    protected function _get_reg_status_selection()
1323
-    {
1324
-        // first get all possible statuses
1325
-        $statuses = EEM_Registration::reg_status_array([], true);
1326
-        // let's add a "don't change" option.
1327
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1328
-        $status_array                                        = array_merge($status_array, $statuses);
1329
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1330
-            'txn_reg_status_change[reg_status]',
1331
-            $status_array,
1332
-            'NAN',
1333
-            'id="txn-admin-payment-reg-status-inp"',
1334
-            'txn-reg-status-change-reg-status'
1335
-        );
1336
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1337
-            'delete_txn_reg_status_change[reg_status]',
1338
-            $status_array,
1339
-            'NAN',
1340
-            'delete-txn-admin-payment-reg-status-inp',
1341
-            'delete-txn-reg-status-change-reg-status'
1342
-        );
1343
-    }
1344
-
1345
-
1346
-    /**
1347
-     *    _get_payment_methods
1348
-     * Gets all the payment methods available generally, or the ones that are already
1349
-     * selected on these payments (in case their payment methods are no longer active).
1350
-     * Has the side-effect of updating the template args' payment_methods item
1351
-     *
1352
-     * @access private
1353
-     * @param EE_Payment[] to show on this page
1354
-     * @return void
1355
-     * @throws EE_Error
1356
-     * @throws InvalidArgumentException
1357
-     * @throws InvalidDataTypeException
1358
-     * @throws InvalidInterfaceException
1359
-     * @throws ReflectionException
1360
-     */
1361
-    private function _get_payment_methods($payments = [])
1362
-    {
1363
-        $payment_methods_of_payments = [];
1364
-        foreach ($payments as $payment) {
1365
-            if ($payment instanceof EE_Payment) {
1366
-                $payment_methods_of_payments[] = $payment->ID();
1367
-            }
1368
-        }
1369
-        if ($payment_methods_of_payments) {
1370
-            $query_args = [
1371
-                [
1372
-                    'OR*payment_method_for_payment' => [
1373
-                        'PMD_ID'    => ['IN', $payment_methods_of_payments],
1374
-                        'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1375
-                    ],
1376
-                ],
1377
-            ];
1378
-        } else {
1379
-            $query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1380
-        }
1381
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1382
-    }
1383
-
1384
-
1385
-    /**
1386
-     * txn_attendees_meta_box
1387
-     *    generates HTML for the Attendees Transaction main meta box
1388
-     *
1389
-     * @access public
1390
-     * @param WP_Post $post
1391
-     * @param array   $metabox
1392
-     * @return void
1393
-     * @throws DomainException
1394
-     * @throws EE_Error
1395
-     * @throws InvalidArgumentException
1396
-     * @throws InvalidDataTypeException
1397
-     * @throws InvalidInterfaceException
1398
-     * @throws ReflectionException
1399
-     */
1400
-    public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1401
-    {
1402
-        /** @noinspection NonSecureExtractUsageInspection */
1403
-        extract($metabox['args']);
1404
-        $this->_template_args['post']            = $post;
1405
-        $this->_template_args['event_attendees'] = [];
1406
-        // process items in cart
1407
-        $line_items = $this->_transaction->get_many_related(
1408
-            'Line_Item',
1409
-            [['LIN_type' => 'line-item']]
1410
-        );
1411
-        if (! empty($line_items)) {
1412
-            foreach ($line_items as $item) {
1413
-                if ($item instanceof EE_Line_Item) {
1414
-                    switch ($item->OBJ_type()) {
1415
-                        case 'Event':
1416
-                            break;
1417
-                        case 'Ticket':
1418
-                            $ticket = $item->ticket();
1419
-                            // right now we're only handling tickets here.
1420
-                            // Cause its expected that only tickets will have attendees right?
1421
-                            if (! $ticket instanceof EE_Ticket) {
1422
-                                break;
1423
-                            }
1424
-                            try {
1425
-                                $event_name = $ticket->get_event_name();
1426
-                            } catch (Exception $e) {
1427
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1428
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1429
-                            }
1430
-                            $event_name   .= ' - ' . $item->name();
1431
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1432
-                            // now get all of the registrations for this transaction that use this ticket
1433
-                            $registrations = $ticket->registrations(
1434
-                                [['TXN_ID' => $this->_transaction->ID()]]
1435
-                            );
1436
-                            foreach ($registrations as $registration) {
1437
-                                if (! $registration instanceof EE_Registration) {
1438
-                                    break;
1439
-                                }
1440
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1441
-                                    = $registration->status_ID();
1442
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1443
-                                    = $registration->count();
1444
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1445
-                                    = $event_name;
1446
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1447
-                                    = $ticket_price;
1448
-                                // attendee info
1449
-                                $attendee = $registration->get_first_related('Attendee');
1450
-                                if ($attendee instanceof EE_Attendee) {
1451
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1452
-                                        = $attendee->ID();
1453
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1454
-                                        = $attendee->full_name();
1455
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1456
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1457
-                                          . esc_html__(
1458
-                                              ' Event',
1459
-                                              'event_espresso'
1460
-                                          )
1461
-                                          . '">' . $attendee->email() . '</a>';
1462
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1463
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1464
-                                } else {
1465
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1466
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1467
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1468
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1469
-                                }
1470
-                            }
1471
-                            break;
1472
-                    }
1473
-                }
1474
-            }
1475
-
1476
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1477
-                [
1478
-                    'action'  => 'edit_transaction',
1479
-                    'process' => 'attendees',
1480
-                ],
1481
-                TXN_ADMIN_URL
1482
-            );
1483
-            echo EEH_Template::display_template(
1484
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1485
-                $this->_template_args,
1486
-                true
1487
-            );
1488
-        } else {
1489
-            printf(
1490
-                esc_html__(
1491
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1492
-                    'event_espresso'
1493
-                ),
1494
-                '<p class="important-notice">',
1495
-                '</p>'
1496
-            );
1497
-        }
1498
-    }
1499
-
1500
-
1501
-    /**
1502
-     * txn_registrant_side_meta_box
1503
-     * generates HTML for the Edit Transaction side meta box
1504
-     *
1505
-     * @access public
1506
-     * @return void
1507
-     * @throws DomainException
1508
-     * @throws EE_Error
1509
-     * @throws InvalidArgumentException
1510
-     * @throws InvalidDataTypeException
1511
-     * @throws InvalidInterfaceException
1512
-     * @throws ReflectionException
1513
-     */
1514
-    public function txn_registrant_side_meta_box()
1515
-    {
1516
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1517
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1518
-            : null;
1519
-        if (! $primary_att instanceof EE_Attendee) {
1520
-            $this->_template_args['no_attendee_message'] = esc_html__(
1521
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1522
-                'event_espresso'
1523
-            );
1524
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1525
-        }
1526
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1527
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1528
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1529
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1530
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1531
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1532
-            [
1533
-                'action' => 'edit_attendee',
1534
-                'post'   => $primary_att->ID(),
1535
-            ],
1536
-            REG_ADMIN_URL
1537
-        );
1538
-        // get formatted address for registrant
1539
-        $formatted_address                         = EEH_Address::format($primary_att);
1540
-        $formatted_address                         =
1541
-            $formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1542
-                ? $formatted_address
1543
-                : '';
1544
-        $this->_template_args['formatted_address'] = $formatted_address;
1545
-        echo EEH_Template::display_template(
1546
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1547
-            $this->_template_args,
1548
-            true
1549
-        );
1550
-    }
1551
-
1552
-
1553
-    /**
1554
-     * txn_billing_info_side_meta_box
1555
-     *    generates HTML for the Edit Transaction side meta box
1556
-     *
1557
-     * @access public
1558
-     * @return void
1559
-     * @throws DomainException
1560
-     */
1561
-    public function txn_billing_info_side_meta_box()
1562
-    {
1563
-        try {
1564
-            $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1565
-            $this->_template_args['billing_form_url'] = add_query_arg(
1566
-                ['action' => 'edit_transaction', 'process' => 'billing'],
1567
-                TXN_ADMIN_URL
1568
-            );
1569
-        } catch (Exception $e) {
1570
-            $this->_template_args['billing_form'] = [];
1571
-            $this->_template_args['billing_form_url'] = '';
1572
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1573
-        }
1574
-
1575
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1576
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1577
-    }
1578
-
1579
-
1580
-    /**
1581
-     * apply_payments_or_refunds
1582
-     *    registers a payment or refund made towards a transaction
1583
-     *
1584
-     * @access public
1585
-     * @return void
1586
-     * @throws EE_Error
1587
-     * @throws InvalidArgumentException
1588
-     * @throws ReflectionException
1589
-     * @throws RuntimeException
1590
-     * @throws InvalidDataTypeException
1591
-     * @throws InvalidInterfaceException
1592
-     */
1593
-    public function apply_payments_or_refunds()
1594
-    {
1595
-        $valid_data = $this->_validate_payment_request_data();
1596
-        $has_access = $this->capabilities->current_user_can(
1597
-            'ee_edit_payments',
1598
-            'apply_payment_or_refund_from_registration_details'
1599
-        );
1600
-        $TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1601
-        $amount     = 0;
1602
-        if (! empty($valid_data) && $has_access) {
1603
-            $PAY_ID = $valid_data['PAY_ID'];
1604
-            // save  the new payment
1605
-            $payment = $this->_create_payment_from_request_data($valid_data);
1606
-            $amount  = $payment->amount();
1607
-            // get the TXN for this payment
1608
-            $transaction = $payment->transaction();
1609
-            // verify transaction
1610
-            if ($transaction instanceof EE_Transaction) {
1611
-                // calculate_total_payments_and_update_status
1612
-                $this->_process_transaction_payments($transaction);
1613
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1614
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1615
-                // apply payment to registrations (if applicable)
1616
-                if (! empty($REG_IDs)) {
1617
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1618
-                    $this->_maybe_send_notifications();
1619
-                    // now process status changes for the same registrations
1620
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1621
-                }
1622
-                $this->_maybe_send_notifications($payment);
1623
-                // prepare to render page
1624
-                do_action(
1625
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1626
-                    $transaction,
1627
-                    $payment
1628
-                );
1629
-            } else {
1630
-                EE_Error::add_error(
1631
-                    esc_html__(
1632
-                        'A valid Transaction for this payment could not be retrieved.',
1633
-                        'event_espresso'
1634
-                    ),
1635
-                    __FILE__,
1636
-                    __FUNCTION__,
1637
-                    __LINE__
1638
-                );
1639
-            }
1640
-        } elseif ($has_access) {
1641
-            EE_Error::add_error(
1642
-                esc_html__(
1643
-                    'The payment form data could not be processed. Please try again.',
1644
-                    'event_espresso'
1645
-                ),
1646
-                __FILE__,
1647
-                __FUNCTION__,
1648
-                __LINE__
1649
-            );
1650
-        } else {
1651
-            EE_Error::add_error(
1652
-                esc_html__(
1653
-                    'You do not have access to apply payments or refunds to a registration.',
1654
-                    'event_espresso'
1655
-                ),
1656
-                __FILE__,
1657
-                __FUNCTION__,
1658
-                __LINE__
1659
-            );
1660
-        }
1661
-        $query_args = [
1662
-            'page'   => 'espresso_transactions',
1663
-            'action' => 'view_transaction',
1664
-            'TXN_ID' => $TXD_ID,
1665
-        ];
1666
-
1667
-        $this->_redirect_after_action(
1668
-            ! EE_Error::has_error(),
1669
-            $amount > 0
1670
-                ? esc_html__('payment', 'event_espresso')
1671
-                : esc_html__('refund', 'event_espresso'),
1672
-            esc_html__('processed', 'event_espresso'),
1673
-            $query_args
1674
-        );
1675
-    }
1676
-
1677
-
1678
-    /**
1679
-     * _validate_payment_request_data
1680
-     *
1681
-     * @return array
1682
-     * @throws EE_Error
1683
-     * @throws InvalidArgumentException
1684
-     * @throws InvalidDataTypeException
1685
-     * @throws InvalidInterfaceException
1686
-     */
1687
-    protected function _validate_payment_request_data()
1688
-    {
1689
-        if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1690
-            return [];
1691
-        }
1692
-        $payment_form = $this->_generate_payment_form_section();
1693
-        try {
1694
-            if ($payment_form->was_submitted()) {
1695
-                $payment_form->receive_form_submission();
1696
-                if (! $payment_form->is_valid()) {
1697
-                    $submission_error_messages = [];
1698
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1699
-                        if ($validation_error instanceof EE_Validation_Error) {
1700
-                            $form_input                  = $validation_error->get_form_section();
1701
-                            $submission_error_messages[] = sprintf(
1702
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1703
-                                $form_input instanceof EE_Form_Input_Base
1704
-                                    ? $form_input->html_label_text()
1705
-                                    : '',
1706
-                                $validation_error->getMessage()
1707
-                            );
1708
-                        }
1709
-                    }
1710
-                    EE_Error::add_error(
1711
-                        implode('<br />', $submission_error_messages),
1712
-                        __FILE__,
1713
-                        __FUNCTION__,
1714
-                        __LINE__
1715
-                    );
1716
-                    return [];
1717
-                }
1718
-            }
1719
-        } catch (EE_Error $e) {
1720
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1721
-            return [];
1722
-        }
1723
-
1724
-        return $payment_form->valid_data();
1725
-    }
1726
-
1727
-
1728
-    /**
1729
-     * _generate_payment_form_section
1730
-     *
1731
-     * @return EE_Form_Section_Proper
1732
-     * @throws EE_Error
1733
-     */
1734
-    protected function _generate_payment_form_section()
1735
-    {
1736
-        return new EE_Form_Section_Proper(
1737
-            [
1738
-                'name'        => 'txn_admin_payment',
1739
-                'subsections' => [
1740
-                    'PAY_ID'          => new EE_Text_Input(
1741
-                        [
1742
-                            'default'               => 0,
1743
-                            'required'              => false,
1744
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1745
-                            'validation_strategies' => [new EE_Int_Normalization()],
1746
-                        ]
1747
-                    ),
1748
-                    'TXN_ID'          => new EE_Text_Input(
1749
-                        [
1750
-                            'default'               => 0,
1751
-                            'required'              => true,
1752
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1753
-                            'validation_strategies' => [new EE_Int_Normalization()],
1754
-                        ]
1755
-                    ),
1756
-                    'type'            => new EE_Text_Input(
1757
-                        [
1758
-                            'default'               => 1,
1759
-                            'required'              => true,
1760
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1761
-                            'validation_strategies' => [new EE_Int_Normalization()],
1762
-                        ]
1763
-                    ),
1764
-                    'amount'          => new EE_Text_Input(
1765
-                        [
1766
-                            'default'               => 0,
1767
-                            'required'              => true,
1768
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1769
-                            'validation_strategies' => [new EE_Float_Normalization()],
1770
-                        ]
1771
-                    ),
1772
-                    'status'          => new EE_Text_Input(
1773
-                        [
1774
-                            'default'         => EEM_Payment::status_id_approved,
1775
-                            'required'        => true,
1776
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1777
-                        ]
1778
-                    ),
1779
-                    'PMD_ID'          => new EE_Text_Input(
1780
-                        [
1781
-                            'default'               => 2,
1782
-                            'required'              => true,
1783
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1784
-                            'validation_strategies' => [new EE_Int_Normalization()],
1785
-                        ]
1786
-                    ),
1787
-                    'date'            => new EE_Text_Input(
1788
-                        [
1789
-                            'default'         => time(),
1790
-                            'required'        => true,
1791
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1792
-                        ]
1793
-                    ),
1794
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1795
-                        [
1796
-                            'default'               => '',
1797
-                            'required'              => false,
1798
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1799
-                            'validation_strategies' => [
1800
-                                new EE_Max_Length_Validation_Strategy(
1801
-                                    esc_html__('Input too long', 'event_espresso'),
1802
-                                    100
1803
-                                ),
1804
-                            ],
1805
-                        ]
1806
-                    ),
1807
-                    'po_number'       => new EE_Text_Input(
1808
-                        [
1809
-                            'default'               => '',
1810
-                            'required'              => false,
1811
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1812
-                            'validation_strategies' => [
1813
-                                new EE_Max_Length_Validation_Strategy(
1814
-                                    esc_html__('Input too long', 'event_espresso'),
1815
-                                    100
1816
-                                ),
1817
-                            ],
1818
-                        ]
1819
-                    ),
1820
-                    'accounting'      => new EE_Text_Input(
1821
-                        [
1822
-                            'default'               => '',
1823
-                            'required'              => false,
1824
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1825
-                            'validation_strategies' => [
1826
-                                new EE_Max_Length_Validation_Strategy(
1827
-                                    esc_html__('Input too long', 'event_espresso'),
1828
-                                    100
1829
-                                ),
1830
-                            ],
1831
-                        ]
1832
-                    ),
1833
-                ],
1834
-            ]
1835
-        );
1836
-    }
1837
-
1838
-
1839
-    /**
1840
-     * _create_payment_from_request_data
1841
-     *
1842
-     * @param array $valid_data
1843
-     * @return EE_Payment
1844
-     * @throws EE_Error
1845
-     * @throws InvalidArgumentException
1846
-     * @throws InvalidDataTypeException
1847
-     * @throws InvalidInterfaceException
1848
-     * @throws ReflectionException
1849
-     */
1850
-    protected function _create_payment_from_request_data($valid_data)
1851
-    {
1852
-        $PAY_ID = $valid_data['PAY_ID'];
1853
-        // get payment amount
1854
-        $amount = $valid_data['amount']
1855
-            ? EEH_Money::strip_localized_money_formatting($valid_data['amount'])
1856
-            : 0;
1857
-        // payments have a type value of 1 and refunds have a type value of -1
1858
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1859
-        $amount = $valid_data['type'] < 0
1860
-            ? $amount * -1
1861
-            : $amount;
1862
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1863
-        $date    = $valid_data['date']
1864
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1865
-            : date('Y-m-d g:i a', current_time('timestamp'));
1866
-        $payment = EE_Payment::new_instance(
1867
-            [
1868
-                'TXN_ID'              => $valid_data['TXN_ID'],
1869
-                'STS_ID'              => $valid_data['status'],
1870
-                'PAY_timestamp'       => $date,
1871
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1872
-                'PMD_ID'              => $valid_data['PMD_ID'],
1873
-                'PAY_amount'          => $amount,
1874
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1875
-                'PAY_po_number'       => $valid_data['po_number'],
1876
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1877
-                'PAY_details'         => $valid_data,
1878
-                'PAY_ID'              => $PAY_ID,
1879
-            ],
1880
-            '',
1881
-            ['Y-m-d', 'g:i a']
1882
-        );
1883
-
1884
-        if (! $payment->save()) {
1885
-            EE_Error::add_error(
1886
-                sprintf(
1887
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1888
-                    $payment->ID()
1889
-                ),
1890
-                __FILE__,
1891
-                __FUNCTION__,
1892
-                __LINE__
1893
-            );
1894
-        }
1895
-
1896
-        return $payment;
1897
-    }
1898
-
1899
-
1900
-    /**
1901
-     * _process_transaction_payments
1902
-     *
1903
-     * @param EE_Transaction $transaction
1904
-     * @return void
1905
-     * @throws EE_Error
1906
-     * @throws InvalidArgumentException
1907
-     * @throws ReflectionException
1908
-     * @throws InvalidDataTypeException
1909
-     * @throws InvalidInterfaceException
1910
-     */
1911
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1912
-    {
1913
-        /** @type EE_Transaction_Payments $transaction_payments */
1914
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1915
-        // update the transaction with this payment
1916
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1917
-            EE_Error::add_success(
1918
-                esc_html__(
1919
-                    'The payment has been processed successfully.',
1920
-                    'event_espresso'
1921
-                ),
1922
-                __FILE__,
1923
-                __FUNCTION__,
1924
-                __LINE__
1925
-            );
1926
-        } else {
1927
-            EE_Error::add_error(
1928
-                esc_html__(
1929
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1930
-                    'event_espresso'
1931
-                ),
1932
-                __FILE__,
1933
-                __FUNCTION__,
1934
-                __LINE__
1935
-            );
1936
-        }
1937
-    }
1938
-
1939
-
1940
-    /**
1941
-     * _get_REG_IDs_to_apply_payment_to
1942
-     * returns a list of registration IDs that the payment will apply to
1943
-     *
1944
-     * @param EE_Payment $payment
1945
-     * @return array
1946
-     * @throws EE_Error
1947
-     * @throws InvalidArgumentException
1948
-     * @throws InvalidDataTypeException
1949
-     * @throws InvalidInterfaceException
1950
-     * @throws ReflectionException
1951
-     */
1952
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1953
-    {
1954
-        // grab array of IDs for specific registrations to apply changes to
1955
-        $apply_to_all = $this->request->getRequestParam(
1956
-            'txn_admin_payment[apply_to_all_registrations]',
1957
-            false,
1958
-            DataType::BOOL
1959
-        );
1960
-        $REG_IDs      = ! $apply_to_all
1961
-            ? $this->request->getRequestParam(
1962
-                'txn_admin_payment[registrations]',
1963
-                [],
1964
-                DataType::INT,
1965
-                true
1966
-            )
1967
-            : [];
1968
-        // nothing specified ? then get all reg IDs
1969
-        if ($apply_to_all || empty($REG_IDs)) {
1970
-            $registrations = $payment->transaction()->registrations(
1971
-                [
1972
-                    [
1973
-                        'STS_ID' => [
1974
-                            'NOT_IN', [ RegStatus::CANCELLED ]
1975
-                        ]
1976
-                    ]
1977
-                ]
1978
-            );
1979
-            $REG_IDs       = ! empty($registrations)
1980
-                ? array_keys($registrations)
1981
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1982
-        }
1983
-        // ensure that REG_IDs are integers and NOT strings
1984
-        return array_map('absint', $REG_IDs);
1985
-    }
1986
-
1987
-
1988
-    /**
1989
-     * @return array
1990
-     */
1991
-    public function existing_reg_payment_REG_IDs()
1992
-    {
1993
-        return $this->_existing_reg_payment_REG_IDs;
1994
-    }
1995
-
1996
-
1997
-    /**
1998
-     * @param array $existing_reg_payment_REG_IDs
1999
-     */
2000
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
2001
-    {
2002
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
2003
-    }
2004
-
2005
-
2006
-    /**
2007
-     * _get_existing_reg_payment_REG_IDs
2008
-     * returns a list of registration IDs that the payment is currently related to
2009
-     * as recorded in the database
2010
-     *
2011
-     * @param EE_Payment $payment
2012
-     * @return array
2013
-     * @throws EE_Error
2014
-     * @throws InvalidArgumentException
2015
-     * @throws InvalidDataTypeException
2016
-     * @throws InvalidInterfaceException
2017
-     * @throws ReflectionException
2018
-     */
2019
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2020
-    {
2021
-        if ($this->existing_reg_payment_REG_IDs() === null) {
2022
-            // let's get any existing reg payment records for this payment
2023
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2024
-            // but we only want the REG IDs, so grab the array keys
2025
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2026
-                ? array_keys($existing_reg_payment_REG_IDs)
2027
-                : [];
2028
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2029
-        }
2030
-
2031
-        return $this->existing_reg_payment_REG_IDs();
2032
-    }
2033
-
2034
-
2035
-    /**
2036
-     * _remove_existing_registration_payments
2037
-     * this calculates the difference between existing relations
2038
-     * to the supplied payment and the new list registration IDs,
2039
-     * removes any related registrations that no longer apply,
2040
-     * and then updates the registration paid fields
2041
-     *
2042
-     * @param EE_Payment $payment
2043
-     * @param int        $PAY_ID
2044
-     * @return bool;
2045
-     * @throws EE_Error
2046
-     * @throws InvalidArgumentException
2047
-     * @throws ReflectionException
2048
-     * @throws InvalidDataTypeException
2049
-     * @throws InvalidInterfaceException
2050
-     */
2051
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2052
-    {
2053
-        // newly created payments will have nothing recorded for $PAY_ID
2054
-        if (absint($PAY_ID) === 0) {
2055
-            return false;
2056
-        }
2057
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2058
-        if (empty($existing_reg_payment_REG_IDs)) {
2059
-            return false;
2060
-        }
2061
-        /** @type EE_Transaction_Payments $transaction_payments */
2062
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2063
-
2064
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2065
-            $payment,
2066
-            [
2067
-                [
2068
-                    'PAY_ID' => $payment->ID(),
2069
-                    'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2070
-                ],
2071
-            ]
2072
-        );
2073
-    }
2074
-
2075
-
2076
-    /**
2077
-     * _update_registration_payments
2078
-     * this applies the payments to the selected registrations
2079
-     * but only if they have not already been paid for
2080
-     *
2081
-     * @param EE_Transaction $transaction
2082
-     * @param EE_Payment     $payment
2083
-     * @param array          $REG_IDs
2084
-     * @return void
2085
-     * @throws EE_Error
2086
-     * @throws InvalidArgumentException
2087
-     * @throws ReflectionException
2088
-     * @throws RuntimeException
2089
-     * @throws InvalidDataTypeException
2090
-     * @throws InvalidInterfaceException
2091
-     */
2092
-    protected function _update_registration_payments(
2093
-        EE_Transaction $transaction,
2094
-        EE_Payment $payment,
2095
-        $REG_IDs = []
2096
-    ) {
2097
-        // we can pass our own custom set of registrations to RegistrationPayments::processRegistrationPayments()
2098
-        // so let's do that using our set of REG_IDs from the form
2099
-        $registration_query_where_params = [
2100
-            'REG_ID' => ['IN', $REG_IDs],
2101
-        ];
2102
-        // but add in some conditions regarding payment,
2103
-        // so that we don't apply payments to registrations that are free or have already been paid for
2104
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2105
-        if (! $payment->is_a_refund()) {
2106
-            $registration_query_where_params['REG_final_price']  = ['!=', 0];
2107
-            $registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2108
-        }
2109
-        $registrations = $transaction->registrations([$registration_query_where_params]);
2110
-        if (! empty($registrations)) {
2111
-            /** @var RegistrationPayments $payment_processor */
2112
-            $payment_processor = LoaderFactory::getShared(RegistrationPayments::class);
2113
-            $payment_processor->processRegistrationPayments($transaction, $payment, $registrations);
2114
-        }
2115
-    }
2116
-
2117
-
2118
-    /**
2119
-     * _process_registration_status_change
2120
-     * This processes requested registration status changes for all the registrations
2121
-     * on a given transaction and (optionally) sends out notifications for the changes.
2122
-     *
2123
-     * @param EE_Transaction $transaction
2124
-     * @param array          $REG_IDs
2125
-     * @return bool
2126
-     * @throws EE_Error
2127
-     * @throws InvalidArgumentException
2128
-     * @throws ReflectionException
2129
-     * @throws InvalidDataTypeException
2130
-     * @throws InvalidInterfaceException
2131
-     */
2132
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2133
-    {
2134
-        // first if there is no change in status then we get out.
2135
-        $reg_status = $reg_status
2136
-            ?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2137
-        if ($reg_status === 'NAN') {
2138
-            // no error message, no change requested, just nothing to do man.
2139
-            return false;
2140
-        }
2141
-        /** @type EE_Transaction_Processor $transaction_processor */
2142
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2143
-
2144
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2145
-        return $transaction_processor->manually_update_registration_statuses(
2146
-            $transaction,
2147
-            $reg_status,
2148
-            [['REG_ID' => ['IN', $REG_IDs]]]
2149
-        );
2150
-    }
2151
-
2152
-
2153
-    /**
2154
-     * _build_payment_json_response
2155
-     *
2156
-     * @access public
2157
-     * @param EE_Payment  $payment
2158
-     * @param array       $REG_IDs
2159
-     * @param bool | null $delete_txn_reg_status_change
2160
-     * @return array
2161
-     * @throws EE_Error
2162
-     * @throws InvalidArgumentException
2163
-     * @throws InvalidDataTypeException
2164
-     * @throws InvalidInterfaceException
2165
-     * @throws ReflectionException
2166
-     */
2167
-    protected function _build_payment_json_response(
2168
-        EE_Payment $payment,
2169
-        $REG_IDs = [],
2170
-        $delete_txn_reg_status_change = null
2171
-    ) {
2172
-        // was the payment deleted ?
2173
-        if (is_bool($delete_txn_reg_status_change)) {
2174
-            return [
2175
-                'PAY_ID'                       => $payment->ID(),
2176
-                'amount'                       => $payment->amount(),
2177
-                'total_paid'                   => $payment->transaction()->paid(),
2178
-                'txn_status'                   => $payment->transaction()->status_ID(),
2179
-                'pay_status'                   => $payment->STS_ID(),
2180
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2181
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2182
-            ];
2183
-        }
2184
-
2185
-        $this->_get_payment_status_array();
2186
-        $payment_method = $payment->payment_method();
2187
-        return [
2188
-            'amount'           => $payment->amount(),
2189
-            'total_paid'       => $payment->transaction()->paid(),
2190
-            'txn_status'       => $payment->transaction()->status_ID(),
2191
-            'pay_status'       => $payment->STS_ID(),
2192
-            'PAY_ID'           => $payment->ID(),
2193
-            'STS_ID'           => $payment->STS_ID(),
2194
-            'status'           => self::$_pay_status[ $payment->STS_ID() ],
2195
-            'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2196
-            'method'           => strtoupper($payment->source()),
2197
-            'PM_ID'            => $payment_method instanceof EE_Payment_Method
2198
-                ? $payment_method->ID()
2199
-                : 1,
2200
-            'gateway'          => $payment_method instanceof EE_Payment_Method
2201
-                ? $payment_method->admin_name()
2202
-                : esc_html__('Unknown', 'event_espresso'),
2203
-            'gateway_response' => $payment->gateway_response(),
2204
-            'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2205
-            'po_number'        => $payment->po_number(),
2206
-            'extra_accntng'    => $payment->extra_accntng(),
2207
-            'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2208
-        ];
2209
-    }
2210
-
2211
-
2212
-    /**
2213
-     * delete_payment
2214
-     *    delete a payment or refund made towards a transaction
2215
-     *
2216
-     * @access public
2217
-     * @return void
2218
-     * @throws EE_Error
2219
-     * @throws InvalidArgumentException
2220
-     * @throws ReflectionException
2221
-     * @throws InvalidDataTypeException
2222
-     * @throws InvalidInterfaceException
2223
-     */
2224
-    public function delete_payment()
2225
-    {
2226
-        $TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2227
-        // $json_response_data = ['return_data' => false];
2228
-        $PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2229
-        $amount     = 0;
2230
-        $can_delete = $this->capabilities->current_user_can(
2231
-            'ee_delete_payments',
2232
-            'delete_payment_from_registration_details'
2233
-        );
2234
-        if ($PAY_ID && $can_delete) {
2235
-            $delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2236
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2237
-            if ($payment instanceof EE_Payment) {
2238
-                $amount  = $payment->amount();
2239
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2240
-                /** @type EE_Transaction_Payments $transaction_payments */
2241
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2242
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2243
-                    if ($delete_txn_reg_status_change) {
2244
-                        $this->_maybe_send_notifications();
2245
-                        $this->_process_registration_status_change(
2246
-                            $payment->transaction(),
2247
-                            $REG_IDs,
2248
-                            $delete_txn_reg_status_change
2249
-                        );
2250
-                    }
2251
-                }
2252
-            } else {
2253
-                EE_Error::add_error(
2254
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2255
-                    __FILE__,
2256
-                    __FUNCTION__,
2257
-                    __LINE__
2258
-                );
2259
-            }
2260
-        } elseif ($can_delete) {
2261
-            EE_Error::add_error(
2262
-                esc_html__(
2263
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2264
-                    'event_espresso'
2265
-                ),
2266
-                __FILE__,
2267
-                __FUNCTION__,
2268
-                __LINE__
2269
-            );
2270
-        } else {
2271
-            EE_Error::add_error(
2272
-                esc_html__(
2273
-                    'You do not have access to delete a payment.',
2274
-                    'event_espresso'
2275
-                ),
2276
-                __FILE__,
2277
-                __FUNCTION__,
2278
-                __LINE__
2279
-            );
2280
-        }
2281
-        $query_args = [
2282
-            'page'   => 'espresso_transactions',
2283
-            'action' => 'view_transaction',
2284
-            'TXN_ID' => $TXD_ID,
2285
-        ];
2286
-        $this->_redirect_after_action(
2287
-            ! EE_Error::has_error(),
2288
-            $amount > 0
2289
-                ? esc_html__('payment', 'event_espresso')
2290
-                : esc_html__('refund', 'event_espresso'),
2291
-            esc_html__('deleted', 'event_espresso'),
2292
-            $query_args
2293
-        );
2294
-    }
2295
-
2296
-
2297
-    /**
2298
-     * _registration_payment_data_array
2299
-     * adds info for 'owing' and 'paid' for each registration to the json response
2300
-     *
2301
-     * @access protected
2302
-     * @param array $REG_IDs
2303
-     * @return array
2304
-     * @throws EE_Error
2305
-     * @throws InvalidArgumentException
2306
-     * @throws InvalidDataTypeException
2307
-     * @throws InvalidInterfaceException
2308
-     * @throws ReflectionException
2309
-     */
2310
-    protected function _registration_payment_data_array($REG_IDs)
2311
-    {
2312
-        $registration_payment_data = [];
2313
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2314
-        if (! empty($REG_IDs)) {
2315
-            $registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2316
-            foreach ($registrations as $registration) {
2317
-                if ($registration instanceof EE_Registration) {
2318
-                    $registration_payment_data[ $registration->ID() ] = [
2319
-                        'paid'  => $registration->pretty_paid(),
2320
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2321
-                    ];
2322
-                }
2323
-            }
2324
-        }
2325
-
2326
-        return $registration_payment_data;
2327
-    }
2328
-
2329
-
2330
-    /**
2331
-     * _maybe_send_notifications
2332
-     * determines whether or not the admin has indicated that notifications should be sent.
2333
-     * If so, will toggle a filter switch for delivering registration notices.
2334
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2335
-     *
2336
-     * @access protected
2337
-     * @param EE_Payment | null $payment
2338
-     */
2339
-    protected function _maybe_send_notifications($payment = null)
2340
-    {
2341
-        switch ($payment instanceof EE_Payment) {
2342
-            // payment notifications
2343
-            case true:
2344
-                if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2345
-                    $this->_process_payment_notification($payment);
2346
-                }
2347
-                break;
2348
-            // registration notifications
2349
-            case false:
2350
-                if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2351
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2352
-                }
2353
-                break;
2354
-        }
2355
-    }
2356
-
2357
-
2358
-    /**
2359
-     * _send_payment_reminder
2360
-     *    generates HTML for the View Transaction Details Admin page
2361
-     *
2362
-     * @access protected
2363
-     * @return void
2364
-     * @throws EE_Error
2365
-     * @throws InvalidArgumentException
2366
-     * @throws InvalidDataTypeException
2367
-     * @throws InvalidInterfaceException
2368
-     */
2369
-    protected function _send_payment_reminder()
2370
-    {
2371
-        $TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2372
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2373
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2374
-        $query_args  = $redirect_to
2375
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2376
-            : [];
2377
-        do_action(
2378
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2379
-            $transaction
2380
-        );
2381
-        $this->_redirect_after_action(
2382
-            false,
2383
-            esc_html__('payment reminder', 'event_espresso'),
2384
-            esc_html__('sent', 'event_espresso'),
2385
-            $query_args,
2386
-            true
2387
-        );
2388
-    }
2389
-
2390
-
2391
-    /**
2392
-     *  get_transactions
2393
-     *    get transactions for given parameters (used by list table)
2394
-     *
2395
-     * @param int     $per_page how many transactions displayed per page
2396
-     * @param boolean $count    return the count or objects
2397
-     * @param string  $view
2398
-     * @return EE_Transaction[]|int int = count || array of transaction objects
2399
-     * @throws EE_Error
2400
-     * @throws InvalidArgumentException
2401
-     * @throws InvalidDataTypeException
2402
-     * @throws InvalidInterfaceException
2403
-     * @throws ReflectionException
2404
-     */
2405
-    public function get_transactions($per_page, $count = false, $view = '')
2406
-    {
2407
-        $start_date = wp_strip_all_tags(
2408
-            $this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2409
-        );
2410
-        $end_date   = wp_strip_all_tags(
2411
-            $this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2412
-        );
2413
-
2414
-        // make sure our timestamps start and end right at the boundaries for each day
2415
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2416
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2417
-
2418
-
2419
-        // convert to timestamps
2420
-        $start_date = strtotime($start_date);
2421
-        $end_date   = strtotime($end_date);
2422
-
2423
-        // makes sure start date is the lowest value and vice versa
2424
-        $start_date = min($start_date, $end_date);
2425
-        $end_date   = max($start_date, $end_date);
2426
-
2427
-        // convert to correct format for query
2428
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2429
-            'TXN_timestamp',
2430
-            date('Y-m-d H:i:s', $start_date),
2431
-            'Y-m-d H:i:s'
2432
-        );
2433
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2434
-            'TXN_timestamp',
2435
-            date('Y-m-d H:i:s', $end_date),
2436
-            'Y-m-d H:i:s'
2437
-        );
2438
-
2439
-
2440
-        // set orderby
2441
-        $orderby = $this->request->getRequestParam('orderby');
2442
-
2443
-        switch ($orderby) {
2444
-            case 'TXN_ID':
2445
-                break;
2446
-            case 'ATT_fname':
2447
-                $orderby = 'Registration.Attendee.ATT_fname';
2448
-                break;
2449
-            case 'event_name':
2450
-                $orderby = 'Registration.Event.EVT_name';
2451
-                break;
2452
-            default: // 'TXN_timestamp'
2453
-                $orderby = 'TXN_timestamp';
2454
-        }
2455
-
2456
-        $sort         = $this->request->getRequestParam('order', 'DESC');
2457
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
2458
-
2459
-        $per_page = absint($per_page)
2460
-            ? $per_page
2461
-            : 10;
2462
-        $per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2463
-
2464
-        $offset = ($current_page - 1) * $per_page;
2465
-        $limit  = [$offset, $per_page];
2466
-
2467
-        $_where = [
2468
-            'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2469
-            'Registration.REG_count' => 1,
2470
-        ];
2471
-
2472
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2473
-        if ($EVT_ID) {
2474
-            $_where['Registration.EVT_ID'] = $EVT_ID;
2475
-        }
2476
-
2477
-        $search_term = $this->request->getRequestParam('s');
2478
-        if ($search_term) {
2479
-            $search_term  = '%' . $search_term . '%';
2480
-            $_where['OR'] = [
2481
-                'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2482
-                'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2483
-                'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2484
-                'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2485
-                'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2486
-                'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2487
-                'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2488
-                'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2489
-                'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2490
-                'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2491
-                'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2492
-                'Registration.REG_final_price'        => ['LIKE', $search_term],
2493
-                'Registration.REG_code'               => ['LIKE', $search_term],
2494
-                'Registration.REG_count'              => ['LIKE', $search_term],
2495
-                'Registration.REG_group_size'         => ['LIKE', $search_term],
2496
-                'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2497
-                'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2498
-                'Payment.PAY_source'                  => ['LIKE', $search_term],
2499
-                'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2500
-                'TXN_session_data'                    => ['LIKE', $search_term],
2501
-                'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2502
-            ];
2503
-        }
2504
-
2505
-        $status = $this->request->getRequestParam('status');
2506
-        // failed transactions
2507
-        $failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2508
-        $abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2509
-        $incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2510
-
2511
-        if ($failed) {
2512
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2513
-        } elseif ($abandoned) {
2514
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2515
-        } elseif ($incomplete) {
2516
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2517
-        } else {
2518
-            $_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2519
-            $_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2520
-        }
2521
-
2522
-        $query_params = apply_filters(
2523
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2524
-            [
2525
-                $_where,
2526
-                'order_by'                 => [$orderby => $sort],
2527
-                'limit'                    => $limit,
2528
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2529
-            ],
2530
-            $this->request->requestParams(),
2531
-            $view,
2532
-            $count
2533
-        );
2534
-
2535
-        return $count
2536
-            ? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2537
-            : EEM_Transaction::instance()->get_all($query_params);
2538
-    }
2539
-
2540
-
2541
-    /**
2542
-     * @throws EE_Error
2543
-     * @throws InvalidArgumentException
2544
-     * @throws InvalidDataTypeException
2545
-     * @throws InvalidInterfaceException
2546
-     * @throws ReflectionException
2547
-     * @throws RuntimeException
2548
-     * @since 4.9.79.p
2549
-     */
2550
-    public function recalculateLineItems()
2551
-    {
2552
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2553
-        /** @var EE_Transaction $transaction */
2554
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2555
-        $success     = $transaction->recalculateLineItems();
2556
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2557
-        $query_args  = $redirect_to
2558
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2559
-            : [];
2560
-        $this->_redirect_after_action(
2561
-            $success,
2562
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2563
-            esc_html__('recalculated', 'event_espresso'),
2564
-            $query_args,
2565
-            true
2566
-        );
2567
-    }
19
+	/**
20
+	 * @var EE_Transaction
21
+	 */
22
+	private $_transaction;
23
+
24
+	/**
25
+	 * @var EE_Session
26
+	 */
27
+	private $_session;
28
+
29
+	/**
30
+	 * @var array $_txn_status
31
+	 */
32
+	private static $_txn_status;
33
+
34
+	/**
35
+	 * @var array $_pay_status
36
+	 */
37
+	private static $_pay_status;
38
+
39
+	/**
40
+	 * @var array $_existing_reg_payment_REG_IDs
41
+	 */
42
+	protected $_existing_reg_payment_REG_IDs;
43
+
44
+
45
+	/**
46
+	 *    _init_page_props
47
+	 *
48
+	 * @return void
49
+	 */
50
+	protected function _init_page_props()
51
+	{
52
+		$this->page_slug        = TXN_PG_SLUG;
53
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
54
+		$this->_admin_base_url  = TXN_ADMIN_URL;
55
+		$this->_admin_base_path = TXN_ADMIN;
56
+	}
57
+
58
+
59
+	/**
60
+	 *    _ajax_hooks
61
+	 *
62
+	 * @return void
63
+	 */
64
+	protected function _ajax_hooks()
65
+	{
66
+	}
67
+
68
+
69
+	/**
70
+	 *    _define_page_props
71
+	 *
72
+	 * @return void
73
+	 */
74
+	protected function _define_page_props()
75
+	{
76
+		$this->_admin_page_title = $this->page_label;
77
+		$this->_labels           = [
78
+			'buttons' => [
79
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
+			],
83
+		];
84
+	}
85
+
86
+
87
+	/**
88
+	 *        grab url requests and route them
89
+	 *
90
+	 * @access private
91
+	 * @return void
92
+	 * @throws EE_Error
93
+	 * @throws InvalidArgumentException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidInterfaceException
96
+	 * @throws ReflectionException
97
+	 */
98
+	public function _set_page_routes()
99
+	{
100
+		$this->_set_transaction_status_array();
101
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
102
+
103
+		$this->_page_routes = [
104
+
105
+			'default' => [
106
+				'func'       => '_transactions_overview_list_table',
107
+				'capability' => 'ee_read_transactions',
108
+			],
109
+
110
+			'view_transaction' => [
111
+				'func'       => '_transaction_details',
112
+				'capability' => 'ee_read_transaction',
113
+				'obj_id'     => $TXN_ID,
114
+			],
115
+
116
+			'send_payment_reminder' => [
117
+				'func'       => '_send_payment_reminder',
118
+				'noheader'   => true,
119
+				'capability' => 'ee_send_message',
120
+			],
121
+
122
+			'espresso_apply_payment' => [
123
+				'func'       => [$this, 'apply_payments_or_refunds'],
124
+				'noheader'   => true,
125
+				'capability' => 'ee_edit_payments',
126
+			],
127
+
128
+			'espresso_apply_refund' => [
129
+				'func'       => [$this, 'apply_payments_or_refunds'],
130
+				'noheader'   => true,
131
+				'capability' => 'ee_edit_payments',
132
+			],
133
+
134
+			'espresso_delete_payment' => [
135
+				'func'       => [$this, 'delete_payment'],
136
+				'noheader'   => true,
137
+				'capability' => 'ee_delete_payments',
138
+			],
139
+
140
+			'espresso_recalculate_line_items' => [
141
+				'func'       => 'recalculateLineItems',
142
+				'noheader'   => true,
143
+				'capability' => 'ee_edit_payments',
144
+			],
145
+
146
+		];
147
+	}
148
+
149
+
150
+	protected function _set_page_config()
151
+	{
152
+		$TXN_ID             = $this->request->getRequestParam('TXN_ID', 0, 'int');
153
+		$this->_page_config = [
154
+			'default'          => [
155
+				'nav'           => [
156
+					'label' => esc_html__('Overview', 'event_espresso'),
157
+					'icon'  => 'dashicons-list-view',
158
+					'order' => 10,
159
+				],
160
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
161
+				'help_tabs'     => [
162
+					'transactions_overview_help_tab'                       => [
163
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
164
+						'filename' => 'transactions_overview',
165
+					],
166
+					'transactions_overview_table_column_headings_help_tab' => [
167
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
168
+						'filename' => 'transactions_overview_table_column_headings',
169
+					],
170
+					'transactions_overview_views_filters_help_tab'         => [
171
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
172
+						'filename' => 'transactions_overview_views_filters_search',
173
+					],
174
+				],
175
+				'require_nonce' => false,
176
+			],
177
+			'view_transaction' => [
178
+				'nav'       => [
179
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
180
+					'icon'       => 'dashicons-cart',
181
+					'order'      => 5,
182
+					'url'        => $TXN_ID
183
+						? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
184
+						: $this->_admin_base_url,
185
+					'persistent' => false,
186
+				],
187
+				'help_tabs' => [
188
+					'transactions_view_transaction_help_tab'                                              => [
189
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
190
+						'filename' => 'transactions_view_transaction',
191
+					],
192
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => [
193
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
194
+						'filename' => 'transactions_view_transaction_transaction_details_table',
195
+					],
196
+					'transactions_view_transaction_attendees_registered_help_tab'                         => [
197
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
198
+						'filename' => 'transactions_view_transaction_attendees_registered',
199
+					],
200
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
201
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
202
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
203
+					],
204
+				],
205
+				'qtips'     => ['Transaction_Details_Tips'],
206
+				'metaboxes' => ['_transaction_details_metaboxes'],
207
+
208
+				'require_nonce' => false,
209
+			],
210
+		];
211
+	}
212
+
213
+
214
+	/**
215
+	 * The below methods aren't used by this class currently
216
+	 */
217
+	protected function _add_screen_options()
218
+	{
219
+		// noop
220
+	}
221
+
222
+
223
+	protected function _add_feature_pointers()
224
+	{
225
+		// noop
226
+	}
227
+
228
+
229
+	public function admin_init()
230
+	{
231
+		$EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
232
+		$event_name    = $this->request->getRequestParam('event_name');
233
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
234
+		// IF a registration was JUST added via the admin...
235
+		if ($EVT_ID && $event_name && $redirect_from) {
236
+			// then set a cookie so that we can block any attempts to use
237
+			// the back button as a way to enter another registration.
238
+			setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
239
+			// and update the global
240
+			$_COOKIE['ee_registration_added'] = $EVT_ID;
241
+		}
242
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
243
+			'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.',
244
+			'event_espresso'
245
+		);
246
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
247
+			'An error occurred! Please refresh the page and try again.',
248
+			'event_espresso'
249
+		);
250
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
251
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
252
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
253
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
254
+			'This transaction has been overpaid ! Payments Total',
255
+			'event_espresso'
256
+		);
257
+	}
258
+
259
+
260
+	public function admin_notices()
261
+	{
262
+		// noop
263
+	}
264
+
265
+
266
+	public function admin_footer_scripts()
267
+	{
268
+		// noop
269
+	}
270
+
271
+
272
+	/**
273
+	 * _set_transaction_status_array
274
+	 * sets list of transaction statuses
275
+	 *
276
+	 * @access private
277
+	 * @return void
278
+	 * @throws EE_Error
279
+	 * @throws InvalidArgumentException
280
+	 * @throws InvalidDataTypeException
281
+	 * @throws InvalidInterfaceException
282
+	 * @throws ReflectionException
283
+	 */
284
+	private function _set_transaction_status_array()
285
+	{
286
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
287
+	}
288
+
289
+
290
+	/**
291
+	 * get_transaction_status_array
292
+	 * return the transaction status array for wp_list_table
293
+	 *
294
+	 * @access public
295
+	 * @return array
296
+	 */
297
+	public function get_transaction_status_array()
298
+	{
299
+		return self::$_txn_status;
300
+	}
301
+
302
+
303
+	/**
304
+	 *    get list of payment statuses
305
+	 *
306
+	 * @access private
307
+	 * @return void
308
+	 * @throws EE_Error
309
+	 * @throws InvalidArgumentException
310
+	 * @throws InvalidDataTypeException
311
+	 * @throws InvalidInterfaceException
312
+	 * @throws ReflectionException
313
+	 */
314
+	private function _get_payment_status_array()
315
+	{
316
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
317
+		$this->_template_args['payment_status'] = self::$_pay_status;
318
+	}
319
+
320
+
321
+	/**
322
+	 *    _add_screen_options_default
323
+	 *
324
+	 * @access protected
325
+	 * @return void
326
+	 * @throws InvalidArgumentException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 */
330
+	protected function _add_screen_options_default()
331
+	{
332
+		$this->_per_page_screen_option();
333
+	}
334
+
335
+
336
+	/**
337
+	 * load_scripts_styles
338
+	 *
339
+	 * @access public
340
+	 * @return void
341
+	 */
342
+	public function load_scripts_styles()
343
+	{
344
+		// enqueue style
345
+		wp_register_style(
346
+			'espresso_txn',
347
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
348
+			[],
349
+			EVENT_ESPRESSO_VERSION
350
+		);
351
+		wp_enqueue_style('espresso_txn');
352
+		// scripts
353
+		wp_register_script(
354
+			'espresso_txn',
355
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
356
+			[
357
+				'ee_admin_js',
358
+				'ee-datepicker',
359
+				'jquery-ui-datepicker',
360
+				'jquery-ui-draggable',
361
+				'ee-dialog',
362
+				'ee-accounting',
363
+				'ee-serialize-full-array',
364
+			],
365
+			EVENT_ESPRESSO_VERSION,
366
+			true
367
+		);
368
+		wp_enqueue_script('espresso_txn');
369
+	}
370
+
371
+
372
+	/**
373
+	 *    load_scripts_styles_view_transaction
374
+	 *
375
+	 * @access public
376
+	 * @return void
377
+	 */
378
+	public function load_scripts_styles_view_transaction()
379
+	{
380
+		// styles
381
+		wp_enqueue_style('espresso-ui-theme');
382
+	}
383
+
384
+
385
+	/**
386
+	 *    load_scripts_styles_default
387
+	 *
388
+	 * @access public
389
+	 * @return void
390
+	 */
391
+	public function load_scripts_styles_default()
392
+	{
393
+		// styles
394
+		wp_enqueue_style('espresso-ui-theme');
395
+	}
396
+
397
+
398
+	/**
399
+	 *    _set_list_table_views_default
400
+	 *
401
+	 * @access protected
402
+	 * @return void
403
+	 */
404
+	protected function _set_list_table_views_default()
405
+	{
406
+		$this->_views = [
407
+			'all'        => [
408
+				'slug'  => 'all',
409
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
410
+				'count' => 0,
411
+			],
412
+			'abandoned'  => [
413
+				'slug'  => 'abandoned',
414
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
415
+				'count' => 0,
416
+			],
417
+			'incomplete' => [
418
+				'slug'  => 'incomplete',
419
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
420
+				'count' => 0,
421
+			],
422
+		];
423
+		if (
424
+			/**
425
+			 * Filters whether a link to the "Failed Transactions" list table
426
+			 * appears on the Transactions Admin Page list table.
427
+			 * List display can be turned back on via the following:
428
+			 * add_filter(
429
+			 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
430
+			 *     '__return_true'
431
+			 * );
432
+			 *
433
+			 * @param boolean                 $display_failed_txns_list
434
+			 * @param Transactions_Admin_Page $this
435
+			 * @since 4.9.70.p
436
+			 */
437
+		apply_filters(
438
+			'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
439
+			false,
440
+			$this
441
+		)
442
+		) {
443
+			$this->_views['failed'] = [
444
+				'slug'  => 'failed',
445
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
446
+				'count' => 0,
447
+			];
448
+		}
449
+	}
450
+
451
+
452
+	/**
453
+	 * _set_transaction_object
454
+	 * This sets the _transaction property for the transaction details screen
455
+	 *
456
+	 * @access private
457
+	 * @return void
458
+	 * @throws EE_Error
459
+	 * @throws InvalidArgumentException
460
+	 * @throws RuntimeException
461
+	 * @throws InvalidDataTypeException
462
+	 * @throws InvalidInterfaceException
463
+	 * @throws ReflectionException
464
+	 */
465
+	private function _set_transaction_object()
466
+	{
467
+		if ($this->_transaction instanceof EE_Transaction) {
468
+			return;
469
+		} //get out we've already set the object
470
+
471
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
472
+
473
+		// get transaction object
474
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
475
+		$this->_session     = $this->_transaction instanceof EE_Transaction
476
+			? $this->_transaction->session_data()
477
+			: null;
478
+		if ($this->_transaction instanceof EE_Transaction) {
479
+			$this->_transaction->verify_abandoned_transaction_status();
480
+		}
481
+
482
+		if (! $this->_transaction instanceof EE_Transaction) {
483
+			$error_msg = sprintf(
484
+				esc_html__(
485
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
486
+					'event_espresso'
487
+				),
488
+				$TXN_ID
489
+			);
490
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
491
+		}
492
+	}
493
+
494
+
495
+	/**
496
+	 *    _transaction_legend_items
497
+	 *
498
+	 * @access protected
499
+	 * @return array
500
+	 * @throws EE_Error
501
+	 * @throws InvalidArgumentException
502
+	 * @throws ReflectionException
503
+	 * @throws InvalidDataTypeException
504
+	 * @throws InvalidInterfaceException
505
+	 */
506
+	protected function _transaction_legend_items()
507
+	{
508
+		EE_Registry::instance()->load_helper('MSG_Template');
509
+		$items = [];
510
+
511
+		if (
512
+			$this->capabilities->current_user_can(
513
+				'ee_read_global_messages',
514
+				'view_filtered_messages'
515
+			)
516
+		) {
517
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
518
+			if (
519
+				is_array($related_for_icon)
520
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
521
+			) {
522
+				$items['view_related_messages'] = [
523
+					'class' => $related_for_icon['css_class'],
524
+					'desc'  => $related_for_icon['label'],
525
+				];
526
+			}
527
+		}
528
+
529
+		$items = apply_filters(
530
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
531
+			array_merge(
532
+				$items,
533
+				[
534
+					'view_details'          => [
535
+						'class' => 'dashicons dashicons-cart',
536
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
537
+					],
538
+					'view_invoice'          => [
539
+						'class' => 'dashicons dashicons-media-spreadsheet',
540
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
541
+					],
542
+					'view_receipt'          => [
543
+						'class' => 'dashicons dashicons-text-page',
544
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
545
+					],
546
+					'view_registration'     => [
547
+						'class' => 'dashicons dashicons-clipboard',
548
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
549
+					],
550
+					'payment_overview_link' => [
551
+						'class' => 'dashicons dashicons-money',
552
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
553
+					],
554
+				]
555
+			)
556
+		);
557
+
558
+		if (
559
+			EEH_MSG_Template::is_mt_active('payment_reminder')
560
+			&& $this->capabilities->current_user_can(
561
+				'ee_send_message',
562
+				'espresso_transactions_send_payment_reminder'
563
+			)
564
+		) {
565
+			$items['send_payment_reminder'] = [
566
+				'class' => 'dashicons dashicons-email-alt',
567
+				'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
568
+			];
569
+		} else {
570
+			$items['blank*'] = [
571
+				'class' => '',
572
+				'desc'  => '',
573
+			];
574
+		}
575
+		$more_items = apply_filters(
576
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
577
+			[
578
+				'overpaid'   => [
579
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
580
+					'desc'  => EEH_Template::pretty_status(
581
+						EEM_Transaction::overpaid_status_code,
582
+						false,
583
+						'sentence'
584
+					),
585
+				],
586
+				'complete'   => [
587
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
588
+					'desc'  => EEH_Template::pretty_status(
589
+						EEM_Transaction::complete_status_code,
590
+						false,
591
+						'sentence'
592
+					),
593
+				],
594
+				'incomplete' => [
595
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
596
+					'desc'  => EEH_Template::pretty_status(
597
+						EEM_Transaction::incomplete_status_code,
598
+						false,
599
+						'sentence'
600
+					),
601
+				],
602
+				'abandoned'  => [
603
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
604
+					'desc'  => EEH_Template::pretty_status(
605
+						EEM_Transaction::abandoned_status_code,
606
+						false,
607
+						'sentence'
608
+					),
609
+				],
610
+				'failed'     => [
611
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
612
+					'desc'  => EEH_Template::pretty_status(
613
+						EEM_Transaction::failed_status_code,
614
+						false,
615
+						'sentence'
616
+					),
617
+				],
618
+			]
619
+		);
620
+
621
+		return array_merge($items, $more_items);
622
+	}
623
+
624
+
625
+	/**
626
+	 *    _transactions_overview_list_table
627
+	 *
628
+	 * @access protected
629
+	 * @return void
630
+	 * @throws DomainException
631
+	 * @throws EE_Error
632
+	 * @throws InvalidArgumentException
633
+	 * @throws InvalidDataTypeException
634
+	 * @throws InvalidInterfaceException
635
+	 * @throws ReflectionException
636
+	 */
637
+	protected function _transactions_overview_list_table()
638
+	{
639
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
640
+
641
+		$EVT_ID                                    = $this->request->getRequestParam('EVT_ID', 0, 'int');
642
+		$event                                     = EEM_Event::instance()->get_one_by_ID($EVT_ID);
643
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
644
+			? sprintf(
645
+				esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
646
+				'<h3>',
647
+				'<a href="'
648
+				. EE_Admin_Page::add_query_args_and_nonce(
649
+					['action' => 'edit', 'post' => $event->ID()],
650
+					EVENTS_ADMIN_URL
651
+				)
652
+				. '" aria-label="'
653
+				. esc_attr__('Click to Edit event', 'event_espresso')
654
+				. '">' . $event->name() . '</a>',
655
+				'</h3>'
656
+			)
657
+			: '';
658
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
659
+		$this->display_admin_list_table_page_with_no_sidebar();
660
+	}
661
+
662
+
663
+	/**
664
+	 *    _transaction_details
665
+	 * generates HTML for the View Transaction Details Admin page
666
+	 *
667
+	 * @access protected
668
+	 * @return void
669
+	 * @throws DomainException
670
+	 * @throws EE_Error
671
+	 * @throws InvalidArgumentException
672
+	 * @throws InvalidDataTypeException
673
+	 * @throws InvalidInterfaceException
674
+	 * @throws RuntimeException
675
+	 * @throws ReflectionException
676
+	 */
677
+	protected function _transaction_details()
678
+	{
679
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
680
+
681
+		$this->_set_transaction_status_array();
682
+
683
+		$this->_template_args                      = [];
684
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
685
+
686
+		$this->_set_transaction_object();
687
+
688
+		if (! $this->_transaction instanceof EE_Transaction) {
689
+			return;
690
+		}
691
+
692
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
693
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
694
+
695
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
696
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
697
+
698
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
699
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
700
+		$this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
701
+
702
+		$txn_total  = $this->_transaction->total();
703
+		$total_paid = $this->_transaction->paid();
704
+		$amount_due = $txn_total - $total_paid;
705
+
706
+		$this->_template_args['grand_total'] = $txn_total;
707
+		$this->_template_args['total_paid']  = $total_paid;
708
+
709
+		$this->_template_args['amount_due']     = EEH_Template::format_currency($amount_due, false, false);
710
+		$this->_template_args['amount_due_raw'] = $amount_due;
711
+
712
+		$this->_template_args['amount_due_class'] = '';
713
+
714
+		if ($txn_total === (float) 0) {
715
+			// free event
716
+			$this->_template_args['amount_due'] = false;
717
+		} elseif ($amount_due < (float) 0) {
718
+			// overpaid
719
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
720
+		} elseif ($amount_due > (float) 0) {
721
+			// monies owing
722
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
723
+		} elseif ($total_paid === (float) 0) {
724
+			// no payments made yet
725
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
726
+		}
727
+
728
+		$payment_method = $this->_transaction->payment_method();
729
+
730
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
731
+			? $payment_method->admin_name()
732
+			: esc_html__('Unknown', 'event_espresso');
733
+
734
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
735
+		// link back to overview
736
+		$this->_template_args['txn_overview_url'] = $this->request->getServerParam(
737
+			'HTTP_REFERER',
738
+			TXN_ADMIN_URL
739
+		);
740
+
741
+
742
+		// next link
743
+		$next_txn                                 = $this->_transaction->next(
744
+			null,
745
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
746
+			'TXN_ID'
747
+		);
748
+		$this->_template_args['next_transaction'] = $next_txn
749
+			? $this->_next_link(
750
+				EE_Admin_Page::add_query_args_and_nonce(
751
+					['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
752
+					TXN_ADMIN_URL
753
+				),
754
+				'dashicons dashicons-arrow-right ee-icon-size-22'
755
+			)
756
+			: '';
757
+		// previous link
758
+		$previous_txn                                 = $this->_transaction->previous(
759
+			null,
760
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
761
+			'TXN_ID'
762
+		);
763
+		$this->_template_args['previous_transaction'] = $previous_txn
764
+			? $this->_previous_link(
765
+				EE_Admin_Page::add_query_args_and_nonce(
766
+					['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
767
+					TXN_ADMIN_URL
768
+				),
769
+				'dashicons dashicons-arrow-left ee-icon-size-22'
770
+			)
771
+			: '';
772
+
773
+		$EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
774
+		$event_name    = $this->request->getRequestParam('event_name');
775
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
776
+
777
+		// were we just redirected here after adding a new registration ???
778
+		if ($EVT_ID && $event_name && $redirect_from) {
779
+			if (
780
+				$this->capabilities->current_user_can(
781
+					'ee_edit_registrations',
782
+					'espresso_registrations_new_registration',
783
+					$EVT_ID
784
+				)
785
+			) {
786
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
787
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
788
+					[
789
+						'page'     => 'espresso_registrations',
790
+						'action'   => 'new_registration',
791
+						'return'   => 'default',
792
+						'TXN_ID'   => $this->_transaction->ID(),
793
+						'event_id' => $EVT_ID,
794
+					],
795
+					REG_ADMIN_URL
796
+				);
797
+				$this->_admin_page_title .= '">';
798
+
799
+				$this->_admin_page_title .= sprintf(
800
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
801
+					htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
802
+				);
803
+				$this->_admin_page_title .= '</a>';
804
+			}
805
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
806
+		}
807
+		// grab messages at the last second
808
+		$this->_template_args['notices'] = EE_Error::get_notices();
809
+		// path to template
810
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
811
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
812
+			$template_path,
813
+			$this->_template_args,
814
+			true
815
+		);
816
+
817
+		// the details template wrapper
818
+		$this->display_admin_page_with_sidebar();
819
+	}
820
+
821
+
822
+	/**
823
+	 *        _transaction_details_metaboxes
824
+	 *
825
+	 * @access protected
826
+	 * @return void
827
+	 * @throws EE_Error
828
+	 * @throws InvalidArgumentException
829
+	 * @throws InvalidDataTypeException
830
+	 * @throws InvalidInterfaceException
831
+	 * @throws RuntimeException
832
+	 * @throws ReflectionException
833
+	 */
834
+	protected function _transaction_details_metaboxes()
835
+	{
836
+		$this->_set_transaction_object();
837
+
838
+		if (! $this->_transaction instanceof EE_Transaction) {
839
+			return;
840
+		}
841
+		$this->addMetaBox(
842
+			'edit-txn-details-mbox',
843
+			'<span>' . esc_html__('Transaction Details', 'event_espresso')
844
+			. '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
845
+			[$this, 'txn_details_meta_box'],
846
+			$this->_wp_page_slug
847
+		);
848
+		$this->addMetaBox(
849
+			'edit-txn-attendees-mbox',
850
+			'<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
851
+			. '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
852
+			[$this, 'txn_attendees_meta_box'],
853
+			$this->_wp_page_slug,
854
+			'normal',
855
+			'high',
856
+			['TXN_ID' => $this->_transaction->ID()]
857
+		);
858
+		$this->addMetaBox(
859
+			'edit-txn-registrant-mbox',
860
+			esc_html__('Primary Contact', 'event_espresso'),
861
+			[$this, 'txn_registrant_side_meta_box'],
862
+			$this->_wp_page_slug,
863
+			'side'
864
+		);
865
+		$this->addMetaBox(
866
+			'edit-txn-billing-info-mbox',
867
+			esc_html__('Billing Information', 'event_espresso'),
868
+			[$this, 'txn_billing_info_side_meta_box'],
869
+			$this->_wp_page_slug,
870
+			'side'
871
+		);
872
+	}
873
+
874
+
875
+	/**
876
+	 * Callback for transaction actions metabox.
877
+	 *
878
+	 * @param EE_Transaction|null $transaction
879
+	 * @return string
880
+	 * @throws DomainException
881
+	 * @throws EE_Error
882
+	 * @throws InvalidArgumentException
883
+	 * @throws InvalidDataTypeException
884
+	 * @throws InvalidInterfaceException
885
+	 * @throws ReflectionException
886
+	 * @throws RuntimeException
887
+	 */
888
+	public function getActionButtons(EE_Transaction $transaction = null)
889
+	{
890
+		$content = '';
891
+		$actions = [];
892
+		if (! $transaction instanceof EE_Transaction) {
893
+			return $content;
894
+		}
895
+		/** @var EE_Registration $primary_registration */
896
+		$primary_registration = $transaction->primary_registration();
897
+		$attendee             = $primary_registration instanceof EE_Registration
898
+			? $primary_registration->attendee()
899
+			: null;
900
+
901
+		if (
902
+			$attendee instanceof EE_Attendee
903
+			&& $this->capabilities->current_user_can(
904
+				'ee_send_message',
905
+				'espresso_transactions_send_payment_reminder'
906
+			)
907
+		) {
908
+			$actions['payment_reminder'] =
909
+				EEH_MSG_Template::is_mt_active('payment_reminder')
910
+				&& $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
911
+				&& $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
912
+					? EEH_Template::get_button_or_link(
913
+					EE_Admin_Page::add_query_args_and_nonce(
914
+						[
915
+							'action'      => 'send_payment_reminder',
916
+							'TXN_ID'      => $this->_transaction->ID(),
917
+							'redirect_to' => 'view_transaction',
918
+						],
919
+						TXN_ADMIN_URL
920
+					),
921
+					esc_html__(' Send Payment Reminder', 'event_espresso'),
922
+					'button button--secondary',
923
+					'dashicons dashicons-email-alt'
924
+				)
925
+					: '';
926
+		}
927
+
928
+		if (
929
+			$this->capabilities->current_user_can(
930
+				'ee_edit_payments',
931
+				'espresso_transactions_recalculate_line_items'
932
+			)
933
+		) {
934
+			$actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
935
+				EE_Admin_Page::add_query_args_and_nonce(
936
+					[
937
+						'action'      => 'espresso_recalculate_line_items',
938
+						'TXN_ID'      => $this->_transaction->ID(),
939
+						'redirect_to' => 'view_transaction',
940
+					],
941
+					TXN_ADMIN_URL
942
+				),
943
+				esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
944
+				'button button--secondary',
945
+				'dashicons dashicons-update'
946
+			);
947
+		}
948
+
949
+		if (
950
+			$primary_registration instanceof EE_Registration
951
+			&& EEH_MSG_Template::is_mt_active('receipt')
952
+		) {
953
+			$actions['receipt'] = EEH_Template::get_button_or_link(
954
+				$primary_registration->receipt_url(),
955
+				esc_html__('View Receipt', 'event_espresso'),
956
+				'button button--secondary',
957
+				'dashicons dashicons-text-page'
958
+			);
959
+		}
960
+
961
+		if (
962
+			$primary_registration instanceof EE_Registration
963
+			&& EEH_MSG_Template::is_mt_active('invoice')
964
+		) {
965
+			$actions['invoice'] = EEH_Template::get_button_or_link(
966
+				$primary_registration->invoice_url(),
967
+				esc_html__('View Invoice', 'event_espresso'),
968
+				'button button--secondary',
969
+				'dashicons dashicons-media-spreadsheet'
970
+			);
971
+		}
972
+		$actions = array_filter(
973
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
974
+		);
975
+		if ($actions) {
976
+			$content .= implode('', $actions);
977
+		}
978
+		return $content;
979
+	}
980
+
981
+
982
+	/**
983
+	 * txn_details_meta_box
984
+	 * generates HTML for the Transaction main meta box
985
+	 *
986
+	 * @return void
987
+	 * @throws DomainException
988
+	 * @throws EE_Error
989
+	 * @throws InvalidArgumentException
990
+	 * @throws InvalidDataTypeException
991
+	 * @throws InvalidInterfaceException
992
+	 * @throws RuntimeException
993
+	 * @throws ReflectionException
994
+	 */
995
+	public function txn_details_meta_box()
996
+	{
997
+		$this->_set_transaction_object();
998
+		$this->_template_args['TXN_ID']              = $this->_transaction->ID();
999
+		$this->_template_args['attendee']            =
1000
+			$this->_transaction->primary_registration() instanceof EE_Registration
1001
+				? $this->_transaction->primary_registration()->attendee()
1002
+				: null;
1003
+		$this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1004
+			'ee_edit_payments',
1005
+			'apply_payment_or_refund_from_registration_details'
1006
+		);
1007
+		$this->_template_args['can_delete_payments'] = $this->capabilities->current_user_can(
1008
+			'ee_delete_payments',
1009
+			'delete_payment_from_registration_details'
1010
+		);
1011
+
1012
+		// get line table
1013
+		EEH_Autoloader::register_line_item_display_autoloaders();
1014
+		$Line_Item_Display                       = new EE_Line_Item_Display(
1015
+			'admin_table',
1016
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1017
+		);
1018
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1019
+			$this->_transaction->total_line_item()
1020
+		);
1021
+		$this->_template_args['REG_code']        =
1022
+			$this->_transaction->primary_registration() instanceof EE_Registration
1023
+				? $this->_transaction->primary_registration()->reg_code()
1024
+				: null;
1025
+		// process taxes
1026
+		$taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1027
+		$this->_template_args['taxes'] = ! empty($taxes)
1028
+			? $taxes
1029
+			: false;
1030
+
1031
+		$this->_template_args['grand_total']     = EEH_Template::format_currency(
1032
+			$this->_transaction->total(),
1033
+			false,
1034
+			false
1035
+		);
1036
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1037
+		$this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1038
+
1039
+		// process payment details
1040
+		$payments = $this->_transaction->payments();
1041
+		if (! empty($payments)) {
1042
+			$this->_template_args['payments']              = $payments;
1043
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1044
+		} else {
1045
+			$this->_template_args['payments']              = false;
1046
+			$this->_template_args['existing_reg_payments'] = [];
1047
+		}
1048
+
1049
+		$this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1050
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1051
+			['action' => 'espresso_delete_payment'],
1052
+			TXN_ADMIN_URL
1053
+		);
1054
+
1055
+		if (isset($txn_details['invoice_number'])) {
1056
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1057
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1058
+				'Invoice Number',
1059
+				'event_espresso'
1060
+			);
1061
+		}
1062
+
1063
+		$this->_template_args['txn_details']['registration_session']['value'] =
1064
+			$this->_transaction->primary_registration() instanceof EE_Registration
1065
+				? $this->_transaction->primary_registration()->session_ID()
1066
+				: null;
1067
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1068
+			'Registration Session',
1069
+			'event_espresso'
1070
+		);
1071
+
1072
+		$this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1073
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1074
+			'Transaction placed from IP',
1075
+			'event_espresso'
1076
+		);
1077
+
1078
+		$this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1079
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1080
+			'Registrant User Agent',
1081
+			'event_espresso'
1082
+		);
1083
+
1084
+		$reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1085
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1086
+			if ($reg_step_status === true) {
1087
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1088
+							  . sprintf(
1089
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1090
+								  ucwords(str_replace('_', ' ', $reg_step))
1091
+							  )
1092
+							  . '</div>';
1093
+			} elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1094
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1095
+							  . sprintf(
1096
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1097
+								  ucwords(str_replace('_', ' ', $reg_step)),
1098
+								  date(
1099
+									  get_option('date_format') . ' ' . get_option('time_format'),
1100
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1101
+								  )
1102
+							  )
1103
+							  . '</div>';
1104
+			} else {
1105
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1106
+							  . sprintf(
1107
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1108
+								  ucwords(str_replace('_', ' ', $reg_step))
1109
+							  )
1110
+							  . '</div>';
1111
+			}
1112
+		}
1113
+		$reg_steps                                                 .= '</ul>';
1114
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1115
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1116
+			'Registration Step Progress',
1117
+			'event_espresso'
1118
+		);
1119
+
1120
+
1121
+		$this->_get_registrations_to_apply_payment_to();
1122
+		$this->_get_payment_methods($payments);
1123
+		$this->_get_payment_status_array();
1124
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1125
+
1126
+		$this->_template_args['transaction_form_url']    = add_query_arg(
1127
+			[
1128
+				'action'  => 'edit_transaction',
1129
+				'process' => 'transaction',
1130
+			],
1131
+			TXN_ADMIN_URL
1132
+		);
1133
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(
1134
+			[
1135
+				'page'   => 'espresso_transactions',
1136
+				'action' => 'espresso_apply_payment',
1137
+			],
1138
+			TXN_ADMIN_URL
1139
+		);
1140
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1141
+			[
1142
+				'page'   => 'espresso_transactions',
1143
+				'action' => 'espresso_delete_payment',
1144
+			],
1145
+			TXN_ADMIN_URL
1146
+		);
1147
+
1148
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1149
+
1150
+		// 'espresso_delete_payment_nonce'
1151
+
1152
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1153
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * _get_registration_payment_IDs
1159
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1160
+	 *
1161
+	 * @access protected
1162
+	 * @param EE_Payment[] $payments
1163
+	 * @return array
1164
+	 * @throws EE_Error
1165
+	 * @throws InvalidArgumentException
1166
+	 * @throws InvalidDataTypeException
1167
+	 * @throws InvalidInterfaceException
1168
+	 * @throws ReflectionException
1169
+	 */
1170
+	protected function _get_registration_payment_IDs($payments = [])
1171
+	{
1172
+		$existing_reg_payments = [];
1173
+		// get all reg payments for these payments
1174
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1175
+			[
1176
+				[
1177
+					'PAY_ID' => [
1178
+						'IN',
1179
+						array_keys($payments),
1180
+					],
1181
+				],
1182
+			]
1183
+		);
1184
+		if (! empty($reg_payments)) {
1185
+			foreach ($payments as $payment) {
1186
+				if (! $payment instanceof EE_Payment) {
1187
+					continue;
1188
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1189
+					$existing_reg_payments[ $payment->ID() ] = [];
1190
+				}
1191
+				foreach ($reg_payments as $reg_payment) {
1192
+					if (
1193
+						$reg_payment instanceof EE_Registration_Payment
1194
+						&& $reg_payment->payment_ID() === $payment->ID()
1195
+					) {
1196
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1197
+					}
1198
+				}
1199
+			}
1200
+		}
1201
+
1202
+		return $existing_reg_payments;
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * _get_registrations_to_apply_payment_to
1208
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1209
+	 * which allows the admin to only apply the payment to the specific registrations
1210
+	 *
1211
+	 * @access protected
1212
+	 * @return void
1213
+	 * @throws EE_Error
1214
+	 * @throws InvalidArgumentException
1215
+	 * @throws InvalidDataTypeException
1216
+	 * @throws InvalidInterfaceException
1217
+	 * @throws ReflectionException
1218
+	 */
1219
+	protected function _get_registrations_to_apply_payment_to()
1220
+	{
1221
+		// we want any registration with an active status (ie: not deleted or cancelled)
1222
+		$query_params                      = [
1223
+			[
1224
+				'STS_ID' => [
1225
+					'IN',
1226
+					[
1227
+						RegStatus::APPROVED,
1228
+						RegStatus::PENDING_PAYMENT,
1229
+						RegStatus::AWAITING_REVIEW,
1230
+					],
1231
+				],
1232
+			],
1233
+		];
1234
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1235
+				'',
1236
+				'txn-admin-apply-payment-to-registrations-dv',
1237
+				'',
1238
+				'clear: both; margin: 1.5em 0 0; display: none;'
1239
+			);
1240
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1241
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1242
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1243
+			EEH_HTML::tr(
1244
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1245
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1246
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1247
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1248
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1249
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1250
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1251
+			)
1252
+		);
1253
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1254
+		// get registrations for TXN
1255
+		$registrations         = $this->_transaction->registrations($query_params);
1256
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1257
+		foreach ($registrations as $registration) {
1258
+			if ($registration instanceof EE_Registration) {
1259
+				$attendee_name                     = $registration->attendee() instanceof EE_Attendee
1260
+					? $registration->attendee()->full_name()
1261
+					: esc_html__('Unknown Attendee', 'event_espresso');
1262
+				$owing                             = $registration->final_price() - $registration->paid();
1263
+				$taxable                           = $registration->ticket()->taxable()
1264
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1265
+					: '';
1266
+				$checked                           = empty($existing_reg_payments)
1267
+													 || in_array($registration->ID(), $existing_reg_payments, true)
1268
+					? ' checked'
1269
+					: '';
1270
+				$disabled                          = $registration->final_price() > 0
1271
+					? ''
1272
+					: ' disabled';
1273
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1274
+					EEH_HTML::td($registration->ID()) .
1275
+					EEH_HTML::td($attendee_name) .
1276
+					EEH_HTML::td(
1277
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1278
+					) .
1279
+					EEH_HTML::td($registration->event_name()) .
1280
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1281
+					EEH_HTML::td(
1282
+						EEH_Template::format_currency($owing),
1283
+						'',
1284
+						'txn-admin-payment-owing-td jst-cntr'
1285
+					) .
1286
+					EEH_HTML::td(
1287
+						'<input type="checkbox" value="' . $registration->ID()
1288
+						. '" name="txn_admin_payment[registrations]"'
1289
+						. $checked . $disabled . '>',
1290
+						'',
1291
+						'jst-cntr'
1292
+					),
1293
+					'apply-payment-registration-row-' . $registration->ID()
1294
+				);
1295
+			}
1296
+		}
1297
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1298
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1299
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1300
+		$registrations_to_apply_payment_to                         .= EEH_HTML::p(
1301
+			esc_html__(
1302
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1303
+				'event_espresso'
1304
+			),
1305
+			'',
1306
+			'clear description'
1307
+		);
1308
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1309
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1310
+	}
1311
+
1312
+
1313
+	/**
1314
+	 * _get_reg_status_selection
1315
+	 *
1316
+	 * @return void
1317
+	 * @throws EE_Error
1318
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1319
+	 *         instead of events.
1320
+	 * @access protected
1321
+	 */
1322
+	protected function _get_reg_status_selection()
1323
+	{
1324
+		// first get all possible statuses
1325
+		$statuses = EEM_Registration::reg_status_array([], true);
1326
+		// let's add a "don't change" option.
1327
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1328
+		$status_array                                        = array_merge($status_array, $statuses);
1329
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1330
+			'txn_reg_status_change[reg_status]',
1331
+			$status_array,
1332
+			'NAN',
1333
+			'id="txn-admin-payment-reg-status-inp"',
1334
+			'txn-reg-status-change-reg-status'
1335
+		);
1336
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1337
+			'delete_txn_reg_status_change[reg_status]',
1338
+			$status_array,
1339
+			'NAN',
1340
+			'delete-txn-admin-payment-reg-status-inp',
1341
+			'delete-txn-reg-status-change-reg-status'
1342
+		);
1343
+	}
1344
+
1345
+
1346
+	/**
1347
+	 *    _get_payment_methods
1348
+	 * Gets all the payment methods available generally, or the ones that are already
1349
+	 * selected on these payments (in case their payment methods are no longer active).
1350
+	 * Has the side-effect of updating the template args' payment_methods item
1351
+	 *
1352
+	 * @access private
1353
+	 * @param EE_Payment[] to show on this page
1354
+	 * @return void
1355
+	 * @throws EE_Error
1356
+	 * @throws InvalidArgumentException
1357
+	 * @throws InvalidDataTypeException
1358
+	 * @throws InvalidInterfaceException
1359
+	 * @throws ReflectionException
1360
+	 */
1361
+	private function _get_payment_methods($payments = [])
1362
+	{
1363
+		$payment_methods_of_payments = [];
1364
+		foreach ($payments as $payment) {
1365
+			if ($payment instanceof EE_Payment) {
1366
+				$payment_methods_of_payments[] = $payment->ID();
1367
+			}
1368
+		}
1369
+		if ($payment_methods_of_payments) {
1370
+			$query_args = [
1371
+				[
1372
+					'OR*payment_method_for_payment' => [
1373
+						'PMD_ID'    => ['IN', $payment_methods_of_payments],
1374
+						'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1375
+					],
1376
+				],
1377
+			];
1378
+		} else {
1379
+			$query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1380
+		}
1381
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1382
+	}
1383
+
1384
+
1385
+	/**
1386
+	 * txn_attendees_meta_box
1387
+	 *    generates HTML for the Attendees Transaction main meta box
1388
+	 *
1389
+	 * @access public
1390
+	 * @param WP_Post $post
1391
+	 * @param array   $metabox
1392
+	 * @return void
1393
+	 * @throws DomainException
1394
+	 * @throws EE_Error
1395
+	 * @throws InvalidArgumentException
1396
+	 * @throws InvalidDataTypeException
1397
+	 * @throws InvalidInterfaceException
1398
+	 * @throws ReflectionException
1399
+	 */
1400
+	public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1401
+	{
1402
+		/** @noinspection NonSecureExtractUsageInspection */
1403
+		extract($metabox['args']);
1404
+		$this->_template_args['post']            = $post;
1405
+		$this->_template_args['event_attendees'] = [];
1406
+		// process items in cart
1407
+		$line_items = $this->_transaction->get_many_related(
1408
+			'Line_Item',
1409
+			[['LIN_type' => 'line-item']]
1410
+		);
1411
+		if (! empty($line_items)) {
1412
+			foreach ($line_items as $item) {
1413
+				if ($item instanceof EE_Line_Item) {
1414
+					switch ($item->OBJ_type()) {
1415
+						case 'Event':
1416
+							break;
1417
+						case 'Ticket':
1418
+							$ticket = $item->ticket();
1419
+							// right now we're only handling tickets here.
1420
+							// Cause its expected that only tickets will have attendees right?
1421
+							if (! $ticket instanceof EE_Ticket) {
1422
+								break;
1423
+							}
1424
+							try {
1425
+								$event_name = $ticket->get_event_name();
1426
+							} catch (Exception $e) {
1427
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1428
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1429
+							}
1430
+							$event_name   .= ' - ' . $item->name();
1431
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1432
+							// now get all of the registrations for this transaction that use this ticket
1433
+							$registrations = $ticket->registrations(
1434
+								[['TXN_ID' => $this->_transaction->ID()]]
1435
+							);
1436
+							foreach ($registrations as $registration) {
1437
+								if (! $registration instanceof EE_Registration) {
1438
+									break;
1439
+								}
1440
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1441
+									= $registration->status_ID();
1442
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1443
+									= $registration->count();
1444
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1445
+									= $event_name;
1446
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1447
+									= $ticket_price;
1448
+								// attendee info
1449
+								$attendee = $registration->get_first_related('Attendee');
1450
+								if ($attendee instanceof EE_Attendee) {
1451
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1452
+										= $attendee->ID();
1453
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1454
+										= $attendee->full_name();
1455
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1456
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1457
+										  . esc_html__(
1458
+											  ' Event',
1459
+											  'event_espresso'
1460
+										  )
1461
+										  . '">' . $attendee->email() . '</a>';
1462
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1463
+										= EEH_Address::format($attendee, 'inline', false, false);
1464
+								} else {
1465
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1466
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1467
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1468
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1469
+								}
1470
+							}
1471
+							break;
1472
+					}
1473
+				}
1474
+			}
1475
+
1476
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1477
+				[
1478
+					'action'  => 'edit_transaction',
1479
+					'process' => 'attendees',
1480
+				],
1481
+				TXN_ADMIN_URL
1482
+			);
1483
+			echo EEH_Template::display_template(
1484
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1485
+				$this->_template_args,
1486
+				true
1487
+			);
1488
+		} else {
1489
+			printf(
1490
+				esc_html__(
1491
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1492
+					'event_espresso'
1493
+				),
1494
+				'<p class="important-notice">',
1495
+				'</p>'
1496
+			);
1497
+		}
1498
+	}
1499
+
1500
+
1501
+	/**
1502
+	 * txn_registrant_side_meta_box
1503
+	 * generates HTML for the Edit Transaction side meta box
1504
+	 *
1505
+	 * @access public
1506
+	 * @return void
1507
+	 * @throws DomainException
1508
+	 * @throws EE_Error
1509
+	 * @throws InvalidArgumentException
1510
+	 * @throws InvalidDataTypeException
1511
+	 * @throws InvalidInterfaceException
1512
+	 * @throws ReflectionException
1513
+	 */
1514
+	public function txn_registrant_side_meta_box()
1515
+	{
1516
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1517
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1518
+			: null;
1519
+		if (! $primary_att instanceof EE_Attendee) {
1520
+			$this->_template_args['no_attendee_message'] = esc_html__(
1521
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1522
+				'event_espresso'
1523
+			);
1524
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1525
+		}
1526
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1527
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1528
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1529
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1530
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1531
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1532
+			[
1533
+				'action' => 'edit_attendee',
1534
+				'post'   => $primary_att->ID(),
1535
+			],
1536
+			REG_ADMIN_URL
1537
+		);
1538
+		// get formatted address for registrant
1539
+		$formatted_address                         = EEH_Address::format($primary_att);
1540
+		$formatted_address                         =
1541
+			$formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1542
+				? $formatted_address
1543
+				: '';
1544
+		$this->_template_args['formatted_address'] = $formatted_address;
1545
+		echo EEH_Template::display_template(
1546
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1547
+			$this->_template_args,
1548
+			true
1549
+		);
1550
+	}
1551
+
1552
+
1553
+	/**
1554
+	 * txn_billing_info_side_meta_box
1555
+	 *    generates HTML for the Edit Transaction side meta box
1556
+	 *
1557
+	 * @access public
1558
+	 * @return void
1559
+	 * @throws DomainException
1560
+	 */
1561
+	public function txn_billing_info_side_meta_box()
1562
+	{
1563
+		try {
1564
+			$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1565
+			$this->_template_args['billing_form_url'] = add_query_arg(
1566
+				['action' => 'edit_transaction', 'process' => 'billing'],
1567
+				TXN_ADMIN_URL
1568
+			);
1569
+		} catch (Exception $e) {
1570
+			$this->_template_args['billing_form'] = [];
1571
+			$this->_template_args['billing_form_url'] = '';
1572
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1573
+		}
1574
+
1575
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1576
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1577
+	}
1578
+
1579
+
1580
+	/**
1581
+	 * apply_payments_or_refunds
1582
+	 *    registers a payment or refund made towards a transaction
1583
+	 *
1584
+	 * @access public
1585
+	 * @return void
1586
+	 * @throws EE_Error
1587
+	 * @throws InvalidArgumentException
1588
+	 * @throws ReflectionException
1589
+	 * @throws RuntimeException
1590
+	 * @throws InvalidDataTypeException
1591
+	 * @throws InvalidInterfaceException
1592
+	 */
1593
+	public function apply_payments_or_refunds()
1594
+	{
1595
+		$valid_data = $this->_validate_payment_request_data();
1596
+		$has_access = $this->capabilities->current_user_can(
1597
+			'ee_edit_payments',
1598
+			'apply_payment_or_refund_from_registration_details'
1599
+		);
1600
+		$TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1601
+		$amount     = 0;
1602
+		if (! empty($valid_data) && $has_access) {
1603
+			$PAY_ID = $valid_data['PAY_ID'];
1604
+			// save  the new payment
1605
+			$payment = $this->_create_payment_from_request_data($valid_data);
1606
+			$amount  = $payment->amount();
1607
+			// get the TXN for this payment
1608
+			$transaction = $payment->transaction();
1609
+			// verify transaction
1610
+			if ($transaction instanceof EE_Transaction) {
1611
+				// calculate_total_payments_and_update_status
1612
+				$this->_process_transaction_payments($transaction);
1613
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1614
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1615
+				// apply payment to registrations (if applicable)
1616
+				if (! empty($REG_IDs)) {
1617
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1618
+					$this->_maybe_send_notifications();
1619
+					// now process status changes for the same registrations
1620
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1621
+				}
1622
+				$this->_maybe_send_notifications($payment);
1623
+				// prepare to render page
1624
+				do_action(
1625
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1626
+					$transaction,
1627
+					$payment
1628
+				);
1629
+			} else {
1630
+				EE_Error::add_error(
1631
+					esc_html__(
1632
+						'A valid Transaction for this payment could not be retrieved.',
1633
+						'event_espresso'
1634
+					),
1635
+					__FILE__,
1636
+					__FUNCTION__,
1637
+					__LINE__
1638
+				);
1639
+			}
1640
+		} elseif ($has_access) {
1641
+			EE_Error::add_error(
1642
+				esc_html__(
1643
+					'The payment form data could not be processed. Please try again.',
1644
+					'event_espresso'
1645
+				),
1646
+				__FILE__,
1647
+				__FUNCTION__,
1648
+				__LINE__
1649
+			);
1650
+		} else {
1651
+			EE_Error::add_error(
1652
+				esc_html__(
1653
+					'You do not have access to apply payments or refunds to a registration.',
1654
+					'event_espresso'
1655
+				),
1656
+				__FILE__,
1657
+				__FUNCTION__,
1658
+				__LINE__
1659
+			);
1660
+		}
1661
+		$query_args = [
1662
+			'page'   => 'espresso_transactions',
1663
+			'action' => 'view_transaction',
1664
+			'TXN_ID' => $TXD_ID,
1665
+		];
1666
+
1667
+		$this->_redirect_after_action(
1668
+			! EE_Error::has_error(),
1669
+			$amount > 0
1670
+				? esc_html__('payment', 'event_espresso')
1671
+				: esc_html__('refund', 'event_espresso'),
1672
+			esc_html__('processed', 'event_espresso'),
1673
+			$query_args
1674
+		);
1675
+	}
1676
+
1677
+
1678
+	/**
1679
+	 * _validate_payment_request_data
1680
+	 *
1681
+	 * @return array
1682
+	 * @throws EE_Error
1683
+	 * @throws InvalidArgumentException
1684
+	 * @throws InvalidDataTypeException
1685
+	 * @throws InvalidInterfaceException
1686
+	 */
1687
+	protected function _validate_payment_request_data()
1688
+	{
1689
+		if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1690
+			return [];
1691
+		}
1692
+		$payment_form = $this->_generate_payment_form_section();
1693
+		try {
1694
+			if ($payment_form->was_submitted()) {
1695
+				$payment_form->receive_form_submission();
1696
+				if (! $payment_form->is_valid()) {
1697
+					$submission_error_messages = [];
1698
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1699
+						if ($validation_error instanceof EE_Validation_Error) {
1700
+							$form_input                  = $validation_error->get_form_section();
1701
+							$submission_error_messages[] = sprintf(
1702
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1703
+								$form_input instanceof EE_Form_Input_Base
1704
+									? $form_input->html_label_text()
1705
+									: '',
1706
+								$validation_error->getMessage()
1707
+							);
1708
+						}
1709
+					}
1710
+					EE_Error::add_error(
1711
+						implode('<br />', $submission_error_messages),
1712
+						__FILE__,
1713
+						__FUNCTION__,
1714
+						__LINE__
1715
+					);
1716
+					return [];
1717
+				}
1718
+			}
1719
+		} catch (EE_Error $e) {
1720
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1721
+			return [];
1722
+		}
1723
+
1724
+		return $payment_form->valid_data();
1725
+	}
1726
+
1727
+
1728
+	/**
1729
+	 * _generate_payment_form_section
1730
+	 *
1731
+	 * @return EE_Form_Section_Proper
1732
+	 * @throws EE_Error
1733
+	 */
1734
+	protected function _generate_payment_form_section()
1735
+	{
1736
+		return new EE_Form_Section_Proper(
1737
+			[
1738
+				'name'        => 'txn_admin_payment',
1739
+				'subsections' => [
1740
+					'PAY_ID'          => new EE_Text_Input(
1741
+						[
1742
+							'default'               => 0,
1743
+							'required'              => false,
1744
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1745
+							'validation_strategies' => [new EE_Int_Normalization()],
1746
+						]
1747
+					),
1748
+					'TXN_ID'          => new EE_Text_Input(
1749
+						[
1750
+							'default'               => 0,
1751
+							'required'              => true,
1752
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1753
+							'validation_strategies' => [new EE_Int_Normalization()],
1754
+						]
1755
+					),
1756
+					'type'            => new EE_Text_Input(
1757
+						[
1758
+							'default'               => 1,
1759
+							'required'              => true,
1760
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1761
+							'validation_strategies' => [new EE_Int_Normalization()],
1762
+						]
1763
+					),
1764
+					'amount'          => new EE_Text_Input(
1765
+						[
1766
+							'default'               => 0,
1767
+							'required'              => true,
1768
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1769
+							'validation_strategies' => [new EE_Float_Normalization()],
1770
+						]
1771
+					),
1772
+					'status'          => new EE_Text_Input(
1773
+						[
1774
+							'default'         => EEM_Payment::status_id_approved,
1775
+							'required'        => true,
1776
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1777
+						]
1778
+					),
1779
+					'PMD_ID'          => new EE_Text_Input(
1780
+						[
1781
+							'default'               => 2,
1782
+							'required'              => true,
1783
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1784
+							'validation_strategies' => [new EE_Int_Normalization()],
1785
+						]
1786
+					),
1787
+					'date'            => new EE_Text_Input(
1788
+						[
1789
+							'default'         => time(),
1790
+							'required'        => true,
1791
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1792
+						]
1793
+					),
1794
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1795
+						[
1796
+							'default'               => '',
1797
+							'required'              => false,
1798
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1799
+							'validation_strategies' => [
1800
+								new EE_Max_Length_Validation_Strategy(
1801
+									esc_html__('Input too long', 'event_espresso'),
1802
+									100
1803
+								),
1804
+							],
1805
+						]
1806
+					),
1807
+					'po_number'       => new EE_Text_Input(
1808
+						[
1809
+							'default'               => '',
1810
+							'required'              => false,
1811
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1812
+							'validation_strategies' => [
1813
+								new EE_Max_Length_Validation_Strategy(
1814
+									esc_html__('Input too long', 'event_espresso'),
1815
+									100
1816
+								),
1817
+							],
1818
+						]
1819
+					),
1820
+					'accounting'      => new EE_Text_Input(
1821
+						[
1822
+							'default'               => '',
1823
+							'required'              => false,
1824
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1825
+							'validation_strategies' => [
1826
+								new EE_Max_Length_Validation_Strategy(
1827
+									esc_html__('Input too long', 'event_espresso'),
1828
+									100
1829
+								),
1830
+							],
1831
+						]
1832
+					),
1833
+				],
1834
+			]
1835
+		);
1836
+	}
1837
+
1838
+
1839
+	/**
1840
+	 * _create_payment_from_request_data
1841
+	 *
1842
+	 * @param array $valid_data
1843
+	 * @return EE_Payment
1844
+	 * @throws EE_Error
1845
+	 * @throws InvalidArgumentException
1846
+	 * @throws InvalidDataTypeException
1847
+	 * @throws InvalidInterfaceException
1848
+	 * @throws ReflectionException
1849
+	 */
1850
+	protected function _create_payment_from_request_data($valid_data)
1851
+	{
1852
+		$PAY_ID = $valid_data['PAY_ID'];
1853
+		// get payment amount
1854
+		$amount = $valid_data['amount']
1855
+			? EEH_Money::strip_localized_money_formatting($valid_data['amount'])
1856
+			: 0;
1857
+		// payments have a type value of 1 and refunds have a type value of -1
1858
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1859
+		$amount = $valid_data['type'] < 0
1860
+			? $amount * -1
1861
+			: $amount;
1862
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1863
+		$date    = $valid_data['date']
1864
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1865
+			: date('Y-m-d g:i a', current_time('timestamp'));
1866
+		$payment = EE_Payment::new_instance(
1867
+			[
1868
+				'TXN_ID'              => $valid_data['TXN_ID'],
1869
+				'STS_ID'              => $valid_data['status'],
1870
+				'PAY_timestamp'       => $date,
1871
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1872
+				'PMD_ID'              => $valid_data['PMD_ID'],
1873
+				'PAY_amount'          => $amount,
1874
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1875
+				'PAY_po_number'       => $valid_data['po_number'],
1876
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1877
+				'PAY_details'         => $valid_data,
1878
+				'PAY_ID'              => $PAY_ID,
1879
+			],
1880
+			'',
1881
+			['Y-m-d', 'g:i a']
1882
+		);
1883
+
1884
+		if (! $payment->save()) {
1885
+			EE_Error::add_error(
1886
+				sprintf(
1887
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1888
+					$payment->ID()
1889
+				),
1890
+				__FILE__,
1891
+				__FUNCTION__,
1892
+				__LINE__
1893
+			);
1894
+		}
1895
+
1896
+		return $payment;
1897
+	}
1898
+
1899
+
1900
+	/**
1901
+	 * _process_transaction_payments
1902
+	 *
1903
+	 * @param EE_Transaction $transaction
1904
+	 * @return void
1905
+	 * @throws EE_Error
1906
+	 * @throws InvalidArgumentException
1907
+	 * @throws ReflectionException
1908
+	 * @throws InvalidDataTypeException
1909
+	 * @throws InvalidInterfaceException
1910
+	 */
1911
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1912
+	{
1913
+		/** @type EE_Transaction_Payments $transaction_payments */
1914
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1915
+		// update the transaction with this payment
1916
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1917
+			EE_Error::add_success(
1918
+				esc_html__(
1919
+					'The payment has been processed successfully.',
1920
+					'event_espresso'
1921
+				),
1922
+				__FILE__,
1923
+				__FUNCTION__,
1924
+				__LINE__
1925
+			);
1926
+		} else {
1927
+			EE_Error::add_error(
1928
+				esc_html__(
1929
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1930
+					'event_espresso'
1931
+				),
1932
+				__FILE__,
1933
+				__FUNCTION__,
1934
+				__LINE__
1935
+			);
1936
+		}
1937
+	}
1938
+
1939
+
1940
+	/**
1941
+	 * _get_REG_IDs_to_apply_payment_to
1942
+	 * returns a list of registration IDs that the payment will apply to
1943
+	 *
1944
+	 * @param EE_Payment $payment
1945
+	 * @return array
1946
+	 * @throws EE_Error
1947
+	 * @throws InvalidArgumentException
1948
+	 * @throws InvalidDataTypeException
1949
+	 * @throws InvalidInterfaceException
1950
+	 * @throws ReflectionException
1951
+	 */
1952
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1953
+	{
1954
+		// grab array of IDs for specific registrations to apply changes to
1955
+		$apply_to_all = $this->request->getRequestParam(
1956
+			'txn_admin_payment[apply_to_all_registrations]',
1957
+			false,
1958
+			DataType::BOOL
1959
+		);
1960
+		$REG_IDs      = ! $apply_to_all
1961
+			? $this->request->getRequestParam(
1962
+				'txn_admin_payment[registrations]',
1963
+				[],
1964
+				DataType::INT,
1965
+				true
1966
+			)
1967
+			: [];
1968
+		// nothing specified ? then get all reg IDs
1969
+		if ($apply_to_all || empty($REG_IDs)) {
1970
+			$registrations = $payment->transaction()->registrations(
1971
+				[
1972
+					[
1973
+						'STS_ID' => [
1974
+							'NOT_IN', [ RegStatus::CANCELLED ]
1975
+						]
1976
+					]
1977
+				]
1978
+			);
1979
+			$REG_IDs       = ! empty($registrations)
1980
+				? array_keys($registrations)
1981
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1982
+		}
1983
+		// ensure that REG_IDs are integers and NOT strings
1984
+		return array_map('absint', $REG_IDs);
1985
+	}
1986
+
1987
+
1988
+	/**
1989
+	 * @return array
1990
+	 */
1991
+	public function existing_reg_payment_REG_IDs()
1992
+	{
1993
+		return $this->_existing_reg_payment_REG_IDs;
1994
+	}
1995
+
1996
+
1997
+	/**
1998
+	 * @param array $existing_reg_payment_REG_IDs
1999
+	 */
2000
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
2001
+	{
2002
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
2003
+	}
2004
+
2005
+
2006
+	/**
2007
+	 * _get_existing_reg_payment_REG_IDs
2008
+	 * returns a list of registration IDs that the payment is currently related to
2009
+	 * as recorded in the database
2010
+	 *
2011
+	 * @param EE_Payment $payment
2012
+	 * @return array
2013
+	 * @throws EE_Error
2014
+	 * @throws InvalidArgumentException
2015
+	 * @throws InvalidDataTypeException
2016
+	 * @throws InvalidInterfaceException
2017
+	 * @throws ReflectionException
2018
+	 */
2019
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2020
+	{
2021
+		if ($this->existing_reg_payment_REG_IDs() === null) {
2022
+			// let's get any existing reg payment records for this payment
2023
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2024
+			// but we only want the REG IDs, so grab the array keys
2025
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2026
+				? array_keys($existing_reg_payment_REG_IDs)
2027
+				: [];
2028
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2029
+		}
2030
+
2031
+		return $this->existing_reg_payment_REG_IDs();
2032
+	}
2033
+
2034
+
2035
+	/**
2036
+	 * _remove_existing_registration_payments
2037
+	 * this calculates the difference between existing relations
2038
+	 * to the supplied payment and the new list registration IDs,
2039
+	 * removes any related registrations that no longer apply,
2040
+	 * and then updates the registration paid fields
2041
+	 *
2042
+	 * @param EE_Payment $payment
2043
+	 * @param int        $PAY_ID
2044
+	 * @return bool;
2045
+	 * @throws EE_Error
2046
+	 * @throws InvalidArgumentException
2047
+	 * @throws ReflectionException
2048
+	 * @throws InvalidDataTypeException
2049
+	 * @throws InvalidInterfaceException
2050
+	 */
2051
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2052
+	{
2053
+		// newly created payments will have nothing recorded for $PAY_ID
2054
+		if (absint($PAY_ID) === 0) {
2055
+			return false;
2056
+		}
2057
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2058
+		if (empty($existing_reg_payment_REG_IDs)) {
2059
+			return false;
2060
+		}
2061
+		/** @type EE_Transaction_Payments $transaction_payments */
2062
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2063
+
2064
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2065
+			$payment,
2066
+			[
2067
+				[
2068
+					'PAY_ID' => $payment->ID(),
2069
+					'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2070
+				],
2071
+			]
2072
+		);
2073
+	}
2074
+
2075
+
2076
+	/**
2077
+	 * _update_registration_payments
2078
+	 * this applies the payments to the selected registrations
2079
+	 * but only if they have not already been paid for
2080
+	 *
2081
+	 * @param EE_Transaction $transaction
2082
+	 * @param EE_Payment     $payment
2083
+	 * @param array          $REG_IDs
2084
+	 * @return void
2085
+	 * @throws EE_Error
2086
+	 * @throws InvalidArgumentException
2087
+	 * @throws ReflectionException
2088
+	 * @throws RuntimeException
2089
+	 * @throws InvalidDataTypeException
2090
+	 * @throws InvalidInterfaceException
2091
+	 */
2092
+	protected function _update_registration_payments(
2093
+		EE_Transaction $transaction,
2094
+		EE_Payment $payment,
2095
+		$REG_IDs = []
2096
+	) {
2097
+		// we can pass our own custom set of registrations to RegistrationPayments::processRegistrationPayments()
2098
+		// so let's do that using our set of REG_IDs from the form
2099
+		$registration_query_where_params = [
2100
+			'REG_ID' => ['IN', $REG_IDs],
2101
+		];
2102
+		// but add in some conditions regarding payment,
2103
+		// so that we don't apply payments to registrations that are free or have already been paid for
2104
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2105
+		if (! $payment->is_a_refund()) {
2106
+			$registration_query_where_params['REG_final_price']  = ['!=', 0];
2107
+			$registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2108
+		}
2109
+		$registrations = $transaction->registrations([$registration_query_where_params]);
2110
+		if (! empty($registrations)) {
2111
+			/** @var RegistrationPayments $payment_processor */
2112
+			$payment_processor = LoaderFactory::getShared(RegistrationPayments::class);
2113
+			$payment_processor->processRegistrationPayments($transaction, $payment, $registrations);
2114
+		}
2115
+	}
2116
+
2117
+
2118
+	/**
2119
+	 * _process_registration_status_change
2120
+	 * This processes requested registration status changes for all the registrations
2121
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2122
+	 *
2123
+	 * @param EE_Transaction $transaction
2124
+	 * @param array          $REG_IDs
2125
+	 * @return bool
2126
+	 * @throws EE_Error
2127
+	 * @throws InvalidArgumentException
2128
+	 * @throws ReflectionException
2129
+	 * @throws InvalidDataTypeException
2130
+	 * @throws InvalidInterfaceException
2131
+	 */
2132
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2133
+	{
2134
+		// first if there is no change in status then we get out.
2135
+		$reg_status = $reg_status
2136
+			?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2137
+		if ($reg_status === 'NAN') {
2138
+			// no error message, no change requested, just nothing to do man.
2139
+			return false;
2140
+		}
2141
+		/** @type EE_Transaction_Processor $transaction_processor */
2142
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2143
+
2144
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2145
+		return $transaction_processor->manually_update_registration_statuses(
2146
+			$transaction,
2147
+			$reg_status,
2148
+			[['REG_ID' => ['IN', $REG_IDs]]]
2149
+		);
2150
+	}
2151
+
2152
+
2153
+	/**
2154
+	 * _build_payment_json_response
2155
+	 *
2156
+	 * @access public
2157
+	 * @param EE_Payment  $payment
2158
+	 * @param array       $REG_IDs
2159
+	 * @param bool | null $delete_txn_reg_status_change
2160
+	 * @return array
2161
+	 * @throws EE_Error
2162
+	 * @throws InvalidArgumentException
2163
+	 * @throws InvalidDataTypeException
2164
+	 * @throws InvalidInterfaceException
2165
+	 * @throws ReflectionException
2166
+	 */
2167
+	protected function _build_payment_json_response(
2168
+		EE_Payment $payment,
2169
+		$REG_IDs = [],
2170
+		$delete_txn_reg_status_change = null
2171
+	) {
2172
+		// was the payment deleted ?
2173
+		if (is_bool($delete_txn_reg_status_change)) {
2174
+			return [
2175
+				'PAY_ID'                       => $payment->ID(),
2176
+				'amount'                       => $payment->amount(),
2177
+				'total_paid'                   => $payment->transaction()->paid(),
2178
+				'txn_status'                   => $payment->transaction()->status_ID(),
2179
+				'pay_status'                   => $payment->STS_ID(),
2180
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2181
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2182
+			];
2183
+		}
2184
+
2185
+		$this->_get_payment_status_array();
2186
+		$payment_method = $payment->payment_method();
2187
+		return [
2188
+			'amount'           => $payment->amount(),
2189
+			'total_paid'       => $payment->transaction()->paid(),
2190
+			'txn_status'       => $payment->transaction()->status_ID(),
2191
+			'pay_status'       => $payment->STS_ID(),
2192
+			'PAY_ID'           => $payment->ID(),
2193
+			'STS_ID'           => $payment->STS_ID(),
2194
+			'status'           => self::$_pay_status[ $payment->STS_ID() ],
2195
+			'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2196
+			'method'           => strtoupper($payment->source()),
2197
+			'PM_ID'            => $payment_method instanceof EE_Payment_Method
2198
+				? $payment_method->ID()
2199
+				: 1,
2200
+			'gateway'          => $payment_method instanceof EE_Payment_Method
2201
+				? $payment_method->admin_name()
2202
+				: esc_html__('Unknown', 'event_espresso'),
2203
+			'gateway_response' => $payment->gateway_response(),
2204
+			'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2205
+			'po_number'        => $payment->po_number(),
2206
+			'extra_accntng'    => $payment->extra_accntng(),
2207
+			'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2208
+		];
2209
+	}
2210
+
2211
+
2212
+	/**
2213
+	 * delete_payment
2214
+	 *    delete a payment or refund made towards a transaction
2215
+	 *
2216
+	 * @access public
2217
+	 * @return void
2218
+	 * @throws EE_Error
2219
+	 * @throws InvalidArgumentException
2220
+	 * @throws ReflectionException
2221
+	 * @throws InvalidDataTypeException
2222
+	 * @throws InvalidInterfaceException
2223
+	 */
2224
+	public function delete_payment()
2225
+	{
2226
+		$TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2227
+		// $json_response_data = ['return_data' => false];
2228
+		$PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2229
+		$amount     = 0;
2230
+		$can_delete = $this->capabilities->current_user_can(
2231
+			'ee_delete_payments',
2232
+			'delete_payment_from_registration_details'
2233
+		);
2234
+		if ($PAY_ID && $can_delete) {
2235
+			$delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2236
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2237
+			if ($payment instanceof EE_Payment) {
2238
+				$amount  = $payment->amount();
2239
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2240
+				/** @type EE_Transaction_Payments $transaction_payments */
2241
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2242
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2243
+					if ($delete_txn_reg_status_change) {
2244
+						$this->_maybe_send_notifications();
2245
+						$this->_process_registration_status_change(
2246
+							$payment->transaction(),
2247
+							$REG_IDs,
2248
+							$delete_txn_reg_status_change
2249
+						);
2250
+					}
2251
+				}
2252
+			} else {
2253
+				EE_Error::add_error(
2254
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2255
+					__FILE__,
2256
+					__FUNCTION__,
2257
+					__LINE__
2258
+				);
2259
+			}
2260
+		} elseif ($can_delete) {
2261
+			EE_Error::add_error(
2262
+				esc_html__(
2263
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2264
+					'event_espresso'
2265
+				),
2266
+				__FILE__,
2267
+				__FUNCTION__,
2268
+				__LINE__
2269
+			);
2270
+		} else {
2271
+			EE_Error::add_error(
2272
+				esc_html__(
2273
+					'You do not have access to delete a payment.',
2274
+					'event_espresso'
2275
+				),
2276
+				__FILE__,
2277
+				__FUNCTION__,
2278
+				__LINE__
2279
+			);
2280
+		}
2281
+		$query_args = [
2282
+			'page'   => 'espresso_transactions',
2283
+			'action' => 'view_transaction',
2284
+			'TXN_ID' => $TXD_ID,
2285
+		];
2286
+		$this->_redirect_after_action(
2287
+			! EE_Error::has_error(),
2288
+			$amount > 0
2289
+				? esc_html__('payment', 'event_espresso')
2290
+				: esc_html__('refund', 'event_espresso'),
2291
+			esc_html__('deleted', 'event_espresso'),
2292
+			$query_args
2293
+		);
2294
+	}
2295
+
2296
+
2297
+	/**
2298
+	 * _registration_payment_data_array
2299
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2300
+	 *
2301
+	 * @access protected
2302
+	 * @param array $REG_IDs
2303
+	 * @return array
2304
+	 * @throws EE_Error
2305
+	 * @throws InvalidArgumentException
2306
+	 * @throws InvalidDataTypeException
2307
+	 * @throws InvalidInterfaceException
2308
+	 * @throws ReflectionException
2309
+	 */
2310
+	protected function _registration_payment_data_array($REG_IDs)
2311
+	{
2312
+		$registration_payment_data = [];
2313
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2314
+		if (! empty($REG_IDs)) {
2315
+			$registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2316
+			foreach ($registrations as $registration) {
2317
+				if ($registration instanceof EE_Registration) {
2318
+					$registration_payment_data[ $registration->ID() ] = [
2319
+						'paid'  => $registration->pretty_paid(),
2320
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2321
+					];
2322
+				}
2323
+			}
2324
+		}
2325
+
2326
+		return $registration_payment_data;
2327
+	}
2328
+
2329
+
2330
+	/**
2331
+	 * _maybe_send_notifications
2332
+	 * determines whether or not the admin has indicated that notifications should be sent.
2333
+	 * If so, will toggle a filter switch for delivering registration notices.
2334
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2335
+	 *
2336
+	 * @access protected
2337
+	 * @param EE_Payment | null $payment
2338
+	 */
2339
+	protected function _maybe_send_notifications($payment = null)
2340
+	{
2341
+		switch ($payment instanceof EE_Payment) {
2342
+			// payment notifications
2343
+			case true:
2344
+				if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2345
+					$this->_process_payment_notification($payment);
2346
+				}
2347
+				break;
2348
+			// registration notifications
2349
+			case false:
2350
+				if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2351
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2352
+				}
2353
+				break;
2354
+		}
2355
+	}
2356
+
2357
+
2358
+	/**
2359
+	 * _send_payment_reminder
2360
+	 *    generates HTML for the View Transaction Details Admin page
2361
+	 *
2362
+	 * @access protected
2363
+	 * @return void
2364
+	 * @throws EE_Error
2365
+	 * @throws InvalidArgumentException
2366
+	 * @throws InvalidDataTypeException
2367
+	 * @throws InvalidInterfaceException
2368
+	 */
2369
+	protected function _send_payment_reminder()
2370
+	{
2371
+		$TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2372
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2373
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2374
+		$query_args  = $redirect_to
2375
+			? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2376
+			: [];
2377
+		do_action(
2378
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2379
+			$transaction
2380
+		);
2381
+		$this->_redirect_after_action(
2382
+			false,
2383
+			esc_html__('payment reminder', 'event_espresso'),
2384
+			esc_html__('sent', 'event_espresso'),
2385
+			$query_args,
2386
+			true
2387
+		);
2388
+	}
2389
+
2390
+
2391
+	/**
2392
+	 *  get_transactions
2393
+	 *    get transactions for given parameters (used by list table)
2394
+	 *
2395
+	 * @param int     $per_page how many transactions displayed per page
2396
+	 * @param boolean $count    return the count or objects
2397
+	 * @param string  $view
2398
+	 * @return EE_Transaction[]|int int = count || array of transaction objects
2399
+	 * @throws EE_Error
2400
+	 * @throws InvalidArgumentException
2401
+	 * @throws InvalidDataTypeException
2402
+	 * @throws InvalidInterfaceException
2403
+	 * @throws ReflectionException
2404
+	 */
2405
+	public function get_transactions($per_page, $count = false, $view = '')
2406
+	{
2407
+		$start_date = wp_strip_all_tags(
2408
+			$this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2409
+		);
2410
+		$end_date   = wp_strip_all_tags(
2411
+			$this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2412
+		);
2413
+
2414
+		// make sure our timestamps start and end right at the boundaries for each day
2415
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2416
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2417
+
2418
+
2419
+		// convert to timestamps
2420
+		$start_date = strtotime($start_date);
2421
+		$end_date   = strtotime($end_date);
2422
+
2423
+		// makes sure start date is the lowest value and vice versa
2424
+		$start_date = min($start_date, $end_date);
2425
+		$end_date   = max($start_date, $end_date);
2426
+
2427
+		// convert to correct format for query
2428
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2429
+			'TXN_timestamp',
2430
+			date('Y-m-d H:i:s', $start_date),
2431
+			'Y-m-d H:i:s'
2432
+		);
2433
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2434
+			'TXN_timestamp',
2435
+			date('Y-m-d H:i:s', $end_date),
2436
+			'Y-m-d H:i:s'
2437
+		);
2438
+
2439
+
2440
+		// set orderby
2441
+		$orderby = $this->request->getRequestParam('orderby');
2442
+
2443
+		switch ($orderby) {
2444
+			case 'TXN_ID':
2445
+				break;
2446
+			case 'ATT_fname':
2447
+				$orderby = 'Registration.Attendee.ATT_fname';
2448
+				break;
2449
+			case 'event_name':
2450
+				$orderby = 'Registration.Event.EVT_name';
2451
+				break;
2452
+			default: // 'TXN_timestamp'
2453
+				$orderby = 'TXN_timestamp';
2454
+		}
2455
+
2456
+		$sort         = $this->request->getRequestParam('order', 'DESC');
2457
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
2458
+
2459
+		$per_page = absint($per_page)
2460
+			? $per_page
2461
+			: 10;
2462
+		$per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2463
+
2464
+		$offset = ($current_page - 1) * $per_page;
2465
+		$limit  = [$offset, $per_page];
2466
+
2467
+		$_where = [
2468
+			'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2469
+			'Registration.REG_count' => 1,
2470
+		];
2471
+
2472
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2473
+		if ($EVT_ID) {
2474
+			$_where['Registration.EVT_ID'] = $EVT_ID;
2475
+		}
2476
+
2477
+		$search_term = $this->request->getRequestParam('s');
2478
+		if ($search_term) {
2479
+			$search_term  = '%' . $search_term . '%';
2480
+			$_where['OR'] = [
2481
+				'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2482
+				'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2483
+				'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2484
+				'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2485
+				'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2486
+				'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2487
+				'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2488
+				'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2489
+				'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2490
+				'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2491
+				'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2492
+				'Registration.REG_final_price'        => ['LIKE', $search_term],
2493
+				'Registration.REG_code'               => ['LIKE', $search_term],
2494
+				'Registration.REG_count'              => ['LIKE', $search_term],
2495
+				'Registration.REG_group_size'         => ['LIKE', $search_term],
2496
+				'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2497
+				'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2498
+				'Payment.PAY_source'                  => ['LIKE', $search_term],
2499
+				'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2500
+				'TXN_session_data'                    => ['LIKE', $search_term],
2501
+				'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2502
+			];
2503
+		}
2504
+
2505
+		$status = $this->request->getRequestParam('status');
2506
+		// failed transactions
2507
+		$failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2508
+		$abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2509
+		$incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2510
+
2511
+		if ($failed) {
2512
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2513
+		} elseif ($abandoned) {
2514
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2515
+		} elseif ($incomplete) {
2516
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2517
+		} else {
2518
+			$_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2519
+			$_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2520
+		}
2521
+
2522
+		$query_params = apply_filters(
2523
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2524
+			[
2525
+				$_where,
2526
+				'order_by'                 => [$orderby => $sort],
2527
+				'limit'                    => $limit,
2528
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2529
+			],
2530
+			$this->request->requestParams(),
2531
+			$view,
2532
+			$count
2533
+		);
2534
+
2535
+		return $count
2536
+			? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2537
+			: EEM_Transaction::instance()->get_all($query_params);
2538
+	}
2539
+
2540
+
2541
+	/**
2542
+	 * @throws EE_Error
2543
+	 * @throws InvalidArgumentException
2544
+	 * @throws InvalidDataTypeException
2545
+	 * @throws InvalidInterfaceException
2546
+	 * @throws ReflectionException
2547
+	 * @throws RuntimeException
2548
+	 * @since 4.9.79.p
2549
+	 */
2550
+	public function recalculateLineItems()
2551
+	{
2552
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2553
+		/** @var EE_Transaction $transaction */
2554
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2555
+		$success     = $transaction->recalculateLineItems();
2556
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2557
+		$query_args  = $redirect_to
2558
+			? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2559
+			: [];
2560
+		$this->_redirect_after_action(
2561
+			$success,
2562
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2563
+			esc_html__('recalculated', 'event_espresso'),
2564
+			$query_args,
2565
+			true
2566
+		);
2567
+	}
2568 2568
 }
Please login to merge, or discard this patch.
admin_pages/maintenance/Maintenance_Admin_Page.core.php 2 patches
Indentation   +958 added lines, -958 removed lines patch added patch discarded remove patch
@@ -15,962 +15,962 @@
 block discarded – undo
15 15
  */
16 16
 class Maintenance_Admin_Page extends EE_Admin_Page
17 17
 {
18
-    /**
19
-     * @var EE_Data_Migration_Manager
20
-     */
21
-    protected $migration_manager;
22
-
23
-    /**
24
-     * @var EE_Maintenance_Mode
25
-     */
26
-    protected $maintenance_mode;
27
-
28
-    /**
29
-     * @var EE_Form_Section_Proper
30
-     */
31
-    protected $datetime_fix_offset_form;
32
-
33
-
34
-    /**
35
-     * @param bool $routing
36
-     * @throws EE_Error
37
-     * @throws ReflectionException
38
-     */
39
-    public function __construct($routing = true)
40
-    {
41
-        $this->migration_manager = EE_Data_Migration_Manager::instance();
42
-        $this->maintenance_mode  = EE_Maintenance_Mode::instance();
43
-        parent::__construct($routing);
44
-    }
45
-
46
-
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug        = EE_MAINTENANCE_PG_SLUG;
50
-        $this->page_label       = EE_MAINTENANCE_LABEL;
51
-        $this->_admin_base_url  = EE_MAINTENANCE_ADMIN_URL;
52
-        $this->_admin_base_path = EE_MAINTENANCE_ADMIN;
53
-    }
54
-
55
-
56
-    protected function _ajax_hooks()
57
-    {
58
-        if (! $this->capabilities->current_user_can('manage_options', 'perform-migrations')) {
59
-            return;
60
-        }
61
-        add_action('wp_ajax_migration_step', [$this, 'migration_step']);
62
-        add_action('wp_ajax_add_error_to_migrations_ran', [$this, 'add_error_to_migrations_ran']);
63
-    }
64
-
65
-
66
-    protected function _define_page_props()
67
-    {
68
-        $this->_admin_page_title = EE_MAINTENANCE_LABEL;
69
-        $this->_labels           = [
70
-            'buttons' => [
71
-                'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
72
-                'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
73
-            ],
74
-        ];
75
-    }
76
-
77
-
78
-    protected function _set_page_routes()
79
-    {
80
-        $this->_page_routes = [
81
-            'default'                             => [
82
-                'func'       => [$this, '_maintenance'],
83
-                'capability' => 'manage_options',
84
-            ],
85
-            'change_maintenance_level'            => [
86
-                'func'       => [$this, '_change_maintenance_level'],
87
-                'capability' => 'manage_options',
88
-                'noheader'   => true,
89
-            ],
90
-            'system_status'                       => [
91
-                'func'       => [$this, '_system_status'],
92
-                'capability' => 'manage_options',
93
-            ],
94
-            'download_system_status'              => [
95
-                'func'       => [$this, '_download_system_status'],
96
-                'capability' => 'manage_options',
97
-                'noheader'   => true,
98
-            ],
99
-            'send_migration_crash_report'         => [
100
-                'func'       => [$this, '_send_migration_crash_report'],
101
-                'capability' => 'manage_options',
102
-                'noheader'   => true,
103
-            ],
104
-            'confirm_migration_crash_report_sent' => [
105
-                'func'       => [$this, '_confirm_migration_crash_report_sent'],
106
-                'capability' => 'manage_options',
107
-            ],
108
-            'data_reset'                          => [
109
-                'func'       => [$this, '_data_reset_and_delete'],
110
-                'capability' => 'manage_options',
111
-            ],
112
-            'reset_db'                            => [
113
-                'func'       => [$this, '_reset_db'],
114
-                'capability' => 'manage_options',
115
-                'noheader'   => true,
116
-                'args'       => ['nuke_old_ee4_data' => true],
117
-            ],
118
-            'start_with_fresh_ee4_db'             => [
119
-                'func'       => [$this, '_reset_db'],
120
-                'capability' => 'manage_options',
121
-                'noheader'   => true,
122
-                'args'       => ['nuke_old_ee4_data' => false],
123
-            ],
124
-            'delete_db'                           => [
125
-                'func'       => [$this, '_delete_db'],
126
-                'capability' => 'manage_options',
127
-                'noheader'   => true,
128
-            ],
129
-            'rerun_migration_from_ee3'            => [
130
-                'func'       => [$this, '_rerun_migration_from_ee3'],
131
-                'capability' => 'manage_options',
132
-                'noheader'   => true,
133
-            ],
134
-            'reset_reservations'                  => [
135
-                'func'       => [$this, '_reset_reservations'],
136
-                'capability' => 'manage_options',
137
-                'noheader'   => true,
138
-            ],
139
-            'reset_capabilities'                  => [
140
-                'func'       => [$this, '_reset_capabilities'],
141
-                'capability' => 'manage_options',
142
-                'noheader'   => true,
143
-            ],
144
-            'reattempt_migration'                 => [
145
-                'func'       => [$this, '_reattempt_migration'],
146
-                'capability' => 'manage_options',
147
-                'noheader'   => true,
148
-            ],
149
-            'datetime_tools'                      => [
150
-                'func'       => [$this, '_datetime_tools'],
151
-                'capability' => 'manage_options',
152
-            ],
153
-            'run_datetime_offset_fix'             => [
154
-                'func'               => [$this, '_apply_datetime_offset'],
155
-                'noheader'           => true,
156
-                'headers_sent_route' => 'datetime_tools',
157
-                'capability'         => 'manage_options',
158
-            ],
159
-        ];
160
-    }
161
-
162
-
163
-    protected function _set_page_config()
164
-    {
165
-        $this->_page_config = [
166
-            'default'        => [
167
-                'nav'           => [
168
-                    'label' => esc_html__('Maintenance', 'event_espresso'),
169
-                    'icon'  => 'dashicons-admin-tools',
170
-                    'order' => 10,
171
-                ],
172
-                'require_nonce' => false,
173
-            ],
174
-            'data_reset'     => [
175
-                'nav'           => [
176
-                    'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
177
-                    'icon'  => 'dashicons-trash',
178
-                    'order' => 20,
179
-                ],
180
-                'require_nonce' => false,
181
-            ],
182
-            'datetime_tools' => [
183
-                'nav'           => [
184
-                    'label' => esc_html__('Datetime Utilities', 'event_espresso'),
185
-                    'icon'  => 'dashicons-calendar-alt',
186
-                    'order' => 25,
187
-                ],
188
-                'require_nonce' => false,
189
-            ],
190
-            'system_status'  => [
191
-                'nav'           => [
192
-                    'label' => esc_html__("System Information", "event_espresso"),
193
-                    'icon'  => 'dashicons-info',
194
-                    'order' => 30,
195
-                ],
196
-                'require_nonce' => false,
197
-            ],
198
-        ];
199
-    }
200
-
201
-
202
-    /**
203
-     * default maintenance page.
204
-     * If we're in maintenance mode level 2, then we need to show the migration scripts and all that UI.
205
-     *
206
-     * @throws EE_Error
207
-     */
208
-    public function _maintenance()
209
-    {
210
-        $show_maintenance_switch         = true;
211
-        $show_backup_db_text             = false;
212
-        $show_migration_progress         = false;
213
-        $script_names                    = [];
214
-        $addons_should_be_upgraded_first = false;
215
-        // it all depends on if we're in maintenance model level 1 (frontend-only) or
216
-        // level 2 (everything except maintenance page)
217
-        try {
218
-            // get the current maintenance level and check if we are removed
219
-            $was_full_site_maintenence_mode = MaintenanceStatus::isFullSite();
220
-            $no_longer_in_maintenence_mode = ! $this->maintenance_mode->set_maintenance_mode_if_db_old();
221
-            if ($was_full_site_maintenence_mode && $no_longer_in_maintenence_mode) {
222
-                // we just took the site out of maintenance mode, so notify the user.
223
-                // unfortunately this message appears to be echoed on the NEXT page load...
224
-                // oh well, we should really be checking for this on addon deactivation anyways
225
-                EE_Error::add_attention(
226
-                    esc_html__(
227
-                        'Site taken out of maintenance mode because no data migration scripts are required',
228
-                        'event_espresso'
229
-                    )
230
-                );
231
-                $this->_process_notices(['page' => 'espresso_maintenance_settings']);
232
-            }
233
-            // in case an exception is thrown while trying to handle migrations
234
-            if (MaintenanceStatus::isFullSite()) {
235
-                $show_maintenance_switch = false;
236
-                $show_migration_progress = true;
237
-                if (! isset($this->_req_data['continue_migration'])) {
238
-                    $show_backup_db_text = true;
239
-                }
240
-                $scripts_needing_to_run          =
241
-                    $this->migration_manager->check_for_applicable_data_migration_scripts();
242
-                $addons_should_be_upgraded_first = $this->migration_manager->addons_need_updating();
243
-                $script_names                    = [];
244
-                $current_script                  = null;
245
-                foreach ($scripts_needing_to_run as $script) {
246
-                    if ($script instanceof EE_Data_Migration_Script_Base) {
247
-                        if (! $current_script) {
248
-                            $current_script = $script;
249
-                            $current_script->migration_page_hooks();
250
-                        }
251
-                        $script_names[] = $script->pretty_name();
252
-                    }
253
-                }
254
-            }
255
-            $most_recent_migration = $this->migration_manager->get_last_ran_script(true);
256
-            $exception_thrown      = false;
257
-        } catch (EE_Error $e) {
258
-            $this->migration_manager->add_error_to_migrations_ran($e->getMessage());
259
-            // now, just so we can display the page correctly, make an error migration script stage object
260
-            // and also put the error on it. It only persists for the duration of this request
261
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
262
-            $most_recent_migration->add_error($e->getMessage());
263
-            $exception_thrown = true;
264
-        }
265
-        $current_db_state = $this->migration_manager->ensure_current_database_state_is_set();
266
-        $current_db_state = str_replace('.decaf', '', $current_db_state);
267
-        if (
268
-            $exception_thrown
269
-            || (
270
-                $most_recent_migration instanceof EE_Data_Migration_Script_Base
271
-                && $most_recent_migration->is_broken()
272
-            )
273
-        ) {
274
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
275
-
276
-            $this->_template_args['support_url'] = 'https://eventespresso.com/support/forums/';
277
-            $this->_template_args['next_url']    = EEH_URL::add_query_args_and_nonce(
278
-                [
279
-                    'action'  => 'confirm_migration_crash_report_sent',
280
-                    'success' => '0',
281
-                ],
282
-                EE_MAINTENANCE_ADMIN_URL
283
-            );
284
-        } elseif ($addons_should_be_upgraded_first) {
285
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
286
-        } else {
287
-            if (
288
-                $most_recent_migration instanceof EE_Data_Migration_Script_Base
289
-                && $most_recent_migration->can_continue()
290
-            ) {
291
-                $show_backup_db_text                    = false;
292
-                $show_continue_current_migration_script = true;
293
-                $show_most_recent_migration             = true;
294
-            } elseif (isset($this->_req_data['continue_migration'])) {
295
-                $show_most_recent_migration             = true;
296
-                $show_continue_current_migration_script = false;
297
-            } else {
298
-                $show_most_recent_migration             = false;
299
-                $show_continue_current_migration_script = false;
300
-            }
301
-            if (isset($current_script)) {
302
-                $migrates_to          = $current_script->migrates_to_version();
303
-                $plugin_slug          = $migrates_to['slug'];
304
-                $new_version          = $migrates_to['version'];
305
-                $this->_template_args = array_merge(
306
-                    $this->_template_args,
307
-                    [
308
-                        'current_db_state' => sprintf(
309
-                            esc_html__("EE%s (%s)", "event_espresso"),
310
-                            $current_db_state[ $plugin_slug ] ?? 3,
311
-                            $plugin_slug
312
-                        ),
313
-                        'next_db_state'    => sprintf(
314
-                            esc_html__("EE%s (%s)", 'event_espresso'),
315
-                            $new_version,
316
-                            $plugin_slug
317
-                        ),
318
-                    ]
319
-                );
320
-            } else {
321
-                $this->_template_args['current_db_state'] = '';
322
-                $this->_template_args['next_db_state']    = '';
323
-            }
324
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
325
-            $this->_template_args = array_merge(
326
-                $this->_template_args,
327
-                [
328
-                    'show_most_recent_migration'             => $show_most_recent_migration,
329
-                    // flag for showing the most recent migration's status and/or errors
330
-                    'show_migration_progress'                => $show_migration_progress,
331
-                    // flag for showing the option to run migrations and see their progress
332
-                    'show_backup_db_text'                    => $show_backup_db_text,
333
-                    // flag for showing text telling the user to back up their DB
334
-                    'show_maintenance_switch'                => $show_maintenance_switch,
335
-                    // flag for showing the option to change maintenance mode between levels 0 and 1
336
-                    'script_names'                           => $script_names,
337
-                    // array of names of scripts that have run
338
-                    'show_continue_current_migration_script' => $show_continue_current_migration_script,
339
-                    // flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
340
-                    'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(
341
-                        ['action' => 'reset_db'],
342
-                        EE_MAINTENANCE_ADMIN_URL
343
-                    ),
344
-                    'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(
345
-                        ['action' => 'data_reset'],
346
-                        EE_MAINTENANCE_ADMIN_URL
347
-                    ),
348
-                    'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(
349
-                        ['action' => 'change_maintenance_level'],
350
-                        EE_MAINTENANCE_ADMIN_URL
351
-                    ),
352
-                    'ultimate_db_state'                      => sprintf(
353
-                        esc_html__("EE%s", 'event_espresso'),
354
-                        espresso_version()
355
-                    ),
356
-                ]
357
-            );
358
-        }
359
-        $this->_template_args['most_recent_migration'] =
360
-            $most_recent_migration;// the actual most recently ran migration
361
-        // now render the migration options part, and put it in a variable
362
-        $migration_options_template_file                = apply_filters(
363
-            'FHEE__ee_migration_page__migration_options_template',
364
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
365
-        );
366
-        $migration_options_html                         = EEH_Template::display_template(
367
-            $migration_options_template_file,
368
-            $this->_template_args,
369
-            true
370
-        );
371
-        $this->_template_args['migration_options_html'] = $migration_options_html;
372
-        $this->_template_args['admin_page_content']     = EEH_Template::display_template(
373
-            $this->_template_path,
374
-            $this->_template_args,
375
-            true
376
-        );
377
-        $this->display_admin_page_with_sidebar();
378
-    }
379
-
380
-
381
-    /**
382
-     * returns JSON and executes another step of the currently-executing data migration (called via ajax)
383
-     *
384
-     * @throws EE_Error
385
-     */
386
-    public function migration_step()
387
-    {
388
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
389
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
390
-        }
391
-        $this->_template_args['data'] = $this->migration_manager->response_to_migration_ajax_request();
392
-        $this->_return_json();
393
-    }
394
-
395
-
396
-    /**
397
-     * Can be used by js when it notices a response with HTML in it in order
398
-     * to log the malformed response
399
-     *
400
-     * @throws EE_Error
401
-     */
402
-    public function add_error_to_migrations_ran()
403
-    {
404
-        $this->migration_manager->add_error_to_migrations_ran($this->_req_data['message']);
405
-        $this->_template_args['data'] = ['ok' => true];
406
-        $this->_return_json();
407
-    }
408
-
409
-
410
-    /**
411
-     * changes the maintenance level, provided there are still no migration scripts that should run
412
-     *
413
-     * @throws EE_Error
414
-     */
415
-    public function _change_maintenance_level()
416
-    {
417
-        $new_level = absint($this->_req_data['maintenance_mode_level']);
418
-        if (! $this->migration_manager->check_for_applicable_data_migration_scripts()) {
419
-            $this->maintenance_mode->set_maintenance_level($new_level);
420
-            $success = true;
421
-        } else {
422
-            $this->maintenance_mode->set_maintenance_mode_if_db_old();
423
-            $success = false;
424
-        }
425
-        $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
426
-    }
427
-
428
-
429
-    /**
430
-     * a tab with options for resetting and/or deleting EE data
431
-     *
432
-     * @throws EE_Error
433
-     * @throws DomainException
434
-     */
435
-    public function _data_reset_and_delete()
436
-    {
437
-        $this->_template_path                              =
438
-            EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
439
-        $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
440
-            'reset_reservations',
441
-            'reset_reservations',
442
-            [],
443
-            'button button--caution ee-confirm'
444
-        );
445
-        $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
446
-            'reset_capabilities',
447
-            'reset_capabilities',
448
-            [],
449
-            'button button--caution ee-confirm'
450
-        );
451
-        $this->_template_args['delete_db_url']             = EE_Admin_Page::add_query_args_and_nonce(
452
-            ['action' => 'delete_db'],
453
-            EE_MAINTENANCE_ADMIN_URL
454
-        );
455
-        $this->_template_args['reset_db_url']              = EE_Admin_Page::add_query_args_and_nonce(
456
-            ['action' => 'reset_db'],
457
-            EE_MAINTENANCE_ADMIN_URL
458
-        );
459
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
460
-            $this->_template_path,
461
-            $this->_template_args,
462
-            true
463
-        );
464
-        $this->display_admin_page_with_no_sidebar();
465
-    }
466
-
467
-
468
-    /**
469
-     * @throws EE_Error
470
-     * @throws ReflectionException
471
-     */
472
-    protected function _reset_reservations()
473
-    {
474
-        if (EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
475
-            EE_Error::add_success(
476
-                esc_html__(
477
-                    'Ticket and datetime reserved counts have been successfully reset.',
478
-                    'event_espresso'
479
-                )
480
-            );
481
-        } else {
482
-            EE_Error::add_success(
483
-                esc_html__(
484
-                    'Ticket and datetime reserved counts were correct and did not need resetting.',
485
-                    'event_espresso'
486
-                )
487
-            );
488
-        }
489
-        $this->_redirect_after_action(true, '', '', ['action' => 'data_reset'], true);
490
-    }
491
-
492
-
493
-    /**
494
-     * @throws EE_Error
495
-     */
496
-    protected function _reset_capabilities()
497
-    {
498
-        $this->capabilities->init_caps(true);
499
-        EE_Error::add_success(
500
-            esc_html__(
501
-                'Default Event Espresso capabilities have been restored for all current roles.',
502
-                'event_espresso'
503
-            )
504
-        );
505
-        $this->_redirect_after_action(false, '', '', ['action' => 'data_reset'], true);
506
-    }
507
-
508
-
509
-    /**
510
-     * resets the DMSs, so we can attempt to continue migrating after a fatal error
511
-     * (only a good idea when someone has somehow tried ot fix whatever caused
512
-     * the fatal error in teh first place)
513
-     *
514
-     * @throws EE_Error
515
-     */
516
-    protected function _reattempt_migration()
517
-    {
518
-        $this->migration_manager->reattempt();
519
-        $this->_redirect_after_action(false, '', '', ['action' => 'default'], true);
520
-    }
521
-
522
-
523
-    /**
524
-     * shows the big ol' System Information page
525
-     *
526
-     * @throws EE_Error
527
-     */
528
-    public function _system_status()
529
-    {
530
-        $this->_template_path                               =
531
-            EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
532
-        $this->_template_args['system_stati']               = EEM_System_Status::instance()->get_system_stati();
533
-        $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
534
-            [
535
-                'action' => 'download_system_status',
536
-            ],
537
-            EE_MAINTENANCE_ADMIN_URL
538
-        );
539
-        $this->_template_args['admin_page_content']         = EEH_Template::display_template(
540
-            $this->_template_path,
541
-            $this->_template_args,
542
-            true
543
-        );
544
-        $this->display_admin_page_with_no_sidebar();
545
-    }
546
-
547
-
548
-    /**
549
-     * Downloads an HTML file of the system status that can be easily stored or emailed
550
-     */
551
-    public function _download_system_status()
552
-    {
553
-        $status_info = EEM_System_Status::instance()->get_system_stati();
554
-        header('Content-Disposition: attachment');
555
-        header("Content-Disposition: attachment; filename=system_status_" . sanitize_key(site_url()) . ".html");
556
-        $output = '<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>';
557
-        $output .= '<h1>' . sprintf(
558
-                __('System Information for %1$s', 'event_espresso'),
559
-                esc_url_raw(site_url())
560
-            ) . '</h1>';
561
-        $output .= EEH_Template::layout_array_as_table($status_info);
562
-        echo esc_html($output);
563
-        die;
564
-    }
565
-
566
-
567
-    /**
568
-     * @throws EE_Error
569
-     */
570
-    public function _send_migration_crash_report()
571
-    {
572
-        $from      = $this->_req_data['from'];
573
-        $from_name = $this->_req_data['from_name'];
574
-        $body      = $this->_req_data['body'];
575
-        try {
576
-            $success = wp_mail(
577
-                EE_SUPPORT_EMAIL,
578
-                'Migration Crash Report',
579
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
580
-                [
581
-                    "from:$from_name<$from>",
582
-                ]
583
-            );
584
-        } catch (Exception $e) {
585
-            $success = false;
586
-        }
587
-        $this->_redirect_after_action(
588
-            $success,
589
-            esc_html__("Migration Crash Report", "event_espresso"),
590
-            esc_html__("sent", "event_espresso"),
591
-            ['success' => $success, 'action' => 'confirm_migration_crash_report_sent']
592
-        );
593
-    }
594
-
595
-
596
-    /**
597
-     * @throws EE_Error
598
-     */
599
-    public function _confirm_migration_crash_report_sent()
600
-    {
601
-        try {
602
-            $most_recent_migration = $this->migration_manager->get_last_ran_script(true);
603
-        } catch (EE_Error $e) {
604
-            $this->migration_manager->add_error_to_migrations_ran($e->getMessage());
605
-            // now, just so we can display the page correctly, make an error migration script stage object
606
-            // and also put the error on it. It only persists for the duration of this request
607
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
608
-            $most_recent_migration->add_error($e->getMessage());
609
-        }
610
-        $success                                       = $this->_req_data['success'] === '1';
611
-        $this->_template_args['success']               = $success;
612
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;
613
-        $this->_template_args['reset_db_action_url']   = EE_Admin_Page::add_query_args_and_nonce(
614
-            ['action' => 'reset_db'],
615
-            EE_MAINTENANCE_ADMIN_URL
616
-        );
617
-        $this->_template_args['reset_db_page_url']     = EE_Admin_Page::add_query_args_and_nonce(
618
-            ['action' => 'data_reset'],
619
-            EE_MAINTENANCE_ADMIN_URL
620
-        );
621
-        $this->_template_args['reattempt_action_url']  = EE_Admin_Page::add_query_args_and_nonce(
622
-            ['action' => 'reattempt_migration'],
623
-            EE_MAINTENANCE_ADMIN_URL
624
-        );
625
-        $this->_template_path                          =
626
-            EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
627
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
628
-            $this->_template_path,
629
-            $this->_template_args,
630
-            true
631
-        );
632
-        $this->display_admin_page_with_sidebar();
633
-    }
634
-
635
-
636
-    /**
637
-     * Resets the entire EE4 database.
638
-     * only sets up ee4 database for a fresh install-
639
-     * doesn't actually clean out the old wp options, or cpts
640
-     * (although it does erase old ee table data)
641
-     *
642
-     * @param boolean $nuke_old_ee4_data controls whether we destroy the old ee4 data,
643
-     *                                   or just try initializing ee4 default data
644
-     * @throws EE_Error
645
-     * @throws ReflectionException
646
-     */
647
-    public function _reset_db($nuke_old_ee4_data = true)
648
-    {
649
-        $this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_OFF);
650
-        if ($nuke_old_ee4_data) {
651
-            EEH_Activation::delete_all_espresso_cpt_data();
652
-            EEH_Activation::delete_all_espresso_tables_and_data(false);
653
-            EEH_Activation::remove_cron_tasks();
654
-        }
655
-        // make sure when we reset the registry's config that it
656
-        // switches to using the new singleton
657
-        EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
658
-        EE_System::instance()->initialize_db_if_no_migrations_required(true);
659
-        EE_System::instance()->redirect_to_about_ee();
660
-    }
661
-
662
-
663
-    /**
664
-     * Deletes ALL EE tables, Records, and Options from the database.
665
-     *
666
-     * @throws EE_Error
667
-     * @throws ReflectionException
668
-     */
669
-    public function _delete_db()
670
-    {
671
-        $this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_OFF);
672
-        EEH_Activation::delete_all_espresso_cpt_data();
673
-        EEH_Activation::delete_all_espresso_tables_and_data();
674
-        EEH_Activation::remove_cron_tasks();
675
-        EEH_Activation::deactivate_event_espresso();
676
-        wp_safe_redirect(admin_url('plugins.php'));
677
-        exit;
678
-    }
679
-
680
-
681
-    /**
682
-     * sets up EE4 to rerun the migrations from ee3 to ee4
683
-     *
684
-     * @throws EE_Error
685
-     * @throws ReflectionException
686
-     */
687
-    public function _rerun_migration_from_ee3()
688
-    {
689
-        $this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_OFF);
690
-        EEH_Activation::delete_all_espresso_cpt_data();
691
-        EEH_Activation::delete_all_espresso_tables_and_data(false);
692
-        // set the db state to something that will require migrations
693
-        update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
694
-        $this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_FULL_SITE);
695
-        $this->_redirect_after_action(
696
-            true,
697
-            esc_html__("Database", 'event_espresso'),
698
-            esc_html__("reset", 'event_espresso')
699
-        );
700
-    }
701
-
702
-
703
-    // none of the below group are currently used for Gateway Settings
704
-    protected function _add_screen_options()
705
-    {
706
-    }
707
-
708
-
709
-    protected function _add_feature_pointers()
710
-    {
711
-    }
712
-
713
-
714
-    public function admin_init()
715
-    {
716
-    }
717
-
718
-
719
-    public function admin_notices()
720
-    {
721
-    }
722
-
723
-
724
-    public function admin_footer_scripts()
725
-    {
726
-    }
727
-
728
-
729
-    public function load_scripts_styles()
730
-    {
731
-        wp_enqueue_script('ee_admin_js');
732
-        wp_enqueue_script(
733
-            'ee-maintenance',
734
-            EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js',
735
-            ['jquery'],
736
-            EVENT_ESPRESSO_VERSION,
737
-            true
738
-        );
739
-        wp_register_style(
740
-            'espresso_maintenance',
741
-            EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css',
742
-            [],
743
-            EVENT_ESPRESSO_VERSION
744
-        );
745
-        wp_enqueue_style('espresso_maintenance');
746
-        // localize script stuff
747
-        wp_localize_script(
748
-            'ee-maintenance',
749
-            'ee_maintenance',
750
-            [
751
-                'migrating'                        => wp_strip_all_tags(__("Updating Database...", "event_espresso")),
752
-                'next'                             => wp_strip_all_tags(__("Next", "event_espresso")),
753
-                'fatal_error'                      => wp_strip_all_tags(
754
-                    __(
755
-                        "A Fatal Error Has Occurred",
756
-                        "event_espresso"
757
-                    )
758
-                ),
759
-                'click_next_when_ready'            => wp_strip_all_tags(
760
-                    __(
761
-                        "The current Database Update has ended. Click 'next' when ready to proceed",
762
-                        "event_espresso"
763
-                    )
764
-                ),
765
-                'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
766
-                'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
767
-                'status_completed'                 => EE_Data_Migration_Manager::status_completed,
768
-                'confirm'                          => wp_strip_all_tags(
769
-                    __(
770
-                        'Are you sure you want to do this? It CANNOT be undone!',
771
-                        'event_espresso'
772
-                    )
773
-                ),
774
-                'confirm_skip_migration'           => wp_strip_all_tags(
775
-                    __(
776
-                        'You have chosen to NOT migrate your existing data. Are you sure you want to continue?',
777
-                        'event_espresso'
778
-                    )
779
-                ),
780
-            ]
781
-        );
782
-    }
783
-
784
-
785
-    public function load_scripts_styles_default()
786
-    {
787
-    }
788
-
789
-
790
-    /**
791
-     * Enqueue scripts and styles for the datetime tools page.
792
-     */
793
-    public function load_scripts_styles_datetime_tools()
794
-    {
795
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
796
-    }
797
-
798
-
799
-    /**
800
-     * @throws EE_Error
801
-     */
802
-    protected function _datetime_tools()
803
-    {
804
-        $form_action                                = EE_Admin_Page::add_query_args_and_nonce(
805
-            [
806
-                'action'        => 'run_datetime_offset_fix',
807
-                'return_action' => $this->_req_action,
808
-            ],
809
-            EE_MAINTENANCE_ADMIN_URL
810
-        );
811
-        $form                                       = $this->_get_datetime_offset_fix_form();
812
-        $this->_admin_page_title                    = esc_html__('Datetime Utilities', 'event_espresso');
813
-        $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
814
-                                                      . $form->get_html_and_js()
815
-                                                      . $form->form_close();
816
-        $this->display_admin_page_with_sidebar();
817
-    }
818
-
819
-
820
-    /**
821
-     * @throws EE_Error
822
-     */
823
-    protected function _get_datetime_offset_fix_form()
824
-    {
825
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
826
-            $this->datetime_fix_offset_form = new EE_Form_Section_Proper(
827
-                [
828
-                    'name'            => 'datetime_offset_fix_option',
829
-                    'layout_strategy' => new EE_Admin_Two_Column_Layout(),
830
-                    'subsections'     => [
831
-                        'title'                  => new EE_Form_Section_HTML(
832
-                            EEH_HTML::h2(
833
-                                esc_html__('Datetime Offset Tool', 'event_espresso')
834
-                            )
835
-                        ),
836
-                        'explanation'            => new EE_Form_Section_HTML(
837
-                            EEH_HTML::p(
838
-                                esc_html__(
839
-                                    'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
840
-                                    'event_espresso'
841
-                                )
842
-                            )
843
-                            . EEH_HTML::p(
844
-                                esc_html__(
845
-                                    'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
846
-                                    'event_espresso'
847
-                                )
848
-                            )
849
-                        ),
850
-                        'offset_input'           => new EE_Float_Input(
851
-                            [
852
-                                'html_name'       => 'offset_for_datetimes',
853
-                                'html_label_text' => esc_html__(
854
-                                    'Offset to apply (in hours):',
855
-                                    'event_espresso'
856
-                                ),
857
-                                'min_value'       => '-12',
858
-                                'max_value'       => '14',
859
-                                'step_value'      => '.25',
860
-                                'default'         => DatetimeOffsetFix::getOffset(),
861
-                            ]
862
-                        ),
863
-                        'date_range_explanation' => new EE_Form_Section_HTML(
864
-                            EEH_HTML::p(
865
-                                esc_html__(
866
-                                    'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.',
867
-                                    'event_espresso'
868
-                                )
869
-                            )
870
-                            . EEH_HTML::p(
871
-                                EEH_HTML::strong(
872
-                                    sprintf(
873
-                                        esc_html__(
874
-                                            'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).',
875
-                                            'event_espresso'
876
-                                        ),
877
-                                        '<a href="https://www.timeanddate.com/worldclock/converter.html">',
878
-                                        '</a>'
879
-                                    )
880
-                                )
881
-                            )
882
-                        ),
883
-                        'date_range_start_date'  => new EE_Datepicker_Input(
884
-                            [
885
-                                'html_name'       => 'offset_date_start_range',
886
-                                'html_label_text' => esc_html__(
887
-                                    'Start Date for dates the offset applied to:',
888
-                                    'event_espresso'
889
-                                ),
890
-                            ]
891
-                        ),
892
-                        'date_range_end_date'    => new EE_Datepicker_Input(
893
-                            [
894
-                                'html_name'       => 'offset_date_end_range',
895
-                                'html_label_text' => esc_html__(
896
-                                    'End Date for dates the offset is applied to:',
897
-                                    'event_espresso'
898
-                                ),
899
-                            ]
900
-                        ),
901
-                        'submit'                 => new EE_Submit_Input(
902
-                            [
903
-                                'html_label_text' => '',
904
-                                'default'         => esc_html__('Apply Offset', 'event_espresso'),
905
-                            ]
906
-                        ),
907
-                    ],
908
-                ]
909
-            );
910
-        }
911
-        return $this->datetime_fix_offset_form;
912
-    }
913
-
914
-
915
-    /**
916
-     * Callback for the run_datetime_offset_fix route.
917
-     *
918
-     * @throws EE_Error
919
-     */
920
-    protected function _apply_datetime_offset()
921
-    {
922
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
923
-            $form = $this->_get_datetime_offset_fix_form();
924
-            $form->receive_form_submission($this->_req_data);
925
-            if ($form->is_valid()) {
926
-                // save offset data so batch processor can get it.
927
-                DatetimeOffsetFix::updateOffset((float) $form->get_input_value('offset_input'));
928
-                $utc_timezone          = new DateTimeZone('UTC');
929
-                $date_range_start_date = DateTime::createFromFormat(
930
-                    'm/d/Y H:i:s',
931
-                    $form->get_input_value('date_range_start_date') . ' 00:00:00',
932
-                    $utc_timezone
933
-                );
934
-                $date_range_end_date   = DateTime::createFromFormat(
935
-                    'm/d/Y H:i:s',
936
-                    $form->get_input_value('date_range_end_date') . ' 23:59:59',
937
-                    $utc_timezone
938
-                );
939
-                if ($date_range_start_date instanceof DateTime) {
940
-                    DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date));
941
-                }
942
-                if ($date_range_end_date instanceof DateTime) {
943
-                    DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date));
944
-                }
945
-                // redirect to batch tool
946
-                wp_redirect(
947
-                    EE_Admin_Page::add_query_args_and_nonce(
948
-                        [
949
-                            'page'        => EED_Batch::PAGE_SLUG,
950
-                            'batch'       => EED_Batch::batch_job,
951
-                            'label'       => esc_html__('Applying Offset', 'event_espresso'),
952
-                            'job_handler' => urlencode('EventEspresso\core\libraries\batch\JobHandlers\DatetimeOffsetFix'),
953
-                            'return_url'  => urlencode(
954
-                                add_query_arg(
955
-                                    [
956
-                                        'action' => 'datetime_tools',
957
-                                    ],
958
-                                    EEH_URL::current_url_without_query_paramaters(
959
-                                        [
960
-                                            'return_action',
961
-                                            'run_datetime_offset_fix_nonce',
962
-                                            'return',
963
-                                            'datetime_tools_nonce',
964
-                                        ]
965
-                                    )
966
-                                )
967
-                            ),
968
-                        ],
969
-                        admin_url()
970
-                    )
971
-                );
972
-                exit;
973
-            }
974
-        }
975
-    }
18
+	/**
19
+	 * @var EE_Data_Migration_Manager
20
+	 */
21
+	protected $migration_manager;
22
+
23
+	/**
24
+	 * @var EE_Maintenance_Mode
25
+	 */
26
+	protected $maintenance_mode;
27
+
28
+	/**
29
+	 * @var EE_Form_Section_Proper
30
+	 */
31
+	protected $datetime_fix_offset_form;
32
+
33
+
34
+	/**
35
+	 * @param bool $routing
36
+	 * @throws EE_Error
37
+	 * @throws ReflectionException
38
+	 */
39
+	public function __construct($routing = true)
40
+	{
41
+		$this->migration_manager = EE_Data_Migration_Manager::instance();
42
+		$this->maintenance_mode  = EE_Maintenance_Mode::instance();
43
+		parent::__construct($routing);
44
+	}
45
+
46
+
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug        = EE_MAINTENANCE_PG_SLUG;
50
+		$this->page_label       = EE_MAINTENANCE_LABEL;
51
+		$this->_admin_base_url  = EE_MAINTENANCE_ADMIN_URL;
52
+		$this->_admin_base_path = EE_MAINTENANCE_ADMIN;
53
+	}
54
+
55
+
56
+	protected function _ajax_hooks()
57
+	{
58
+		if (! $this->capabilities->current_user_can('manage_options', 'perform-migrations')) {
59
+			return;
60
+		}
61
+		add_action('wp_ajax_migration_step', [$this, 'migration_step']);
62
+		add_action('wp_ajax_add_error_to_migrations_ran', [$this, 'add_error_to_migrations_ran']);
63
+	}
64
+
65
+
66
+	protected function _define_page_props()
67
+	{
68
+		$this->_admin_page_title = EE_MAINTENANCE_LABEL;
69
+		$this->_labels           = [
70
+			'buttons' => [
71
+				'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
72
+				'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
73
+			],
74
+		];
75
+	}
76
+
77
+
78
+	protected function _set_page_routes()
79
+	{
80
+		$this->_page_routes = [
81
+			'default'                             => [
82
+				'func'       => [$this, '_maintenance'],
83
+				'capability' => 'manage_options',
84
+			],
85
+			'change_maintenance_level'            => [
86
+				'func'       => [$this, '_change_maintenance_level'],
87
+				'capability' => 'manage_options',
88
+				'noheader'   => true,
89
+			],
90
+			'system_status'                       => [
91
+				'func'       => [$this, '_system_status'],
92
+				'capability' => 'manage_options',
93
+			],
94
+			'download_system_status'              => [
95
+				'func'       => [$this, '_download_system_status'],
96
+				'capability' => 'manage_options',
97
+				'noheader'   => true,
98
+			],
99
+			'send_migration_crash_report'         => [
100
+				'func'       => [$this, '_send_migration_crash_report'],
101
+				'capability' => 'manage_options',
102
+				'noheader'   => true,
103
+			],
104
+			'confirm_migration_crash_report_sent' => [
105
+				'func'       => [$this, '_confirm_migration_crash_report_sent'],
106
+				'capability' => 'manage_options',
107
+			],
108
+			'data_reset'                          => [
109
+				'func'       => [$this, '_data_reset_and_delete'],
110
+				'capability' => 'manage_options',
111
+			],
112
+			'reset_db'                            => [
113
+				'func'       => [$this, '_reset_db'],
114
+				'capability' => 'manage_options',
115
+				'noheader'   => true,
116
+				'args'       => ['nuke_old_ee4_data' => true],
117
+			],
118
+			'start_with_fresh_ee4_db'             => [
119
+				'func'       => [$this, '_reset_db'],
120
+				'capability' => 'manage_options',
121
+				'noheader'   => true,
122
+				'args'       => ['nuke_old_ee4_data' => false],
123
+			],
124
+			'delete_db'                           => [
125
+				'func'       => [$this, '_delete_db'],
126
+				'capability' => 'manage_options',
127
+				'noheader'   => true,
128
+			],
129
+			'rerun_migration_from_ee3'            => [
130
+				'func'       => [$this, '_rerun_migration_from_ee3'],
131
+				'capability' => 'manage_options',
132
+				'noheader'   => true,
133
+			],
134
+			'reset_reservations'                  => [
135
+				'func'       => [$this, '_reset_reservations'],
136
+				'capability' => 'manage_options',
137
+				'noheader'   => true,
138
+			],
139
+			'reset_capabilities'                  => [
140
+				'func'       => [$this, '_reset_capabilities'],
141
+				'capability' => 'manage_options',
142
+				'noheader'   => true,
143
+			],
144
+			'reattempt_migration'                 => [
145
+				'func'       => [$this, '_reattempt_migration'],
146
+				'capability' => 'manage_options',
147
+				'noheader'   => true,
148
+			],
149
+			'datetime_tools'                      => [
150
+				'func'       => [$this, '_datetime_tools'],
151
+				'capability' => 'manage_options',
152
+			],
153
+			'run_datetime_offset_fix'             => [
154
+				'func'               => [$this, '_apply_datetime_offset'],
155
+				'noheader'           => true,
156
+				'headers_sent_route' => 'datetime_tools',
157
+				'capability'         => 'manage_options',
158
+			],
159
+		];
160
+	}
161
+
162
+
163
+	protected function _set_page_config()
164
+	{
165
+		$this->_page_config = [
166
+			'default'        => [
167
+				'nav'           => [
168
+					'label' => esc_html__('Maintenance', 'event_espresso'),
169
+					'icon'  => 'dashicons-admin-tools',
170
+					'order' => 10,
171
+				],
172
+				'require_nonce' => false,
173
+			],
174
+			'data_reset'     => [
175
+				'nav'           => [
176
+					'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
177
+					'icon'  => 'dashicons-trash',
178
+					'order' => 20,
179
+				],
180
+				'require_nonce' => false,
181
+			],
182
+			'datetime_tools' => [
183
+				'nav'           => [
184
+					'label' => esc_html__('Datetime Utilities', 'event_espresso'),
185
+					'icon'  => 'dashicons-calendar-alt',
186
+					'order' => 25,
187
+				],
188
+				'require_nonce' => false,
189
+			],
190
+			'system_status'  => [
191
+				'nav'           => [
192
+					'label' => esc_html__("System Information", "event_espresso"),
193
+					'icon'  => 'dashicons-info',
194
+					'order' => 30,
195
+				],
196
+				'require_nonce' => false,
197
+			],
198
+		];
199
+	}
200
+
201
+
202
+	/**
203
+	 * default maintenance page.
204
+	 * If we're in maintenance mode level 2, then we need to show the migration scripts and all that UI.
205
+	 *
206
+	 * @throws EE_Error
207
+	 */
208
+	public function _maintenance()
209
+	{
210
+		$show_maintenance_switch         = true;
211
+		$show_backup_db_text             = false;
212
+		$show_migration_progress         = false;
213
+		$script_names                    = [];
214
+		$addons_should_be_upgraded_first = false;
215
+		// it all depends on if we're in maintenance model level 1 (frontend-only) or
216
+		// level 2 (everything except maintenance page)
217
+		try {
218
+			// get the current maintenance level and check if we are removed
219
+			$was_full_site_maintenence_mode = MaintenanceStatus::isFullSite();
220
+			$no_longer_in_maintenence_mode = ! $this->maintenance_mode->set_maintenance_mode_if_db_old();
221
+			if ($was_full_site_maintenence_mode && $no_longer_in_maintenence_mode) {
222
+				// we just took the site out of maintenance mode, so notify the user.
223
+				// unfortunately this message appears to be echoed on the NEXT page load...
224
+				// oh well, we should really be checking for this on addon deactivation anyways
225
+				EE_Error::add_attention(
226
+					esc_html__(
227
+						'Site taken out of maintenance mode because no data migration scripts are required',
228
+						'event_espresso'
229
+					)
230
+				);
231
+				$this->_process_notices(['page' => 'espresso_maintenance_settings']);
232
+			}
233
+			// in case an exception is thrown while trying to handle migrations
234
+			if (MaintenanceStatus::isFullSite()) {
235
+				$show_maintenance_switch = false;
236
+				$show_migration_progress = true;
237
+				if (! isset($this->_req_data['continue_migration'])) {
238
+					$show_backup_db_text = true;
239
+				}
240
+				$scripts_needing_to_run          =
241
+					$this->migration_manager->check_for_applicable_data_migration_scripts();
242
+				$addons_should_be_upgraded_first = $this->migration_manager->addons_need_updating();
243
+				$script_names                    = [];
244
+				$current_script                  = null;
245
+				foreach ($scripts_needing_to_run as $script) {
246
+					if ($script instanceof EE_Data_Migration_Script_Base) {
247
+						if (! $current_script) {
248
+							$current_script = $script;
249
+							$current_script->migration_page_hooks();
250
+						}
251
+						$script_names[] = $script->pretty_name();
252
+					}
253
+				}
254
+			}
255
+			$most_recent_migration = $this->migration_manager->get_last_ran_script(true);
256
+			$exception_thrown      = false;
257
+		} catch (EE_Error $e) {
258
+			$this->migration_manager->add_error_to_migrations_ran($e->getMessage());
259
+			// now, just so we can display the page correctly, make an error migration script stage object
260
+			// and also put the error on it. It only persists for the duration of this request
261
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
262
+			$most_recent_migration->add_error($e->getMessage());
263
+			$exception_thrown = true;
264
+		}
265
+		$current_db_state = $this->migration_manager->ensure_current_database_state_is_set();
266
+		$current_db_state = str_replace('.decaf', '', $current_db_state);
267
+		if (
268
+			$exception_thrown
269
+			|| (
270
+				$most_recent_migration instanceof EE_Data_Migration_Script_Base
271
+				&& $most_recent_migration->is_broken()
272
+			)
273
+		) {
274
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
275
+
276
+			$this->_template_args['support_url'] = 'https://eventespresso.com/support/forums/';
277
+			$this->_template_args['next_url']    = EEH_URL::add_query_args_and_nonce(
278
+				[
279
+					'action'  => 'confirm_migration_crash_report_sent',
280
+					'success' => '0',
281
+				],
282
+				EE_MAINTENANCE_ADMIN_URL
283
+			);
284
+		} elseif ($addons_should_be_upgraded_first) {
285
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
286
+		} else {
287
+			if (
288
+				$most_recent_migration instanceof EE_Data_Migration_Script_Base
289
+				&& $most_recent_migration->can_continue()
290
+			) {
291
+				$show_backup_db_text                    = false;
292
+				$show_continue_current_migration_script = true;
293
+				$show_most_recent_migration             = true;
294
+			} elseif (isset($this->_req_data['continue_migration'])) {
295
+				$show_most_recent_migration             = true;
296
+				$show_continue_current_migration_script = false;
297
+			} else {
298
+				$show_most_recent_migration             = false;
299
+				$show_continue_current_migration_script = false;
300
+			}
301
+			if (isset($current_script)) {
302
+				$migrates_to          = $current_script->migrates_to_version();
303
+				$plugin_slug          = $migrates_to['slug'];
304
+				$new_version          = $migrates_to['version'];
305
+				$this->_template_args = array_merge(
306
+					$this->_template_args,
307
+					[
308
+						'current_db_state' => sprintf(
309
+							esc_html__("EE%s (%s)", "event_espresso"),
310
+							$current_db_state[ $plugin_slug ] ?? 3,
311
+							$plugin_slug
312
+						),
313
+						'next_db_state'    => sprintf(
314
+							esc_html__("EE%s (%s)", 'event_espresso'),
315
+							$new_version,
316
+							$plugin_slug
317
+						),
318
+					]
319
+				);
320
+			} else {
321
+				$this->_template_args['current_db_state'] = '';
322
+				$this->_template_args['next_db_state']    = '';
323
+			}
324
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
325
+			$this->_template_args = array_merge(
326
+				$this->_template_args,
327
+				[
328
+					'show_most_recent_migration'             => $show_most_recent_migration,
329
+					// flag for showing the most recent migration's status and/or errors
330
+					'show_migration_progress'                => $show_migration_progress,
331
+					// flag for showing the option to run migrations and see their progress
332
+					'show_backup_db_text'                    => $show_backup_db_text,
333
+					// flag for showing text telling the user to back up their DB
334
+					'show_maintenance_switch'                => $show_maintenance_switch,
335
+					// flag for showing the option to change maintenance mode between levels 0 and 1
336
+					'script_names'                           => $script_names,
337
+					// array of names of scripts that have run
338
+					'show_continue_current_migration_script' => $show_continue_current_migration_script,
339
+					// flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
340
+					'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(
341
+						['action' => 'reset_db'],
342
+						EE_MAINTENANCE_ADMIN_URL
343
+					),
344
+					'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(
345
+						['action' => 'data_reset'],
346
+						EE_MAINTENANCE_ADMIN_URL
347
+					),
348
+					'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(
349
+						['action' => 'change_maintenance_level'],
350
+						EE_MAINTENANCE_ADMIN_URL
351
+					),
352
+					'ultimate_db_state'                      => sprintf(
353
+						esc_html__("EE%s", 'event_espresso'),
354
+						espresso_version()
355
+					),
356
+				]
357
+			);
358
+		}
359
+		$this->_template_args['most_recent_migration'] =
360
+			$most_recent_migration;// the actual most recently ran migration
361
+		// now render the migration options part, and put it in a variable
362
+		$migration_options_template_file                = apply_filters(
363
+			'FHEE__ee_migration_page__migration_options_template',
364
+			EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
365
+		);
366
+		$migration_options_html                         = EEH_Template::display_template(
367
+			$migration_options_template_file,
368
+			$this->_template_args,
369
+			true
370
+		);
371
+		$this->_template_args['migration_options_html'] = $migration_options_html;
372
+		$this->_template_args['admin_page_content']     = EEH_Template::display_template(
373
+			$this->_template_path,
374
+			$this->_template_args,
375
+			true
376
+		);
377
+		$this->display_admin_page_with_sidebar();
378
+	}
379
+
380
+
381
+	/**
382
+	 * returns JSON and executes another step of the currently-executing data migration (called via ajax)
383
+	 *
384
+	 * @throws EE_Error
385
+	 */
386
+	public function migration_step()
387
+	{
388
+		if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
389
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
390
+		}
391
+		$this->_template_args['data'] = $this->migration_manager->response_to_migration_ajax_request();
392
+		$this->_return_json();
393
+	}
394
+
395
+
396
+	/**
397
+	 * Can be used by js when it notices a response with HTML in it in order
398
+	 * to log the malformed response
399
+	 *
400
+	 * @throws EE_Error
401
+	 */
402
+	public function add_error_to_migrations_ran()
403
+	{
404
+		$this->migration_manager->add_error_to_migrations_ran($this->_req_data['message']);
405
+		$this->_template_args['data'] = ['ok' => true];
406
+		$this->_return_json();
407
+	}
408
+
409
+
410
+	/**
411
+	 * changes the maintenance level, provided there are still no migration scripts that should run
412
+	 *
413
+	 * @throws EE_Error
414
+	 */
415
+	public function _change_maintenance_level()
416
+	{
417
+		$new_level = absint($this->_req_data['maintenance_mode_level']);
418
+		if (! $this->migration_manager->check_for_applicable_data_migration_scripts()) {
419
+			$this->maintenance_mode->set_maintenance_level($new_level);
420
+			$success = true;
421
+		} else {
422
+			$this->maintenance_mode->set_maintenance_mode_if_db_old();
423
+			$success = false;
424
+		}
425
+		$this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
426
+	}
427
+
428
+
429
+	/**
430
+	 * a tab with options for resetting and/or deleting EE data
431
+	 *
432
+	 * @throws EE_Error
433
+	 * @throws DomainException
434
+	 */
435
+	public function _data_reset_and_delete()
436
+	{
437
+		$this->_template_path                              =
438
+			EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
439
+		$this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
440
+			'reset_reservations',
441
+			'reset_reservations',
442
+			[],
443
+			'button button--caution ee-confirm'
444
+		);
445
+		$this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
446
+			'reset_capabilities',
447
+			'reset_capabilities',
448
+			[],
449
+			'button button--caution ee-confirm'
450
+		);
451
+		$this->_template_args['delete_db_url']             = EE_Admin_Page::add_query_args_and_nonce(
452
+			['action' => 'delete_db'],
453
+			EE_MAINTENANCE_ADMIN_URL
454
+		);
455
+		$this->_template_args['reset_db_url']              = EE_Admin_Page::add_query_args_and_nonce(
456
+			['action' => 'reset_db'],
457
+			EE_MAINTENANCE_ADMIN_URL
458
+		);
459
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
460
+			$this->_template_path,
461
+			$this->_template_args,
462
+			true
463
+		);
464
+		$this->display_admin_page_with_no_sidebar();
465
+	}
466
+
467
+
468
+	/**
469
+	 * @throws EE_Error
470
+	 * @throws ReflectionException
471
+	 */
472
+	protected function _reset_reservations()
473
+	{
474
+		if (EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
475
+			EE_Error::add_success(
476
+				esc_html__(
477
+					'Ticket and datetime reserved counts have been successfully reset.',
478
+					'event_espresso'
479
+				)
480
+			);
481
+		} else {
482
+			EE_Error::add_success(
483
+				esc_html__(
484
+					'Ticket and datetime reserved counts were correct and did not need resetting.',
485
+					'event_espresso'
486
+				)
487
+			);
488
+		}
489
+		$this->_redirect_after_action(true, '', '', ['action' => 'data_reset'], true);
490
+	}
491
+
492
+
493
+	/**
494
+	 * @throws EE_Error
495
+	 */
496
+	protected function _reset_capabilities()
497
+	{
498
+		$this->capabilities->init_caps(true);
499
+		EE_Error::add_success(
500
+			esc_html__(
501
+				'Default Event Espresso capabilities have been restored for all current roles.',
502
+				'event_espresso'
503
+			)
504
+		);
505
+		$this->_redirect_after_action(false, '', '', ['action' => 'data_reset'], true);
506
+	}
507
+
508
+
509
+	/**
510
+	 * resets the DMSs, so we can attempt to continue migrating after a fatal error
511
+	 * (only a good idea when someone has somehow tried ot fix whatever caused
512
+	 * the fatal error in teh first place)
513
+	 *
514
+	 * @throws EE_Error
515
+	 */
516
+	protected function _reattempt_migration()
517
+	{
518
+		$this->migration_manager->reattempt();
519
+		$this->_redirect_after_action(false, '', '', ['action' => 'default'], true);
520
+	}
521
+
522
+
523
+	/**
524
+	 * shows the big ol' System Information page
525
+	 *
526
+	 * @throws EE_Error
527
+	 */
528
+	public function _system_status()
529
+	{
530
+		$this->_template_path                               =
531
+			EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
532
+		$this->_template_args['system_stati']               = EEM_System_Status::instance()->get_system_stati();
533
+		$this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
534
+			[
535
+				'action' => 'download_system_status',
536
+			],
537
+			EE_MAINTENANCE_ADMIN_URL
538
+		);
539
+		$this->_template_args['admin_page_content']         = EEH_Template::display_template(
540
+			$this->_template_path,
541
+			$this->_template_args,
542
+			true
543
+		);
544
+		$this->display_admin_page_with_no_sidebar();
545
+	}
546
+
547
+
548
+	/**
549
+	 * Downloads an HTML file of the system status that can be easily stored or emailed
550
+	 */
551
+	public function _download_system_status()
552
+	{
553
+		$status_info = EEM_System_Status::instance()->get_system_stati();
554
+		header('Content-Disposition: attachment');
555
+		header("Content-Disposition: attachment; filename=system_status_" . sanitize_key(site_url()) . ".html");
556
+		$output = '<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>';
557
+		$output .= '<h1>' . sprintf(
558
+				__('System Information for %1$s', 'event_espresso'),
559
+				esc_url_raw(site_url())
560
+			) . '</h1>';
561
+		$output .= EEH_Template::layout_array_as_table($status_info);
562
+		echo esc_html($output);
563
+		die;
564
+	}
565
+
566
+
567
+	/**
568
+	 * @throws EE_Error
569
+	 */
570
+	public function _send_migration_crash_report()
571
+	{
572
+		$from      = $this->_req_data['from'];
573
+		$from_name = $this->_req_data['from_name'];
574
+		$body      = $this->_req_data['body'];
575
+		try {
576
+			$success = wp_mail(
577
+				EE_SUPPORT_EMAIL,
578
+				'Migration Crash Report',
579
+				$body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
580
+				[
581
+					"from:$from_name<$from>",
582
+				]
583
+			);
584
+		} catch (Exception $e) {
585
+			$success = false;
586
+		}
587
+		$this->_redirect_after_action(
588
+			$success,
589
+			esc_html__("Migration Crash Report", "event_espresso"),
590
+			esc_html__("sent", "event_espresso"),
591
+			['success' => $success, 'action' => 'confirm_migration_crash_report_sent']
592
+		);
593
+	}
594
+
595
+
596
+	/**
597
+	 * @throws EE_Error
598
+	 */
599
+	public function _confirm_migration_crash_report_sent()
600
+	{
601
+		try {
602
+			$most_recent_migration = $this->migration_manager->get_last_ran_script(true);
603
+		} catch (EE_Error $e) {
604
+			$this->migration_manager->add_error_to_migrations_ran($e->getMessage());
605
+			// now, just so we can display the page correctly, make an error migration script stage object
606
+			// and also put the error on it. It only persists for the duration of this request
607
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
608
+			$most_recent_migration->add_error($e->getMessage());
609
+		}
610
+		$success                                       = $this->_req_data['success'] === '1';
611
+		$this->_template_args['success']               = $success;
612
+		$this->_template_args['most_recent_migration'] = $most_recent_migration;
613
+		$this->_template_args['reset_db_action_url']   = EE_Admin_Page::add_query_args_and_nonce(
614
+			['action' => 'reset_db'],
615
+			EE_MAINTENANCE_ADMIN_URL
616
+		);
617
+		$this->_template_args['reset_db_page_url']     = EE_Admin_Page::add_query_args_and_nonce(
618
+			['action' => 'data_reset'],
619
+			EE_MAINTENANCE_ADMIN_URL
620
+		);
621
+		$this->_template_args['reattempt_action_url']  = EE_Admin_Page::add_query_args_and_nonce(
622
+			['action' => 'reattempt_migration'],
623
+			EE_MAINTENANCE_ADMIN_URL
624
+		);
625
+		$this->_template_path                          =
626
+			EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
627
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
628
+			$this->_template_path,
629
+			$this->_template_args,
630
+			true
631
+		);
632
+		$this->display_admin_page_with_sidebar();
633
+	}
634
+
635
+
636
+	/**
637
+	 * Resets the entire EE4 database.
638
+	 * only sets up ee4 database for a fresh install-
639
+	 * doesn't actually clean out the old wp options, or cpts
640
+	 * (although it does erase old ee table data)
641
+	 *
642
+	 * @param boolean $nuke_old_ee4_data controls whether we destroy the old ee4 data,
643
+	 *                                   or just try initializing ee4 default data
644
+	 * @throws EE_Error
645
+	 * @throws ReflectionException
646
+	 */
647
+	public function _reset_db($nuke_old_ee4_data = true)
648
+	{
649
+		$this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_OFF);
650
+		if ($nuke_old_ee4_data) {
651
+			EEH_Activation::delete_all_espresso_cpt_data();
652
+			EEH_Activation::delete_all_espresso_tables_and_data(false);
653
+			EEH_Activation::remove_cron_tasks();
654
+		}
655
+		// make sure when we reset the registry's config that it
656
+		// switches to using the new singleton
657
+		EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
658
+		EE_System::instance()->initialize_db_if_no_migrations_required(true);
659
+		EE_System::instance()->redirect_to_about_ee();
660
+	}
661
+
662
+
663
+	/**
664
+	 * Deletes ALL EE tables, Records, and Options from the database.
665
+	 *
666
+	 * @throws EE_Error
667
+	 * @throws ReflectionException
668
+	 */
669
+	public function _delete_db()
670
+	{
671
+		$this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_OFF);
672
+		EEH_Activation::delete_all_espresso_cpt_data();
673
+		EEH_Activation::delete_all_espresso_tables_and_data();
674
+		EEH_Activation::remove_cron_tasks();
675
+		EEH_Activation::deactivate_event_espresso();
676
+		wp_safe_redirect(admin_url('plugins.php'));
677
+		exit;
678
+	}
679
+
680
+
681
+	/**
682
+	 * sets up EE4 to rerun the migrations from ee3 to ee4
683
+	 *
684
+	 * @throws EE_Error
685
+	 * @throws ReflectionException
686
+	 */
687
+	public function _rerun_migration_from_ee3()
688
+	{
689
+		$this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_OFF);
690
+		EEH_Activation::delete_all_espresso_cpt_data();
691
+		EEH_Activation::delete_all_espresso_tables_and_data(false);
692
+		// set the db state to something that will require migrations
693
+		update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
694
+		$this->maintenance_mode->set_maintenance_level(EE_Maintenance_Mode::STATUS_FULL_SITE);
695
+		$this->_redirect_after_action(
696
+			true,
697
+			esc_html__("Database", 'event_espresso'),
698
+			esc_html__("reset", 'event_espresso')
699
+		);
700
+	}
701
+
702
+
703
+	// none of the below group are currently used for Gateway Settings
704
+	protected function _add_screen_options()
705
+	{
706
+	}
707
+
708
+
709
+	protected function _add_feature_pointers()
710
+	{
711
+	}
712
+
713
+
714
+	public function admin_init()
715
+	{
716
+	}
717
+
718
+
719
+	public function admin_notices()
720
+	{
721
+	}
722
+
723
+
724
+	public function admin_footer_scripts()
725
+	{
726
+	}
727
+
728
+
729
+	public function load_scripts_styles()
730
+	{
731
+		wp_enqueue_script('ee_admin_js');
732
+		wp_enqueue_script(
733
+			'ee-maintenance',
734
+			EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js',
735
+			['jquery'],
736
+			EVENT_ESPRESSO_VERSION,
737
+			true
738
+		);
739
+		wp_register_style(
740
+			'espresso_maintenance',
741
+			EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css',
742
+			[],
743
+			EVENT_ESPRESSO_VERSION
744
+		);
745
+		wp_enqueue_style('espresso_maintenance');
746
+		// localize script stuff
747
+		wp_localize_script(
748
+			'ee-maintenance',
749
+			'ee_maintenance',
750
+			[
751
+				'migrating'                        => wp_strip_all_tags(__("Updating Database...", "event_espresso")),
752
+				'next'                             => wp_strip_all_tags(__("Next", "event_espresso")),
753
+				'fatal_error'                      => wp_strip_all_tags(
754
+					__(
755
+						"A Fatal Error Has Occurred",
756
+						"event_espresso"
757
+					)
758
+				),
759
+				'click_next_when_ready'            => wp_strip_all_tags(
760
+					__(
761
+						"The current Database Update has ended. Click 'next' when ready to proceed",
762
+						"event_espresso"
763
+					)
764
+				),
765
+				'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
766
+				'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
767
+				'status_completed'                 => EE_Data_Migration_Manager::status_completed,
768
+				'confirm'                          => wp_strip_all_tags(
769
+					__(
770
+						'Are you sure you want to do this? It CANNOT be undone!',
771
+						'event_espresso'
772
+					)
773
+				),
774
+				'confirm_skip_migration'           => wp_strip_all_tags(
775
+					__(
776
+						'You have chosen to NOT migrate your existing data. Are you sure you want to continue?',
777
+						'event_espresso'
778
+					)
779
+				),
780
+			]
781
+		);
782
+	}
783
+
784
+
785
+	public function load_scripts_styles_default()
786
+	{
787
+	}
788
+
789
+
790
+	/**
791
+	 * Enqueue scripts and styles for the datetime tools page.
792
+	 */
793
+	public function load_scripts_styles_datetime_tools()
794
+	{
795
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
796
+	}
797
+
798
+
799
+	/**
800
+	 * @throws EE_Error
801
+	 */
802
+	protected function _datetime_tools()
803
+	{
804
+		$form_action                                = EE_Admin_Page::add_query_args_and_nonce(
805
+			[
806
+				'action'        => 'run_datetime_offset_fix',
807
+				'return_action' => $this->_req_action,
808
+			],
809
+			EE_MAINTENANCE_ADMIN_URL
810
+		);
811
+		$form                                       = $this->_get_datetime_offset_fix_form();
812
+		$this->_admin_page_title                    = esc_html__('Datetime Utilities', 'event_espresso');
813
+		$this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
814
+													  . $form->get_html_and_js()
815
+													  . $form->form_close();
816
+		$this->display_admin_page_with_sidebar();
817
+	}
818
+
819
+
820
+	/**
821
+	 * @throws EE_Error
822
+	 */
823
+	protected function _get_datetime_offset_fix_form()
824
+	{
825
+		if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
826
+			$this->datetime_fix_offset_form = new EE_Form_Section_Proper(
827
+				[
828
+					'name'            => 'datetime_offset_fix_option',
829
+					'layout_strategy' => new EE_Admin_Two_Column_Layout(),
830
+					'subsections'     => [
831
+						'title'                  => new EE_Form_Section_HTML(
832
+							EEH_HTML::h2(
833
+								esc_html__('Datetime Offset Tool', 'event_espresso')
834
+							)
835
+						),
836
+						'explanation'            => new EE_Form_Section_HTML(
837
+							EEH_HTML::p(
838
+								esc_html__(
839
+									'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
840
+									'event_espresso'
841
+								)
842
+							)
843
+							. EEH_HTML::p(
844
+								esc_html__(
845
+									'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
846
+									'event_espresso'
847
+								)
848
+							)
849
+						),
850
+						'offset_input'           => new EE_Float_Input(
851
+							[
852
+								'html_name'       => 'offset_for_datetimes',
853
+								'html_label_text' => esc_html__(
854
+									'Offset to apply (in hours):',
855
+									'event_espresso'
856
+								),
857
+								'min_value'       => '-12',
858
+								'max_value'       => '14',
859
+								'step_value'      => '.25',
860
+								'default'         => DatetimeOffsetFix::getOffset(),
861
+							]
862
+						),
863
+						'date_range_explanation' => new EE_Form_Section_HTML(
864
+							EEH_HTML::p(
865
+								esc_html__(
866
+									'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.',
867
+									'event_espresso'
868
+								)
869
+							)
870
+							. EEH_HTML::p(
871
+								EEH_HTML::strong(
872
+									sprintf(
873
+										esc_html__(
874
+											'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).',
875
+											'event_espresso'
876
+										),
877
+										'<a href="https://www.timeanddate.com/worldclock/converter.html">',
878
+										'</a>'
879
+									)
880
+								)
881
+							)
882
+						),
883
+						'date_range_start_date'  => new EE_Datepicker_Input(
884
+							[
885
+								'html_name'       => 'offset_date_start_range',
886
+								'html_label_text' => esc_html__(
887
+									'Start Date for dates the offset applied to:',
888
+									'event_espresso'
889
+								),
890
+							]
891
+						),
892
+						'date_range_end_date'    => new EE_Datepicker_Input(
893
+							[
894
+								'html_name'       => 'offset_date_end_range',
895
+								'html_label_text' => esc_html__(
896
+									'End Date for dates the offset is applied to:',
897
+									'event_espresso'
898
+								),
899
+							]
900
+						),
901
+						'submit'                 => new EE_Submit_Input(
902
+							[
903
+								'html_label_text' => '',
904
+								'default'         => esc_html__('Apply Offset', 'event_espresso'),
905
+							]
906
+						),
907
+					],
908
+				]
909
+			);
910
+		}
911
+		return $this->datetime_fix_offset_form;
912
+	}
913
+
914
+
915
+	/**
916
+	 * Callback for the run_datetime_offset_fix route.
917
+	 *
918
+	 * @throws EE_Error
919
+	 */
920
+	protected function _apply_datetime_offset()
921
+	{
922
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
923
+			$form = $this->_get_datetime_offset_fix_form();
924
+			$form->receive_form_submission($this->_req_data);
925
+			if ($form->is_valid()) {
926
+				// save offset data so batch processor can get it.
927
+				DatetimeOffsetFix::updateOffset((float) $form->get_input_value('offset_input'));
928
+				$utc_timezone          = new DateTimeZone('UTC');
929
+				$date_range_start_date = DateTime::createFromFormat(
930
+					'm/d/Y H:i:s',
931
+					$form->get_input_value('date_range_start_date') . ' 00:00:00',
932
+					$utc_timezone
933
+				);
934
+				$date_range_end_date   = DateTime::createFromFormat(
935
+					'm/d/Y H:i:s',
936
+					$form->get_input_value('date_range_end_date') . ' 23:59:59',
937
+					$utc_timezone
938
+				);
939
+				if ($date_range_start_date instanceof DateTime) {
940
+					DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date));
941
+				}
942
+				if ($date_range_end_date instanceof DateTime) {
943
+					DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date));
944
+				}
945
+				// redirect to batch tool
946
+				wp_redirect(
947
+					EE_Admin_Page::add_query_args_and_nonce(
948
+						[
949
+							'page'        => EED_Batch::PAGE_SLUG,
950
+							'batch'       => EED_Batch::batch_job,
951
+							'label'       => esc_html__('Applying Offset', 'event_espresso'),
952
+							'job_handler' => urlencode('EventEspresso\core\libraries\batch\JobHandlers\DatetimeOffsetFix'),
953
+							'return_url'  => urlencode(
954
+								add_query_arg(
955
+									[
956
+										'action' => 'datetime_tools',
957
+									],
958
+									EEH_URL::current_url_without_query_paramaters(
959
+										[
960
+											'return_action',
961
+											'run_datetime_offset_fix_nonce',
962
+											'return',
963
+											'datetime_tools_nonce',
964
+										]
965
+									)
966
+								)
967
+							),
968
+						],
969
+						admin_url()
970
+					)
971
+				);
972
+				exit;
973
+			}
974
+		}
975
+	}
976 976
 }
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@  discard block
 block discarded – undo
55 55
 
56 56
     protected function _ajax_hooks()
57 57
     {
58
-        if (! $this->capabilities->current_user_can('manage_options', 'perform-migrations')) {
58
+        if ( ! $this->capabilities->current_user_can('manage_options', 'perform-migrations')) {
59 59
             return;
60 60
         }
61 61
         add_action('wp_ajax_migration_step', [$this, 'migration_step']);
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
             if (MaintenanceStatus::isFullSite()) {
235 235
                 $show_maintenance_switch = false;
236 236
                 $show_migration_progress = true;
237
-                if (! isset($this->_req_data['continue_migration'])) {
237
+                if ( ! isset($this->_req_data['continue_migration'])) {
238 238
                     $show_backup_db_text = true;
239 239
                 }
240 240
                 $scripts_needing_to_run          =
@@ -244,7 +244,7 @@  discard block
 block discarded – undo
244 244
                 $current_script                  = null;
245 245
                 foreach ($scripts_needing_to_run as $script) {
246 246
                     if ($script instanceof EE_Data_Migration_Script_Base) {
247
-                        if (! $current_script) {
247
+                        if ( ! $current_script) {
248 248
                             $current_script = $script;
249 249
                             $current_script->migration_page_hooks();
250 250
                         }
@@ -271,7 +271,7 @@  discard block
 block discarded – undo
271 271
                 && $most_recent_migration->is_broken()
272 272
             )
273 273
         ) {
274
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
274
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_was_borked_page.template.php';
275 275
 
276 276
             $this->_template_args['support_url'] = 'https://eventespresso.com/support/forums/';
277 277
             $this->_template_args['next_url']    = EEH_URL::add_query_args_and_nonce(
@@ -282,7 +282,7 @@  discard block
 block discarded – undo
282 282
                 EE_MAINTENANCE_ADMIN_URL
283 283
             );
284 284
         } elseif ($addons_should_be_upgraded_first) {
285
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
285
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_upgrade_addons_before_migrating.template.php';
286 286
         } else {
287 287
             if (
288 288
                 $most_recent_migration instanceof EE_Data_Migration_Script_Base
@@ -307,7 +307,7 @@  discard block
 block discarded – undo
307 307
                     [
308 308
                         'current_db_state' => sprintf(
309 309
                             esc_html__("EE%s (%s)", "event_espresso"),
310
-                            $current_db_state[ $plugin_slug ] ?? 3,
310
+                            $current_db_state[$plugin_slug] ?? 3,
311 311
                             $plugin_slug
312 312
                         ),
313 313
                         'next_db_state'    => sprintf(
@@ -321,7 +321,7 @@  discard block
 block discarded – undo
321 321
                 $this->_template_args['current_db_state'] = '';
322 322
                 $this->_template_args['next_db_state']    = '';
323 323
             }
324
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
324
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_page.template.php';
325 325
             $this->_template_args = array_merge(
326 326
                 $this->_template_args,
327 327
                 [
@@ -357,13 +357,13 @@  discard block
 block discarded – undo
357 357
             );
358 358
         }
359 359
         $this->_template_args['most_recent_migration'] =
360
-            $most_recent_migration;// the actual most recently ran migration
360
+            $most_recent_migration; // the actual most recently ran migration
361 361
         // now render the migration options part, and put it in a variable
362
-        $migration_options_template_file                = apply_filters(
362
+        $migration_options_template_file = apply_filters(
363 363
             'FHEE__ee_migration_page__migration_options_template',
364
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
364
+            EE_MAINTENANCE_TEMPLATE_PATH.'migration_options_from_ee4.template.php'
365 365
         );
366
-        $migration_options_html                         = EEH_Template::display_template(
366
+        $migration_options_html = EEH_Template::display_template(
367 367
             $migration_options_template_file,
368 368
             $this->_template_args,
369 369
             true
@@ -385,7 +385,7 @@  discard block
 block discarded – undo
385 385
      */
386 386
     public function migration_step()
387 387
     {
388
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
388
+        if ( ! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
389 389
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
390 390
         }
391 391
         $this->_template_args['data'] = $this->migration_manager->response_to_migration_ajax_request();
@@ -415,7 +415,7 @@  discard block
 block discarded – undo
415 415
     public function _change_maintenance_level()
416 416
     {
417 417
         $new_level = absint($this->_req_data['maintenance_mode_level']);
418
-        if (! $this->migration_manager->check_for_applicable_data_migration_scripts()) {
418
+        if ( ! $this->migration_manager->check_for_applicable_data_migration_scripts()) {
419 419
             $this->maintenance_mode->set_maintenance_level($new_level);
420 420
             $success = true;
421 421
         } else {
@@ -435,7 +435,7 @@  discard block
 block discarded – undo
435 435
     public function _data_reset_and_delete()
436 436
     {
437 437
         $this->_template_path                              =
438
-            EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
438
+            EE_MAINTENANCE_TEMPLATE_PATH.'ee_data_reset_and_delete.template.php';
439 439
         $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
440 440
             'reset_reservations',
441 441
             'reset_reservations',
@@ -448,15 +448,15 @@  discard block
 block discarded – undo
448 448
             [],
449 449
             'button button--caution ee-confirm'
450 450
         );
451
-        $this->_template_args['delete_db_url']             = EE_Admin_Page::add_query_args_and_nonce(
451
+        $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
452 452
             ['action' => 'delete_db'],
453 453
             EE_MAINTENANCE_ADMIN_URL
454 454
         );
455
-        $this->_template_args['reset_db_url']              = EE_Admin_Page::add_query_args_and_nonce(
455
+        $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
456 456
             ['action' => 'reset_db'],
457 457
             EE_MAINTENANCE_ADMIN_URL
458 458
         );
459
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
459
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
460 460
             $this->_template_path,
461 461
             $this->_template_args,
462 462
             true
@@ -528,7 +528,7 @@  discard block
 block discarded – undo
528 528
     public function _system_status()
529 529
     {
530 530
         $this->_template_path                               =
531
-            EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
531
+            EE_MAINTENANCE_TEMPLATE_PATH.'ee_system_stati_page.template.php';
532 532
         $this->_template_args['system_stati']               = EEM_System_Status::instance()->get_system_stati();
533 533
         $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
534 534
             [
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
             ],
537 537
             EE_MAINTENANCE_ADMIN_URL
538 538
         );
539
-        $this->_template_args['admin_page_content']         = EEH_Template::display_template(
539
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
540 540
             $this->_template_path,
541 541
             $this->_template_args,
542 542
             true
@@ -552,12 +552,12 @@  discard block
 block discarded – undo
552 552
     {
553 553
         $status_info = EEM_System_Status::instance()->get_system_stati();
554 554
         header('Content-Disposition: attachment');
555
-        header("Content-Disposition: attachment; filename=system_status_" . sanitize_key(site_url()) . ".html");
555
+        header("Content-Disposition: attachment; filename=system_status_".sanitize_key(site_url()).".html");
556 556
         $output = '<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>';
557
-        $output .= '<h1>' . sprintf(
557
+        $output .= '<h1>'.sprintf(
558 558
                 __('System Information for %1$s', 'event_espresso'),
559 559
                 esc_url_raw(site_url())
560
-            ) . '</h1>';
560
+            ).'</h1>';
561 561
         $output .= EEH_Template::layout_array_as_table($status_info);
562 562
         echo esc_html($output);
563 563
         die;
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
             $success = wp_mail(
577 577
                 EE_SUPPORT_EMAIL,
578 578
                 'Migration Crash Report',
579
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
579
+                $body."/r/n<br>".print_r(EEM_System_Status::instance()->get_system_stati(), true),
580 580
                 [
581 581
                     "from:$from_name<$from>",
582 582
                 ]
@@ -614,16 +614,16 @@  discard block
 block discarded – undo
614 614
             ['action' => 'reset_db'],
615 615
             EE_MAINTENANCE_ADMIN_URL
616 616
         );
617
-        $this->_template_args['reset_db_page_url']     = EE_Admin_Page::add_query_args_and_nonce(
617
+        $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(
618 618
             ['action' => 'data_reset'],
619 619
             EE_MAINTENANCE_ADMIN_URL
620 620
         );
621
-        $this->_template_args['reattempt_action_url']  = EE_Admin_Page::add_query_args_and_nonce(
621
+        $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(
622 622
             ['action' => 'reattempt_migration'],
623 623
             EE_MAINTENANCE_ADMIN_URL
624 624
         );
625 625
         $this->_template_path                          =
626
-            EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
626
+            EE_MAINTENANCE_TEMPLATE_PATH.'ee_confirm_migration_crash_report_sent.template.php';
627 627
         $this->_template_args['admin_page_content']    = EEH_Template::display_template(
628 628
             $this->_template_path,
629 629
             $this->_template_args,
@@ -731,14 +731,14 @@  discard block
 block discarded – undo
731 731
         wp_enqueue_script('ee_admin_js');
732 732
         wp_enqueue_script(
733 733
             'ee-maintenance',
734
-            EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js',
734
+            EE_MAINTENANCE_ASSETS_URL.'ee-maintenance.js',
735 735
             ['jquery'],
736 736
             EVENT_ESPRESSO_VERSION,
737 737
             true
738 738
         );
739 739
         wp_register_style(
740 740
             'espresso_maintenance',
741
-            EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css',
741
+            EE_MAINTENANCE_ASSETS_URL.'ee-maintenance.css',
742 742
             [],
743 743
             EVENT_ESPRESSO_VERSION
744 744
         );
@@ -801,7 +801,7 @@  discard block
 block discarded – undo
801 801
      */
802 802
     protected function _datetime_tools()
803 803
     {
804
-        $form_action                                = EE_Admin_Page::add_query_args_and_nonce(
804
+        $form_action = EE_Admin_Page::add_query_args_and_nonce(
805 805
             [
806 806
                 'action'        => 'run_datetime_offset_fix',
807 807
                 'return_action' => $this->_req_action,
@@ -822,7 +822,7 @@  discard block
 block discarded – undo
822 822
      */
823 823
     protected function _get_datetime_offset_fix_form()
824 824
     {
825
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
825
+        if ( ! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
826 826
             $this->datetime_fix_offset_form = new EE_Form_Section_Proper(
827 827
                 [
828 828
                     'name'            => 'datetime_offset_fix_option',
@@ -928,12 +928,12 @@  discard block
 block discarded – undo
928 928
                 $utc_timezone          = new DateTimeZone('UTC');
929 929
                 $date_range_start_date = DateTime::createFromFormat(
930 930
                     'm/d/Y H:i:s',
931
-                    $form->get_input_value('date_range_start_date') . ' 00:00:00',
931
+                    $form->get_input_value('date_range_start_date').' 00:00:00',
932 932
                     $utc_timezone
933 933
                 );
934
-                $date_range_end_date   = DateTime::createFromFormat(
934
+                $date_range_end_date = DateTime::createFromFormat(
935 935
                     'm/d/Y H:i:s',
936
-                    $form->get_input_value('date_range_end_date') . ' 23:59:59',
936
+                    $form->get_input_value('date_range_end_date').' 23:59:59',
937 937
                     $utc_timezone
938 938
                 );
939 939
                 if ($date_range_start_date instanceof DateTime) {
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2976 added lines, -2976 removed lines patch added patch discarded remove patch
@@ -22,2983 +22,2983 @@
 block discarded – undo
22 22
  */
23 23
 class Events_Admin_Page extends EE_Admin_Page_CPT
24 24
 {
25
-    /**
26
-     * primary key for the event model
27
-     */
28
-    private int $EVT_ID = 0;
29
-
30
-    /**
31
-     * This will hold the event object for event_details screen.
32
-     *
33
-     * @var EE_Event|null $_event
34
-     */
35
-    protected ?EE_Event $_event = null;
36
-
37
-    /**
38
-     * This will hold the category object for category_details screen.
39
-     */
40
-    protected ?stdClass $_category = null;
41
-
42
-    protected ?EEM_Event $_event_model = null;
43
-
44
-    /**
45
-     * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
-     */
47
-    protected $_cpt_model_obj;
48
-
49
-    protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
-
51
-    protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
-
53
-
54
-    /**
55
-     * Initialize page props for this admin page group.
56
-     */
57
-    protected function _init_page_props()
58
-    {
59
-        // is there a evt_id in the request?
60
-        $this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
-        $this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
-        $this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
-
64
-        $this->page_slug        = EVENTS_PG_SLUG;
65
-        $this->page_label       = EVENTS_LABEL;
66
-        $this->_admin_base_url  = EVENTS_ADMIN_URL;
67
-        $this->_admin_base_path = EVENTS_ADMIN;
68
-        $this->_cpt_model_names = [
69
-            'create_new' => 'EEM_Event',
70
-            'edit'       => 'EEM_Event',
71
-        ];
72
-        $this->_cpt_edit_routes = [
73
-            'espresso_events' => 'edit',
74
-        ];
75
-        add_action(
76
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
-            [$this, 'verify_event_edit'],
78
-            10,
79
-            2
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets the ajax hooks used for this admin page group.
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
-    }
91
-
92
-
93
-    /**
94
-     * Sets the page properties for this admin page group.
95
-     */
96
-    protected function _define_page_props()
97
-    {
98
-        $this->_admin_page_title = EVENTS_LABEL;
99
-        $this->_labels           = [
100
-            'buttons'      => [
101
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
102
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
-            ],
108
-            'editor_title' => [
109
-                'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
-            ],
111
-            'publishbox'   => [
112
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
114
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
-            ],
118
-        ];
119
-    }
120
-
121
-
122
-    /**
123
-     * Sets the page routes property for this admin page group.
124
-     */
125
-    protected function _set_page_routes()
126
-    {
127
-        $this->_page_routes = [
128
-            'default'                       => [
129
-                'func'       => [$this, '_events_overview_list_table'],
130
-                'capability' => 'ee_read_events',
131
-            ],
132
-            'create_new'                    => [
133
-                'func'       => [$this, '_create_new_cpt_item'],
134
-                'capability' => 'ee_edit_events',
135
-            ],
136
-            'edit'                          => [
137
-                'func'       => [$this, '_edit_cpt_item'],
138
-                'capability' => 'ee_edit_event',
139
-                'obj_id'     => $this->EVT_ID,
140
-            ],
141
-            'copy_event'                    => [
142
-                'func'       => [$this, '_copy_events'],
143
-                'capability' => 'ee_edit_event',
144
-                'obj_id'     => $this->EVT_ID,
145
-                'noheader'   => true,
146
-            ],
147
-            'trash_event'                   => [
148
-                'func'       => [$this, '_trash_or_restore_event'],
149
-                'args'       => ['event_status' => 'trash'],
150
-                'capability' => 'ee_delete_event',
151
-                'obj_id'     => $this->EVT_ID,
152
-                'noheader'   => true,
153
-            ],
154
-            'trash_events'                  => [
155
-                'func'       => [$this, '_trash_or_restore_events'],
156
-                'args'       => ['event_status' => 'trash'],
157
-                'capability' => 'ee_delete_events',
158
-                'noheader'   => true,
159
-            ],
160
-            'restore_event'                 => [
161
-                'func'       => [$this, '_trash_or_restore_event'],
162
-                'args'       => ['event_status' => 'draft'],
163
-                'capability' => 'ee_delete_event',
164
-                'obj_id'     => $this->EVT_ID,
165
-                'noheader'   => true,
166
-            ],
167
-            'restore_events'                => [
168
-                'func'       => [$this, '_trash_or_restore_events'],
169
-                'args'       => ['event_status' => 'draft'],
170
-                'capability' => 'ee_delete_events',
171
-                'noheader'   => true,
172
-            ],
173
-            'delete_event'                  => [
174
-                'func'       => [$this, '_delete_event'],
175
-                'capability' => 'ee_delete_event',
176
-                'obj_id'     => $this->EVT_ID,
177
-                'noheader'   => true,
178
-            ],
179
-            'delete_events'                 => [
180
-                'func'       => [$this, '_delete_events'],
181
-                'capability' => 'ee_delete_events',
182
-                'noheader'   => true,
183
-            ],
184
-            'view_report'                   => [
185
-                'func'       => [$this, '_view_report'],
186
-                'capability' => 'ee_edit_events',
187
-            ],
188
-            'default_event_settings'        => [
189
-                'func'       => [$this, '_default_event_settings'],
190
-                'capability' => 'manage_options',
191
-            ],
192
-            'update_default_event_settings' => [
193
-                'func'       => [$this, '_update_default_event_settings'],
194
-                'capability' => 'manage_options',
195
-                'noheader'   => true,
196
-            ],
197
-            'template_settings'             => [
198
-                'func'       => [$this, '_template_settings'],
199
-                'capability' => 'manage_options',
200
-            ],
201
-            // event category tab related
202
-            'add_category'                  => [
203
-                'func'       => [$this, '_category_details'],
204
-                'capability' => 'ee_edit_event_category',
205
-                'args'       => ['view' => 'add'],
206
-            ],
207
-            'edit_category'                 => [
208
-                'func'       => [$this, '_category_details'],
209
-                'capability' => 'ee_edit_event_category',
210
-                'args'       => ['view' => 'edit'],
211
-            ],
212
-            'delete_categories'             => [
213
-                'func'       => [$this, '_delete_categories'],
214
-                'capability' => 'ee_delete_event_category',
215
-                'noheader'   => true,
216
-            ],
217
-            'delete_category'               => [
218
-                'func'       => [$this, '_delete_categories'],
219
-                'capability' => 'ee_delete_event_category',
220
-                'noheader'   => true,
221
-            ],
222
-            'insert_category'               => [
223
-                'func'       => [$this, '_insert_or_update_category'],
224
-                'args'       => ['new_category' => true],
225
-                'capability' => 'ee_edit_event_category',
226
-                'noheader'   => true,
227
-            ],
228
-            'update_category'               => [
229
-                'func'       => [$this, '_insert_or_update_category'],
230
-                'args'       => ['new_category' => false],
231
-                'capability' => 'ee_edit_event_category',
232
-                'noheader'   => true,
233
-            ],
234
-            'category_list'                 => [
235
-                'func'       => [$this, '_category_list_table'],
236
-                'capability' => 'ee_manage_event_categories',
237
-            ],
238
-            'preview_deletion'              => [
239
-                'func'       => [$this, 'previewDeletion'],
240
-                'capability' => 'ee_delete_events',
241
-            ],
242
-            'confirm_deletion'              => [
243
-                'func'       => [$this, 'confirmDeletion'],
244
-                'capability' => 'ee_delete_events',
245
-                'noheader'   => true,
246
-            ],
247
-        ];
248
-    }
249
-
250
-
251
-    /**
252
-     * Set the _page_config property for this admin page group.
253
-     */
254
-    protected function _set_page_config()
255
-    {
256
-        $post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
-        $EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
-        $this->_page_config = [
259
-            'default'                => [
260
-                'nav'           => [
261
-                    'label' => esc_html__('Overview', 'event_espresso'),
262
-                    'icon'  => 'dashicons-list-view',
263
-                    'order' => 10,
264
-                ],
265
-                'list_table'    => 'Events_Admin_List_Table',
266
-                'help_tabs'     => [
267
-                    'events_overview_help_tab'                       => [
268
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
269
-                        'filename' => 'events_overview',
270
-                    ],
271
-                    'events_overview_table_column_headings_help_tab' => [
272
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
-                        'filename' => 'events_overview_table_column_headings',
274
-                    ],
275
-                    'events_overview_filters_help_tab'               => [
276
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
-                        'filename' => 'events_overview_filters',
278
-                    ],
279
-                    'events_overview_view_help_tab'                  => [
280
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
-                        'filename' => 'events_overview_views',
282
-                    ],
283
-                    'events_overview_other_help_tab'                 => [
284
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
-                        'filename' => 'events_overview_other',
286
-                    ],
287
-                ],
288
-                'require_nonce' => false,
289
-            ],
290
-            'create_new'             => [
291
-                'nav'           => [
292
-                    'label'      => esc_html__('Add New Event', 'event_espresso'),
293
-                    'icon'       => 'dashicons-plus-alt',
294
-                    'order'      => 15,
295
-                    'persistent' => false,
296
-                ],
297
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
-                'help_tabs'     => [
299
-                    'event_editor_help_tab'                            => [
300
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
301
-                        'filename' => 'event_editor',
302
-                    ],
303
-                    'event_editor_title_richtexteditor_help_tab'       => [
304
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
-                        'filename' => 'event_editor_title_richtexteditor',
306
-                    ],
307
-                    'event_editor_venue_details_help_tab'              => [
308
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
-                        'filename' => 'event_editor_venue_details',
310
-                    ],
311
-                    'event_editor_event_datetimes_help_tab'            => [
312
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
-                        'filename' => 'event_editor_event_datetimes',
314
-                    ],
315
-                    'event_editor_event_tickets_help_tab'              => [
316
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
-                        'filename' => 'event_editor_event_tickets',
318
-                    ],
319
-                    'event_editor_event_registration_options_help_tab' => [
320
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
-                        'filename' => 'event_editor_event_registration_options',
322
-                    ],
323
-                    'event_editor_tags_categories_help_tab'            => [
324
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
-                        'filename' => 'event_editor_tags_categories',
326
-                    ],
327
-                    'event_editor_questions_registrants_help_tab'      => [
328
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
-                        'filename' => 'event_editor_questions_registrants',
330
-                    ],
331
-                    'event_editor_save_new_event_help_tab'             => [
332
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
333
-                        'filename' => 'event_editor_save_new_event',
334
-                    ],
335
-                    'event_editor_other_help_tab'                      => [
336
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
337
-                        'filename' => 'event_editor_other',
338
-                    ],
339
-                ],
340
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
-                'require_nonce' => false,
342
-            ],
343
-            'edit'                   => [
344
-                'nav'           => [
345
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
346
-                    'icon'       => 'dashicons-edit',
347
-                    'order'      => 15,
348
-                    'persistent' => false,
349
-                    'url'        => $post_id
350
-                        ? EE_Admin_Page::add_query_args_and_nonce(
351
-                            ['post' => $post_id, 'action' => 'edit'],
352
-                            $this->_current_page_view_url
353
-                        )
354
-                        : $this->_admin_base_url,
355
-                ],
356
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
-                'help_tabs'     => [
358
-                    'event_editor_help_tab'                            => [
359
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
360
-                        'filename' => 'event_editor',
361
-                    ],
362
-                    'event_editor_title_richtexteditor_help_tab'       => [
363
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
-                        'filename' => 'event_editor_title_richtexteditor',
365
-                    ],
366
-                    'event_editor_venue_details_help_tab'              => [
367
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
-                        'filename' => 'event_editor_venue_details',
369
-                    ],
370
-                    'event_editor_event_datetimes_help_tab'            => [
371
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
-                        'filename' => 'event_editor_event_datetimes',
373
-                    ],
374
-                    'event_editor_event_tickets_help_tab'              => [
375
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
-                        'filename' => 'event_editor_event_tickets',
377
-                    ],
378
-                    'event_editor_event_registration_options_help_tab' => [
379
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
-                        'filename' => 'event_editor_event_registration_options',
381
-                    ],
382
-                    'event_editor_tags_categories_help_tab'            => [
383
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
-                        'filename' => 'event_editor_tags_categories',
385
-                    ],
386
-                    'event_editor_questions_registrants_help_tab'      => [
387
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
-                        'filename' => 'event_editor_questions_registrants',
389
-                    ],
390
-                    'event_editor_save_new_event_help_tab'             => [
391
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
392
-                        'filename' => 'event_editor_save_new_event',
393
-                    ],
394
-                    'event_editor_other_help_tab'                      => [
395
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
396
-                        'filename' => 'event_editor_other',
397
-                    ],
398
-                ],
399
-                'require_nonce' => false,
400
-            ],
401
-            'default_event_settings' => [
402
-                'nav'           => [
403
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
404
-                    'icon'  => 'dashicons-admin-generic',
405
-                    'order' => 40,
406
-                ],
407
-                'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
-                'labels'        => [
409
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
-                ],
411
-                'help_tabs'     => [
412
-                    'default_settings_help_tab'        => [
413
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
-                        'filename' => 'events_default_settings',
415
-                    ],
416
-                    'default_settings_status_help_tab' => [
417
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
-                        'filename' => 'events_default_settings_status',
419
-                    ],
420
-                    'default_maximum_tickets_help_tab' => [
421
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
-                        'filename' => 'events_default_settings_max_tickets',
423
-                    ],
424
-                ],
425
-                'require_nonce' => false,
426
-            ],
427
-            // template settings
428
-            'template_settings'      => [
429
-                'nav'           => [
430
-                    'label' => esc_html__('Templates', 'event_espresso'),
431
-                    'icon'  => 'dashicons-layout',
432
-                    'order' => 30,
433
-                ],
434
-                'metaboxes'     => $this->_default_espresso_metaboxes,
435
-                'help_tabs'     => [
436
-                    'general_settings_templates_help_tab' => [
437
-                        'title'    => esc_html__('Templates', 'event_espresso'),
438
-                        'filename' => 'general_settings_templates',
439
-                    ],
440
-                ],
441
-                'require_nonce' => false,
442
-            ],
443
-            // event category stuff
444
-            'add_category'           => [
445
-                'nav'           => [
446
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
447
-                    'icon'       => 'dashicons-plus-alt',
448
-                    'order'      => 25,
449
-                    'persistent' => false,
450
-                ],
451
-                'help_tabs'     => [
452
-                    'add_category_help_tab' => [
453
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
-                        'filename' => 'events_add_category',
455
-                    ],
456
-                ],
457
-                'metaboxes'     => ['_publish_post_box'],
458
-                'require_nonce' => false,
459
-            ],
460
-            'edit_category'          => [
461
-                'nav'           => [
462
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
463
-                    'icon'       => 'dashicons-edit',
464
-                    'order'      => 25,
465
-                    'persistent' => false,
466
-                    'url'        => $EVT_CAT_ID
467
-                        ? add_query_arg(
468
-                            ['EVT_CAT_ID' => $EVT_CAT_ID],
469
-                            $this->_current_page_view_url
470
-                        )
471
-                        : $this->_admin_base_url,
472
-                ],
473
-                'help_tabs'     => [
474
-                    'edit_category_help_tab' => [
475
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
-                        'filename' => 'events_edit_category',
477
-                    ],
478
-                ],
479
-                'metaboxes'     => ['_publish_post_box'],
480
-                'require_nonce' => false,
481
-            ],
482
-            'category_list'          => [
483
-                'nav'           => [
484
-                    'label' => esc_html__('Categories', 'event_espresso'),
485
-                    'icon'  => 'dashicons-networking',
486
-                    'order' => 20,
487
-                ],
488
-                'list_table'    => 'Event_Categories_Admin_List_Table',
489
-                'help_tabs'     => [
490
-                    'events_categories_help_tab'                       => [
491
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
492
-                        'filename' => 'events_categories',
493
-                    ],
494
-                    'events_categories_table_column_headings_help_tab' => [
495
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
-                        'filename' => 'events_categories_table_column_headings',
497
-                    ],
498
-                    'events_categories_view_help_tab'                  => [
499
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
-                        'filename' => 'events_categories_views',
501
-                    ],
502
-                    'events_categories_other_help_tab'                 => [
503
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
-                        'filename' => 'events_categories_other',
505
-                    ],
506
-                ],
507
-                'metaboxes'     => $this->_default_espresso_metaboxes,
508
-                'require_nonce' => false,
509
-            ],
510
-            'preview_deletion'       => [
511
-                'nav'           => [
512
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
-                    'icon'       => 'dashicons-remove',
514
-                    'order'      => 15,
515
-                    'persistent' => false,
516
-                    'url'        => '',
517
-                ],
518
-                'require_nonce' => false,
519
-            ],
520
-        ];
521
-    }
522
-
523
-
524
-    /**
525
-     * Used to register any global screen options if necessary for every route in this admin page group.
526
-     */
527
-    protected function _add_screen_options()
528
-    {
529
-    }
530
-
531
-
532
-    /**
533
-     * Implementing the screen options for the 'default' route.
534
-     *
535
-     * @throws InvalidArgumentException
536
-     * @throws InvalidDataTypeException
537
-     * @throws InvalidInterfaceException
538
-     */
539
-    protected function _add_screen_options_default()
540
-    {
541
-        $this->_per_page_screen_option();
542
-    }
543
-
544
-
545
-    /**
546
-     * Implementing screen options for the category list route.
547
-     *
548
-     * @throws InvalidArgumentException
549
-     * @throws InvalidDataTypeException
550
-     * @throws InvalidInterfaceException
551
-     */
552
-    protected function _add_screen_options_category_list()
553
-    {
554
-        $page_title              = $this->_admin_page_title;
555
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
-        $this->_per_page_screen_option();
557
-        $this->_admin_page_title = $page_title;
558
-    }
559
-
560
-
561
-    /**
562
-     * Used to register any global feature pointers for the admin page group.
563
-     */
564
-    protected function _add_feature_pointers()
565
-    {
566
-    }
567
-
568
-
569
-    /**
570
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
571
-     */
572
-    public function load_scripts_styles()
573
-    {
574
-        wp_enqueue_style(
575
-            'events-admin-css',
576
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
577
-            [],
578
-            EVENT_ESPRESSO_VERSION
579
-        );
580
-        wp_enqueue_style(
581
-            'ee-cat-admin',
582
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
-            ['editor-buttons'],
584
-            EVENT_ESPRESSO_VERSION
585
-        );
586
-        // scripts
587
-        wp_enqueue_script(
588
-            'event_editor_js',
589
-            EVENTS_ASSETS_URL . 'event_editor.js',
590
-            [
591
-                EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
592
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
593
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
594
-            ],
595
-            EVENT_ESPRESSO_VERSION,
596
-            true
597
-        );
598
-    }
599
-
600
-
601
-    /**
602
-     * Enqueuing scripts and styles specific to this view
603
-     */
604
-    public function load_scripts_styles_create_new()
605
-    {
606
-        $this->load_scripts_styles_edit();
607
-    }
608
-
609
-
610
-    /**
611
-     * Enqueuing scripts and styles specific to this view
612
-     */
613
-    public function load_scripts_styles_edit()
614
-    {
615
-        // styles
616
-        wp_enqueue_style('espresso-ui-theme');
617
-        wp_enqueue_style(
618
-            'event-editor-css',
619
-            EVENTS_ASSETS_URL . 'event-editor.css',
620
-            ['ee-admin-css'],
621
-            EVENT_ESPRESSO_VERSION
622
-        );
623
-        // scripts
624
-        if (! $this->admin_config->useAdvancedEditor()) {
625
-            wp_enqueue_script(
626
-                'event-datetime-metabox',
627
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
628
-                ['event_editor_js', 'ee-datepicker'],
629
-                EVENT_ESPRESSO_VERSION
630
-            );
631
-        }
632
-    }
633
-
634
-
635
-    /**
636
-     * Populating the _views property for the category list table view.
637
-     */
638
-    protected function _set_list_table_views_category_list()
639
-    {
640
-        $this->_views = [
641
-            'all' => [
642
-                'slug'        => 'all',
643
-                'label'       => esc_html__('All', 'event_espresso'),
644
-                'count'       => 0,
645
-                'bulk_action' => [
646
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
647
-                ],
648
-            ],
649
-        ];
650
-    }
651
-
652
-
653
-    /**
654
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
655
-     */
656
-    public function admin_init()
657
-    {
658
-        EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
659
-            esc_html__(
660
-                'Do you really want to delete this image? Please remember to update your event to complete the removal.',
661
-                'event_espresso'
662
-            )
663
-        );
664
-
665
-        EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
666
-            __(
667
-                'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
668
-                'event_espresso'
669
-            )
670
-        );
671
-    }
672
-
673
-
674
-    /**
675
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
676
-     * group.
677
-     */
678
-    public function admin_notices()
679
-    {
680
-    }
681
-
682
-
683
-    /**
684
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
685
-     * this admin page group.
686
-     */
687
-    public function admin_footer_scripts()
688
-    {
689
-    }
690
-
691
-
692
-    /**
693
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
694
-     * warning (via EE_Error::add_error());
695
-     *
696
-     * @param EE_Event|null $event Event object
697
-     * @param string        $req_type
698
-     * @return void
699
-     * @throws EE_Error
700
-     * @throws ReflectionException
701
-     */
702
-    public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
703
-    {
704
-        // don't need to do this when processing
705
-        if (! empty($req_type)) {
706
-            return;
707
-        }
708
-        // no event?
709
-        if (! $event instanceof EE_Event) {
710
-            $event = $this->_cpt_model_obj;
711
-        }
712
-        // STILL no event?
713
-        if (! $event instanceof EE_Event) {
714
-            return;
715
-        }
716
-        // don't need to keep calling this
717
-        remove_action(
718
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
719
-            [$this, 'verify_event_edit']
720
-        );
721
-        $orig_status = $event->status();
722
-        // first check if event is active.
723
-        if (
724
-            $orig_status === EEM_Event::cancelled
725
-            || $orig_status === EEM_Event::postponed
726
-            || $event->is_expired()
727
-            || $event->is_inactive()
728
-        ) {
729
-            return;
730
-        }
731
-        // made it here so it IS active... next check that any of the tickets are sold.
732
-        if ($event->is_sold_out(true)) {
733
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
734
-                EE_Error::add_attention(
735
-                    sprintf(
736
-                        esc_html__(
737
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
738
-                            'event_espresso'
739
-                        ),
740
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
741
-                    )
742
-                );
743
-            }
744
-            return;
745
-        }
746
-        if ($orig_status === EEM_Event::sold_out) {
747
-            EE_Error::add_attention(
748
-                sprintf(
749
-                    esc_html__(
750
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
751
-                        'event_espresso'
752
-                    ),
753
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
754
-                )
755
-            );
756
-        }
757
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
758
-        if (! $event->tickets_on_sale()) {
759
-            return;
760
-        }
761
-        // made it here so show warning
762
-        $this->_edit_event_warning();
763
-    }
764
-
765
-
766
-    /**
767
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
768
-     * When needed, hook this into a EE_Error::add_error() notice.
769
-     *
770
-     * @access protected
771
-     * @return void
772
-     */
773
-    protected function _edit_event_warning()
774
-    {
775
-        // we don't want to add warnings during these requests
776
-        if ($this->request->getRequestParam('action') === 'editpost') {
777
-            return;
778
-        }
779
-        EE_Error::add_attention(
780
-            sprintf(
781
-                esc_html__(
782
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
783
-                    'event_espresso'
784
-                ),
785
-                '<a class="espresso-help-tab-lnk ee-help-tab-link">',
786
-                '</a>'
787
-            )
788
-        );
789
-    }
790
-
791
-
792
-    /**
793
-     * When a user is creating a new event, notify them if they haven't set their timezone.
794
-     * Otherwise, do the normal logic
25
+	/**
26
+	 * primary key for the event model
27
+	 */
28
+	private int $EVT_ID = 0;
29
+
30
+	/**
31
+	 * This will hold the event object for event_details screen.
32
+	 *
33
+	 * @var EE_Event|null $_event
34
+	 */
35
+	protected ?EE_Event $_event = null;
36
+
37
+	/**
38
+	 * This will hold the category object for category_details screen.
39
+	 */
40
+	protected ?stdClass $_category = null;
41
+
42
+	protected ?EEM_Event $_event_model = null;
43
+
44
+	/**
45
+	 * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
+	 */
47
+	protected $_cpt_model_obj;
48
+
49
+	protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
+
51
+	protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
+
53
+
54
+	/**
55
+	 * Initialize page props for this admin page group.
56
+	 */
57
+	protected function _init_page_props()
58
+	{
59
+		// is there a evt_id in the request?
60
+		$this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
+		$this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
+		$this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
+
64
+		$this->page_slug        = EVENTS_PG_SLUG;
65
+		$this->page_label       = EVENTS_LABEL;
66
+		$this->_admin_base_url  = EVENTS_ADMIN_URL;
67
+		$this->_admin_base_path = EVENTS_ADMIN;
68
+		$this->_cpt_model_names = [
69
+			'create_new' => 'EEM_Event',
70
+			'edit'       => 'EEM_Event',
71
+		];
72
+		$this->_cpt_edit_routes = [
73
+			'espresso_events' => 'edit',
74
+		];
75
+		add_action(
76
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
+			[$this, 'verify_event_edit'],
78
+			10,
79
+			2
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets the ajax hooks used for this admin page group.
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Sets the page properties for this admin page group.
95
+	 */
96
+	protected function _define_page_props()
97
+	{
98
+		$this->_admin_page_title = EVENTS_LABEL;
99
+		$this->_labels           = [
100
+			'buttons'      => [
101
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
102
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
+			],
108
+			'editor_title' => [
109
+				'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
+			],
111
+			'publishbox'   => [
112
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
114
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
+			],
118
+		];
119
+	}
120
+
121
+
122
+	/**
123
+	 * Sets the page routes property for this admin page group.
124
+	 */
125
+	protected function _set_page_routes()
126
+	{
127
+		$this->_page_routes = [
128
+			'default'                       => [
129
+				'func'       => [$this, '_events_overview_list_table'],
130
+				'capability' => 'ee_read_events',
131
+			],
132
+			'create_new'                    => [
133
+				'func'       => [$this, '_create_new_cpt_item'],
134
+				'capability' => 'ee_edit_events',
135
+			],
136
+			'edit'                          => [
137
+				'func'       => [$this, '_edit_cpt_item'],
138
+				'capability' => 'ee_edit_event',
139
+				'obj_id'     => $this->EVT_ID,
140
+			],
141
+			'copy_event'                    => [
142
+				'func'       => [$this, '_copy_events'],
143
+				'capability' => 'ee_edit_event',
144
+				'obj_id'     => $this->EVT_ID,
145
+				'noheader'   => true,
146
+			],
147
+			'trash_event'                   => [
148
+				'func'       => [$this, '_trash_or_restore_event'],
149
+				'args'       => ['event_status' => 'trash'],
150
+				'capability' => 'ee_delete_event',
151
+				'obj_id'     => $this->EVT_ID,
152
+				'noheader'   => true,
153
+			],
154
+			'trash_events'                  => [
155
+				'func'       => [$this, '_trash_or_restore_events'],
156
+				'args'       => ['event_status' => 'trash'],
157
+				'capability' => 'ee_delete_events',
158
+				'noheader'   => true,
159
+			],
160
+			'restore_event'                 => [
161
+				'func'       => [$this, '_trash_or_restore_event'],
162
+				'args'       => ['event_status' => 'draft'],
163
+				'capability' => 'ee_delete_event',
164
+				'obj_id'     => $this->EVT_ID,
165
+				'noheader'   => true,
166
+			],
167
+			'restore_events'                => [
168
+				'func'       => [$this, '_trash_or_restore_events'],
169
+				'args'       => ['event_status' => 'draft'],
170
+				'capability' => 'ee_delete_events',
171
+				'noheader'   => true,
172
+			],
173
+			'delete_event'                  => [
174
+				'func'       => [$this, '_delete_event'],
175
+				'capability' => 'ee_delete_event',
176
+				'obj_id'     => $this->EVT_ID,
177
+				'noheader'   => true,
178
+			],
179
+			'delete_events'                 => [
180
+				'func'       => [$this, '_delete_events'],
181
+				'capability' => 'ee_delete_events',
182
+				'noheader'   => true,
183
+			],
184
+			'view_report'                   => [
185
+				'func'       => [$this, '_view_report'],
186
+				'capability' => 'ee_edit_events',
187
+			],
188
+			'default_event_settings'        => [
189
+				'func'       => [$this, '_default_event_settings'],
190
+				'capability' => 'manage_options',
191
+			],
192
+			'update_default_event_settings' => [
193
+				'func'       => [$this, '_update_default_event_settings'],
194
+				'capability' => 'manage_options',
195
+				'noheader'   => true,
196
+			],
197
+			'template_settings'             => [
198
+				'func'       => [$this, '_template_settings'],
199
+				'capability' => 'manage_options',
200
+			],
201
+			// event category tab related
202
+			'add_category'                  => [
203
+				'func'       => [$this, '_category_details'],
204
+				'capability' => 'ee_edit_event_category',
205
+				'args'       => ['view' => 'add'],
206
+			],
207
+			'edit_category'                 => [
208
+				'func'       => [$this, '_category_details'],
209
+				'capability' => 'ee_edit_event_category',
210
+				'args'       => ['view' => 'edit'],
211
+			],
212
+			'delete_categories'             => [
213
+				'func'       => [$this, '_delete_categories'],
214
+				'capability' => 'ee_delete_event_category',
215
+				'noheader'   => true,
216
+			],
217
+			'delete_category'               => [
218
+				'func'       => [$this, '_delete_categories'],
219
+				'capability' => 'ee_delete_event_category',
220
+				'noheader'   => true,
221
+			],
222
+			'insert_category'               => [
223
+				'func'       => [$this, '_insert_or_update_category'],
224
+				'args'       => ['new_category' => true],
225
+				'capability' => 'ee_edit_event_category',
226
+				'noheader'   => true,
227
+			],
228
+			'update_category'               => [
229
+				'func'       => [$this, '_insert_or_update_category'],
230
+				'args'       => ['new_category' => false],
231
+				'capability' => 'ee_edit_event_category',
232
+				'noheader'   => true,
233
+			],
234
+			'category_list'                 => [
235
+				'func'       => [$this, '_category_list_table'],
236
+				'capability' => 'ee_manage_event_categories',
237
+			],
238
+			'preview_deletion'              => [
239
+				'func'       => [$this, 'previewDeletion'],
240
+				'capability' => 'ee_delete_events',
241
+			],
242
+			'confirm_deletion'              => [
243
+				'func'       => [$this, 'confirmDeletion'],
244
+				'capability' => 'ee_delete_events',
245
+				'noheader'   => true,
246
+			],
247
+		];
248
+	}
249
+
250
+
251
+	/**
252
+	 * Set the _page_config property for this admin page group.
253
+	 */
254
+	protected function _set_page_config()
255
+	{
256
+		$post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
+		$EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
+		$this->_page_config = [
259
+			'default'                => [
260
+				'nav'           => [
261
+					'label' => esc_html__('Overview', 'event_espresso'),
262
+					'icon'  => 'dashicons-list-view',
263
+					'order' => 10,
264
+				],
265
+				'list_table'    => 'Events_Admin_List_Table',
266
+				'help_tabs'     => [
267
+					'events_overview_help_tab'                       => [
268
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
269
+						'filename' => 'events_overview',
270
+					],
271
+					'events_overview_table_column_headings_help_tab' => [
272
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
+						'filename' => 'events_overview_table_column_headings',
274
+					],
275
+					'events_overview_filters_help_tab'               => [
276
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
+						'filename' => 'events_overview_filters',
278
+					],
279
+					'events_overview_view_help_tab'                  => [
280
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
+						'filename' => 'events_overview_views',
282
+					],
283
+					'events_overview_other_help_tab'                 => [
284
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
+						'filename' => 'events_overview_other',
286
+					],
287
+				],
288
+				'require_nonce' => false,
289
+			],
290
+			'create_new'             => [
291
+				'nav'           => [
292
+					'label'      => esc_html__('Add New Event', 'event_espresso'),
293
+					'icon'       => 'dashicons-plus-alt',
294
+					'order'      => 15,
295
+					'persistent' => false,
296
+				],
297
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
+				'help_tabs'     => [
299
+					'event_editor_help_tab'                            => [
300
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
301
+						'filename' => 'event_editor',
302
+					],
303
+					'event_editor_title_richtexteditor_help_tab'       => [
304
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
+						'filename' => 'event_editor_title_richtexteditor',
306
+					],
307
+					'event_editor_venue_details_help_tab'              => [
308
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
+						'filename' => 'event_editor_venue_details',
310
+					],
311
+					'event_editor_event_datetimes_help_tab'            => [
312
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
+						'filename' => 'event_editor_event_datetimes',
314
+					],
315
+					'event_editor_event_tickets_help_tab'              => [
316
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
+						'filename' => 'event_editor_event_tickets',
318
+					],
319
+					'event_editor_event_registration_options_help_tab' => [
320
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
+						'filename' => 'event_editor_event_registration_options',
322
+					],
323
+					'event_editor_tags_categories_help_tab'            => [
324
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
+						'filename' => 'event_editor_tags_categories',
326
+					],
327
+					'event_editor_questions_registrants_help_tab'      => [
328
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
+						'filename' => 'event_editor_questions_registrants',
330
+					],
331
+					'event_editor_save_new_event_help_tab'             => [
332
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
333
+						'filename' => 'event_editor_save_new_event',
334
+					],
335
+					'event_editor_other_help_tab'                      => [
336
+						'title'    => esc_html__('Event Other', 'event_espresso'),
337
+						'filename' => 'event_editor_other',
338
+					],
339
+				],
340
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
+				'require_nonce' => false,
342
+			],
343
+			'edit'                   => [
344
+				'nav'           => [
345
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
346
+					'icon'       => 'dashicons-edit',
347
+					'order'      => 15,
348
+					'persistent' => false,
349
+					'url'        => $post_id
350
+						? EE_Admin_Page::add_query_args_and_nonce(
351
+							['post' => $post_id, 'action' => 'edit'],
352
+							$this->_current_page_view_url
353
+						)
354
+						: $this->_admin_base_url,
355
+				],
356
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
+				'help_tabs'     => [
358
+					'event_editor_help_tab'                            => [
359
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
360
+						'filename' => 'event_editor',
361
+					],
362
+					'event_editor_title_richtexteditor_help_tab'       => [
363
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
+						'filename' => 'event_editor_title_richtexteditor',
365
+					],
366
+					'event_editor_venue_details_help_tab'              => [
367
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
+						'filename' => 'event_editor_venue_details',
369
+					],
370
+					'event_editor_event_datetimes_help_tab'            => [
371
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
+						'filename' => 'event_editor_event_datetimes',
373
+					],
374
+					'event_editor_event_tickets_help_tab'              => [
375
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
+						'filename' => 'event_editor_event_tickets',
377
+					],
378
+					'event_editor_event_registration_options_help_tab' => [
379
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
+						'filename' => 'event_editor_event_registration_options',
381
+					],
382
+					'event_editor_tags_categories_help_tab'            => [
383
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
+						'filename' => 'event_editor_tags_categories',
385
+					],
386
+					'event_editor_questions_registrants_help_tab'      => [
387
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
+						'filename' => 'event_editor_questions_registrants',
389
+					],
390
+					'event_editor_save_new_event_help_tab'             => [
391
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
392
+						'filename' => 'event_editor_save_new_event',
393
+					],
394
+					'event_editor_other_help_tab'                      => [
395
+						'title'    => esc_html__('Event Other', 'event_espresso'),
396
+						'filename' => 'event_editor_other',
397
+					],
398
+				],
399
+				'require_nonce' => false,
400
+			],
401
+			'default_event_settings' => [
402
+				'nav'           => [
403
+					'label' => esc_html__('Default Settings', 'event_espresso'),
404
+					'icon'  => 'dashicons-admin-generic',
405
+					'order' => 40,
406
+				],
407
+				'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
+				'labels'        => [
409
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
+				],
411
+				'help_tabs'     => [
412
+					'default_settings_help_tab'        => [
413
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
+						'filename' => 'events_default_settings',
415
+					],
416
+					'default_settings_status_help_tab' => [
417
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
+						'filename' => 'events_default_settings_status',
419
+					],
420
+					'default_maximum_tickets_help_tab' => [
421
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
+						'filename' => 'events_default_settings_max_tickets',
423
+					],
424
+				],
425
+				'require_nonce' => false,
426
+			],
427
+			// template settings
428
+			'template_settings'      => [
429
+				'nav'           => [
430
+					'label' => esc_html__('Templates', 'event_espresso'),
431
+					'icon'  => 'dashicons-layout',
432
+					'order' => 30,
433
+				],
434
+				'metaboxes'     => $this->_default_espresso_metaboxes,
435
+				'help_tabs'     => [
436
+					'general_settings_templates_help_tab' => [
437
+						'title'    => esc_html__('Templates', 'event_espresso'),
438
+						'filename' => 'general_settings_templates',
439
+					],
440
+				],
441
+				'require_nonce' => false,
442
+			],
443
+			// event category stuff
444
+			'add_category'           => [
445
+				'nav'           => [
446
+					'label'      => esc_html__('Add Category', 'event_espresso'),
447
+					'icon'       => 'dashicons-plus-alt',
448
+					'order'      => 25,
449
+					'persistent' => false,
450
+				],
451
+				'help_tabs'     => [
452
+					'add_category_help_tab' => [
453
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
+						'filename' => 'events_add_category',
455
+					],
456
+				],
457
+				'metaboxes'     => ['_publish_post_box'],
458
+				'require_nonce' => false,
459
+			],
460
+			'edit_category'          => [
461
+				'nav'           => [
462
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
463
+					'icon'       => 'dashicons-edit',
464
+					'order'      => 25,
465
+					'persistent' => false,
466
+					'url'        => $EVT_CAT_ID
467
+						? add_query_arg(
468
+							['EVT_CAT_ID' => $EVT_CAT_ID],
469
+							$this->_current_page_view_url
470
+						)
471
+						: $this->_admin_base_url,
472
+				],
473
+				'help_tabs'     => [
474
+					'edit_category_help_tab' => [
475
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
+						'filename' => 'events_edit_category',
477
+					],
478
+				],
479
+				'metaboxes'     => ['_publish_post_box'],
480
+				'require_nonce' => false,
481
+			],
482
+			'category_list'          => [
483
+				'nav'           => [
484
+					'label' => esc_html__('Categories', 'event_espresso'),
485
+					'icon'  => 'dashicons-networking',
486
+					'order' => 20,
487
+				],
488
+				'list_table'    => 'Event_Categories_Admin_List_Table',
489
+				'help_tabs'     => [
490
+					'events_categories_help_tab'                       => [
491
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
492
+						'filename' => 'events_categories',
493
+					],
494
+					'events_categories_table_column_headings_help_tab' => [
495
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
+						'filename' => 'events_categories_table_column_headings',
497
+					],
498
+					'events_categories_view_help_tab'                  => [
499
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
+						'filename' => 'events_categories_views',
501
+					],
502
+					'events_categories_other_help_tab'                 => [
503
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
+						'filename' => 'events_categories_other',
505
+					],
506
+				],
507
+				'metaboxes'     => $this->_default_espresso_metaboxes,
508
+				'require_nonce' => false,
509
+			],
510
+			'preview_deletion'       => [
511
+				'nav'           => [
512
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
+					'icon'       => 'dashicons-remove',
514
+					'order'      => 15,
515
+					'persistent' => false,
516
+					'url'        => '',
517
+				],
518
+				'require_nonce' => false,
519
+			],
520
+		];
521
+	}
522
+
523
+
524
+	/**
525
+	 * Used to register any global screen options if necessary for every route in this admin page group.
526
+	 */
527
+	protected function _add_screen_options()
528
+	{
529
+	}
530
+
531
+
532
+	/**
533
+	 * Implementing the screen options for the 'default' route.
534
+	 *
535
+	 * @throws InvalidArgumentException
536
+	 * @throws InvalidDataTypeException
537
+	 * @throws InvalidInterfaceException
538
+	 */
539
+	protected function _add_screen_options_default()
540
+	{
541
+		$this->_per_page_screen_option();
542
+	}
543
+
544
+
545
+	/**
546
+	 * Implementing screen options for the category list route.
547
+	 *
548
+	 * @throws InvalidArgumentException
549
+	 * @throws InvalidDataTypeException
550
+	 * @throws InvalidInterfaceException
551
+	 */
552
+	protected function _add_screen_options_category_list()
553
+	{
554
+		$page_title              = $this->_admin_page_title;
555
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
+		$this->_per_page_screen_option();
557
+		$this->_admin_page_title = $page_title;
558
+	}
559
+
560
+
561
+	/**
562
+	 * Used to register any global feature pointers for the admin page group.
563
+	 */
564
+	protected function _add_feature_pointers()
565
+	{
566
+	}
567
+
568
+
569
+	/**
570
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
571
+	 */
572
+	public function load_scripts_styles()
573
+	{
574
+		wp_enqueue_style(
575
+			'events-admin-css',
576
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
577
+			[],
578
+			EVENT_ESPRESSO_VERSION
579
+		);
580
+		wp_enqueue_style(
581
+			'ee-cat-admin',
582
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
+			['editor-buttons'],
584
+			EVENT_ESPRESSO_VERSION
585
+		);
586
+		// scripts
587
+		wp_enqueue_script(
588
+			'event_editor_js',
589
+			EVENTS_ASSETS_URL . 'event_editor.js',
590
+			[
591
+				EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
592
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
593
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
594
+			],
595
+			EVENT_ESPRESSO_VERSION,
596
+			true
597
+		);
598
+	}
599
+
600
+
601
+	/**
602
+	 * Enqueuing scripts and styles specific to this view
603
+	 */
604
+	public function load_scripts_styles_create_new()
605
+	{
606
+		$this->load_scripts_styles_edit();
607
+	}
608
+
609
+
610
+	/**
611
+	 * Enqueuing scripts and styles specific to this view
612
+	 */
613
+	public function load_scripts_styles_edit()
614
+	{
615
+		// styles
616
+		wp_enqueue_style('espresso-ui-theme');
617
+		wp_enqueue_style(
618
+			'event-editor-css',
619
+			EVENTS_ASSETS_URL . 'event-editor.css',
620
+			['ee-admin-css'],
621
+			EVENT_ESPRESSO_VERSION
622
+		);
623
+		// scripts
624
+		if (! $this->admin_config->useAdvancedEditor()) {
625
+			wp_enqueue_script(
626
+				'event-datetime-metabox',
627
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
628
+				['event_editor_js', 'ee-datepicker'],
629
+				EVENT_ESPRESSO_VERSION
630
+			);
631
+		}
632
+	}
633
+
634
+
635
+	/**
636
+	 * Populating the _views property for the category list table view.
637
+	 */
638
+	protected function _set_list_table_views_category_list()
639
+	{
640
+		$this->_views = [
641
+			'all' => [
642
+				'slug'        => 'all',
643
+				'label'       => esc_html__('All', 'event_espresso'),
644
+				'count'       => 0,
645
+				'bulk_action' => [
646
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
647
+				],
648
+			],
649
+		];
650
+	}
651
+
652
+
653
+	/**
654
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
655
+	 */
656
+	public function admin_init()
657
+	{
658
+		EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
659
+			esc_html__(
660
+				'Do you really want to delete this image? Please remember to update your event to complete the removal.',
661
+				'event_espresso'
662
+			)
663
+		);
664
+
665
+		EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
666
+			__(
667
+				'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
668
+				'event_espresso'
669
+			)
670
+		);
671
+	}
672
+
673
+
674
+	/**
675
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
676
+	 * group.
677
+	 */
678
+	public function admin_notices()
679
+	{
680
+	}
681
+
682
+
683
+	/**
684
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
685
+	 * this admin page group.
686
+	 */
687
+	public function admin_footer_scripts()
688
+	{
689
+	}
690
+
691
+
692
+	/**
693
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
694
+	 * warning (via EE_Error::add_error());
695
+	 *
696
+	 * @param EE_Event|null $event Event object
697
+	 * @param string        $req_type
698
+	 * @return void
699
+	 * @throws EE_Error
700
+	 * @throws ReflectionException
701
+	 */
702
+	public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
703
+	{
704
+		// don't need to do this when processing
705
+		if (! empty($req_type)) {
706
+			return;
707
+		}
708
+		// no event?
709
+		if (! $event instanceof EE_Event) {
710
+			$event = $this->_cpt_model_obj;
711
+		}
712
+		// STILL no event?
713
+		if (! $event instanceof EE_Event) {
714
+			return;
715
+		}
716
+		// don't need to keep calling this
717
+		remove_action(
718
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
719
+			[$this, 'verify_event_edit']
720
+		);
721
+		$orig_status = $event->status();
722
+		// first check if event is active.
723
+		if (
724
+			$orig_status === EEM_Event::cancelled
725
+			|| $orig_status === EEM_Event::postponed
726
+			|| $event->is_expired()
727
+			|| $event->is_inactive()
728
+		) {
729
+			return;
730
+		}
731
+		// made it here so it IS active... next check that any of the tickets are sold.
732
+		if ($event->is_sold_out(true)) {
733
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
734
+				EE_Error::add_attention(
735
+					sprintf(
736
+						esc_html__(
737
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
738
+							'event_espresso'
739
+						),
740
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
741
+					)
742
+				);
743
+			}
744
+			return;
745
+		}
746
+		if ($orig_status === EEM_Event::sold_out) {
747
+			EE_Error::add_attention(
748
+				sprintf(
749
+					esc_html__(
750
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
751
+						'event_espresso'
752
+					),
753
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
754
+				)
755
+			);
756
+		}
757
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
758
+		if (! $event->tickets_on_sale()) {
759
+			return;
760
+		}
761
+		// made it here so show warning
762
+		$this->_edit_event_warning();
763
+	}
764
+
765
+
766
+	/**
767
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
768
+	 * When needed, hook this into a EE_Error::add_error() notice.
769
+	 *
770
+	 * @access protected
771
+	 * @return void
772
+	 */
773
+	protected function _edit_event_warning()
774
+	{
775
+		// we don't want to add warnings during these requests
776
+		if ($this->request->getRequestParam('action') === 'editpost') {
777
+			return;
778
+		}
779
+		EE_Error::add_attention(
780
+			sprintf(
781
+				esc_html__(
782
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
783
+					'event_espresso'
784
+				),
785
+				'<a class="espresso-help-tab-lnk ee-help-tab-link">',
786
+				'</a>'
787
+			)
788
+		);
789
+	}
790
+
791
+
792
+	/**
793
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
794
+	 * Otherwise, do the normal logic
795
+	 *
796
+	 * @return void
797
+	 * @throws EE_Error
798
+	 * @throws InvalidArgumentException
799
+	 * @throws InvalidDataTypeException
800
+	 * @throws InvalidInterfaceException
801
+	 * @throws ReflectionException
802
+	 */
803
+	protected function _create_new_cpt_item()
804
+	{
805
+		$has_timezone_string = get_option('timezone_string');
806
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
807
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
808
+			EE_Error::add_attention(
809
+				sprintf(
810
+					esc_html__(
811
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
812
+						'event_espresso'
813
+					),
814
+					'<br>',
815
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
816
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
817
+					. '</select>',
818
+					'<button class="button button--secondary timezone-submit">',
819
+					'</button><span class="spinner"></span>'
820
+				),
821
+				__FILE__,
822
+				__FUNCTION__,
823
+				__LINE__
824
+			);
825
+		}
826
+		parent::_create_new_cpt_item();
827
+	}
828
+
829
+
830
+	/**
831
+	 * Sets the _views property for the default route in this admin page group.
832
+	 */
833
+	protected function _set_list_table_views_default()
834
+	{
835
+		$this->_views = [
836
+			'all'   => [
837
+				'slug'        => 'all',
838
+				'label'       => esc_html__('View All Events', 'event_espresso'),
839
+				'count'       => 0,
840
+				'bulk_action' => [
841
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
842
+				],
843
+			],
844
+			'draft' => [
845
+				'slug'        => 'draft',
846
+				'label'       => esc_html__('Draft', 'event_espresso'),
847
+				'count'       => 0,
848
+				'bulk_action' => [
849
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
850
+				],
851
+			],
852
+		];
853
+		if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
854
+			$this->_views['trash'] = [
855
+				'slug'        => 'trash',
856
+				'label'       => esc_html__('Trash', 'event_espresso'),
857
+				'count'       => 0,
858
+				'bulk_action' => [
859
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
860
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
861
+				],
862
+			];
863
+		}
864
+	}
865
+
866
+
867
+	/**
868
+	 * Provides the legend item array for the default list table view.
869
+	 *
870
+	 * @return array
871
+	 * @throws EE_Error
872
+	 * @throws EE_Error
873
+	 */
874
+	protected function _event_legend_items(): array
875
+	{
876
+		$items    = [
877
+			'view_details'   => [
878
+				'class' => 'dashicons dashicons-visibility',
879
+				'desc'  => esc_html__('View Event', 'event_espresso'),
880
+			],
881
+			'edit_event'     => [
882
+				'class' => 'dashicons dashicons-calendar-alt',
883
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
884
+			],
885
+			'view_attendees' => [
886
+				'class' => 'dashicons dashicons-groups',
887
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
888
+			],
889
+		];
890
+		$items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
891
+		$statuses = [
892
+			'sold_out_status'  => [
893
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
894
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
895
+			],
896
+			'active_status'    => [
897
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
898
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
899
+			],
900
+			'upcoming_status'  => [
901
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
902
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
903
+			],
904
+			'postponed_status' => [
905
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
906
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
907
+			],
908
+			'cancelled_status' => [
909
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
910
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
911
+			],
912
+			'expired_status'   => [
913
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
914
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
915
+			],
916
+			'inactive_status'  => [
917
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
918
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
919
+			],
920
+		];
921
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
922
+		return array_merge($items, $statuses);
923
+	}
924
+
925
+
926
+	/**
927
+	 * @return EEM_Event
928
+	 * @throws EE_Error
929
+	 * @throws InvalidArgumentException
930
+	 * @throws InvalidDataTypeException
931
+	 * @throws InvalidInterfaceException
932
+	 * @throws ReflectionException
933
+	 */
934
+	private function _event_model(): EEM_Event
935
+	{
936
+		if (! $this->_event_model instanceof EEM_Event) {
937
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
938
+		}
939
+		return $this->_event_model;
940
+	}
941
+
942
+
943
+	/**
944
+	 * Adds extra buttons to the WP CPT permalink field row.
945
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
946
+	 *
947
+	 * @param string      $return    the current html
948
+	 * @param int         $id        the post id for the page
949
+	 * @param string|null $new_title What the title is
950
+	 * @param string|null $new_slug  what the slug is
951
+	 * @return string            The new html string for the permalink area
952
+	 * @deprecated 5.0.0.p
953
+	 * @see        TicketSelectorShortcodeButton::addButton
954
+	 */
955
+	public function extra_permalink_field_buttons(
956
+		string $return,
957
+		int $id,
958
+		?string $new_title,
959
+		?string $new_slug
960
+	): string {
961
+		return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
962
+	}
963
+
964
+
965
+	/**
966
+	 * _events_overview_list_table
967
+	 * This contains the logic for showing the events_overview list
968
+	 *
969
+	 * @access protected
970
+	 * @return void
971
+	 * @throws DomainException
972
+	 * @throws EE_Error
973
+	 * @throws InvalidArgumentException
974
+	 * @throws InvalidDataTypeException
975
+	 * @throws InvalidInterfaceException
976
+	 */
977
+	protected function _events_overview_list_table()
978
+	{
979
+		$after_list_table = [];
980
+		$links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
981
+		$links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
982
+		$links_html       .= EEH_HTML::div(
983
+			EEH_Template::get_button_or_link(
984
+				get_post_type_archive_link(EspressoPostType::EVENTS),
985
+				esc_html__('View Event Archive Page', 'event_espresso'),
986
+				'button button--small button--secondary'
987
+			),
988
+			'',
989
+			'ee-admin-button-row ee-admin-button-row--align-start'
990
+		);
991
+		$links_html       .= EEH_HTML::divx();
992
+
993
+		$after_list_table['view_event_list_button'] = $links_html;
994
+
995
+		$after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
996
+		$this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
997
+				'create_new',
998
+				'add',
999
+				[],
1000
+				'add-new-h2'
1001
+			);
1002
+
1003
+		$this->_template_args['after_list_table'] = array_merge(
1004
+			(array) $this->_template_args['after_list_table'],
1005
+			$after_list_table
1006
+		);
1007
+		$this->display_admin_list_table_page_with_no_sidebar();
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * this allows for extra misc actions in the default WP publish box
1013
+	 *
1014
+	 * @return void
1015
+	 * @throws DomainException
1016
+	 * @throws EE_Error
1017
+	 * @throws InvalidArgumentException
1018
+	 * @throws InvalidDataTypeException
1019
+	 * @throws InvalidInterfaceException
1020
+	 * @throws ReflectionException
1021
+	 */
1022
+	public function extra_misc_actions_publish_box()
1023
+	{
1024
+		$this->_generate_publish_box_extra_content();
1025
+	}
1026
+
1027
+
1028
+	/**
1029
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1030
+	 * saved.
1031
+	 * Typically you would use this to save any additional data.
1032
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1033
+	 * ALSO very important.  When a post transitions from scheduled to published,
1034
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1035
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1036
+	 *
1037
+	 * @access protected
1038
+	 * @abstract
1039
+	 * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1040
+	 * @param WP_Post $post    The post object of the cpt that was saved.
1041
+	 * @return void
1042
+	 * @throws EE_Error
1043
+	 * @throws InvalidArgumentException
1044
+	 * @throws InvalidDataTypeException
1045
+	 * @throws InvalidInterfaceException
1046
+	 * @throws ReflectionException
1047
+	 */
1048
+	protected function _insert_update_cpt_item($post_id, $post)
1049
+	{
1050
+		if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1051
+			// get out we're not processing an event save.
1052
+			return;
1053
+		}
1054
+		$event_values = [
1055
+			'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1056
+			'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1057
+			'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1058
+		];
1059
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1060
+		if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
+			$event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1062
+				'display_ticket_selector',
1063
+				false,
1064
+				'bool'
1065
+			);
1066
+			$event_values['EVT_additional_limit']            = min(
1067
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1068
+				$this->request->getRequestParam(
1069
+					'additional_limit',
1070
+					EEM_Event::get_default_additional_limit(),
1071
+					'int'
1072
+				)
1073
+			);
1074
+			$event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1075
+				'EVT_default_registration_status',
1076
+				EE_Registry::instance()->CFG->registration->default_STS_ID
1077
+			);
1078
+
1079
+			$event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1080
+			$event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1081
+			$event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1082
+		} elseif ($post instanceof WP_Post) {
1083
+			$event_values['EVT_name'] = $post->post_title;
1084
+			$event_values['EVT_desc'] = $post->post_content;
1085
+		}
1086
+		// update event
1087
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1088
+		// get event_object for other metaboxes...
1089
+		// though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1090
+		// i have to set up where conditions to override the filters in the model
1091
+		// that filter out auto-draft and inherit statuses so we GET the inherit id!
1092
+		/** @var EE_Event $event */
1093
+		$event = $this->_event_model()->get_one(
1094
+			[
1095
+				[
1096
+					$this->_event_model()->primary_key_name() => $post_id,
1097
+					'OR'                                      => [
1098
+						'status'   => $post->post_status,
1099
+						// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1100
+						// but the returned object here has a status of "publish", so use the original post status as well
1101
+						'status*1' => $this->request->getRequestParam('original_post_status'),
1102
+					],
1103
+					'status' => ['NOT IN', ['auto-draft']],
1104
+				],
1105
+			]
1106
+		);
1107
+
1108
+		if (! $event instanceof EE_Event) {
1109
+			return;
1110
+		}
1111
+
1112
+		// the following are default callbacks for event attachment updates
1113
+		// that can be overridden by caffeinated functionality and/or addons.
1114
+		$event_update_callbacks = [];
1115
+		if (! $this->admin_config->useAdvancedEditor()) {
1116
+			$event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1117
+			$event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1118
+		}
1119
+		$event_update_callbacks = apply_filters(
1120
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1121
+			$event_update_callbacks
1122
+		);
1123
+
1124
+		$att_success = true;
1125
+		foreach ($event_update_callbacks as $e_callback) {
1126
+			$_success = is_callable($e_callback)
1127
+				? $e_callback($event, $this->request->requestParams())
1128
+				: false;
1129
+			// if ANY of these updates fail then we want the appropriate global error message
1130
+			$att_success = $_success !== false ? $att_success : false;
1131
+		}
1132
+		// any errors?
1133
+		if ($success && $att_success === false) {
1134
+			EE_Error::add_error(
1135
+				esc_html__(
1136
+					'Event Details saved successfully but something went wrong with saving attachments.',
1137
+					'event_espresso'
1138
+				),
1139
+				__FILE__,
1140
+				__FUNCTION__,
1141
+				__LINE__
1142
+			);
1143
+		} elseif ($success === false) {
1144
+			EE_Error::add_error(
1145
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1146
+				__FILE__,
1147
+				__FUNCTION__,
1148
+				__LINE__
1149
+			);
1150
+		}
1151
+	}
1152
+
1153
+
1154
+	/**
1155
+	 * @param int $post_id
1156
+	 * @param int $revision_id
1157
+	 * @throws EE_Error
1158
+	 * @throws EE_Error
1159
+	 * @throws ReflectionException
1160
+	 * @see parent::restore_item()
1161
+	 */
1162
+	protected function _restore_cpt_item(int $post_id, int $revision_id)
1163
+	{
1164
+		// copy existing event meta to new post
1165
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1166
+		if ($post_evt instanceof EE_Event) {
1167
+			// meta revision restore
1168
+			$post_evt->restore_revision($revision_id);
1169
+			// related objs restore
1170
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1171
+		}
1172
+	}
1173
+
1174
+
1175
+	/**
1176
+	 * Attach the venue to the Event
1177
+	 *
1178
+	 * @param EE_Event $event Event Object to add the venue to
1179
+	 * @param array    $data  The request data from the form
1180
+	 * @return bool           Success or fail.
1181
+	 * @throws EE_Error
1182
+	 * @throws ReflectionException
1183
+	 */
1184
+	protected function _default_venue_update(EE_Event $event, array $data): bool
1185
+	{
1186
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1187
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1188
+		$venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1189
+		// very important.  If we don't have a venue name...
1190
+		// then we'll get out because not necessary to create empty venue
1191
+		if (empty($data['venue_title'])) {
1192
+			return false;
1193
+		}
1194
+		$venue_array = [
1195
+			'VNU_wp_user'         => $event->get('EVT_wp_user'),
1196
+			'VNU_name'            => $data['venue_title'],
1197
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1198
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1199
+			'VNU_short_desc'      => ! empty($data['venue_short_description'])
1200
+				? $data['venue_short_description']
1201
+				: null,
1202
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1203
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1204
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1205
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1206
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1207
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1208
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1209
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1210
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1211
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1212
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1213
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1214
+			'status'              => 'publish',
1215
+		];
1216
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1217
+		if (! empty($venue_id)) {
1218
+			$update_where  = [$venue_model->primary_key_name() => $venue_id];
1219
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1220
+			// we've gotta make sure that the venue is always attached to a revision..
1221
+			// add_relation_to should take care of making sure that the relation is already present.
1222
+			$event->_add_relation_to($venue_id, 'Venue');
1223
+			return $rows_affected > 0;
1224
+		}
1225
+		// we insert the venue
1226
+		$venue_id = $venue_model->insert($venue_array);
1227
+		$event->_add_relation_to($venue_id, 'Venue');
1228
+		return ! empty($venue_id);
1229
+		// when we have the ancestor come in it's already been handled by the revision save.
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1235
+	 *
1236
+	 * @param EE_Event $event The Event object we're attaching data to
1237
+	 * @param array    $data  The request data from the form
1238
+	 * @return array
1239
+	 * @throws EE_Error
1240
+	 * @throws ReflectionException
1241
+	 * @throws Exception
1242
+	 */
1243
+	protected function _default_tickets_update(EE_Event $event, array $data): array
1244
+	{
1245
+		if ($this->admin_config->useAdvancedEditor()) {
1246
+			return [];
1247
+		}
1248
+		$datetime       = null;
1249
+		$saved_tickets  = [];
1250
+		$event_timezone = $event->get_timezone();
1251
+		$date_formats   = ['Y-m-d', 'h:i a'];
1252
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1253
+			// trim all values to ensure any excess whitespace is removed.
1254
+			$datetime_data                = array_map('trim', $datetime_data);
1255
+			$datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1256
+					? $datetime_data['DTT_EVT_end']
1257
+					: $datetime_data['DTT_EVT_start'];
1258
+			$datetime_values              = [
1259
+				'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1260
+				'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1261
+				'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1262
+				'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1263
+				'DTT_order'     => $row,
1264
+			];
1265
+			// if we have an id then let's get existing object first and then set the new values.
1266
+			//  Otherwise we instantiate a new object for save.
1267
+			if (! empty($datetime_data['DTT_ID'])) {
1268
+				$datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1269
+				if (! $datetime instanceof EE_Datetime) {
1270
+					throw new RuntimeException(
1271
+						sprintf(
1272
+							esc_html__(
1273
+								'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1274
+								'event_espresso'
1275
+							),
1276
+							$datetime_data['DTT_ID']
1277
+						)
1278
+					);
1279
+				}
1280
+				$datetime->set_date_format($date_formats[0]);
1281
+				$datetime->set_time_format($date_formats[1]);
1282
+				foreach ($datetime_values as $field => $value) {
1283
+					$datetime->set($field, $value);
1284
+				}
1285
+			} else {
1286
+				$datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1287
+			}
1288
+			if (! $datetime instanceof EE_Datetime) {
1289
+				throw new RuntimeException(
1290
+					sprintf(
1291
+						esc_html__(
1292
+							'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1293
+							'event_espresso'
1294
+						),
1295
+						print_r($datetime_values, true)
1296
+					)
1297
+				);
1298
+			}
1299
+			// before going any further make sure our dates are setup correctly
1300
+			// so that the end date is always equal or greater than the start date.
1301
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1302
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1303
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1304
+			}
1305
+			$datetime->save();
1306
+			$event->_add_relation_to($datetime, 'Datetime');
1307
+		}
1308
+		// no datetimes get deleted so we don't do any of that logic here.
1309
+		// update tickets next
1310
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1311
+
1312
+		// set up some default start and end dates in case those are not present in the incoming data
1313
+		$default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1314
+		$default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1315
+		// use the start date of the first datetime for the end date
1316
+		$first_datetime   = $event->first_datetime();
1317
+		$default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1318
+
1319
+		// now process the incoming data
1320
+		foreach ($data['edit_tickets'] as $row => $ticket_data) {
1321
+			$update_prices = false;
1322
+			$ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1323
+			// trim inputs to ensure any excess whitespace is removed.
1324
+			$ticket_data   = array_map('trim', $ticket_data);
1325
+			$ticket_values = [
1326
+				'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1327
+				'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1328
+				'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1329
+				'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1330
+				'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1331
+					? $ticket_data['TKT_start_date']
1332
+					: $default_start_date,
1333
+				'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1334
+					? $ticket_data['TKT_end_date']
1335
+					: $default_end_date,
1336
+				'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1337
+									 || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1338
+					? $ticket_data['TKT_qty']
1339
+					: EE_INF,
1340
+				'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1341
+									 || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1342
+					? $ticket_data['TKT_uses']
1343
+					: EE_INF,
1344
+				'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1345
+				'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1346
+				'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1347
+				'TKT_price'       => (float) $ticket_price,
1348
+				'TKT_row'         => $row,
1349
+			];
1350
+			// if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1351
+			// which means in turn that the prices will become new prices as well.
1352
+			if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1353
+				$ticket_values['TKT_ID']         = 0;
1354
+				$ticket_values['TKT_is_default'] = 0;
1355
+				$update_prices                   = true;
1356
+			}
1357
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1358
+			// we actually do our saves ahead of adding any relations because its entirely possible that this
1359
+			// ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1360
+			// keep in mind that if the ticket has been sold (and we have changed pricing information),
1361
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1362
+			if (! empty($ticket_data['TKT_ID'])) {
1363
+				$existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1364
+				if (! $existing_ticket instanceof EE_Ticket) {
1365
+					throw new RuntimeException(
1366
+						sprintf(
1367
+							esc_html__(
1368
+								'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1369
+								'event_espresso'
1370
+							),
1371
+							$ticket_data['TKT_ID']
1372
+						)
1373
+					);
1374
+				}
1375
+				$ticket_sold = $existing_ticket->count_related(
1376
+						'Registration',
1377
+						[
1378
+							[
1379
+								'STS_ID' => [
1380
+									'NOT IN',
1381
+									[RegStatus::INCOMPLETE],
1382
+								],
1383
+							],
1384
+						]
1385
+					) > 0;
1386
+				// let's just check the total price for the existing ticket and determine if it matches the new total price.
1387
+				// if they are different then we create a new ticket (if $ticket_sold)
1388
+				// if they aren't different then we go ahead and modify existing ticket.
1389
+				$create_new_ticket = $ticket_sold
1390
+									 && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1391
+									 && ! $existing_ticket->deleted();
1392
+				$existing_ticket->set_date_format($date_formats[0]);
1393
+				$existing_ticket->set_time_format($date_formats[1]);
1394
+				// set new values
1395
+				foreach ($ticket_values as $field => $value) {
1396
+					if ($field == 'TKT_qty') {
1397
+						$existing_ticket->set_qty($value);
1398
+					} elseif ($field == 'TKT_price') {
1399
+						$existing_ticket->set('TKT_price', $ticket_price);
1400
+					} else {
1401
+						$existing_ticket->set($field, $value);
1402
+					}
1403
+				}
1404
+				$ticket = $existing_ticket;
1405
+				// if $create_new_ticket is false then we can safely update the existing ticket.
1406
+				//  Otherwise we have to create a new ticket.
1407
+				if ($create_new_ticket) {
1408
+					// archive the old ticket first
1409
+					$existing_ticket->set('TKT_deleted', 1);
1410
+					$existing_ticket->save();
1411
+					// make sure this ticket is still recorded in our $saved_tickets
1412
+					// so we don't run it through the regular trash routine.
1413
+					$saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1414
+					// create new ticket that's a copy of the existing except,
1415
+					// (a new id of course and not archived) AND has the new TKT_price associated with it.
1416
+					$new_ticket = clone $existing_ticket;
1417
+					$new_ticket->set('TKT_ID', 0);
1418
+					$new_ticket->set('TKT_deleted', 0);
1419
+					$new_ticket->set('TKT_sold', 0);
1420
+					// now we need to make sure that $new prices are created as well and attached to new ticket.
1421
+					$update_prices = true;
1422
+					$ticket        = $new_ticket;
1423
+				}
1424
+			} else {
1425
+				// no TKT_id so a new ticket
1426
+				$ticket_values['TKT_price'] = $ticket_price;
1427
+				$ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1428
+				$update_prices              = true;
1429
+			}
1430
+			if (! $ticket instanceof EE_Ticket) {
1431
+				throw new RuntimeException(
1432
+					sprintf(
1433
+						esc_html__(
1434
+							'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1435
+							'event_espresso'
1436
+						),
1437
+						print_r($ticket_values, true)
1438
+					)
1439
+				);
1440
+			}
1441
+			// cap ticket qty by datetime reg limits
1442
+			$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1443
+			// update ticket.
1444
+			$ticket->save();
1445
+			// before going any further make sure our dates are setup correctly
1446
+			// so that the end date is always equal or greater than the start date.
1447
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1448
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1449
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1450
+				$ticket->save();
1451
+			}
1452
+			// initially let's add the ticket to the datetime
1453
+			$datetime->_add_relation_to($ticket, 'Ticket');
1454
+			$saved_tickets[ $ticket->ID() ] = $ticket;
1455
+			// add prices to ticket
1456
+			$prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1457
+				? $data['edit_prices'][ $row ]
1458
+				: [];
1459
+			$this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1460
+		}
1461
+		// however now we need to handle permanently deleting tickets via the ui.
1462
+		// Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1463
+		// However, it does allow for deleting tickets that have no tickets sold,
1464
+		// in which case we want to get rid of permanently because there is no need to save in db.
1465
+		$old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1466
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1467
+		foreach ($tickets_removed as $id) {
1468
+			$id = absint($id);
1469
+			// get the ticket for this id
1470
+			$ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1471
+			if (! $ticket_to_remove instanceof EE_Ticket) {
1472
+				continue;
1473
+			}
1474
+			// need to get all the related datetimes on this ticket and remove from every single one of them
1475
+			// (remember this process can ONLY kick off if there are NO tickets sold)
1476
+			$related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1477
+			foreach ($related_datetimes as $related_datetime) {
1478
+				$ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1479
+			}
1480
+			// need to do the same for prices (except these prices can also be deleted because again,
1481
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1482
+			$ticket_to_remove->delete_related_permanently('Price');
1483
+			// finally let's delete this ticket
1484
+			// (which should not be blocked at this point b/c we've removed all our relationships)
1485
+			$ticket_to_remove->delete_permanently();
1486
+		}
1487
+		return [$datetime, $saved_tickets];
1488
+	}
1489
+
1490
+
1491
+	/**
1492
+	 * This attaches a list of given prices to a ticket.
1493
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices)
1494
+	 * because if there is a change in price information on a ticket, a new ticket is created anyways
1495
+	 * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1496
+	 *
1497
+	 * @access  private
1498
+	 * @param array     $prices_data Array of prices from the form.
1499
+	 * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1500
+	 * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1501
+	 * @return  void
1502
+	 * @throws EE_Error
1503
+	 * @throws ReflectionException
1504
+	 */
1505
+	private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1506
+	{
1507
+		$timezone = $ticket->get_timezone();
1508
+		foreach ($prices_data as $row => $price_data) {
1509
+			$price_values = [
1510
+				'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1511
+				'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1512
+				'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1513
+				'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1514
+				'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1515
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1516
+				'PRC_order'      => $row,
1517
+			];
1518
+			if ($new_prices || empty($price_values['PRC_ID'])) {
1519
+				$price_values['PRC_ID'] = 0;
1520
+				$price                  = EE_Price::new_instance($price_values, $timezone);
1521
+			} else {
1522
+				$price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1523
+				// update this price with new values
1524
+				foreach ($price_values as $field => $new_price) {
1525
+					$price->set($field, $new_price);
1526
+				}
1527
+			}
1528
+			if (! $price instanceof EE_Price) {
1529
+				throw new RuntimeException(
1530
+					sprintf(
1531
+						esc_html__(
1532
+							'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1533
+							'event_espresso'
1534
+						),
1535
+						print_r($price_values, true)
1536
+					)
1537
+				);
1538
+			}
1539
+			$price->save();
1540
+			$ticket->_add_relation_to($price, 'Price');
1541
+		}
1542
+	}
1543
+
1544
+
1545
+	/**
1546
+	 * Add in our autosave ajax handlers
1547
+	 */
1548
+	protected function _ee_autosave_create_new()
1549
+	{
1550
+	}
1551
+
1552
+
1553
+	/**
1554
+	 * More autosave handlers.
1555
+	 */
1556
+	protected function _ee_autosave_edit()
1557
+	{
1558
+	}
1559
+
1560
+
1561
+	/**
1562
+	 * @throws EE_Error
1563
+	 * @throws ReflectionException
1564
+	 */
1565
+	private function _generate_publish_box_extra_content()
1566
+	{
1567
+		// load formatter helper
1568
+		// args for getting related registrations
1569
+		$approved_query_args        = [
1570
+			[
1571
+				'REG_deleted' => 0,
1572
+				'STS_ID'      => RegStatus::APPROVED,
1573
+			],
1574
+		];
1575
+		$not_approved_query_args    = [
1576
+			[
1577
+				'REG_deleted' => 0,
1578
+				'STS_ID'      => RegStatus::AWAITING_REVIEW,
1579
+			],
1580
+		];
1581
+		$pending_payment_query_args = [
1582
+			[
1583
+				'REG_deleted' => 0,
1584
+				'STS_ID'      => RegStatus::PENDING_PAYMENT,
1585
+			],
1586
+		];
1587
+		// publish box
1588
+		$publish_box_extra_args = [
1589
+			'view_approved_reg_url'        => add_query_arg(
1590
+				[
1591
+					'action'      => 'default',
1592
+					'event_id'    => $this->_cpt_model_obj->ID(),
1593
+					'_reg_status' => RegStatus::APPROVED,
1594
+					'use_filters' => true,
1595
+				],
1596
+				REG_ADMIN_URL
1597
+			),
1598
+			'view_not_approved_reg_url'    => add_query_arg(
1599
+				[
1600
+					'action'      => 'default',
1601
+					'event_id'    => $this->_cpt_model_obj->ID(),
1602
+					'_reg_status' => RegStatus::AWAITING_REVIEW,
1603
+					'use_filters' => true,
1604
+				],
1605
+				REG_ADMIN_URL
1606
+			),
1607
+			'view_pending_payment_reg_url' => add_query_arg(
1608
+				[
1609
+					'action'      => 'default',
1610
+					'event_id'    => $this->_cpt_model_obj->ID(),
1611
+					'_reg_status' => RegStatus::PENDING_PAYMENT,
1612
+					'use_filters' => true,
1613
+				],
1614
+				REG_ADMIN_URL
1615
+			),
1616
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1617
+				'Registration',
1618
+				$approved_query_args
1619
+			),
1620
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1621
+				'Registration',
1622
+				$not_approved_query_args
1623
+			),
1624
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1625
+				'Registration',
1626
+				$pending_payment_query_args
1627
+			),
1628
+			'misc_pub_section_class'       => apply_filters(
1629
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1630
+				'misc-pub-section'
1631
+			),
1632
+		];
1633
+		ob_start();
1634
+		do_action(
1635
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1636
+			$this->_cpt_model_obj
1637
+		);
1638
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1639
+		// load template
1640
+		EEH_Template::display_template(
1641
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1642
+			$publish_box_extra_args
1643
+		);
1644
+	}
1645
+
1646
+
1647
+	/**
1648
+	 * @return EE_Event
1649
+	 */
1650
+	public function get_event_object()
1651
+	{
1652
+		return $this->_cpt_model_obj;
1653
+	}
1654
+
1655
+
1656
+
1657
+
1658
+	/** METABOXES * */
1659
+	/**
1660
+	 * _register_event_editor_meta_boxes
1661
+	 * add all metaboxes related to the event_editor
1662
+	 *
1663
+	 * @return void
1664
+	 * @throws EE_Error
1665
+	 * @throws ReflectionException
1666
+	 */
1667
+	protected function _register_event_editor_meta_boxes()
1668
+	{
1669
+		$this->verify_cpt_object();
1670
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1671
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1672
+		if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1673
+			$this->addMetaBox(
1674
+				'espresso_event_editor_event_options',
1675
+				esc_html__('Event Registration Options', 'event_espresso'),
1676
+				[$this, 'registration_options_meta_box'],
1677
+				$this->page_slug,
1678
+				'side'
1679
+			);
1680
+		}
1681
+		if (! $use_advanced_editor) {
1682
+			$this->addMetaBox(
1683
+				'espresso_event_editor_tickets',
1684
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1685
+				[$this, 'ticket_metabox'],
1686
+				$this->page_slug,
1687
+				'normal',
1688
+				'high'
1689
+			);
1690
+		} elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1691
+			add_action(
1692
+				'add_meta_boxes_espresso_events',
1693
+				function () {
1694
+					global $current_screen;
1695
+					remove_meta_box('authordiv', $current_screen, 'normal');
1696
+				},
1697
+				99
1698
+			);
1699
+		}
1700
+		// NOTE: if you're looking for other metaboxes in here,
1701
+		// where a metabox has a related management page in the admin
1702
+		// you will find it setup in the related management page's "_Hooks" file.
1703
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1704
+	}
1705
+
1706
+
1707
+	/**
1708
+	 * @throws DomainException
1709
+	 * @throws EE_Error
1710
+	 * @throws ReflectionException
1711
+	 */
1712
+	public function ticket_metabox()
1713
+	{
1714
+		$existing_datetime_ids = $existing_ticket_ids = [];
1715
+		// defaults for template args
1716
+		$template_args = [
1717
+			'ticket_rows'       => '',
1718
+			'total_ticket_rows' => 1,
1719
+			'trash_icon'        => 'dashicons dashicons-lock',
1720
+			'disabled'          => '',
1721
+		];
1722
+		$event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1723
+		/**
1724
+		 * 1. Start with retrieving Datetimes
1725
+		 * 2. Fore each datetime get related tickets
1726
+		 * 3. For each ticket get related prices
1727
+		 */
1728
+		/** @var EEM_Datetime $datetime_model */
1729
+		$datetime_model = EE_Registry::instance()->load_model('Datetime');
1730
+		/** @var EEM_Ticket $datetime_model */
1731
+		$ticket_model = EE_Registry::instance()->load_model('Ticket');
1732
+		$times        = $datetime_model->get_all_event_dates($event_id);
1733
+		/** @type EE_Datetime $first_datetime */
1734
+		$first_datetime = reset($times);
1735
+		// do we get related tickets?
1736
+		if (
1737
+			$first_datetime instanceof EE_Datetime
1738
+			&& $first_datetime->ID() !== 0
1739
+		) {
1740
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1741
+			$template_args['time']   = $first_datetime;
1742
+			$related_tickets         = $first_datetime->tickets(
1743
+				[
1744
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1745
+					'default_where_conditions' => 'none',
1746
+				]
1747
+			);
1748
+			if (! empty($related_tickets)) {
1749
+				$template_args['total_ticket_rows'] = count($related_tickets);
1750
+				$row                                = 0;
1751
+				foreach ($related_tickets as $ticket) {
1752
+					$existing_ticket_ids[]        = $ticket->get('TKT_ID');
1753
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1754
+					$row++;
1755
+				}
1756
+			} else {
1757
+				$template_args['total_ticket_rows'] = 1;
1758
+				/** @type EE_Ticket $ticket */
1759
+				$ticket                       = $ticket_model->create_default_object();
1760
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1761
+			}
1762
+		} else {
1763
+			$template_args['time'] = $times[0];
1764
+			/** @type EE_Ticket[] $tickets */
1765
+			$tickets                      = $ticket_model->get_all_default_tickets();
1766
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1767
+			// NOTE: we're just sending the first default row
1768
+			// (decaf can't manage default tickets so this should be sufficient);
1769
+		}
1770
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1771
+			'event_editor_event_datetimes_help_tab'
1772
+		);
1773
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1774
+		$template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1775
+		$template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1776
+		$template_args['ticket_js_structure']      = $this->_get_ticket_row(
1777
+			$ticket_model->create_default_object(),
1778
+			true
1779
+		);
1780
+		$template                                  = apply_filters(
1781
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1782
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1783
+		);
1784
+		EEH_Template::display_template($template, $template_args);
1785
+	}
1786
+
1787
+
1788
+	/**
1789
+	 * Setup an individual ticket form for the decaf event editor page
1790
+	 *
1791
+	 * @access private
1792
+	 * @param EE_Ticket $ticket   the ticket object
1793
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1794
+	 * @param int       $row
1795
+	 * @return string generated html for the ticket row.
1796
+	 * @throws EE_Error
1797
+	 * @throws ReflectionException
1798
+	 */
1799
+	private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1800
+	{
1801
+		$template_args = [
1802
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1803
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1804
+				? ' tkt-archived'
1805
+				: '',
1806
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1807
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1808
+			'TKT_name'            => $ticket->get('TKT_name'),
1809
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1810
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1811
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1812
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1813
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1814
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1815
+			'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1816
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1817
+				? 'dashicons dashicons-post-trash clickable'
1818
+				: 'dashicons dashicons-lock entity-locked',
1819
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1820
+				: ' disabled=disabled',
1821
+		];
1822
+
1823
+		$price         = $ticket->ID() !== 0
1824
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1825
+			: null;
1826
+		$price         = $price instanceof EE_Price
1827
+			? $price
1828
+			: EEM_Price::instance()->create_default_object();
1829
+		$price_args    = [
1830
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1831
+			'PRC_amount'            => $price->get('PRC_amount'),
1832
+			'PRT_ID'                => $price->get('PRT_ID'),
1833
+			'PRC_ID'                => $price->get('PRC_ID'),
1834
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1835
+		];
1836
+		// make sure we have default start and end dates if skeleton
1837
+		// handle rows that should NOT be empty
1838
+		if (empty($template_args['TKT_start_date'])) {
1839
+			// if empty then the start date will be now.
1840
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1841
+		}
1842
+		if (empty($template_args['TKT_end_date'])) {
1843
+			// get the earliest datetime (if present);
1844
+			$earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1845
+				? $this->_cpt_model_obj->get_first_related(
1846
+					'Datetime',
1847
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1848
+				)
1849
+				: null;
1850
+			$template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1851
+				? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1852
+				: date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1853
+		}
1854
+		$template_args = array_merge($template_args, $price_args);
1855
+		$template      = apply_filters(
1856
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1857
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1858
+			$ticket
1859
+		);
1860
+		return EEH_Template::display_template($template, $template_args, true);
1861
+	}
1862
+
1863
+
1864
+	/**
1865
+	 * @throws EE_Error
1866
+	 * @throws ReflectionException
1867
+	 */
1868
+	public function registration_options_meta_box()
1869
+	{
1870
+		$yes_no_values             = [
1871
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1872
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1873
+		];
1874
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1875
+			[
1876
+				RegStatus::CANCELLED,
1877
+				RegStatus::DECLINED,
1878
+				RegStatus::INCOMPLETE,
1879
+			],
1880
+			true
1881
+		);
1882
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1883
+		$template_args['_event']                          = $this->_cpt_model_obj;
1884
+		$template_args['event']                           = $this->_cpt_model_obj;
1885
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1886
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1887
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1888
+			'default_reg_status',
1889
+			$default_reg_status_values,
1890
+			$this->_cpt_model_obj->default_registration_status(),
1891
+			'',
1892
+			'ee-input-width--reg',
1893
+			false
1894
+		);
1895
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
1896
+			'display_desc',
1897
+			$yes_no_values,
1898
+			$this->_cpt_model_obj->display_description()
1899
+		);
1900
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1901
+			'display_ticket_selector',
1902
+			$yes_no_values,
1903
+			$this->_cpt_model_obj->display_ticket_selector(),
1904
+			'',
1905
+			'ee-input-width--small',
1906
+			false
1907
+		);
1908
+		$template_args['additional_registration_options'] = apply_filters(
1909
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1910
+			'',
1911
+			$template_args,
1912
+			$yes_no_values,
1913
+			$default_reg_status_values
1914
+		);
1915
+		EEH_Template::display_template(
1916
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1917
+			$template_args
1918
+		);
1919
+	}
1920
+
1921
+
1922
+	/**
1923
+	 * _get_events()
1924
+	 * This method simply returns all the events (for the given _view and paging)
1925
+	 *
1926
+	 * @access public
1927
+	 * @param int  $per_page     count of items per page (20 default);
1928
+	 * @param int  $current_page what is the current page being viewed.
1929
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1930
+	 *                           If FALSE then we return an array of event objects
1931
+	 *                           that match the given _view and paging parameters.
1932
+	 * @return array|int         an array of event objects or a count of them.
1933
+	 * @throws Exception
1934
+	 */
1935
+	public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1936
+	{
1937
+		$EEM_Event   = $this->_event_model();
1938
+		$offset      = ($current_page - 1) * $per_page;
1939
+		$limit       = $count ? null : $offset . ',' . $per_page;
1940
+		$orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1941
+		$order       = $this->request->getRequestParam('order', 'DESC');
1942
+		$month_range = $this->request->getRequestParam('month_range');
1943
+		$where  = [];
1944
+		$status = $this->request->getRequestParam('status');
1945
+		$timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1946
+		// determine what post_status our condition will have for the query.
1947
+		switch ($status) {
1948
+			case 'month':
1949
+			case 'today':
1950
+			case null:
1951
+			case 'all':
1952
+				break;
1953
+			case 'draft':
1954
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1955
+				break;
1956
+			default:
1957
+				$where['status'] = $status;
1958
+		}
1959
+		// categories? The default for all categories is -1
1960
+		$category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1961
+		if ($category !== -1) {
1962
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1963
+			$where['Term_Taxonomy.term_id']  = $category;
1964
+		}
1965
+		// date where conditions
1966
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1967
+		if ($month_range) {
1968
+			$where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1969
+		} elseif ($status === 'today') {
1970
+			$DateTime                        = new DateTime(
1971
+				'now',
1972
+				new DateTimeZone($timezone_string)
1973
+			);
1974
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1975
+			$end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1976
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1977
+		} elseif ($status === 'month') {
1978
+			$now                             = date('Y-m-01');
1979
+			$DateTime                        = new DateTime(
1980
+				$now,
1981
+				new DateTimeZone($timezone_string)
1982
+			);
1983
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1984
+			$end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1985
+														->setTime(23, 59, 59)
1986
+														->format(implode(' ', $start_formats));
1987
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1988
+		}
1989
+		if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1990
+			$where['EVT_wp_user'] = get_current_user_id();
1991
+		} else {
1992
+			if (! isset($where['status'])) {
1993
+				if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1994
+					$where['OR'] = [
1995
+						'status*restrict_private' => ['!=', 'private'],
1996
+						'AND'                     => [
1997
+							'status*inclusive' => ['=', 'private'],
1998
+							'EVT_wp_user'      => get_current_user_id(),
1999
+						],
2000
+					];
2001
+				}
2002
+			}
2003
+		}
2004
+		$wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2005
+		if (
2006
+			$wp_user
2007
+			&& $wp_user !== get_current_user_id()
2008
+			&& $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2009
+		) {
2010
+			$where['EVT_wp_user'] = $wp_user;
2011
+		}
2012
+		// search query handling
2013
+		$search_term = $this->request->getRequestParam('s');
2014
+		if ($search_term) {
2015
+			$search_term = '%' . $search_term . '%';
2016
+			$where['OR'] = [
2017
+				'EVT_name'       => ['LIKE', $search_term],
2018
+				'EVT_desc'       => ['LIKE', $search_term],
2019
+				'EVT_short_desc' => ['LIKE', $search_term],
2020
+			];
2021
+		}
2022
+		// filter events by venue.
2023
+		$venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2024
+		if ($venue) {
2025
+			$where['Venue.VNU_ID'] = $venue;
2026
+		}
2027
+		$request_params = $this->request->requestParams();
2028
+		$where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2029
+		$query_params   = apply_filters(
2030
+			'FHEE__Events_Admin_Page__get_events__query_params',
2031
+			[
2032
+				$where,
2033
+				'limit'    => $limit,
2034
+				'order_by' => $orderby,
2035
+				'order'    => $order,
2036
+				'group_by' => 'EVT_ID',
2037
+			],
2038
+			$request_params
2039
+		);
2040
+
2041
+		// let's first check if we have special requests coming in.
2042
+		$active_status = $this->request->getRequestParam('active_status');
2043
+		if ($active_status) {
2044
+			switch ($active_status) {
2045
+				case 'upcoming':
2046
+					return $EEM_Event->get_upcoming_events($query_params, $count);
2047
+				case 'expired':
2048
+					return $EEM_Event->get_expired_events($query_params, $count);
2049
+				case 'active':
2050
+					return $EEM_Event->get_active_events($query_params, $count);
2051
+				case 'inactive':
2052
+					return $EEM_Event->get_inactive_events($query_params, $count);
2053
+			}
2054
+		}
2055
+
2056
+		return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2057
+	}
2058
+
2059
+
2060
+	/**
2061
+	 * @param string $month_range
2062
+	 * @param string $timezone_string
2063
+	 * @return array
2064
+	 * @throws Exception
2065
+	 * @since 5.0.21.p
2066
+	 */
2067
+	public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2068
+	{
2069
+		$timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2070
+		$pieces = explode(' ', $month_range, 3);
2071
+		// simulate the FIRST day of the month, that fixes issues for months like February
2072
+		// where PHP doesn't know what to assume for date.
2073
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2074
+		$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2075
+		$year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2076
+		$DateTime = new DateTime(
2077
+			"$year_r-$month_r-01 00:00:00",
2078
+			new DateTimeZone($timezone_string)
2079
+		);
2080
+		$start    = $DateTime->getTimestamp();
2081
+		// set the datetime to be the end of the month
2082
+		$DateTime->setDate(
2083
+			$year_r,
2084
+			$month_r,
2085
+			$DateTime->format('t')
2086
+		)->setTime(23, 59, 59);
2087
+		$end                             = $DateTime->getTimestamp();
2088
+		return ['BETWEEN', [$start, $end]];
2089
+	}
2090
+
2091
+
2092
+	/**
2093
+	 * handling for WordPress CPT actions (trash, restore, delete)
2094
+	 *
2095
+	 * @param string $post_id
2096
+	 * @throws EE_Error
2097
+	 * @throws ReflectionException
2098
+	 */
2099
+	public function trash_cpt_item($post_id)
2100
+	{
2101
+		$this->request->setRequestParam('EVT_ID', $post_id);
2102
+		$this->_trash_or_restore_event('trash', false);
2103
+	}
2104
+
2105
+
2106
+	/**
2107
+	 * @param string $post_id
2108
+	 * @throws EE_Error
2109
+	 * @throws ReflectionException
2110
+	 */
2111
+	public function restore_cpt_item($post_id)
2112
+	{
2113
+		$this->request->setRequestParam('EVT_ID', $post_id);
2114
+		$this->_trash_or_restore_event('draft', false);
2115
+	}
2116
+
2117
+
2118
+	/**
2119
+	 * @param string $post_id
2120
+	 * @throws EE_Error
2121
+	 * @throws EE_Error
2122
+	 */
2123
+	public function delete_cpt_item($post_id)
2124
+	{
2125
+		throw new EE_Error(
2126
+			esc_html__(
2127
+				'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2128
+				'event_espresso'
2129
+			)
2130
+		);
2131
+		// $this->request->setRequestParam('EVT_ID', $post_id);
2132
+		// $this->_delete_event();
2133
+	}
2134
+
2135
+
2136
+	/**
2137
+	 * _trash_or_restore_event
2138
+	 *
2139
+	 * @access protected
2140
+	 * @param string $event_status
2141
+	 * @param bool   $redirect_after
2142
+	 * @throws EE_Error
2143
+	 * @throws EE_Error
2144
+	 * @throws ReflectionException
2145
+	 */
2146
+	protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2147
+	{
2148
+		// loop thru events
2149
+		if ($this->EVT_ID) {
2150
+			// clean status
2151
+			$event_status = sanitize_key($event_status);
2152
+			// grab status
2153
+			if (! empty($event_status)) {
2154
+				$success = $this->_change_event_status($this->EVT_ID, $event_status);
2155
+			} else {
2156
+				$success = false;
2157
+				$msg     = esc_html__(
2158
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2159
+					'event_espresso'
2160
+				);
2161
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2162
+			}
2163
+		} else {
2164
+			$success = false;
2165
+			$msg     = esc_html__(
2166
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2167
+				'event_espresso'
2168
+			);
2169
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2170
+		}
2171
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2172
+		if ($redirect_after) {
2173
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2174
+		}
2175
+	}
2176
+
2177
+
2178
+	/**
2179
+	 * _trash_or_restore_events
2180
+	 *
2181
+	 * @access protected
2182
+	 * @param string $event_status
2183
+	 * @return void
2184
+	 * @throws EE_Error
2185
+	 * @throws EE_Error
2186
+	 * @throws ReflectionException
2187
+	 */
2188
+	protected function _trash_or_restore_events(string $event_status = 'trash')
2189
+	{
2190
+		// clean status
2191
+		$event_status = sanitize_key($event_status);
2192
+		// grab status
2193
+		if (! empty($event_status)) {
2194
+			$success = true;
2195
+			// determine the event id and set to array.
2196
+			$EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2197
+			// loop thru events
2198
+			foreach ($EVT_IDs as $EVT_ID) {
2199
+				if ($EVT_ID = absint($EVT_ID)) {
2200
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2201
+					$success = $results !== false ? $success : false;
2202
+				} else {
2203
+					$msg = sprintf(
2204
+						esc_html__(
2205
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2206
+							'event_espresso'
2207
+						),
2208
+						$EVT_ID
2209
+					);
2210
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2211
+					$success = false;
2212
+				}
2213
+			}
2214
+		} else {
2215
+			$success = false;
2216
+			$msg     = esc_html__(
2217
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2218
+				'event_espresso'
2219
+			);
2220
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2221
+		}
2222
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2223
+		$success = $success ? 2 : false;
2224
+		$action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2225
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2226
+	}
2227
+
2228
+
2229
+	/**
2230
+	 * @param int    $EVT_ID
2231
+	 * @param string $event_status
2232
+	 * @return bool
2233
+	 * @throws EE_Error
2234
+	 * @throws ReflectionException
2235
+	 */
2236
+	private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2237
+	{
2238
+		// grab event id
2239
+		if (! $EVT_ID) {
2240
+			$msg = esc_html__(
2241
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2242
+				'event_espresso'
2243
+			);
2244
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2245
+			return false;
2246
+		}
2247
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2248
+		// clean status
2249
+		$event_status = sanitize_key($event_status);
2250
+		// grab status
2251
+		if (empty($event_status)) {
2252
+			$msg = esc_html__(
2253
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2254
+				'event_espresso'
2255
+			);
2256
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2257
+			return false;
2258
+		}
2259
+		// was event trashed or restored ?
2260
+		switch ($event_status) {
2261
+			case 'draft':
2262
+				$action = 'restored from the trash';
2263
+				$hook   = 'AHEE_event_restored_from_trash';
2264
+				break;
2265
+			case 'trash':
2266
+				$action = 'moved to the trash';
2267
+				$hook   = 'AHEE_event_moved_to_trash';
2268
+				break;
2269
+			default:
2270
+				$action = 'updated';
2271
+				$hook   = false;
2272
+		}
2273
+		// use class to change status
2274
+		$this->_cpt_model_obj->set_status($event_status);
2275
+		$success = $this->_cpt_model_obj->save();
2276
+		if (! $success) {
2277
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2278
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2279
+			return false;
2280
+		}
2281
+		if ($hook) {
2282
+			do_action($hook);
2283
+			// fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2284
+			// because events side step that and it otherwise won't get called
2285
+			do_action(
2286
+				'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2287
+				$this->_cpt_model_obj,
2288
+				$hook === 'AHEE_event_moved_to_trash',
2289
+				$success
2290
+			);
2291
+		}
2292
+		return true;
2293
+	}
2294
+
2295
+
2296
+	/**
2297
+	 * @param array $event_ids
2298
+	 * @return array
2299
+	 * @since   4.10.23.p
2300
+	 */
2301
+	private function cleanEventIds(array $event_ids): array
2302
+	{
2303
+		return array_map('absint', $event_ids);
2304
+	}
2305
+
2306
+
2307
+	/**
2308
+	 * @return array
2309
+	 * @since   4.10.23.p
2310
+	 */
2311
+	private function getEventIdsFromRequest(): array
2312
+	{
2313
+		if ($this->request->requestParamIsSet('EVT_IDs')) {
2314
+			return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2315
+		} else {
2316
+			return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2317
+		}
2318
+	}
2319
+
2320
+
2321
+	/**
2322
+	 * @param bool $preview_delete
2323
+	 * @throws EE_Error
2324
+	 * @throws ReflectionException
2325
+	 */
2326
+	protected function _delete_event(bool $preview_delete = true)
2327
+	{
2328
+		$this->_delete_events($preview_delete);
2329
+	}
2330
+
2331
+
2332
+	/**
2333
+	 * Gets the tree traversal batch persister.
2334
+	 *
2335
+	 * @return NodeGroupDao
2336
+	 * @throws InvalidArgumentException
2337
+	 * @throws InvalidDataTypeException
2338
+	 * @throws InvalidInterfaceException
2339
+	 * @since 4.10.12.p
2340
+	 */
2341
+	protected function getModelObjNodeGroupPersister(): NodeGroupDao
2342
+	{
2343
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2344
+			$this->model_obj_node_group_persister =
2345
+				$this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2346
+		}
2347
+		return $this->model_obj_node_group_persister;
2348
+	}
2349
+
2350
+
2351
+	/**
2352
+	 * @param bool $preview_delete
2353
+	 * @return void
2354
+	 * @throws EE_Error
2355
+	 * @throws ReflectionException
2356
+	 */
2357
+	protected function _delete_events(bool $preview_delete = true)
2358
+	{
2359
+		$event_ids = $this->getEventIdsFromRequest();
2360
+		if ($preview_delete) {
2361
+			$this->generateDeletionPreview($event_ids);
2362
+		} else {
2363
+			foreach ($event_ids as $event_id) {
2364
+				$event = EEM_Event::instance()->get_one_by_ID($event_id);
2365
+				if ($event instanceof EE_Event) {
2366
+					$event->delete_permanently();
2367
+				}
2368
+			}
2369
+		}
2370
+	}
2371
+
2372
+
2373
+	/**
2374
+	 * @param array $event_ids
2375
+	 */
2376
+	protected function generateDeletionPreview(array $event_ids)
2377
+	{
2378
+		$event_ids = $this->cleanEventIds($event_ids);
2379
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2380
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2381
+		$return_url        = EE_Admin_Page::add_query_args_and_nonce(
2382
+			[
2383
+				'action'            => 'preview_deletion',
2384
+				'deletion_job_code' => $deletion_job_code,
2385
+			],
2386
+			$this->_admin_base_url
2387
+		);
2388
+		EEH_URL::safeRedirectAndExit(
2389
+			EE_Admin_Page::add_query_args_and_nonce(
2390
+				[
2391
+					'page'              => EED_Batch::PAGE_SLUG,
2392
+					'batch'             => EED_Batch::batch_job,
2393
+					'EVT_IDs'           => $event_ids,
2394
+					'deletion_job_code' => $deletion_job_code,
2395
+					'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2396
+					'return_url'        => urlencode($return_url),
2397
+				],
2398
+				admin_url()
2399
+			)
2400
+		);
2401
+	}
2402
+
2403
+
2404
+	/**
2405
+	 * Checks for a POST submission
2406
+	 *
2407
+	 * @since 4.10.12.p
2408
+	 */
2409
+	protected function confirmDeletion()
2410
+	{
2411
+		$deletion_redirect_logic = $this->getLoader()->getShared(
2412
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2413
+		);
2414
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2415
+	}
2416
+
2417
+
2418
+	/**
2419
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2420
+	 *
2421
+	 * @throws EE_Error
2422
+	 * @since 4.10.12.p
2423
+	 */
2424
+	protected function previewDeletion()
2425
+	{
2426
+		$preview_deletion_logic = $this->getLoader()->getShared(
2427
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2428
+		);
2429
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2430
+		$this->display_admin_page_with_no_sidebar();
2431
+	}
2432
+
2433
+
2434
+	/**
2435
+	 * get total number of events
2436
+	 *
2437
+	 * @access public
2438
+	 * @return int
2439
+	 * @throws EE_Error
2440
+	 * @throws EE_Error
2441
+	 * @throws ReflectionException
2442
+	 */
2443
+	public function total_events(): int
2444
+	{
2445
+		return EEM_Event::instance()->count(
2446
+			['caps' => 'read_admin'],
2447
+			'EVT_ID',
2448
+			true
2449
+		);
2450
+	}
2451
+
2452
+
2453
+	/**
2454
+	 * get total number of draft events
2455
+	 *
2456
+	 * @access public
2457
+	 * @return int
2458
+	 * @throws EE_Error
2459
+	 * @throws EE_Error
2460
+	 * @throws ReflectionException
2461
+	 */
2462
+	public function total_events_draft(): int
2463
+	{
2464
+		return EEM_Event::instance()->count(
2465
+			[
2466
+				['status' => ['IN', ['draft', 'auto-draft']]],
2467
+				'caps' => 'read_admin',
2468
+			],
2469
+			'EVT_ID',
2470
+			true
2471
+		);
2472
+	}
2473
+
2474
+
2475
+	/**
2476
+	 * get total number of trashed events
2477
+	 *
2478
+	 * @access public
2479
+	 * @return int
2480
+	 * @throws EE_Error
2481
+	 * @throws EE_Error
2482
+	 * @throws ReflectionException
2483
+	 */
2484
+	public function total_trashed_events(): int
2485
+	{
2486
+		return EEM_Event::instance()->count(
2487
+			[
2488
+				['status' => 'trash'],
2489
+				'caps' => 'read_admin',
2490
+			],
2491
+			'EVT_ID',
2492
+			true
2493
+		);
2494
+	}
2495
+
2496
+
2497
+	/**
2498
+	 *    _default_event_settings
2499
+	 *    This generates the Default Settings Tab
2500
+	 *
2501
+	 * @return void
2502
+	 * @throws DomainException
2503
+	 * @throws EE_Error
2504
+	 * @throws InvalidArgumentException
2505
+	 * @throws InvalidDataTypeException
2506
+	 * @throws InvalidInterfaceException
2507
+	 * @throws ReflectionException
2508
+	 */
2509
+	protected function _default_event_settings()
2510
+	{
2511
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2512
+		$this->_set_publish_post_box_vars();
2513
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
2514
+			$this->_default_event_settings_form()->get_html(),
2515
+			'',
2516
+			'padding'
2517
+		);
2518
+		$this->display_admin_page_with_sidebar();
2519
+	}
2520
+
2521
+
2522
+	/**
2523
+	 * Return the form for event settings.
2524
+	 *
2525
+	 * @return EE_Form_Section_Proper
2526
+	 * @throws EE_Error
2527
+	 * @throws ReflectionException
2528
+	 */
2529
+	protected function _default_event_settings_form(): EE_Form_Section_Proper
2530
+	{
2531
+		$registration_config              = EE_Registry::instance()->CFG->registration;
2532
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2533
+		// exclude
2534
+			[
2535
+				RegStatus::CANCELLED,
2536
+				RegStatus::DECLINED,
2537
+				RegStatus::INCOMPLETE,
2538
+				RegStatus::WAIT_LIST,
2539
+			],
2540
+			true
2541
+		);
2542
+		// setup Advanced Editor ???
2543
+		if (
2544
+			$this->raw_req_action === 'default_event_settings'
2545
+			|| $this->raw_req_action === 'update_default_event_settings'
2546
+		) {
2547
+			$this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2548
+		}
2549
+		return new EE_Form_Section_Proper(
2550
+			[
2551
+				'name'            => 'update_default_event_settings',
2552
+				'html_id'         => 'update_default_event_settings',
2553
+				'html_class'      => 'form-table',
2554
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2555
+				'subsections'     => apply_filters(
2556
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2557
+					[
2558
+						'defaults_section_header' => new EE_Form_Section_HTML(
2559
+							EEH_HTML::h2(
2560
+								esc_html__('Default Settings', 'event_espresso'),
2561
+								'',
2562
+								'ee-admin-settings-hdr'
2563
+							)
2564
+						),
2565
+						'default_reg_status'      => new EE_Select_Input(
2566
+							$registration_stati_for_selection,
2567
+							[
2568
+								'default'         => isset($registration_config->default_STS_ID)
2569
+													 && array_key_exists(
2570
+														 $registration_config->default_STS_ID,
2571
+														 $registration_stati_for_selection
2572
+													 )
2573
+									? sanitize_text_field($registration_config->default_STS_ID)
2574
+									: RegStatus::PENDING_PAYMENT,
2575
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2576
+													 . EEH_Template::get_help_tab_link(
2577
+										'default_settings_status_help_tab'
2578
+									),
2579
+								'html_help_text'  => esc_html__(
2580
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2581
+									'event_espresso'
2582
+								),
2583
+								'html_class'      => 'ee-input-width--small',
2584
+							]
2585
+						),
2586
+						'default_max_tickets'     => new EE_Integer_Input(
2587
+							[
2588
+								'default'         => $registration_config->default_maximum_number_of_tickets
2589
+													 ?? EEM_Event::get_default_additional_limit(),
2590
+								'html_label_text' => esc_html__(
2591
+														 'Default Maximum Tickets Allowed Per Order:',
2592
+														 'event_espresso'
2593
+													 )
2594
+													 . EEH_Template::get_help_tab_link(
2595
+										'default_maximum_tickets_help_tab"'
2596
+									),
2597
+								'html_help_text'  => esc_html__(
2598
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2599
+									'event_espresso'
2600
+								),
2601
+								'html_class'      => 'ee-input-width--tiny',
2602
+							]
2603
+						),
2604
+					]
2605
+				),
2606
+			]
2607
+		);
2608
+	}
2609
+
2610
+
2611
+	/**
2612
+	 * @return void
2613
+	 * @throws EE_Error
2614
+	 * @throws InvalidArgumentException
2615
+	 * @throws InvalidDataTypeException
2616
+	 * @throws InvalidInterfaceException
2617
+	 * @throws ReflectionException
2618
+	 */
2619
+	protected function _update_default_event_settings()
2620
+	{
2621
+		$form = $this->_default_event_settings_form();
2622
+		if ($form->was_submitted()) {
2623
+			$form->receive_form_submission();
2624
+			if ($form->is_valid()) {
2625
+				$registration_config = EE_Registry::instance()->CFG->registration;
2626
+				$valid_data          = $form->valid_data();
2627
+				if (isset($valid_data['default_reg_status'])) {
2628
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2629
+				}
2630
+				if (isset($valid_data['default_max_tickets'])) {
2631
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2632
+				}
2633
+				do_action(
2634
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2635
+					$valid_data,
2636
+					EE_Registry::instance()->CFG,
2637
+					$this
2638
+				);
2639
+				// update because data was valid!
2640
+				EE_Registry::instance()->CFG->update_espresso_config();
2641
+				EE_Error::overwrite_success();
2642
+				EE_Error::add_success(
2643
+					esc_html__('Default Event Settings were updated', 'event_espresso')
2644
+				);
2645
+			}
2646
+		}
2647
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2648
+	}
2649
+
2650
+
2651
+	/*************        Templates        *************
795 2652
      *
796
-     * @return void
797
-     * @throws EE_Error
798
-     * @throws InvalidArgumentException
799
-     * @throws InvalidDataTypeException
800
-     * @throws InvalidInterfaceException
801
-     * @throws ReflectionException
802
-     */
803
-    protected function _create_new_cpt_item()
804
-    {
805
-        $has_timezone_string = get_option('timezone_string');
806
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
807
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
808
-            EE_Error::add_attention(
809
-                sprintf(
810
-                    esc_html__(
811
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
812
-                        'event_espresso'
813
-                    ),
814
-                    '<br>',
815
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
816
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
817
-                    . '</select>',
818
-                    '<button class="button button--secondary timezone-submit">',
819
-                    '</button><span class="spinner"></span>'
820
-                ),
821
-                __FILE__,
822
-                __FUNCTION__,
823
-                __LINE__
824
-            );
825
-        }
826
-        parent::_create_new_cpt_item();
827
-    }
828
-
829
-
830
-    /**
831
-     * Sets the _views property for the default route in this admin page group.
832
-     */
833
-    protected function _set_list_table_views_default()
834
-    {
835
-        $this->_views = [
836
-            'all'   => [
837
-                'slug'        => 'all',
838
-                'label'       => esc_html__('View All Events', 'event_espresso'),
839
-                'count'       => 0,
840
-                'bulk_action' => [
841
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
842
-                ],
843
-            ],
844
-            'draft' => [
845
-                'slug'        => 'draft',
846
-                'label'       => esc_html__('Draft', 'event_espresso'),
847
-                'count'       => 0,
848
-                'bulk_action' => [
849
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
850
-                ],
851
-            ],
852
-        ];
853
-        if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
854
-            $this->_views['trash'] = [
855
-                'slug'        => 'trash',
856
-                'label'       => esc_html__('Trash', 'event_espresso'),
857
-                'count'       => 0,
858
-                'bulk_action' => [
859
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
860
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
861
-                ],
862
-            ];
863
-        }
864
-    }
865
-
866
-
867
-    /**
868
-     * Provides the legend item array for the default list table view.
869
-     *
870
-     * @return array
871
-     * @throws EE_Error
872
-     * @throws EE_Error
873
-     */
874
-    protected function _event_legend_items(): array
875
-    {
876
-        $items    = [
877
-            'view_details'   => [
878
-                'class' => 'dashicons dashicons-visibility',
879
-                'desc'  => esc_html__('View Event', 'event_espresso'),
880
-            ],
881
-            'edit_event'     => [
882
-                'class' => 'dashicons dashicons-calendar-alt',
883
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
884
-            ],
885
-            'view_attendees' => [
886
-                'class' => 'dashicons dashicons-groups',
887
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
888
-            ],
889
-        ];
890
-        $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
891
-        $statuses = [
892
-            'sold_out_status'  => [
893
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
894
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
895
-            ],
896
-            'active_status'    => [
897
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
898
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
899
-            ],
900
-            'upcoming_status'  => [
901
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
902
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
903
-            ],
904
-            'postponed_status' => [
905
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
906
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
907
-            ],
908
-            'cancelled_status' => [
909
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
910
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
911
-            ],
912
-            'expired_status'   => [
913
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
914
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
915
-            ],
916
-            'inactive_status'  => [
917
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
918
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
919
-            ],
920
-        ];
921
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
922
-        return array_merge($items, $statuses);
923
-    }
924
-
925
-
926
-    /**
927
-     * @return EEM_Event
928
-     * @throws EE_Error
929
-     * @throws InvalidArgumentException
930
-     * @throws InvalidDataTypeException
931
-     * @throws InvalidInterfaceException
932
-     * @throws ReflectionException
933
-     */
934
-    private function _event_model(): EEM_Event
935
-    {
936
-        if (! $this->_event_model instanceof EEM_Event) {
937
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
938
-        }
939
-        return $this->_event_model;
940
-    }
941
-
942
-
943
-    /**
944
-     * Adds extra buttons to the WP CPT permalink field row.
945
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
946
-     *
947
-     * @param string      $return    the current html
948
-     * @param int         $id        the post id for the page
949
-     * @param string|null $new_title What the title is
950
-     * @param string|null $new_slug  what the slug is
951
-     * @return string            The new html string for the permalink area
952
-     * @deprecated 5.0.0.p
953
-     * @see        TicketSelectorShortcodeButton::addButton
954
-     */
955
-    public function extra_permalink_field_buttons(
956
-        string $return,
957
-        int $id,
958
-        ?string $new_title,
959
-        ?string $new_slug
960
-    ): string {
961
-        return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
962
-    }
963
-
964
-
965
-    /**
966
-     * _events_overview_list_table
967
-     * This contains the logic for showing the events_overview list
968
-     *
969
-     * @access protected
970
-     * @return void
971
-     * @throws DomainException
972
-     * @throws EE_Error
973
-     * @throws InvalidArgumentException
974
-     * @throws InvalidDataTypeException
975
-     * @throws InvalidInterfaceException
976
-     */
977
-    protected function _events_overview_list_table()
978
-    {
979
-        $after_list_table = [];
980
-        $links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
981
-        $links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
982
-        $links_html       .= EEH_HTML::div(
983
-            EEH_Template::get_button_or_link(
984
-                get_post_type_archive_link(EspressoPostType::EVENTS),
985
-                esc_html__('View Event Archive Page', 'event_espresso'),
986
-                'button button--small button--secondary'
987
-            ),
988
-            '',
989
-            'ee-admin-button-row ee-admin-button-row--align-start'
990
-        );
991
-        $links_html       .= EEH_HTML::divx();
992
-
993
-        $after_list_table['view_event_list_button'] = $links_html;
994
-
995
-        $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
996
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
997
-                'create_new',
998
-                'add',
999
-                [],
1000
-                'add-new-h2'
1001
-            );
1002
-
1003
-        $this->_template_args['after_list_table'] = array_merge(
1004
-            (array) $this->_template_args['after_list_table'],
1005
-            $after_list_table
1006
-        );
1007
-        $this->display_admin_list_table_page_with_no_sidebar();
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * this allows for extra misc actions in the default WP publish box
1013
-     *
1014
-     * @return void
1015
-     * @throws DomainException
1016
-     * @throws EE_Error
1017
-     * @throws InvalidArgumentException
1018
-     * @throws InvalidDataTypeException
1019
-     * @throws InvalidInterfaceException
1020
-     * @throws ReflectionException
1021
-     */
1022
-    public function extra_misc_actions_publish_box()
1023
-    {
1024
-        $this->_generate_publish_box_extra_content();
1025
-    }
1026
-
1027
-
1028
-    /**
1029
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1030
-     * saved.
1031
-     * Typically you would use this to save any additional data.
1032
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1033
-     * ALSO very important.  When a post transitions from scheduled to published,
1034
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1035
-     * other meta saves. So MAKE sure that you handle this accordingly.
1036
-     *
1037
-     * @access protected
1038
-     * @abstract
1039
-     * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1040
-     * @param WP_Post $post    The post object of the cpt that was saved.
1041
-     * @return void
1042
-     * @throws EE_Error
1043
-     * @throws InvalidArgumentException
1044
-     * @throws InvalidDataTypeException
1045
-     * @throws InvalidInterfaceException
1046
-     * @throws ReflectionException
1047
-     */
1048
-    protected function _insert_update_cpt_item($post_id, $post)
1049
-    {
1050
-        if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1051
-            // get out we're not processing an event save.
1052
-            return;
1053
-        }
1054
-        $event_values = [
1055
-            'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1056
-            'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1057
-            'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1058
-        ];
1059
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1060
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1062
-                'display_ticket_selector',
1063
-                false,
1064
-                'bool'
1065
-            );
1066
-            $event_values['EVT_additional_limit']            = min(
1067
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1068
-                $this->request->getRequestParam(
1069
-                    'additional_limit',
1070
-                    EEM_Event::get_default_additional_limit(),
1071
-                    'int'
1072
-                )
1073
-            );
1074
-            $event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1075
-                'EVT_default_registration_status',
1076
-                EE_Registry::instance()->CFG->registration->default_STS_ID
1077
-            );
1078
-
1079
-            $event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1080
-            $event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1081
-            $event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1082
-        } elseif ($post instanceof WP_Post) {
1083
-            $event_values['EVT_name'] = $post->post_title;
1084
-            $event_values['EVT_desc'] = $post->post_content;
1085
-        }
1086
-        // update event
1087
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1088
-        // get event_object for other metaboxes...
1089
-        // though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1090
-        // i have to set up where conditions to override the filters in the model
1091
-        // that filter out auto-draft and inherit statuses so we GET the inherit id!
1092
-        /** @var EE_Event $event */
1093
-        $event = $this->_event_model()->get_one(
1094
-            [
1095
-                [
1096
-                    $this->_event_model()->primary_key_name() => $post_id,
1097
-                    'OR'                                      => [
1098
-                        'status'   => $post->post_status,
1099
-                        // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1100
-                        // but the returned object here has a status of "publish", so use the original post status as well
1101
-                        'status*1' => $this->request->getRequestParam('original_post_status'),
1102
-                    ],
1103
-                    'status' => ['NOT IN', ['auto-draft']],
1104
-                ],
1105
-            ]
1106
-        );
1107
-
1108
-        if (! $event instanceof EE_Event) {
1109
-            return;
1110
-        }
1111
-
1112
-        // the following are default callbacks for event attachment updates
1113
-        // that can be overridden by caffeinated functionality and/or addons.
1114
-        $event_update_callbacks = [];
1115
-        if (! $this->admin_config->useAdvancedEditor()) {
1116
-            $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1117
-            $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1118
-        }
1119
-        $event_update_callbacks = apply_filters(
1120
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1121
-            $event_update_callbacks
1122
-        );
1123
-
1124
-        $att_success = true;
1125
-        foreach ($event_update_callbacks as $e_callback) {
1126
-            $_success = is_callable($e_callback)
1127
-                ? $e_callback($event, $this->request->requestParams())
1128
-                : false;
1129
-            // if ANY of these updates fail then we want the appropriate global error message
1130
-            $att_success = $_success !== false ? $att_success : false;
1131
-        }
1132
-        // any errors?
1133
-        if ($success && $att_success === false) {
1134
-            EE_Error::add_error(
1135
-                esc_html__(
1136
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1137
-                    'event_espresso'
1138
-                ),
1139
-                __FILE__,
1140
-                __FUNCTION__,
1141
-                __LINE__
1142
-            );
1143
-        } elseif ($success === false) {
1144
-            EE_Error::add_error(
1145
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1146
-                __FILE__,
1147
-                __FUNCTION__,
1148
-                __LINE__
1149
-            );
1150
-        }
1151
-    }
1152
-
1153
-
1154
-    /**
1155
-     * @param int $post_id
1156
-     * @param int $revision_id
1157
-     * @throws EE_Error
1158
-     * @throws EE_Error
1159
-     * @throws ReflectionException
1160
-     * @see parent::restore_item()
1161
-     */
1162
-    protected function _restore_cpt_item(int $post_id, int $revision_id)
1163
-    {
1164
-        // copy existing event meta to new post
1165
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1166
-        if ($post_evt instanceof EE_Event) {
1167
-            // meta revision restore
1168
-            $post_evt->restore_revision($revision_id);
1169
-            // related objs restore
1170
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1171
-        }
1172
-    }
1173
-
1174
-
1175
-    /**
1176
-     * Attach the venue to the Event
1177
-     *
1178
-     * @param EE_Event $event Event Object to add the venue to
1179
-     * @param array    $data  The request data from the form
1180
-     * @return bool           Success or fail.
1181
-     * @throws EE_Error
1182
-     * @throws ReflectionException
1183
-     */
1184
-    protected function _default_venue_update(EE_Event $event, array $data): bool
1185
-    {
1186
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1187
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1188
-        $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1189
-        // very important.  If we don't have a venue name...
1190
-        // then we'll get out because not necessary to create empty venue
1191
-        if (empty($data['venue_title'])) {
1192
-            return false;
1193
-        }
1194
-        $venue_array = [
1195
-            'VNU_wp_user'         => $event->get('EVT_wp_user'),
1196
-            'VNU_name'            => $data['venue_title'],
1197
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1198
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1199
-            'VNU_short_desc'      => ! empty($data['venue_short_description'])
1200
-                ? $data['venue_short_description']
1201
-                : null,
1202
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1203
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1204
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1205
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1206
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1207
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1208
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1209
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1210
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1211
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1212
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1213
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1214
-            'status'              => 'publish',
1215
-        ];
1216
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1217
-        if (! empty($venue_id)) {
1218
-            $update_where  = [$venue_model->primary_key_name() => $venue_id];
1219
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1220
-            // we've gotta make sure that the venue is always attached to a revision..
1221
-            // add_relation_to should take care of making sure that the relation is already present.
1222
-            $event->_add_relation_to($venue_id, 'Venue');
1223
-            return $rows_affected > 0;
1224
-        }
1225
-        // we insert the venue
1226
-        $venue_id = $venue_model->insert($venue_array);
1227
-        $event->_add_relation_to($venue_id, 'Venue');
1228
-        return ! empty($venue_id);
1229
-        // when we have the ancestor come in it's already been handled by the revision save.
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1235
-     *
1236
-     * @param EE_Event $event The Event object we're attaching data to
1237
-     * @param array    $data  The request data from the form
1238
-     * @return array
1239
-     * @throws EE_Error
1240
-     * @throws ReflectionException
1241
-     * @throws Exception
1242
-     */
1243
-    protected function _default_tickets_update(EE_Event $event, array $data): array
1244
-    {
1245
-        if ($this->admin_config->useAdvancedEditor()) {
1246
-            return [];
1247
-        }
1248
-        $datetime       = null;
1249
-        $saved_tickets  = [];
1250
-        $event_timezone = $event->get_timezone();
1251
-        $date_formats   = ['Y-m-d', 'h:i a'];
1252
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1253
-            // trim all values to ensure any excess whitespace is removed.
1254
-            $datetime_data                = array_map('trim', $datetime_data);
1255
-            $datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1256
-                    ? $datetime_data['DTT_EVT_end']
1257
-                    : $datetime_data['DTT_EVT_start'];
1258
-            $datetime_values              = [
1259
-                'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1260
-                'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1261
-                'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1262
-                'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1263
-                'DTT_order'     => $row,
1264
-            ];
1265
-            // if we have an id then let's get existing object first and then set the new values.
1266
-            //  Otherwise we instantiate a new object for save.
1267
-            if (! empty($datetime_data['DTT_ID'])) {
1268
-                $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1269
-                if (! $datetime instanceof EE_Datetime) {
1270
-                    throw new RuntimeException(
1271
-                        sprintf(
1272
-                            esc_html__(
1273
-                                'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1274
-                                'event_espresso'
1275
-                            ),
1276
-                            $datetime_data['DTT_ID']
1277
-                        )
1278
-                    );
1279
-                }
1280
-                $datetime->set_date_format($date_formats[0]);
1281
-                $datetime->set_time_format($date_formats[1]);
1282
-                foreach ($datetime_values as $field => $value) {
1283
-                    $datetime->set($field, $value);
1284
-                }
1285
-            } else {
1286
-                $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1287
-            }
1288
-            if (! $datetime instanceof EE_Datetime) {
1289
-                throw new RuntimeException(
1290
-                    sprintf(
1291
-                        esc_html__(
1292
-                            'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1293
-                            'event_espresso'
1294
-                        ),
1295
-                        print_r($datetime_values, true)
1296
-                    )
1297
-                );
1298
-            }
1299
-            // before going any further make sure our dates are setup correctly
1300
-            // so that the end date is always equal or greater than the start date.
1301
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1302
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1303
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1304
-            }
1305
-            $datetime->save();
1306
-            $event->_add_relation_to($datetime, 'Datetime');
1307
-        }
1308
-        // no datetimes get deleted so we don't do any of that logic here.
1309
-        // update tickets next
1310
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1311
-
1312
-        // set up some default start and end dates in case those are not present in the incoming data
1313
-        $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1314
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1315
-        // use the start date of the first datetime for the end date
1316
-        $first_datetime   = $event->first_datetime();
1317
-        $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1318
-
1319
-        // now process the incoming data
1320
-        foreach ($data['edit_tickets'] as $row => $ticket_data) {
1321
-            $update_prices = false;
1322
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1323
-            // trim inputs to ensure any excess whitespace is removed.
1324
-            $ticket_data   = array_map('trim', $ticket_data);
1325
-            $ticket_values = [
1326
-                'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1327
-                'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1328
-                'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1329
-                'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1330
-                'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1331
-                    ? $ticket_data['TKT_start_date']
1332
-                    : $default_start_date,
1333
-                'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1334
-                    ? $ticket_data['TKT_end_date']
1335
-                    : $default_end_date,
1336
-                'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1337
-                                     || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1338
-                    ? $ticket_data['TKT_qty']
1339
-                    : EE_INF,
1340
-                'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1341
-                                     || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1342
-                    ? $ticket_data['TKT_uses']
1343
-                    : EE_INF,
1344
-                'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1345
-                'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1346
-                'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1347
-                'TKT_price'       => (float) $ticket_price,
1348
-                'TKT_row'         => $row,
1349
-            ];
1350
-            // if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1351
-            // which means in turn that the prices will become new prices as well.
1352
-            if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1353
-                $ticket_values['TKT_ID']         = 0;
1354
-                $ticket_values['TKT_is_default'] = 0;
1355
-                $update_prices                   = true;
1356
-            }
1357
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1358
-            // we actually do our saves ahead of adding any relations because its entirely possible that this
1359
-            // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1360
-            // keep in mind that if the ticket has been sold (and we have changed pricing information),
1361
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1362
-            if (! empty($ticket_data['TKT_ID'])) {
1363
-                $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1364
-                if (! $existing_ticket instanceof EE_Ticket) {
1365
-                    throw new RuntimeException(
1366
-                        sprintf(
1367
-                            esc_html__(
1368
-                                'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1369
-                                'event_espresso'
1370
-                            ),
1371
-                            $ticket_data['TKT_ID']
1372
-                        )
1373
-                    );
1374
-                }
1375
-                $ticket_sold = $existing_ticket->count_related(
1376
-                        'Registration',
1377
-                        [
1378
-                            [
1379
-                                'STS_ID' => [
1380
-                                    'NOT IN',
1381
-                                    [RegStatus::INCOMPLETE],
1382
-                                ],
1383
-                            ],
1384
-                        ]
1385
-                    ) > 0;
1386
-                // let's just check the total price for the existing ticket and determine if it matches the new total price.
1387
-                // if they are different then we create a new ticket (if $ticket_sold)
1388
-                // if they aren't different then we go ahead and modify existing ticket.
1389
-                $create_new_ticket = $ticket_sold
1390
-                                     && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1391
-                                     && ! $existing_ticket->deleted();
1392
-                $existing_ticket->set_date_format($date_formats[0]);
1393
-                $existing_ticket->set_time_format($date_formats[1]);
1394
-                // set new values
1395
-                foreach ($ticket_values as $field => $value) {
1396
-                    if ($field == 'TKT_qty') {
1397
-                        $existing_ticket->set_qty($value);
1398
-                    } elseif ($field == 'TKT_price') {
1399
-                        $existing_ticket->set('TKT_price', $ticket_price);
1400
-                    } else {
1401
-                        $existing_ticket->set($field, $value);
1402
-                    }
1403
-                }
1404
-                $ticket = $existing_ticket;
1405
-                // if $create_new_ticket is false then we can safely update the existing ticket.
1406
-                //  Otherwise we have to create a new ticket.
1407
-                if ($create_new_ticket) {
1408
-                    // archive the old ticket first
1409
-                    $existing_ticket->set('TKT_deleted', 1);
1410
-                    $existing_ticket->save();
1411
-                    // make sure this ticket is still recorded in our $saved_tickets
1412
-                    // so we don't run it through the regular trash routine.
1413
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1414
-                    // create new ticket that's a copy of the existing except,
1415
-                    // (a new id of course and not archived) AND has the new TKT_price associated with it.
1416
-                    $new_ticket = clone $existing_ticket;
1417
-                    $new_ticket->set('TKT_ID', 0);
1418
-                    $new_ticket->set('TKT_deleted', 0);
1419
-                    $new_ticket->set('TKT_sold', 0);
1420
-                    // now we need to make sure that $new prices are created as well and attached to new ticket.
1421
-                    $update_prices = true;
1422
-                    $ticket        = $new_ticket;
1423
-                }
1424
-            } else {
1425
-                // no TKT_id so a new ticket
1426
-                $ticket_values['TKT_price'] = $ticket_price;
1427
-                $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1428
-                $update_prices              = true;
1429
-            }
1430
-            if (! $ticket instanceof EE_Ticket) {
1431
-                throw new RuntimeException(
1432
-                    sprintf(
1433
-                        esc_html__(
1434
-                            'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1435
-                            'event_espresso'
1436
-                        ),
1437
-                        print_r($ticket_values, true)
1438
-                    )
1439
-                );
1440
-            }
1441
-            // cap ticket qty by datetime reg limits
1442
-            $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1443
-            // update ticket.
1444
-            $ticket->save();
1445
-            // before going any further make sure our dates are setup correctly
1446
-            // so that the end date is always equal or greater than the start date.
1447
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1448
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1449
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1450
-                $ticket->save();
1451
-            }
1452
-            // initially let's add the ticket to the datetime
1453
-            $datetime->_add_relation_to($ticket, 'Ticket');
1454
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1455
-            // add prices to ticket
1456
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1457
-                ? $data['edit_prices'][ $row ]
1458
-                : [];
1459
-            $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1460
-        }
1461
-        // however now we need to handle permanently deleting tickets via the ui.
1462
-        // Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1463
-        // However, it does allow for deleting tickets that have no tickets sold,
1464
-        // in which case we want to get rid of permanently because there is no need to save in db.
1465
-        $old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1466
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1467
-        foreach ($tickets_removed as $id) {
1468
-            $id = absint($id);
1469
-            // get the ticket for this id
1470
-            $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1471
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1472
-                continue;
1473
-            }
1474
-            // need to get all the related datetimes on this ticket and remove from every single one of them
1475
-            // (remember this process can ONLY kick off if there are NO tickets sold)
1476
-            $related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1477
-            foreach ($related_datetimes as $related_datetime) {
1478
-                $ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1479
-            }
1480
-            // need to do the same for prices (except these prices can also be deleted because again,
1481
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1482
-            $ticket_to_remove->delete_related_permanently('Price');
1483
-            // finally let's delete this ticket
1484
-            // (which should not be blocked at this point b/c we've removed all our relationships)
1485
-            $ticket_to_remove->delete_permanently();
1486
-        }
1487
-        return [$datetime, $saved_tickets];
1488
-    }
1489
-
1490
-
1491
-    /**
1492
-     * This attaches a list of given prices to a ticket.
1493
-     * Note we dont' have to worry about ever removing relationships (or archiving prices)
1494
-     * because if there is a change in price information on a ticket, a new ticket is created anyways
1495
-     * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1496
-     *
1497
-     * @access  private
1498
-     * @param array     $prices_data Array of prices from the form.
1499
-     * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1500
-     * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1501
-     * @return  void
1502
-     * @throws EE_Error
1503
-     * @throws ReflectionException
1504
-     */
1505
-    private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1506
-    {
1507
-        $timezone = $ticket->get_timezone();
1508
-        foreach ($prices_data as $row => $price_data) {
1509
-            $price_values = [
1510
-                'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1511
-                'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1512
-                'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1513
-                'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1514
-                'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1515
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1516
-                'PRC_order'      => $row,
1517
-            ];
1518
-            if ($new_prices || empty($price_values['PRC_ID'])) {
1519
-                $price_values['PRC_ID'] = 0;
1520
-                $price                  = EE_Price::new_instance($price_values, $timezone);
1521
-            } else {
1522
-                $price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1523
-                // update this price with new values
1524
-                foreach ($price_values as $field => $new_price) {
1525
-                    $price->set($field, $new_price);
1526
-                }
1527
-            }
1528
-            if (! $price instanceof EE_Price) {
1529
-                throw new RuntimeException(
1530
-                    sprintf(
1531
-                        esc_html__(
1532
-                            'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1533
-                            'event_espresso'
1534
-                        ),
1535
-                        print_r($price_values, true)
1536
-                    )
1537
-                );
1538
-            }
1539
-            $price->save();
1540
-            $ticket->_add_relation_to($price, 'Price');
1541
-        }
1542
-    }
1543
-
1544
-
1545
-    /**
1546
-     * Add in our autosave ajax handlers
1547
-     */
1548
-    protected function _ee_autosave_create_new()
1549
-    {
1550
-    }
1551
-
1552
-
1553
-    /**
1554
-     * More autosave handlers.
1555
-     */
1556
-    protected function _ee_autosave_edit()
1557
-    {
1558
-    }
1559
-
1560
-
1561
-    /**
1562
-     * @throws EE_Error
1563
-     * @throws ReflectionException
1564
-     */
1565
-    private function _generate_publish_box_extra_content()
1566
-    {
1567
-        // load formatter helper
1568
-        // args for getting related registrations
1569
-        $approved_query_args        = [
1570
-            [
1571
-                'REG_deleted' => 0,
1572
-                'STS_ID'      => RegStatus::APPROVED,
1573
-            ],
1574
-        ];
1575
-        $not_approved_query_args    = [
1576
-            [
1577
-                'REG_deleted' => 0,
1578
-                'STS_ID'      => RegStatus::AWAITING_REVIEW,
1579
-            ],
1580
-        ];
1581
-        $pending_payment_query_args = [
1582
-            [
1583
-                'REG_deleted' => 0,
1584
-                'STS_ID'      => RegStatus::PENDING_PAYMENT,
1585
-            ],
1586
-        ];
1587
-        // publish box
1588
-        $publish_box_extra_args = [
1589
-            'view_approved_reg_url'        => add_query_arg(
1590
-                [
1591
-                    'action'      => 'default',
1592
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1593
-                    '_reg_status' => RegStatus::APPROVED,
1594
-                    'use_filters' => true,
1595
-                ],
1596
-                REG_ADMIN_URL
1597
-            ),
1598
-            'view_not_approved_reg_url'    => add_query_arg(
1599
-                [
1600
-                    'action'      => 'default',
1601
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1602
-                    '_reg_status' => RegStatus::AWAITING_REVIEW,
1603
-                    'use_filters' => true,
1604
-                ],
1605
-                REG_ADMIN_URL
1606
-            ),
1607
-            'view_pending_payment_reg_url' => add_query_arg(
1608
-                [
1609
-                    'action'      => 'default',
1610
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1611
-                    '_reg_status' => RegStatus::PENDING_PAYMENT,
1612
-                    'use_filters' => true,
1613
-                ],
1614
-                REG_ADMIN_URL
1615
-            ),
1616
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1617
-                'Registration',
1618
-                $approved_query_args
1619
-            ),
1620
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1621
-                'Registration',
1622
-                $not_approved_query_args
1623
-            ),
1624
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1625
-                'Registration',
1626
-                $pending_payment_query_args
1627
-            ),
1628
-            'misc_pub_section_class'       => apply_filters(
1629
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1630
-                'misc-pub-section'
1631
-            ),
1632
-        ];
1633
-        ob_start();
1634
-        do_action(
1635
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1636
-            $this->_cpt_model_obj
1637
-        );
1638
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1639
-        // load template
1640
-        EEH_Template::display_template(
1641
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1642
-            $publish_box_extra_args
1643
-        );
1644
-    }
1645
-
1646
-
1647
-    /**
1648
-     * @return EE_Event
1649
-     */
1650
-    public function get_event_object()
1651
-    {
1652
-        return $this->_cpt_model_obj;
1653
-    }
1654
-
1655
-
1656
-
1657
-
1658
-    /** METABOXES * */
1659
-    /**
1660
-     * _register_event_editor_meta_boxes
1661
-     * add all metaboxes related to the event_editor
1662
-     *
1663
-     * @return void
1664
-     * @throws EE_Error
1665
-     * @throws ReflectionException
1666
-     */
1667
-    protected function _register_event_editor_meta_boxes()
1668
-    {
1669
-        $this->verify_cpt_object();
1670
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1671
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1672
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1673
-            $this->addMetaBox(
1674
-                'espresso_event_editor_event_options',
1675
-                esc_html__('Event Registration Options', 'event_espresso'),
1676
-                [$this, 'registration_options_meta_box'],
1677
-                $this->page_slug,
1678
-                'side'
1679
-            );
1680
-        }
1681
-        if (! $use_advanced_editor) {
1682
-            $this->addMetaBox(
1683
-                'espresso_event_editor_tickets',
1684
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1685
-                [$this, 'ticket_metabox'],
1686
-                $this->page_slug,
1687
-                'normal',
1688
-                'high'
1689
-            );
1690
-        } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1691
-            add_action(
1692
-                'add_meta_boxes_espresso_events',
1693
-                function () {
1694
-                    global $current_screen;
1695
-                    remove_meta_box('authordiv', $current_screen, 'normal');
1696
-                },
1697
-                99
1698
-            );
1699
-        }
1700
-        // NOTE: if you're looking for other metaboxes in here,
1701
-        // where a metabox has a related management page in the admin
1702
-        // you will find it setup in the related management page's "_Hooks" file.
1703
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1704
-    }
1705
-
1706
-
1707
-    /**
1708
-     * @throws DomainException
1709
-     * @throws EE_Error
1710
-     * @throws ReflectionException
1711
-     */
1712
-    public function ticket_metabox()
1713
-    {
1714
-        $existing_datetime_ids = $existing_ticket_ids = [];
1715
-        // defaults for template args
1716
-        $template_args = [
1717
-            'ticket_rows'       => '',
1718
-            'total_ticket_rows' => 1,
1719
-            'trash_icon'        => 'dashicons dashicons-lock',
1720
-            'disabled'          => '',
1721
-        ];
1722
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1723
-        /**
1724
-         * 1. Start with retrieving Datetimes
1725
-         * 2. Fore each datetime get related tickets
1726
-         * 3. For each ticket get related prices
1727
-         */
1728
-        /** @var EEM_Datetime $datetime_model */
1729
-        $datetime_model = EE_Registry::instance()->load_model('Datetime');
1730
-        /** @var EEM_Ticket $datetime_model */
1731
-        $ticket_model = EE_Registry::instance()->load_model('Ticket');
1732
-        $times        = $datetime_model->get_all_event_dates($event_id);
1733
-        /** @type EE_Datetime $first_datetime */
1734
-        $first_datetime = reset($times);
1735
-        // do we get related tickets?
1736
-        if (
1737
-            $first_datetime instanceof EE_Datetime
1738
-            && $first_datetime->ID() !== 0
1739
-        ) {
1740
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1741
-            $template_args['time']   = $first_datetime;
1742
-            $related_tickets         = $first_datetime->tickets(
1743
-                [
1744
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1745
-                    'default_where_conditions' => 'none',
1746
-                ]
1747
-            );
1748
-            if (! empty($related_tickets)) {
1749
-                $template_args['total_ticket_rows'] = count($related_tickets);
1750
-                $row                                = 0;
1751
-                foreach ($related_tickets as $ticket) {
1752
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1753
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1754
-                    $row++;
1755
-                }
1756
-            } else {
1757
-                $template_args['total_ticket_rows'] = 1;
1758
-                /** @type EE_Ticket $ticket */
1759
-                $ticket                       = $ticket_model->create_default_object();
1760
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1761
-            }
1762
-        } else {
1763
-            $template_args['time'] = $times[0];
1764
-            /** @type EE_Ticket[] $tickets */
1765
-            $tickets                      = $ticket_model->get_all_default_tickets();
1766
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1767
-            // NOTE: we're just sending the first default row
1768
-            // (decaf can't manage default tickets so this should be sufficient);
1769
-        }
1770
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1771
-            'event_editor_event_datetimes_help_tab'
1772
-        );
1773
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1774
-        $template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1775
-        $template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1776
-        $template_args['ticket_js_structure']      = $this->_get_ticket_row(
1777
-            $ticket_model->create_default_object(),
1778
-            true
1779
-        );
1780
-        $template                                  = apply_filters(
1781
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1782
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1783
-        );
1784
-        EEH_Template::display_template($template, $template_args);
1785
-    }
1786
-
1787
-
1788
-    /**
1789
-     * Setup an individual ticket form for the decaf event editor page
1790
-     *
1791
-     * @access private
1792
-     * @param EE_Ticket $ticket   the ticket object
1793
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1794
-     * @param int       $row
1795
-     * @return string generated html for the ticket row.
1796
-     * @throws EE_Error
1797
-     * @throws ReflectionException
1798
-     */
1799
-    private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1800
-    {
1801
-        $template_args = [
1802
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1803
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1804
-                ? ' tkt-archived'
1805
-                : '',
1806
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1807
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1808
-            'TKT_name'            => $ticket->get('TKT_name'),
1809
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1810
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1811
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1812
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1813
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1814
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1815
-            'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1816
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1817
-                ? 'dashicons dashicons-post-trash clickable'
1818
-                : 'dashicons dashicons-lock entity-locked',
1819
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1820
-                : ' disabled=disabled',
1821
-        ];
1822
-
1823
-        $price         = $ticket->ID() !== 0
1824
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1825
-            : null;
1826
-        $price         = $price instanceof EE_Price
1827
-            ? $price
1828
-            : EEM_Price::instance()->create_default_object();
1829
-        $price_args    = [
1830
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1831
-            'PRC_amount'            => $price->get('PRC_amount'),
1832
-            'PRT_ID'                => $price->get('PRT_ID'),
1833
-            'PRC_ID'                => $price->get('PRC_ID'),
1834
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1835
-        ];
1836
-        // make sure we have default start and end dates if skeleton
1837
-        // handle rows that should NOT be empty
1838
-        if (empty($template_args['TKT_start_date'])) {
1839
-            // if empty then the start date will be now.
1840
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1841
-        }
1842
-        if (empty($template_args['TKT_end_date'])) {
1843
-            // get the earliest datetime (if present);
1844
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1845
-                ? $this->_cpt_model_obj->get_first_related(
1846
-                    'Datetime',
1847
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1848
-                )
1849
-                : null;
1850
-            $template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1851
-                ? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1852
-                : date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1853
-        }
1854
-        $template_args = array_merge($template_args, $price_args);
1855
-        $template      = apply_filters(
1856
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1857
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1858
-            $ticket
1859
-        );
1860
-        return EEH_Template::display_template($template, $template_args, true);
1861
-    }
1862
-
1863
-
1864
-    /**
1865
-     * @throws EE_Error
1866
-     * @throws ReflectionException
1867
-     */
1868
-    public function registration_options_meta_box()
1869
-    {
1870
-        $yes_no_values             = [
1871
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1872
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1873
-        ];
1874
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1875
-            [
1876
-                RegStatus::CANCELLED,
1877
-                RegStatus::DECLINED,
1878
-                RegStatus::INCOMPLETE,
1879
-            ],
1880
-            true
1881
-        );
1882
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1883
-        $template_args['_event']                          = $this->_cpt_model_obj;
1884
-        $template_args['event']                           = $this->_cpt_model_obj;
1885
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1886
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1887
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1888
-            'default_reg_status',
1889
-            $default_reg_status_values,
1890
-            $this->_cpt_model_obj->default_registration_status(),
1891
-            '',
1892
-            'ee-input-width--reg',
1893
-            false
1894
-        );
1895
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1896
-            'display_desc',
1897
-            $yes_no_values,
1898
-            $this->_cpt_model_obj->display_description()
1899
-        );
1900
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1901
-            'display_ticket_selector',
1902
-            $yes_no_values,
1903
-            $this->_cpt_model_obj->display_ticket_selector(),
1904
-            '',
1905
-            'ee-input-width--small',
1906
-            false
1907
-        );
1908
-        $template_args['additional_registration_options'] = apply_filters(
1909
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1910
-            '',
1911
-            $template_args,
1912
-            $yes_no_values,
1913
-            $default_reg_status_values
1914
-        );
1915
-        EEH_Template::display_template(
1916
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1917
-            $template_args
1918
-        );
1919
-    }
1920
-
1921
-
1922
-    /**
1923
-     * _get_events()
1924
-     * This method simply returns all the events (for the given _view and paging)
1925
-     *
1926
-     * @access public
1927
-     * @param int  $per_page     count of items per page (20 default);
1928
-     * @param int  $current_page what is the current page being viewed.
1929
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1930
-     *                           If FALSE then we return an array of event objects
1931
-     *                           that match the given _view and paging parameters.
1932
-     * @return array|int         an array of event objects or a count of them.
1933
-     * @throws Exception
1934
-     */
1935
-    public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1936
-    {
1937
-        $EEM_Event   = $this->_event_model();
1938
-        $offset      = ($current_page - 1) * $per_page;
1939
-        $limit       = $count ? null : $offset . ',' . $per_page;
1940
-        $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1941
-        $order       = $this->request->getRequestParam('order', 'DESC');
1942
-        $month_range = $this->request->getRequestParam('month_range');
1943
-        $where  = [];
1944
-        $status = $this->request->getRequestParam('status');
1945
-        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1946
-        // determine what post_status our condition will have for the query.
1947
-        switch ($status) {
1948
-            case 'month':
1949
-            case 'today':
1950
-            case null:
1951
-            case 'all':
1952
-                break;
1953
-            case 'draft':
1954
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1955
-                break;
1956
-            default:
1957
-                $where['status'] = $status;
1958
-        }
1959
-        // categories? The default for all categories is -1
1960
-        $category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1961
-        if ($category !== -1) {
1962
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1963
-            $where['Term_Taxonomy.term_id']  = $category;
1964
-        }
1965
-        // date where conditions
1966
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1967
-        if ($month_range) {
1968
-            $where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1969
-        } elseif ($status === 'today') {
1970
-            $DateTime                        = new DateTime(
1971
-                'now',
1972
-                new DateTimeZone($timezone_string)
1973
-            );
1974
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1975
-            $end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1976
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1977
-        } elseif ($status === 'month') {
1978
-            $now                             = date('Y-m-01');
1979
-            $DateTime                        = new DateTime(
1980
-                $now,
1981
-                new DateTimeZone($timezone_string)
1982
-            );
1983
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1984
-            $end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1985
-                                                        ->setTime(23, 59, 59)
1986
-                                                        ->format(implode(' ', $start_formats));
1987
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1988
-        }
1989
-        if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1990
-            $where['EVT_wp_user'] = get_current_user_id();
1991
-        } else {
1992
-            if (! isset($where['status'])) {
1993
-                if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1994
-                    $where['OR'] = [
1995
-                        'status*restrict_private' => ['!=', 'private'],
1996
-                        'AND'                     => [
1997
-                            'status*inclusive' => ['=', 'private'],
1998
-                            'EVT_wp_user'      => get_current_user_id(),
1999
-                        ],
2000
-                    ];
2001
-                }
2002
-            }
2003
-        }
2004
-        $wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2005
-        if (
2006
-            $wp_user
2007
-            && $wp_user !== get_current_user_id()
2008
-            && $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2009
-        ) {
2010
-            $where['EVT_wp_user'] = $wp_user;
2011
-        }
2012
-        // search query handling
2013
-        $search_term = $this->request->getRequestParam('s');
2014
-        if ($search_term) {
2015
-            $search_term = '%' . $search_term . '%';
2016
-            $where['OR'] = [
2017
-                'EVT_name'       => ['LIKE', $search_term],
2018
-                'EVT_desc'       => ['LIKE', $search_term],
2019
-                'EVT_short_desc' => ['LIKE', $search_term],
2020
-            ];
2021
-        }
2022
-        // filter events by venue.
2023
-        $venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2024
-        if ($venue) {
2025
-            $where['Venue.VNU_ID'] = $venue;
2026
-        }
2027
-        $request_params = $this->request->requestParams();
2028
-        $where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2029
-        $query_params   = apply_filters(
2030
-            'FHEE__Events_Admin_Page__get_events__query_params',
2031
-            [
2032
-                $where,
2033
-                'limit'    => $limit,
2034
-                'order_by' => $orderby,
2035
-                'order'    => $order,
2036
-                'group_by' => 'EVT_ID',
2037
-            ],
2038
-            $request_params
2039
-        );
2040
-
2041
-        // let's first check if we have special requests coming in.
2042
-        $active_status = $this->request->getRequestParam('active_status');
2043
-        if ($active_status) {
2044
-            switch ($active_status) {
2045
-                case 'upcoming':
2046
-                    return $EEM_Event->get_upcoming_events($query_params, $count);
2047
-                case 'expired':
2048
-                    return $EEM_Event->get_expired_events($query_params, $count);
2049
-                case 'active':
2050
-                    return $EEM_Event->get_active_events($query_params, $count);
2051
-                case 'inactive':
2052
-                    return $EEM_Event->get_inactive_events($query_params, $count);
2053
-            }
2054
-        }
2055
-
2056
-        return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2057
-    }
2058
-
2059
-
2060
-    /**
2061
-     * @param string $month_range
2062
-     * @param string $timezone_string
2063
-     * @return array
2064
-     * @throws Exception
2065
-     * @since 5.0.21.p
2066
-     */
2067
-    public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2068
-    {
2069
-        $timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2070
-        $pieces = explode(' ', $month_range, 3);
2071
-        // simulate the FIRST day of the month, that fixes issues for months like February
2072
-        // where PHP doesn't know what to assume for date.
2073
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2074
-        $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2075
-        $year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2076
-        $DateTime = new DateTime(
2077
-            "$year_r-$month_r-01 00:00:00",
2078
-            new DateTimeZone($timezone_string)
2079
-        );
2080
-        $start    = $DateTime->getTimestamp();
2081
-        // set the datetime to be the end of the month
2082
-        $DateTime->setDate(
2083
-            $year_r,
2084
-            $month_r,
2085
-            $DateTime->format('t')
2086
-        )->setTime(23, 59, 59);
2087
-        $end                             = $DateTime->getTimestamp();
2088
-        return ['BETWEEN', [$start, $end]];
2089
-    }
2090
-
2091
-
2092
-    /**
2093
-     * handling for WordPress CPT actions (trash, restore, delete)
2094
-     *
2095
-     * @param string $post_id
2096
-     * @throws EE_Error
2097
-     * @throws ReflectionException
2098
-     */
2099
-    public function trash_cpt_item($post_id)
2100
-    {
2101
-        $this->request->setRequestParam('EVT_ID', $post_id);
2102
-        $this->_trash_or_restore_event('trash', false);
2103
-    }
2104
-
2105
-
2106
-    /**
2107
-     * @param string $post_id
2108
-     * @throws EE_Error
2109
-     * @throws ReflectionException
2110
-     */
2111
-    public function restore_cpt_item($post_id)
2112
-    {
2113
-        $this->request->setRequestParam('EVT_ID', $post_id);
2114
-        $this->_trash_or_restore_event('draft', false);
2115
-    }
2116
-
2117
-
2118
-    /**
2119
-     * @param string $post_id
2120
-     * @throws EE_Error
2121
-     * @throws EE_Error
2122
-     */
2123
-    public function delete_cpt_item($post_id)
2124
-    {
2125
-        throw new EE_Error(
2126
-            esc_html__(
2127
-                'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2128
-                'event_espresso'
2129
-            )
2130
-        );
2131
-        // $this->request->setRequestParam('EVT_ID', $post_id);
2132
-        // $this->_delete_event();
2133
-    }
2134
-
2135
-
2136
-    /**
2137
-     * _trash_or_restore_event
2138
-     *
2139
-     * @access protected
2140
-     * @param string $event_status
2141
-     * @param bool   $redirect_after
2142
-     * @throws EE_Error
2143
-     * @throws EE_Error
2144
-     * @throws ReflectionException
2145
-     */
2146
-    protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2147
-    {
2148
-        // loop thru events
2149
-        if ($this->EVT_ID) {
2150
-            // clean status
2151
-            $event_status = sanitize_key($event_status);
2152
-            // grab status
2153
-            if (! empty($event_status)) {
2154
-                $success = $this->_change_event_status($this->EVT_ID, $event_status);
2155
-            } else {
2156
-                $success = false;
2157
-                $msg     = esc_html__(
2158
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2159
-                    'event_espresso'
2160
-                );
2161
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2162
-            }
2163
-        } else {
2164
-            $success = false;
2165
-            $msg     = esc_html__(
2166
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2167
-                'event_espresso'
2168
-            );
2169
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2170
-        }
2171
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2172
-        if ($redirect_after) {
2173
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2174
-        }
2175
-    }
2176
-
2177
-
2178
-    /**
2179
-     * _trash_or_restore_events
2180
-     *
2181
-     * @access protected
2182
-     * @param string $event_status
2183
-     * @return void
2184
-     * @throws EE_Error
2185
-     * @throws EE_Error
2186
-     * @throws ReflectionException
2187
-     */
2188
-    protected function _trash_or_restore_events(string $event_status = 'trash')
2189
-    {
2190
-        // clean status
2191
-        $event_status = sanitize_key($event_status);
2192
-        // grab status
2193
-        if (! empty($event_status)) {
2194
-            $success = true;
2195
-            // determine the event id and set to array.
2196
-            $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2197
-            // loop thru events
2198
-            foreach ($EVT_IDs as $EVT_ID) {
2199
-                if ($EVT_ID = absint($EVT_ID)) {
2200
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2201
-                    $success = $results !== false ? $success : false;
2202
-                } else {
2203
-                    $msg = sprintf(
2204
-                        esc_html__(
2205
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2206
-                            'event_espresso'
2207
-                        ),
2208
-                        $EVT_ID
2209
-                    );
2210
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2211
-                    $success = false;
2212
-                }
2213
-            }
2214
-        } else {
2215
-            $success = false;
2216
-            $msg     = esc_html__(
2217
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2218
-                'event_espresso'
2219
-            );
2220
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2221
-        }
2222
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2223
-        $success = $success ? 2 : false;
2224
-        $action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2225
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2226
-    }
2227
-
2228
-
2229
-    /**
2230
-     * @param int    $EVT_ID
2231
-     * @param string $event_status
2232
-     * @return bool
2233
-     * @throws EE_Error
2234
-     * @throws ReflectionException
2235
-     */
2236
-    private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2237
-    {
2238
-        // grab event id
2239
-        if (! $EVT_ID) {
2240
-            $msg = esc_html__(
2241
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2242
-                'event_espresso'
2243
-            );
2244
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2245
-            return false;
2246
-        }
2247
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2248
-        // clean status
2249
-        $event_status = sanitize_key($event_status);
2250
-        // grab status
2251
-        if (empty($event_status)) {
2252
-            $msg = esc_html__(
2253
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2254
-                'event_espresso'
2255
-            );
2256
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2257
-            return false;
2258
-        }
2259
-        // was event trashed or restored ?
2260
-        switch ($event_status) {
2261
-            case 'draft':
2262
-                $action = 'restored from the trash';
2263
-                $hook   = 'AHEE_event_restored_from_trash';
2264
-                break;
2265
-            case 'trash':
2266
-                $action = 'moved to the trash';
2267
-                $hook   = 'AHEE_event_moved_to_trash';
2268
-                break;
2269
-            default:
2270
-                $action = 'updated';
2271
-                $hook   = false;
2272
-        }
2273
-        // use class to change status
2274
-        $this->_cpt_model_obj->set_status($event_status);
2275
-        $success = $this->_cpt_model_obj->save();
2276
-        if (! $success) {
2277
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2278
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2279
-            return false;
2280
-        }
2281
-        if ($hook) {
2282
-            do_action($hook);
2283
-            // fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2284
-            // because events side step that and it otherwise won't get called
2285
-            do_action(
2286
-                'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2287
-                $this->_cpt_model_obj,
2288
-                $hook === 'AHEE_event_moved_to_trash',
2289
-                $success
2290
-            );
2291
-        }
2292
-        return true;
2293
-    }
2294
-
2295
-
2296
-    /**
2297
-     * @param array $event_ids
2298
-     * @return array
2299
-     * @since   4.10.23.p
2300
-     */
2301
-    private function cleanEventIds(array $event_ids): array
2302
-    {
2303
-        return array_map('absint', $event_ids);
2304
-    }
2305
-
2306
-
2307
-    /**
2308
-     * @return array
2309
-     * @since   4.10.23.p
2310
-     */
2311
-    private function getEventIdsFromRequest(): array
2312
-    {
2313
-        if ($this->request->requestParamIsSet('EVT_IDs')) {
2314
-            return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2315
-        } else {
2316
-            return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2317
-        }
2318
-    }
2319
-
2320
-
2321
-    /**
2322
-     * @param bool $preview_delete
2323
-     * @throws EE_Error
2324
-     * @throws ReflectionException
2325
-     */
2326
-    protected function _delete_event(bool $preview_delete = true)
2327
-    {
2328
-        $this->_delete_events($preview_delete);
2329
-    }
2330
-
2331
-
2332
-    /**
2333
-     * Gets the tree traversal batch persister.
2334
-     *
2335
-     * @return NodeGroupDao
2336
-     * @throws InvalidArgumentException
2337
-     * @throws InvalidDataTypeException
2338
-     * @throws InvalidInterfaceException
2339
-     * @since 4.10.12.p
2340
-     */
2341
-    protected function getModelObjNodeGroupPersister(): NodeGroupDao
2342
-    {
2343
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2344
-            $this->model_obj_node_group_persister =
2345
-                $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2346
-        }
2347
-        return $this->model_obj_node_group_persister;
2348
-    }
2349
-
2350
-
2351
-    /**
2352
-     * @param bool $preview_delete
2353
-     * @return void
2354
-     * @throws EE_Error
2355
-     * @throws ReflectionException
2356
-     */
2357
-    protected function _delete_events(bool $preview_delete = true)
2358
-    {
2359
-        $event_ids = $this->getEventIdsFromRequest();
2360
-        if ($preview_delete) {
2361
-            $this->generateDeletionPreview($event_ids);
2362
-        } else {
2363
-            foreach ($event_ids as $event_id) {
2364
-                $event = EEM_Event::instance()->get_one_by_ID($event_id);
2365
-                if ($event instanceof EE_Event) {
2366
-                    $event->delete_permanently();
2367
-                }
2368
-            }
2369
-        }
2370
-    }
2371
-
2372
-
2373
-    /**
2374
-     * @param array $event_ids
2375
-     */
2376
-    protected function generateDeletionPreview(array $event_ids)
2377
-    {
2378
-        $event_ids = $this->cleanEventIds($event_ids);
2379
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2380
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2381
-        $return_url        = EE_Admin_Page::add_query_args_and_nonce(
2382
-            [
2383
-                'action'            => 'preview_deletion',
2384
-                'deletion_job_code' => $deletion_job_code,
2385
-            ],
2386
-            $this->_admin_base_url
2387
-        );
2388
-        EEH_URL::safeRedirectAndExit(
2389
-            EE_Admin_Page::add_query_args_and_nonce(
2390
-                [
2391
-                    'page'              => EED_Batch::PAGE_SLUG,
2392
-                    'batch'             => EED_Batch::batch_job,
2393
-                    'EVT_IDs'           => $event_ids,
2394
-                    'deletion_job_code' => $deletion_job_code,
2395
-                    'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2396
-                    'return_url'        => urlencode($return_url),
2397
-                ],
2398
-                admin_url()
2399
-            )
2400
-        );
2401
-    }
2402
-
2403
-
2404
-    /**
2405
-     * Checks for a POST submission
2406
-     *
2407
-     * @since 4.10.12.p
2408
-     */
2409
-    protected function confirmDeletion()
2410
-    {
2411
-        $deletion_redirect_logic = $this->getLoader()->getShared(
2412
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2413
-        );
2414
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2415
-    }
2416
-
2417
-
2418
-    /**
2419
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2420
-     *
2421
-     * @throws EE_Error
2422
-     * @since 4.10.12.p
2423
-     */
2424
-    protected function previewDeletion()
2425
-    {
2426
-        $preview_deletion_logic = $this->getLoader()->getShared(
2427
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2428
-        );
2429
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2430
-        $this->display_admin_page_with_no_sidebar();
2431
-    }
2432
-
2433
-
2434
-    /**
2435
-     * get total number of events
2436
-     *
2437
-     * @access public
2438
-     * @return int
2439
-     * @throws EE_Error
2440
-     * @throws EE_Error
2441
-     * @throws ReflectionException
2442
-     */
2443
-    public function total_events(): int
2444
-    {
2445
-        return EEM_Event::instance()->count(
2446
-            ['caps' => 'read_admin'],
2447
-            'EVT_ID',
2448
-            true
2449
-        );
2450
-    }
2451
-
2452
-
2453
-    /**
2454
-     * get total number of draft events
2455
-     *
2456
-     * @access public
2457
-     * @return int
2458
-     * @throws EE_Error
2459
-     * @throws EE_Error
2460
-     * @throws ReflectionException
2461
-     */
2462
-    public function total_events_draft(): int
2463
-    {
2464
-        return EEM_Event::instance()->count(
2465
-            [
2466
-                ['status' => ['IN', ['draft', 'auto-draft']]],
2467
-                'caps' => 'read_admin',
2468
-            ],
2469
-            'EVT_ID',
2470
-            true
2471
-        );
2472
-    }
2473
-
2474
-
2475
-    /**
2476
-     * get total number of trashed events
2477
-     *
2478
-     * @access public
2479
-     * @return int
2480
-     * @throws EE_Error
2481
-     * @throws EE_Error
2482
-     * @throws ReflectionException
2483
-     */
2484
-    public function total_trashed_events(): int
2485
-    {
2486
-        return EEM_Event::instance()->count(
2487
-            [
2488
-                ['status' => 'trash'],
2489
-                'caps' => 'read_admin',
2490
-            ],
2491
-            'EVT_ID',
2492
-            true
2493
-        );
2494
-    }
2495
-
2496
-
2497
-    /**
2498
-     *    _default_event_settings
2499
-     *    This generates the Default Settings Tab
2500
-     *
2501
-     * @return void
2502
-     * @throws DomainException
2503
-     * @throws EE_Error
2504
-     * @throws InvalidArgumentException
2505
-     * @throws InvalidDataTypeException
2506
-     * @throws InvalidInterfaceException
2507
-     * @throws ReflectionException
2508
-     */
2509
-    protected function _default_event_settings()
2510
-    {
2511
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2512
-        $this->_set_publish_post_box_vars();
2513
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
2514
-            $this->_default_event_settings_form()->get_html(),
2515
-            '',
2516
-            'padding'
2517
-        );
2518
-        $this->display_admin_page_with_sidebar();
2519
-    }
2520
-
2521
-
2522
-    /**
2523
-     * Return the form for event settings.
2524
-     *
2525
-     * @return EE_Form_Section_Proper
2526
-     * @throws EE_Error
2527
-     * @throws ReflectionException
2528
-     */
2529
-    protected function _default_event_settings_form(): EE_Form_Section_Proper
2530
-    {
2531
-        $registration_config              = EE_Registry::instance()->CFG->registration;
2532
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2533
-        // exclude
2534
-            [
2535
-                RegStatus::CANCELLED,
2536
-                RegStatus::DECLINED,
2537
-                RegStatus::INCOMPLETE,
2538
-                RegStatus::WAIT_LIST,
2539
-            ],
2540
-            true
2541
-        );
2542
-        // setup Advanced Editor ???
2543
-        if (
2544
-            $this->raw_req_action === 'default_event_settings'
2545
-            || $this->raw_req_action === 'update_default_event_settings'
2546
-        ) {
2547
-            $this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2548
-        }
2549
-        return new EE_Form_Section_Proper(
2550
-            [
2551
-                'name'            => 'update_default_event_settings',
2552
-                'html_id'         => 'update_default_event_settings',
2553
-                'html_class'      => 'form-table',
2554
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2555
-                'subsections'     => apply_filters(
2556
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2557
-                    [
2558
-                        'defaults_section_header' => new EE_Form_Section_HTML(
2559
-                            EEH_HTML::h2(
2560
-                                esc_html__('Default Settings', 'event_espresso'),
2561
-                                '',
2562
-                                'ee-admin-settings-hdr'
2563
-                            )
2564
-                        ),
2565
-                        'default_reg_status'      => new EE_Select_Input(
2566
-                            $registration_stati_for_selection,
2567
-                            [
2568
-                                'default'         => isset($registration_config->default_STS_ID)
2569
-                                                     && array_key_exists(
2570
-                                                         $registration_config->default_STS_ID,
2571
-                                                         $registration_stati_for_selection
2572
-                                                     )
2573
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2574
-                                    : RegStatus::PENDING_PAYMENT,
2575
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2576
-                                                     . EEH_Template::get_help_tab_link(
2577
-                                        'default_settings_status_help_tab'
2578
-                                    ),
2579
-                                'html_help_text'  => esc_html__(
2580
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2581
-                                    'event_espresso'
2582
-                                ),
2583
-                                'html_class'      => 'ee-input-width--small',
2584
-                            ]
2585
-                        ),
2586
-                        'default_max_tickets'     => new EE_Integer_Input(
2587
-                            [
2588
-                                'default'         => $registration_config->default_maximum_number_of_tickets
2589
-                                                     ?? EEM_Event::get_default_additional_limit(),
2590
-                                'html_label_text' => esc_html__(
2591
-                                                         'Default Maximum Tickets Allowed Per Order:',
2592
-                                                         'event_espresso'
2593
-                                                     )
2594
-                                                     . EEH_Template::get_help_tab_link(
2595
-                                        'default_maximum_tickets_help_tab"'
2596
-                                    ),
2597
-                                'html_help_text'  => esc_html__(
2598
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2599
-                                    'event_espresso'
2600
-                                ),
2601
-                                'html_class'      => 'ee-input-width--tiny',
2602
-                            ]
2603
-                        ),
2604
-                    ]
2605
-                ),
2606
-            ]
2607
-        );
2608
-    }
2609
-
2610
-
2611
-    /**
2612
-     * @return void
2613
-     * @throws EE_Error
2614
-     * @throws InvalidArgumentException
2615
-     * @throws InvalidDataTypeException
2616
-     * @throws InvalidInterfaceException
2617
-     * @throws ReflectionException
2618
-     */
2619
-    protected function _update_default_event_settings()
2620
-    {
2621
-        $form = $this->_default_event_settings_form();
2622
-        if ($form->was_submitted()) {
2623
-            $form->receive_form_submission();
2624
-            if ($form->is_valid()) {
2625
-                $registration_config = EE_Registry::instance()->CFG->registration;
2626
-                $valid_data          = $form->valid_data();
2627
-                if (isset($valid_data['default_reg_status'])) {
2628
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2629
-                }
2630
-                if (isset($valid_data['default_max_tickets'])) {
2631
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2632
-                }
2633
-                do_action(
2634
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2635
-                    $valid_data,
2636
-                    EE_Registry::instance()->CFG,
2637
-                    $this
2638
-                );
2639
-                // update because data was valid!
2640
-                EE_Registry::instance()->CFG->update_espresso_config();
2641
-                EE_Error::overwrite_success();
2642
-                EE_Error::add_success(
2643
-                    esc_html__('Default Event Settings were updated', 'event_espresso')
2644
-                );
2645
-            }
2646
-        }
2647
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2648
-    }
2649
-
2650
-
2651
-    /*************        Templates        *************
2652
-     *
2653
-     * @throws EE_Error
2654
-     */
2655
-    protected function _template_settings()
2656
-    {
2657
-        $this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2658
-        $this->_template_args['preview_img']  = '<img src="'
2659
-                                                . EVENTS_ASSETS_URL
2660
-                                                . '/images/'
2661
-                                                . 'caffeinated_template_features.jpg" alt="'
2662
-                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2663
-                                                . '" />';
2664
-        $this->_template_args['preview_text'] = '<strong>'
2665
-                                                . esc_html__(
2666
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2667
-                                                    'event_espresso'
2668
-                                                ) . '</strong>';
2669
-        $this->display_admin_caf_preview_page('template_settings_tab');
2670
-    }
2671
-
2672
-
2673
-    /** Event Category Stuff **/
2674
-    /**
2675
-     * set the _category property with the category object for the loaded page.
2676
-     *
2677
-     * @access private
2678
-     * @return void
2679
-     */
2680
-    private function _set_category_object()
2681
-    {
2682
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2683
-            return;
2684
-        } //already have the category object so get out.
2685
-        // set default category object
2686
-        $this->_set_empty_category_object();
2687
-        // only set if we've got an id
2688
-        $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2689
-        if (! $category_ID) {
2690
-            return;
2691
-        }
2692
-        $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2693
-        if (! empty($term)) {
2694
-            $this->_category->category_name       = $term->name;
2695
-            $this->_category->category_identifier = $term->slug;
2696
-            $this->_category->category_desc       = $term->description;
2697
-            $this->_category->id                  = $term->term_id;
2698
-            $this->_category->parent              = $term->parent;
2699
-        }
2700
-    }
2701
-
2702
-
2703
-    /**
2704
-     * Clears out category properties.
2705
-     */
2706
-    private function _set_empty_category_object()
2707
-    {
2708
-        $this->_category                = new stdClass();
2709
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2710
-        $this->_category->id            = $this->_category->parent = 0;
2711
-    }
2712
-
2713
-
2714
-    /**
2715
-     * @throws DomainException
2716
-     * @throws EE_Error
2717
-     * @throws InvalidArgumentException
2718
-     * @throws InvalidDataTypeException
2719
-     * @throws InvalidInterfaceException
2720
-     */
2721
-    protected function _category_list_table()
2722
-    {
2723
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2724
-        $this->_admin_page_title .= ' ';
2725
-        $this->_admin_page_title .= $this->get_action_link_or_button(
2726
-            'add_category',
2727
-            'add_category',
2728
-            [],
2729
-            'add-new-h2'
2730
-        );
2731
-        $this->display_admin_list_table_page_with_sidebar();
2732
-    }
2733
-
2734
-
2735
-    /**
2736
-     * Output category details view.
2737
-     *
2738
-     * @throws EE_Error
2739
-     * @throws EE_Error
2740
-     */
2741
-    protected function _category_details($view)
2742
-    {
2743
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2744
-        $this->_set_add_edit_form_tags($route);
2745
-        $this->_set_category_object();
2746
-        $id            = ! empty($this->_category->id) ? $this->_category->id : '';
2747
-        $delete_action = 'delete_category';
2748
-        // custom redirect
2749
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2750
-            ['action' => 'category_list'],
2751
-            $this->_admin_base_url
2752
-        );
2753
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2754
-        // take care of contents
2755
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2756
-        $this->display_admin_page_with_sidebar();
2757
-    }
2758
-
2759
-
2760
-    /**
2761
-     * Output category details content.
2762
-     *
2763
-     * @throws DomainException
2764
-     */
2765
-    protected function _category_details_content(): string
2766
-    {
2767
-        $editor_args['category_desc'] = [
2768
-            'type'          => 'wp_editor',
2769
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2770
-            'class'         => 'my_editor_custom',
2771
-            'wpeditor_args' => ['media_buttons' => false],
2772
-        ];
2773
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2774
-        $all_terms                    = get_terms(
2775
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2776
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2777
-        );
2778
-        // setup category select for term parents.
2779
-        $category_select_values[] = [
2780
-            'text' => esc_html__('No Parent', 'event_espresso'),
2781
-            'id'   => 0,
2782
-        ];
2783
-        foreach ($all_terms as $term) {
2784
-            $category_select_values[] = [
2785
-                'text' => $term->name,
2786
-                'id'   => $term->term_id,
2787
-            ];
2788
-        }
2789
-        $category_select = EEH_Form_Fields::select_input(
2790
-            'category_parent',
2791
-            $category_select_values,
2792
-            $this->_category->parent
2793
-        );
2794
-        $template_args   = [
2795
-            'category'                 => $this->_category,
2796
-            'category_select'          => $category_select,
2797
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2798
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2799
-            'disable'                  => '',
2800
-            'disabled_message'         => false,
2801
-        ];
2802
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2803
-        return EEH_Template::display_template($template, $template_args, true);
2804
-    }
2805
-
2806
-
2807
-    /**
2808
-     * Handles deleting categories.
2809
-     *
2810
-     * @throws EE_Error
2811
-     */
2812
-    protected function _delete_categories()
2813
-    {
2814
-        $category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2815
-        foreach ($category_IDs as $category_ID) {
2816
-            $this->_delete_category($category_ID);
2817
-        }
2818
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2819
-        $query_args = [
2820
-            'action' => 'category_list',
2821
-        ];
2822
-        $this->_redirect_after_action(0, '', '', $query_args);
2823
-    }
2824
-
2825
-
2826
-    /**
2827
-     * Handles deleting specific category.
2828
-     *
2829
-     * @param int $cat_id
2830
-     */
2831
-    protected function _delete_category(int $cat_id)
2832
-    {
2833
-        $cat_id = absint($cat_id);
2834
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2835
-    }
2836
-
2837
-
2838
-    /**
2839
-     * Handles triggering the update or insertion of a new category.
2840
-     *
2841
-     * @param bool $new_category true means we're triggering the insert of a new category.
2842
-     * @throws EE_Error
2843
-     * @throws EE_Error
2844
-     */
2845
-    protected function _insert_or_update_category(bool $new_category)
2846
-    {
2847
-        $cat_id  = $this->_insert_category($new_category);
2848
-        $success = 0; // we already have a success message so lets not send another.
2849
-        if ($cat_id) {
2850
-            $query_args = [
2851
-                'action'     => 'edit_category',
2852
-                'EVT_CAT_ID' => $cat_id,
2853
-            ];
2854
-        } else {
2855
-            $query_args = ['action' => 'add_category'];
2856
-        }
2857
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2858
-    }
2859
-
2860
-
2861
-    /**
2862
-     * Inserts or updates category
2863
-     *
2864
-     * @param bool $new_category (true indicates we're updating a category).
2865
-     * @return bool|mixed|string
2866
-     */
2867
-    private function _insert_category(bool $new_category)
2868
-    {
2869
-        $category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2870
-        $category_name       = $this->request->getRequestParam('category_name', '');
2871
-        $category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2872
-        $category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2873
-        $category_identifier = $this->request->getRequestParam('category_identifier', '');
2874
-
2875
-        if (empty($category_name)) {
2876
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2877
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2878
-            return 0;
2879
-        }
2880
-        $term_args = [
2881
-            'name'        => $category_name,
2882
-            'description' => $category_desc,
2883
-            'parent'      => $category_parent,
2884
-        ];
2885
-        // was the category_identifier input disabled?
2886
-        if ($category_identifier) {
2887
-            $term_args['slug'] = $category_identifier;
2888
-        }
2889
-        $insert_ids = $new_category
2890
-            ? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2891
-            : wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2892
-
2893
-        if ($insert_ids instanceof WP_Error) {
2894
-            EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2895
-            return 0;
2896
-        }
2897
-        $category_ID = $insert_ids['term_id'] ?? 0;
2898
-        if (! $category_ID) {
2899
-            EE_Error::add_error(
2900
-                esc_html__(
2901
-                    'An error occurred and the category has not been saved to the database.',
2902
-                    'event_espresso'
2903
-                ),
2904
-                __FILE__,
2905
-                __FUNCTION__,
2906
-                __LINE__
2907
-            );
2908
-            return 0;
2909
-        }
2910
-        EE_Error::add_success(
2911
-            sprintf(
2912
-                esc_html__('The category %s was successfully saved', 'event_espresso'),
2913
-                $category_name
2914
-            )
2915
-        );
2916
-        return $category_ID;
2917
-    }
2918
-
2919
-
2920
-    /**
2921
-     * Gets categories or count of categories matching the arguments in the request.
2922
-     *
2923
-     * @param int  $per_page
2924
-     * @param int  $current_page
2925
-     * @param bool $count
2926
-     * @return EE_Term_Taxonomy[]|int
2927
-     * @throws EE_Error
2928
-     * @throws ReflectionException
2929
-     */
2930
-    public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2931
-    {
2932
-        // testing term stuff
2933
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2934
-        $order       = $this->request->getRequestParam('order', 'DESC');
2935
-        $limit       = ($current_page - 1) * $per_page;
2936
-        $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2937
-        $search_term = $this->request->getRequestParam('s');
2938
-        if ($search_term) {
2939
-            $search_term = '%' . $search_term . '%';
2940
-            $where['OR'] = [
2941
-                'Term.name'   => ['LIKE', $search_term],
2942
-                'description' => ['LIKE', $search_term],
2943
-            ];
2944
-        }
2945
-        $query_params = [
2946
-            $where,
2947
-            'order_by'   => [$orderby => $order],
2948
-            'limit'      => $limit . ',' . $per_page,
2949
-            'force_join' => ['Term'],
2950
-        ];
2951
-        return $count
2952
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2953
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2954
-    }
2955
-
2956
-    /* end category stuff */
2957
-
2958
-
2959
-    /**************/
2960
-
2961
-
2962
-    /**
2963
-     * Callback for the `ee_save_timezone_setting` ajax action.
2964
-     *
2965
-     * @throws EE_Error
2966
-     * @throws InvalidArgumentException
2967
-     * @throws InvalidDataTypeException
2968
-     * @throws InvalidInterfaceException
2969
-     */
2970
-    public function saveTimezoneString()
2971
-    {
2972
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2973
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2974
-        }
2975
-        $timezone_string = $this->request->getRequestParam('timezone_selected');
2976
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2977
-            EE_Error::add_error(
2978
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2979
-                __FILE__,
2980
-                __FUNCTION__,
2981
-                __LINE__
2982
-            );
2983
-            $this->_template_args['error'] = true;
2984
-            $this->_return_json();
2985
-        }
2986
-
2987
-        update_option('timezone_string', $timezone_string);
2988
-        EE_Error::add_success(
2989
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2990
-        );
2991
-        $this->_template_args['success'] = true;
2992
-        $this->_return_json(true, ['action' => 'create_new']);
2993
-    }
2994
-
2995
-
2996
-    /**
2997 2653
      * @throws EE_Error
2998
-     * @deprecated 4.10.25.p
2999 2654
      */
3000
-    public function save_timezonestring_setting()
3001
-    {
3002
-        $this->saveTimezoneString();
3003
-    }
2655
+	protected function _template_settings()
2656
+	{
2657
+		$this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2658
+		$this->_template_args['preview_img']  = '<img src="'
2659
+												. EVENTS_ASSETS_URL
2660
+												. '/images/'
2661
+												. 'caffeinated_template_features.jpg" alt="'
2662
+												. esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2663
+												. '" />';
2664
+		$this->_template_args['preview_text'] = '<strong>'
2665
+												. esc_html__(
2666
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2667
+													'event_espresso'
2668
+												) . '</strong>';
2669
+		$this->display_admin_caf_preview_page('template_settings_tab');
2670
+	}
2671
+
2672
+
2673
+	/** Event Category Stuff **/
2674
+	/**
2675
+	 * set the _category property with the category object for the loaded page.
2676
+	 *
2677
+	 * @access private
2678
+	 * @return void
2679
+	 */
2680
+	private function _set_category_object()
2681
+	{
2682
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2683
+			return;
2684
+		} //already have the category object so get out.
2685
+		// set default category object
2686
+		$this->_set_empty_category_object();
2687
+		// only set if we've got an id
2688
+		$category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2689
+		if (! $category_ID) {
2690
+			return;
2691
+		}
2692
+		$term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2693
+		if (! empty($term)) {
2694
+			$this->_category->category_name       = $term->name;
2695
+			$this->_category->category_identifier = $term->slug;
2696
+			$this->_category->category_desc       = $term->description;
2697
+			$this->_category->id                  = $term->term_id;
2698
+			$this->_category->parent              = $term->parent;
2699
+		}
2700
+	}
2701
+
2702
+
2703
+	/**
2704
+	 * Clears out category properties.
2705
+	 */
2706
+	private function _set_empty_category_object()
2707
+	{
2708
+		$this->_category                = new stdClass();
2709
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2710
+		$this->_category->id            = $this->_category->parent = 0;
2711
+	}
2712
+
2713
+
2714
+	/**
2715
+	 * @throws DomainException
2716
+	 * @throws EE_Error
2717
+	 * @throws InvalidArgumentException
2718
+	 * @throws InvalidDataTypeException
2719
+	 * @throws InvalidInterfaceException
2720
+	 */
2721
+	protected function _category_list_table()
2722
+	{
2723
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2724
+		$this->_admin_page_title .= ' ';
2725
+		$this->_admin_page_title .= $this->get_action_link_or_button(
2726
+			'add_category',
2727
+			'add_category',
2728
+			[],
2729
+			'add-new-h2'
2730
+		);
2731
+		$this->display_admin_list_table_page_with_sidebar();
2732
+	}
2733
+
2734
+
2735
+	/**
2736
+	 * Output category details view.
2737
+	 *
2738
+	 * @throws EE_Error
2739
+	 * @throws EE_Error
2740
+	 */
2741
+	protected function _category_details($view)
2742
+	{
2743
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2744
+		$this->_set_add_edit_form_tags($route);
2745
+		$this->_set_category_object();
2746
+		$id            = ! empty($this->_category->id) ? $this->_category->id : '';
2747
+		$delete_action = 'delete_category';
2748
+		// custom redirect
2749
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2750
+			['action' => 'category_list'],
2751
+			$this->_admin_base_url
2752
+		);
2753
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2754
+		// take care of contents
2755
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2756
+		$this->display_admin_page_with_sidebar();
2757
+	}
2758
+
2759
+
2760
+	/**
2761
+	 * Output category details content.
2762
+	 *
2763
+	 * @throws DomainException
2764
+	 */
2765
+	protected function _category_details_content(): string
2766
+	{
2767
+		$editor_args['category_desc'] = [
2768
+			'type'          => 'wp_editor',
2769
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2770
+			'class'         => 'my_editor_custom',
2771
+			'wpeditor_args' => ['media_buttons' => false],
2772
+		];
2773
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2774
+		$all_terms                    = get_terms(
2775
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2776
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2777
+		);
2778
+		// setup category select for term parents.
2779
+		$category_select_values[] = [
2780
+			'text' => esc_html__('No Parent', 'event_espresso'),
2781
+			'id'   => 0,
2782
+		];
2783
+		foreach ($all_terms as $term) {
2784
+			$category_select_values[] = [
2785
+				'text' => $term->name,
2786
+				'id'   => $term->term_id,
2787
+			];
2788
+		}
2789
+		$category_select = EEH_Form_Fields::select_input(
2790
+			'category_parent',
2791
+			$category_select_values,
2792
+			$this->_category->parent
2793
+		);
2794
+		$template_args   = [
2795
+			'category'                 => $this->_category,
2796
+			'category_select'          => $category_select,
2797
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2798
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2799
+			'disable'                  => '',
2800
+			'disabled_message'         => false,
2801
+		];
2802
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2803
+		return EEH_Template::display_template($template, $template_args, true);
2804
+	}
2805
+
2806
+
2807
+	/**
2808
+	 * Handles deleting categories.
2809
+	 *
2810
+	 * @throws EE_Error
2811
+	 */
2812
+	protected function _delete_categories()
2813
+	{
2814
+		$category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2815
+		foreach ($category_IDs as $category_ID) {
2816
+			$this->_delete_category($category_ID);
2817
+		}
2818
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2819
+		$query_args = [
2820
+			'action' => 'category_list',
2821
+		];
2822
+		$this->_redirect_after_action(0, '', '', $query_args);
2823
+	}
2824
+
2825
+
2826
+	/**
2827
+	 * Handles deleting specific category.
2828
+	 *
2829
+	 * @param int $cat_id
2830
+	 */
2831
+	protected function _delete_category(int $cat_id)
2832
+	{
2833
+		$cat_id = absint($cat_id);
2834
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2835
+	}
2836
+
2837
+
2838
+	/**
2839
+	 * Handles triggering the update or insertion of a new category.
2840
+	 *
2841
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2842
+	 * @throws EE_Error
2843
+	 * @throws EE_Error
2844
+	 */
2845
+	protected function _insert_or_update_category(bool $new_category)
2846
+	{
2847
+		$cat_id  = $this->_insert_category($new_category);
2848
+		$success = 0; // we already have a success message so lets not send another.
2849
+		if ($cat_id) {
2850
+			$query_args = [
2851
+				'action'     => 'edit_category',
2852
+				'EVT_CAT_ID' => $cat_id,
2853
+			];
2854
+		} else {
2855
+			$query_args = ['action' => 'add_category'];
2856
+		}
2857
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2858
+	}
2859
+
2860
+
2861
+	/**
2862
+	 * Inserts or updates category
2863
+	 *
2864
+	 * @param bool $new_category (true indicates we're updating a category).
2865
+	 * @return bool|mixed|string
2866
+	 */
2867
+	private function _insert_category(bool $new_category)
2868
+	{
2869
+		$category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2870
+		$category_name       = $this->request->getRequestParam('category_name', '');
2871
+		$category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2872
+		$category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2873
+		$category_identifier = $this->request->getRequestParam('category_identifier', '');
2874
+
2875
+		if (empty($category_name)) {
2876
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2877
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2878
+			return 0;
2879
+		}
2880
+		$term_args = [
2881
+			'name'        => $category_name,
2882
+			'description' => $category_desc,
2883
+			'parent'      => $category_parent,
2884
+		];
2885
+		// was the category_identifier input disabled?
2886
+		if ($category_identifier) {
2887
+			$term_args['slug'] = $category_identifier;
2888
+		}
2889
+		$insert_ids = $new_category
2890
+			? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2891
+			: wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2892
+
2893
+		if ($insert_ids instanceof WP_Error) {
2894
+			EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2895
+			return 0;
2896
+		}
2897
+		$category_ID = $insert_ids['term_id'] ?? 0;
2898
+		if (! $category_ID) {
2899
+			EE_Error::add_error(
2900
+				esc_html__(
2901
+					'An error occurred and the category has not been saved to the database.',
2902
+					'event_espresso'
2903
+				),
2904
+				__FILE__,
2905
+				__FUNCTION__,
2906
+				__LINE__
2907
+			);
2908
+			return 0;
2909
+		}
2910
+		EE_Error::add_success(
2911
+			sprintf(
2912
+				esc_html__('The category %s was successfully saved', 'event_espresso'),
2913
+				$category_name
2914
+			)
2915
+		);
2916
+		return $category_ID;
2917
+	}
2918
+
2919
+
2920
+	/**
2921
+	 * Gets categories or count of categories matching the arguments in the request.
2922
+	 *
2923
+	 * @param int  $per_page
2924
+	 * @param int  $current_page
2925
+	 * @param bool $count
2926
+	 * @return EE_Term_Taxonomy[]|int
2927
+	 * @throws EE_Error
2928
+	 * @throws ReflectionException
2929
+	 */
2930
+	public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2931
+	{
2932
+		// testing term stuff
2933
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2934
+		$order       = $this->request->getRequestParam('order', 'DESC');
2935
+		$limit       = ($current_page - 1) * $per_page;
2936
+		$where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2937
+		$search_term = $this->request->getRequestParam('s');
2938
+		if ($search_term) {
2939
+			$search_term = '%' . $search_term . '%';
2940
+			$where['OR'] = [
2941
+				'Term.name'   => ['LIKE', $search_term],
2942
+				'description' => ['LIKE', $search_term],
2943
+			];
2944
+		}
2945
+		$query_params = [
2946
+			$where,
2947
+			'order_by'   => [$orderby => $order],
2948
+			'limit'      => $limit . ',' . $per_page,
2949
+			'force_join' => ['Term'],
2950
+		];
2951
+		return $count
2952
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2953
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2954
+	}
2955
+
2956
+	/* end category stuff */
2957
+
2958
+
2959
+	/**************/
2960
+
2961
+
2962
+	/**
2963
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2964
+	 *
2965
+	 * @throws EE_Error
2966
+	 * @throws InvalidArgumentException
2967
+	 * @throws InvalidDataTypeException
2968
+	 * @throws InvalidInterfaceException
2969
+	 */
2970
+	public function saveTimezoneString()
2971
+	{
2972
+		if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2973
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2974
+		}
2975
+		$timezone_string = $this->request->getRequestParam('timezone_selected');
2976
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2977
+			EE_Error::add_error(
2978
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2979
+				__FILE__,
2980
+				__FUNCTION__,
2981
+				__LINE__
2982
+			);
2983
+			$this->_template_args['error'] = true;
2984
+			$this->_return_json();
2985
+		}
2986
+
2987
+		update_option('timezone_string', $timezone_string);
2988
+		EE_Error::add_success(
2989
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2990
+		);
2991
+		$this->_template_args['success'] = true;
2992
+		$this->_return_json(true, ['action' => 'create_new']);
2993
+	}
2994
+
2995
+
2996
+	/**
2997
+	 * @throws EE_Error
2998
+	 * @deprecated 4.10.25.p
2999
+	 */
3000
+	public function save_timezonestring_setting()
3001
+	{
3002
+		$this->saveTimezoneString();
3003
+	}
3004 3004
 }
Please login to merge, or discard this patch.
Spacing   +87 added lines, -87 removed lines patch added patch discarded remove patch
@@ -573,20 +573,20 @@  discard block
 block discarded – undo
573 573
     {
574 574
         wp_enqueue_style(
575 575
             'events-admin-css',
576
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
576
+            EVENTS_ASSETS_URL.'events-admin-page.css',
577 577
             [],
578 578
             EVENT_ESPRESSO_VERSION
579 579
         );
580 580
         wp_enqueue_style(
581 581
             'ee-cat-admin',
582
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
582
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
583 583
             ['editor-buttons'],
584 584
             EVENT_ESPRESSO_VERSION
585 585
         );
586 586
         // scripts
587 587
         wp_enqueue_script(
588 588
             'event_editor_js',
589
-            EVENTS_ASSETS_URL . 'event_editor.js',
589
+            EVENTS_ASSETS_URL.'event_editor.js',
590 590
             [
591 591
                 EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
592 592
                 JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
@@ -616,15 +616,15 @@  discard block
 block discarded – undo
616 616
         wp_enqueue_style('espresso-ui-theme');
617 617
         wp_enqueue_style(
618 618
             'event-editor-css',
619
-            EVENTS_ASSETS_URL . 'event-editor.css',
619
+            EVENTS_ASSETS_URL.'event-editor.css',
620 620
             ['ee-admin-css'],
621 621
             EVENT_ESPRESSO_VERSION
622 622
         );
623 623
         // scripts
624
-        if (! $this->admin_config->useAdvancedEditor()) {
624
+        if ( ! $this->admin_config->useAdvancedEditor()) {
625 625
             wp_enqueue_script(
626 626
                 'event-datetime-metabox',
627
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
628 628
                 ['event_editor_js', 'ee-datepicker'],
629 629
                 EVENT_ESPRESSO_VERSION
630 630
             );
@@ -702,15 +702,15 @@  discard block
 block discarded – undo
702 702
     public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
703 703
     {
704 704
         // don't need to do this when processing
705
-        if (! empty($req_type)) {
705
+        if ( ! empty($req_type)) {
706 706
             return;
707 707
         }
708 708
         // no event?
709
-        if (! $event instanceof EE_Event) {
709
+        if ( ! $event instanceof EE_Event) {
710 710
             $event = $this->_cpt_model_obj;
711 711
         }
712 712
         // STILL no event?
713
-        if (! $event instanceof EE_Event) {
713
+        if ( ! $event instanceof EE_Event) {
714 714
             return;
715 715
         }
716 716
         // don't need to keep calling this
@@ -755,7 +755,7 @@  discard block
 block discarded – undo
755 755
             );
756 756
         }
757 757
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
758
-        if (! $event->tickets_on_sale()) {
758
+        if ( ! $event->tickets_on_sale()) {
759 759
             return;
760 760
         }
761 761
         // made it here so show warning
@@ -804,7 +804,7 @@  discard block
 block discarded – undo
804 804
     {
805 805
         $has_timezone_string = get_option('timezone_string');
806 806
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
807
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
808 808
             EE_Error::add_attention(
809 809
                 sprintf(
810 810
                     esc_html__(
@@ -873,7 +873,7 @@  discard block
 block discarded – undo
873 873
      */
874 874
     protected function _event_legend_items(): array
875 875
     {
876
-        $items    = [
876
+        $items = [
877 877
             'view_details'   => [
878 878
                 'class' => 'dashicons dashicons-visibility',
879 879
                 'desc'  => esc_html__('View Event', 'event_espresso'),
@@ -890,31 +890,31 @@  discard block
 block discarded – undo
890 890
         $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
891 891
         $statuses = [
892 892
             'sold_out_status'  => [
893
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
893
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::sold_out,
894 894
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
895 895
             ],
896 896
             'active_status'    => [
897
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
897
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::active,
898 898
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
899 899
             ],
900 900
             'upcoming_status'  => [
901
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
901
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::upcoming,
902 902
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
903 903
             ],
904 904
             'postponed_status' => [
905
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
905
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::postponed,
906 906
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
907 907
             ],
908 908
             'cancelled_status' => [
909
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
909
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::cancelled,
910 910
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
911 911
             ],
912 912
             'expired_status'   => [
913
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
913
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::expired,
914 914
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
915 915
             ],
916 916
             'inactive_status'  => [
917
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
917
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::inactive,
918 918
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
919 919
             ],
920 920
         ];
@@ -933,7 +933,7 @@  discard block
 block discarded – undo
933 933
      */
934 934
     private function _event_model(): EEM_Event
935 935
     {
936
-        if (! $this->_event_model instanceof EEM_Event) {
936
+        if ( ! $this->_event_model instanceof EEM_Event) {
937 937
             $this->_event_model = EE_Registry::instance()->load_model('Event');
938 938
         }
939 939
         return $this->_event_model;
@@ -988,12 +988,12 @@  discard block
 block discarded – undo
988 988
             '',
989 989
             'ee-admin-button-row ee-admin-button-row--align-start'
990 990
         );
991
-        $links_html       .= EEH_HTML::divx();
991
+        $links_html .= EEH_HTML::divx();
992 992
 
993 993
         $after_list_table['view_event_list_button'] = $links_html;
994 994
 
995 995
         $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
996
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
996
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
997 997
                 'create_new',
998 998
                 'add',
999 999
                 [],
@@ -1057,13 +1057,13 @@  discard block
 block discarded – undo
1057 1057
             'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1058 1058
         ];
1059 1059
         // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1060
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1060
+        if ( ! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
+            $event_values['EVT_display_ticket_selector'] = $this->request->getRequestParam(
1062 1062
                 'display_ticket_selector',
1063 1063
                 false,
1064 1064
                 'bool'
1065 1065
             );
1066
-            $event_values['EVT_additional_limit']            = min(
1066
+            $event_values['EVT_additional_limit'] = min(
1067 1067
                 apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1068 1068
                 $this->request->getRequestParam(
1069 1069
                     'additional_limit',
@@ -1105,14 +1105,14 @@  discard block
 block discarded – undo
1105 1105
             ]
1106 1106
         );
1107 1107
 
1108
-        if (! $event instanceof EE_Event) {
1108
+        if ( ! $event instanceof EE_Event) {
1109 1109
             return;
1110 1110
         }
1111 1111
 
1112 1112
         // the following are default callbacks for event attachment updates
1113 1113
         // that can be overridden by caffeinated functionality and/or addons.
1114 1114
         $event_update_callbacks = [];
1115
-        if (! $this->admin_config->useAdvancedEditor()) {
1115
+        if ( ! $this->admin_config->useAdvancedEditor()) {
1116 1116
             $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1117 1117
             $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1118 1118
         }
@@ -1183,7 +1183,7 @@  discard block
 block discarded – undo
1183 1183
      */
1184 1184
     protected function _default_venue_update(EE_Event $event, array $data): bool
1185 1185
     {
1186
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1186
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1187 1187
         $venue_model = EE_Registry::instance()->load_model('Venue');
1188 1188
         $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1189 1189
         // very important.  If we don't have a venue name...
@@ -1214,7 +1214,7 @@  discard block
 block discarded – undo
1214 1214
             'status'              => 'publish',
1215 1215
         ];
1216 1216
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1217
-        if (! empty($venue_id)) {
1217
+        if ( ! empty($venue_id)) {
1218 1218
             $update_where  = [$venue_model->primary_key_name() => $venue_id];
1219 1219
             $rows_affected = $venue_model->update($venue_array, [$update_where]);
1220 1220
             // we've gotta make sure that the venue is always attached to a revision..
@@ -1264,9 +1264,9 @@  discard block
 block discarded – undo
1264 1264
             ];
1265 1265
             // if we have an id then let's get existing object first and then set the new values.
1266 1266
             //  Otherwise we instantiate a new object for save.
1267
-            if (! empty($datetime_data['DTT_ID'])) {
1267
+            if ( ! empty($datetime_data['DTT_ID'])) {
1268 1268
                 $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1269
-                if (! $datetime instanceof EE_Datetime) {
1269
+                if ( ! $datetime instanceof EE_Datetime) {
1270 1270
                     throw new RuntimeException(
1271 1271
                         sprintf(
1272 1272
                             esc_html__(
@@ -1285,7 +1285,7 @@  discard block
 block discarded – undo
1285 1285
             } else {
1286 1286
                 $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1287 1287
             }
1288
-            if (! $datetime instanceof EE_Datetime) {
1288
+            if ( ! $datetime instanceof EE_Datetime) {
1289 1289
                 throw new RuntimeException(
1290 1290
                     sprintf(
1291 1291
                         esc_html__(
@@ -1311,7 +1311,7 @@  discard block
 block discarded – undo
1311 1311
 
1312 1312
         // set up some default start and end dates in case those are not present in the incoming data
1313 1313
         $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1314
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1314
+        $default_start_date = $default_start_date->format($date_formats[0].' '.$date_formats[1]);
1315 1315
         // use the start date of the first datetime for the end date
1316 1316
         $first_datetime   = $event->first_datetime();
1317 1317
         $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
@@ -1319,7 +1319,7 @@  discard block
 block discarded – undo
1319 1319
         // now process the incoming data
1320 1320
         foreach ($data['edit_tickets'] as $row => $ticket_data) {
1321 1321
             $update_prices = false;
1322
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1322
+            $ticket_price  = $data['edit_prices'][$row][1]['PRC_amount'] ?? 0;
1323 1323
             // trim inputs to ensure any excess whitespace is removed.
1324 1324
             $ticket_data   = array_map('trim', $ticket_data);
1325 1325
             $ticket_values = [
@@ -1359,9 +1359,9 @@  discard block
 block discarded – undo
1359 1359
             // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1360 1360
             // keep in mind that if the ticket has been sold (and we have changed pricing information),
1361 1361
             // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1362
-            if (! empty($ticket_data['TKT_ID'])) {
1362
+            if ( ! empty($ticket_data['TKT_ID'])) {
1363 1363
                 $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1364
-                if (! $existing_ticket instanceof EE_Ticket) {
1364
+                if ( ! $existing_ticket instanceof EE_Ticket) {
1365 1365
                     throw new RuntimeException(
1366 1366
                         sprintf(
1367 1367
                             esc_html__(
@@ -1410,7 +1410,7 @@  discard block
 block discarded – undo
1410 1410
                     $existing_ticket->save();
1411 1411
                     // make sure this ticket is still recorded in our $saved_tickets
1412 1412
                     // so we don't run it through the regular trash routine.
1413
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1413
+                    $saved_tickets[$existing_ticket->ID()] = $existing_ticket;
1414 1414
                     // create new ticket that's a copy of the existing except,
1415 1415
                     // (a new id of course and not archived) AND has the new TKT_price associated with it.
1416 1416
                     $new_ticket = clone $existing_ticket;
@@ -1427,7 +1427,7 @@  discard block
 block discarded – undo
1427 1427
                 $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1428 1428
                 $update_prices              = true;
1429 1429
             }
1430
-            if (! $ticket instanceof EE_Ticket) {
1430
+            if ( ! $ticket instanceof EE_Ticket) {
1431 1431
                 throw new RuntimeException(
1432 1432
                     sprintf(
1433 1433
                         esc_html__(
@@ -1451,10 +1451,10 @@  discard block
 block discarded – undo
1451 1451
             }
1452 1452
             // initially let's add the ticket to the datetime
1453 1453
             $datetime->_add_relation_to($ticket, 'Ticket');
1454
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1454
+            $saved_tickets[$ticket->ID()] = $ticket;
1455 1455
             // add prices to ticket
1456
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1457
-                ? $data['edit_prices'][ $row ]
1456
+            $prices_data = isset($data['edit_prices'][$row]) && is_array($data['edit_prices'][$row])
1457
+                ? $data['edit_prices'][$row]
1458 1458
                 : [];
1459 1459
             $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1460 1460
         }
@@ -1468,7 +1468,7 @@  discard block
 block discarded – undo
1468 1468
             $id = absint($id);
1469 1469
             // get the ticket for this id
1470 1470
             $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1471
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1471
+            if ( ! $ticket_to_remove instanceof EE_Ticket) {
1472 1472
                 continue;
1473 1473
             }
1474 1474
             // need to get all the related datetimes on this ticket and remove from every single one of them
@@ -1525,7 +1525,7 @@  discard block
 block discarded – undo
1525 1525
                     $price->set($field, $new_price);
1526 1526
                 }
1527 1527
             }
1528
-            if (! $price instanceof EE_Price) {
1528
+            if ( ! $price instanceof EE_Price) {
1529 1529
                 throw new RuntimeException(
1530 1530
                     sprintf(
1531 1531
                         esc_html__(
@@ -1566,13 +1566,13 @@  discard block
 block discarded – undo
1566 1566
     {
1567 1567
         // load formatter helper
1568 1568
         // args for getting related registrations
1569
-        $approved_query_args        = [
1569
+        $approved_query_args = [
1570 1570
             [
1571 1571
                 'REG_deleted' => 0,
1572 1572
                 'STS_ID'      => RegStatus::APPROVED,
1573 1573
             ],
1574 1574
         ];
1575
-        $not_approved_query_args    = [
1575
+        $not_approved_query_args = [
1576 1576
             [
1577 1577
                 'REG_deleted' => 0,
1578 1578
                 'STS_ID'      => RegStatus::AWAITING_REVIEW,
@@ -1638,7 +1638,7 @@  discard block
 block discarded – undo
1638 1638
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1639 1639
         // load template
1640 1640
         EEH_Template::display_template(
1641
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1641
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1642 1642
             $publish_box_extra_args
1643 1643
         );
1644 1644
     }
@@ -1669,7 +1669,7 @@  discard block
 block discarded – undo
1669 1669
         $this->verify_cpt_object();
1670 1670
         $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1671 1671
         // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1672
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1672
+        if ( ! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1673 1673
             $this->addMetaBox(
1674 1674
                 'espresso_event_editor_event_options',
1675 1675
                 esc_html__('Event Registration Options', 'event_espresso'),
@@ -1678,7 +1678,7 @@  discard block
 block discarded – undo
1678 1678
                 'side'
1679 1679
             );
1680 1680
         }
1681
-        if (! $use_advanced_editor) {
1681
+        if ( ! $use_advanced_editor) {
1682 1682
             $this->addMetaBox(
1683 1683
                 'espresso_event_editor_tickets',
1684 1684
                 esc_html__('Event Datetime & Ticket', 'event_espresso'),
@@ -1690,7 +1690,7 @@  discard block
 block discarded – undo
1690 1690
         } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1691 1691
             add_action(
1692 1692
                 'add_meta_boxes_espresso_events',
1693
-                function () {
1693
+                function() {
1694 1694
                     global $current_screen;
1695 1695
                     remove_meta_box('authordiv', $current_screen, 'normal');
1696 1696
                 },
@@ -1719,7 +1719,7 @@  discard block
 block discarded – undo
1719 1719
             'trash_icon'        => 'dashicons dashicons-lock',
1720 1720
             'disabled'          => '',
1721 1721
         ];
1722
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1722
+        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1723 1723
         /**
1724 1724
          * 1. Start with retrieving Datetimes
1725 1725
          * 2. Fore each datetime get related tickets
@@ -1745,24 +1745,24 @@  discard block
 block discarded – undo
1745 1745
                     'default_where_conditions' => 'none',
1746 1746
                 ]
1747 1747
             );
1748
-            if (! empty($related_tickets)) {
1748
+            if ( ! empty($related_tickets)) {
1749 1749
                 $template_args['total_ticket_rows'] = count($related_tickets);
1750 1750
                 $row                                = 0;
1751 1751
                 foreach ($related_tickets as $ticket) {
1752
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1752
+                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1753 1753
                     $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1754 1754
                     $row++;
1755 1755
                 }
1756 1756
             } else {
1757 1757
                 $template_args['total_ticket_rows'] = 1;
1758 1758
                 /** @type EE_Ticket $ticket */
1759
-                $ticket                       = $ticket_model->create_default_object();
1759
+                $ticket = $ticket_model->create_default_object();
1760 1760
                 $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1761 1761
             }
1762 1762
         } else {
1763 1763
             $template_args['time'] = $times[0];
1764 1764
             /** @type EE_Ticket[] $tickets */
1765
-            $tickets                      = $ticket_model->get_all_default_tickets();
1765
+            $tickets = $ticket_model->get_all_default_tickets();
1766 1766
             $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1767 1767
             // NOTE: we're just sending the first default row
1768 1768
             // (decaf can't manage default tickets so this should be sufficient);
@@ -1777,9 +1777,9 @@  discard block
 block discarded – undo
1777 1777
             $ticket_model->create_default_object(),
1778 1778
             true
1779 1779
         );
1780
-        $template                                  = apply_filters(
1780
+        $template = apply_filters(
1781 1781
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1782
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1782
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1783 1783
         );
1784 1784
         EEH_Template::display_template($template, $template_args);
1785 1785
     }
@@ -1799,7 +1799,7 @@  discard block
 block discarded – undo
1799 1799
     private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1800 1800
     {
1801 1801
         $template_args = [
1802
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1802
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1803 1803
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1804 1804
                 ? ' tkt-archived'
1805 1805
                 : '',
@@ -1812,11 +1812,11 @@  discard block
 block discarded – undo
1812 1812
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1813 1813
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1814 1814
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1815
-            'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1816
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1815
+            'trash_icon'          => ($skeleton || ( ! $ticket->get('TKT_deleted')))
1816
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1817 1817
                 ? 'dashicons dashicons-post-trash clickable'
1818 1818
                 : 'dashicons dashicons-lock entity-locked',
1819
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1819
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1820 1820
                 : ' disabled=disabled',
1821 1821
         ];
1822 1822
 
@@ -1841,7 +1841,7 @@  discard block
 block discarded – undo
1841 1841
         }
1842 1842
         if (empty($template_args['TKT_end_date'])) {
1843 1843
             // get the earliest datetime (if present);
1844
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1844
+            $earliest_datetime = $this->_cpt_model_obj->ID() > 0
1845 1845
                 ? $this->_cpt_model_obj->get_first_related(
1846 1846
                     'Datetime',
1847 1847
                     ['order_by' => ['DTT_EVT_start' => 'ASC']]
@@ -1854,7 +1854,7 @@  discard block
 block discarded – undo
1854 1854
         $template_args = array_merge($template_args, $price_args);
1855 1855
         $template      = apply_filters(
1856 1856
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1857
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1857
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1858 1858
             $ticket
1859 1859
         );
1860 1860
         return EEH_Template::display_template($template, $template_args, true);
@@ -1867,7 +1867,7 @@  discard block
 block discarded – undo
1867 1867
      */
1868 1868
     public function registration_options_meta_box()
1869 1869
     {
1870
-        $yes_no_values             = [
1870
+        $yes_no_values = [
1871 1871
             ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1872 1872
             ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1873 1873
         ];
@@ -1892,12 +1892,12 @@  discard block
 block discarded – undo
1892 1892
             'ee-input-width--reg',
1893 1893
             false
1894 1894
         );
1895
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1895
+        $template_args['display_description'] = EEH_Form_Fields::select_input(
1896 1896
             'display_desc',
1897 1897
             $yes_no_values,
1898 1898
             $this->_cpt_model_obj->display_description()
1899 1899
         );
1900
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1900
+        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1901 1901
             'display_ticket_selector',
1902 1902
             $yes_no_values,
1903 1903
             $this->_cpt_model_obj->display_ticket_selector(),
@@ -1913,7 +1913,7 @@  discard block
 block discarded – undo
1913 1913
             $default_reg_status_values
1914 1914
         );
1915 1915
         EEH_Template::display_template(
1916
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1916
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1917 1917
             $template_args
1918 1918
         );
1919 1919
     }
@@ -1936,7 +1936,7 @@  discard block
 block discarded – undo
1936 1936
     {
1937 1937
         $EEM_Event   = $this->_event_model();
1938 1938
         $offset      = ($current_page - 1) * $per_page;
1939
-        $limit       = $count ? null : $offset . ',' . $per_page;
1939
+        $limit       = $count ? null : $offset.','.$per_page;
1940 1940
         $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1941 1941
         $order       = $this->request->getRequestParam('order', 'DESC');
1942 1942
         $month_range = $this->request->getRequestParam('month_range');
@@ -1986,11 +1986,11 @@  discard block
 block discarded – undo
1986 1986
                                                         ->format(implode(' ', $start_formats));
1987 1987
             $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1988 1988
         }
1989
-        if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1989
+        if ( ! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1990 1990
             $where['EVT_wp_user'] = get_current_user_id();
1991 1991
         } else {
1992
-            if (! isset($where['status'])) {
1993
-                if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1992
+            if ( ! isset($where['status'])) {
1993
+                if ( ! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1994 1994
                     $where['OR'] = [
1995 1995
                         'status*restrict_private' => ['!=', 'private'],
1996 1996
                         'AND'                     => [
@@ -2012,7 +2012,7 @@  discard block
 block discarded – undo
2012 2012
         // search query handling
2013 2013
         $search_term = $this->request->getRequestParam('s');
2014 2014
         if ($search_term) {
2015
-            $search_term = '%' . $search_term . '%';
2015
+            $search_term = '%'.$search_term.'%';
2016 2016
             $where['OR'] = [
2017 2017
                 'EVT_name'       => ['LIKE', $search_term],
2018 2018
                 'EVT_desc'       => ['LIKE', $search_term],
@@ -2077,14 +2077,14 @@  discard block
 block discarded – undo
2077 2077
             "$year_r-$month_r-01 00:00:00",
2078 2078
             new DateTimeZone($timezone_string)
2079 2079
         );
2080
-        $start    = $DateTime->getTimestamp();
2080
+        $start = $DateTime->getTimestamp();
2081 2081
         // set the datetime to be the end of the month
2082 2082
         $DateTime->setDate(
2083 2083
             $year_r,
2084 2084
             $month_r,
2085 2085
             $DateTime->format('t')
2086 2086
         )->setTime(23, 59, 59);
2087
-        $end                             = $DateTime->getTimestamp();
2087
+        $end = $DateTime->getTimestamp();
2088 2088
         return ['BETWEEN', [$start, $end]];
2089 2089
     }
2090 2090
 
@@ -2150,7 +2150,7 @@  discard block
 block discarded – undo
2150 2150
             // clean status
2151 2151
             $event_status = sanitize_key($event_status);
2152 2152
             // grab status
2153
-            if (! empty($event_status)) {
2153
+            if ( ! empty($event_status)) {
2154 2154
                 $success = $this->_change_event_status($this->EVT_ID, $event_status);
2155 2155
             } else {
2156 2156
                 $success = false;
@@ -2190,7 +2190,7 @@  discard block
 block discarded – undo
2190 2190
         // clean status
2191 2191
         $event_status = sanitize_key($event_status);
2192 2192
         // grab status
2193
-        if (! empty($event_status)) {
2193
+        if ( ! empty($event_status)) {
2194 2194
             $success = true;
2195 2195
             // determine the event id and set to array.
2196 2196
             $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
@@ -2236,7 +2236,7 @@  discard block
 block discarded – undo
2236 2236
     private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2237 2237
     {
2238 2238
         // grab event id
2239
-        if (! $EVT_ID) {
2239
+        if ( ! $EVT_ID) {
2240 2240
             $msg = esc_html__(
2241 2241
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2242 2242
                 'event_espresso'
@@ -2273,7 +2273,7 @@  discard block
 block discarded – undo
2273 2273
         // use class to change status
2274 2274
         $this->_cpt_model_obj->set_status($event_status);
2275 2275
         $success = $this->_cpt_model_obj->save();
2276
-        if (! $success) {
2276
+        if ( ! $success) {
2277 2277
             $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2278 2278
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2279 2279
             return false;
@@ -2340,7 +2340,7 @@  discard block
 block discarded – undo
2340 2340
      */
2341 2341
     protected function getModelObjNodeGroupPersister(): NodeGroupDao
2342 2342
     {
2343
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2343
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2344 2344
             $this->model_obj_node_group_persister =
2345 2345
                 $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2346 2346
         }
@@ -2665,7 +2665,7 @@  discard block
 block discarded – undo
2665 2665
                                                 . esc_html__(
2666 2666
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2667 2667
                                                     'event_espresso'
2668
-                                                ) . '</strong>';
2668
+                                                ).'</strong>';
2669 2669
         $this->display_admin_caf_preview_page('template_settings_tab');
2670 2670
     }
2671 2671
 
@@ -2686,11 +2686,11 @@  discard block
 block discarded – undo
2686 2686
         $this->_set_empty_category_object();
2687 2687
         // only set if we've got an id
2688 2688
         $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2689
-        if (! $category_ID) {
2689
+        if ( ! $category_ID) {
2690 2690
             return;
2691 2691
         }
2692 2692
         $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2693
-        if (! empty($term)) {
2693
+        if ( ! empty($term)) {
2694 2694
             $this->_category->category_name       = $term->name;
2695 2695
             $this->_category->category_identifier = $term->slug;
2696 2696
             $this->_category->category_desc       = $term->description;
@@ -2791,7 +2791,7 @@  discard block
 block discarded – undo
2791 2791
             $category_select_values,
2792 2792
             $this->_category->parent
2793 2793
         );
2794
-        $template_args   = [
2794
+        $template_args = [
2795 2795
             'category'                 => $this->_category,
2796 2796
             'category_select'          => $category_select,
2797 2797
             'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
@@ -2799,7 +2799,7 @@  discard block
 block discarded – undo
2799 2799
             'disable'                  => '',
2800 2800
             'disabled_message'         => false,
2801 2801
         ];
2802
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2802
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2803 2803
         return EEH_Template::display_template($template, $template_args, true);
2804 2804
     }
2805 2805
 
@@ -2895,7 +2895,7 @@  discard block
 block discarded – undo
2895 2895
             return 0;
2896 2896
         }
2897 2897
         $category_ID = $insert_ids['term_id'] ?? 0;
2898
-        if (! $category_ID) {
2898
+        if ( ! $category_ID) {
2899 2899
             EE_Error::add_error(
2900 2900
                 esc_html__(
2901 2901
                     'An error occurred and the category has not been saved to the database.',
@@ -2936,7 +2936,7 @@  discard block
 block discarded – undo
2936 2936
         $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2937 2937
         $search_term = $this->request->getRequestParam('s');
2938 2938
         if ($search_term) {
2939
-            $search_term = '%' . $search_term . '%';
2939
+            $search_term = '%'.$search_term.'%';
2940 2940
             $where['OR'] = [
2941 2941
                 'Term.name'   => ['LIKE', $search_term],
2942 2942
                 'description' => ['LIKE', $search_term],
@@ -2945,7 +2945,7 @@  discard block
 block discarded – undo
2945 2945
         $query_params = [
2946 2946
             $where,
2947 2947
             'order_by'   => [$orderby => $order],
2948
-            'limit'      => $limit . ',' . $per_page,
2948
+            'limit'      => $limit.','.$per_page,
2949 2949
             'force_join' => ['Term'],
2950 2950
         ];
2951 2951
         return $count
@@ -2969,7 +2969,7 @@  discard block
 block discarded – undo
2969 2969
      */
2970 2970
     public function saveTimezoneString()
2971 2971
     {
2972
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2972
+        if ( ! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2973 2973
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2974 2974
         }
2975 2975
         $timezone_string = $this->request->getRequestParam('timezone_selected');
Please login to merge, or discard this patch.
admin_pages/registrations/EE_Registrations_List_Table.class.php 2 patches
Indentation   +1140 added lines, -1140 removed lines patch added patch discarded remove patch
@@ -19,637 +19,637 @@  discard block
 block discarded – undo
19 19
  */
20 20
 class EE_Registrations_List_Table extends EE_Admin_List_Table
21 21
 {
22
-    /**
23
-     * @var Registrations_Admin_Page
24
-     */
25
-    protected EE_Admin_Page $_admin_page;
26
-
27
-    protected RegistrationsListTableUserCapabilities $caps_handler;
28
-
29
-    private array $_status;
30
-
31
-    /**
32
-     * An array of transaction details for the related transaction to the registration being processed.
33
-     * This is set via the _set_related_details method.
34
-     *
35
-     * @var array
36
-     */
37
-    protected array $_transaction_details = [];
38
-
39
-    /**
40
-     * An array of event details for the related event to the registration being processed.
41
-     * This is set via the _set_related_details method.
42
-     *
43
-     * @var array
44
-     */
45
-    protected array $_event_details = [];
46
-
47
-    private array $filters = [];
48
-
49
-    private int $EVT_ID = 0;
50
-
51
-    private int $DTT_ID = 0;
52
-
53
-    private int $TKT_ID = 0;
54
-
55
-
56
-    /**
57
-     * @param Registrations_Admin_Page $admin_page
58
-     */
59
-    public function __construct(Registrations_Admin_Page $admin_page)
60
-    {
61
-        $this->caps_handler = new RegistrationsListTableUserCapabilities(EE_Registry::instance()->CAP);
62
-        $this->request      = $this->request ?? LoaderFactory::getShared(RequestInterface::class);
63
-        $this->setupFilters();
64
-        parent::__construct($admin_page);
65
-        $this->_status = $this->_admin_page->get_registration_status_array();
66
-    }
67
-
68
-
69
-    private function setupFilters()
70
-    {
71
-        // for event filtering
72
-        $this->EVT_ID = $this->request->getRequestParam('event_id', 0, DataType::INTEGER);
73
-        $this->EVT_ID = $this->request->getRequestParam('EVT_ID', $this->EVT_ID, DataType::INTEGER);
74
-        // for datetime filtering
75
-        $this->DTT_ID = $this->request->getRequestParam('datetime_id', 0, DataType::INTEGER);
76
-        $this->DTT_ID = $this->request->getRequestParam('DTT_ID', $this->DTT_ID, DataType::INTEGER);
77
-        // for ticket filtering
78
-        $this->TKT_ID = $this->request->getRequestParam('ticket_id', 0, DataType::INTEGER);
79
-        $this->TKT_ID = $this->request->getRequestParam('TKT_ID', $this->TKT_ID, DataType::INTEGER);
80
-
81
-        $filters = [
82
-            'event_id'    => $this->EVT_ID,
83
-            'datetime_id' => $this->DTT_ID,
84
-            'ticket_id'   => $this->TKT_ID,
85
-        ];
86
-        foreach ($filters as $filter_key => $filter_value) {
87
-            if ($filter_value) {
88
-                $this->filters[ $filter_key ] = $filter_value;
89
-            }
90
-        }
91
-
92
-        add_filter(
93
-            'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
94
-            [$this, 'filterExtraQueryArgs'],
95
-            10,
96
-            2
97
-        );
98
-    }
99
-
100
-
101
-    /**
102
-     * @param array         $extra_query_args
103
-     * @param EE_Admin_Page $admin_page
104
-     * @return void
105
-     * @since 5.0.13.p
106
-     */
107
-    public function filterExtraQueryArgs(array $extra_query_args, EE_Admin_Page $admin_page): array
108
-    {
109
-        if ($admin_page instanceof Registrations_Admin_Page) {
110
-            foreach ($admin_page->get_views() as $view_details) {
111
-                foreach ($this->filters as $filter_key => $filter_value) {
112
-                    $extra_query_args[ $view_details['slug'] ][ $filter_key ] = $filter_value;
113
-                }
114
-            }
115
-        }
116
-        return $extra_query_args;
117
-    }
118
-
119
-
120
-    /**
121
-     * @return void
122
-     * @throws EE_Error
123
-     * @throws ReflectionException
124
-     */
125
-    protected function _setup_data()
126
-    {
127
-        $this->_data           = $this->_admin_page->get_registrations($this->_per_page);
128
-        $this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true);
129
-    }
130
-
131
-
132
-    /**
133
-     * @return void
134
-     */
135
-    protected function _set_properties()
136
-    {
137
-        $this->_wp_list_args = [
138
-            'singular' => esc_html__('registration', 'event_espresso'),
139
-            'plural'   => esc_html__('registrations', 'event_espresso'),
140
-            'ajax'     => true,
141
-            'screen'   => $this->_admin_page->get_current_screen()->id,
142
-        ];
143
-
144
-        if ($this->EVT_ID) {
145
-            $this->_columns = [
146
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
147
-                'id'               => esc_html__('ID', 'event_espresso'),
148
-                'ATT_fname'        => esc_html__('Name', 'event_espresso'),
149
-                'ATT_email'        => esc_html__('Email', 'event_espresso'),
150
-                '_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
151
-                'REG_ticket'       => esc_html__('Ticket', 'event_espresso'),
152
-                '_REG_final_price' => esc_html__('Price', 'event_espresso'),
153
-                '_REG_paid'        => esc_html__('REG Paid', 'event_espresso'),
154
-                'TXN_total'        => esc_html__('TXN Paid/Total', 'event_espresso'),
155
-                'actions'          => $this->actionsColumnHeader(),
156
-            ];
157
-        } elseif ($this->TKT_ID) {
158
-            $this->_columns = [
159
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
160
-                'id'               => esc_html__('ID', 'event_espresso'),
161
-                'ATT_fname'        => esc_html__('Name', 'event_espresso'),
162
-                'ATT_email'        => esc_html__('Email', 'event_espresso'),
163
-                '_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
164
-                '_REG_final_price' => esc_html__('Price', 'event_espresso'),
165
-                '_REG_paid'        => esc_html__('REG Paid', 'event_espresso'),
166
-                'TXN_total'        => esc_html__('TXN Paid/Total', 'event_espresso'),
167
-                'actions'          => $this->actionsColumnHeader(),
168
-            ];
169
-        } else {
170
-            $this->_columns = [
171
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
172
-                'id'               => esc_html__('ID', 'event_espresso'),
173
-                'ATT_fname'        => esc_html__('Name', 'event_espresso'),
174
-                '_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
175
-                'event_name'       => esc_html__('Event', 'event_espresso'),
176
-                'DTT_EVT_start'    => esc_html__('Event Date', 'event_espresso'),
177
-                'REG_ticket'       => esc_html__('Ticket', 'event_espresso'),
178
-                '_REG_final_price' => esc_html__('Price', 'event_espresso'),
179
-                '_REG_paid'        => esc_html__('REG Paid', 'event_espresso'),
180
-                'TXN_total'        => esc_html__('TXN Paid/Total', 'event_espresso'),
181
-                'actions'          => $this->actionsColumnHeader(),
182
-            ];
183
-        }
184
-
185
-        $this->_primary_column   = 'id';
186
-        $this->_sortable_columns = [
187
-            '_REG_date'     => ['_REG_date' => true],   // true means its already sorted
188
-            /**
189
-             * Allows users to change the default sort if they wish.
190
-             * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
191
-             * name.
192
-             */
193
-            'ATT_fname'     => [
194
-                'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
195
-                true,
196
-                $this,
197
-            ]
198
-                ? ['ATT_lname' => false]
199
-                : ['ATT_fname' => false],
200
-            'event_name'    => ['event_name' => false],
201
-            'DTT_EVT_start' => ['DTT_EVT_start' => false],
202
-            'id'            => ['REG_ID' => false],
203
-        ];
204
-        $this->_hidden_columns   = [];
205
-
206
-        $csv_report = RegistrationsCsvReportParams::getRequestParams(
207
-            $this->getReturnUrl(),
208
-            $this->_admin_page->get_request_data(),
209
-            $this->EVT_ID,
210
-            $this->DTT_ID
211
-        );
212
-        if (! empty($csv_report)) {
213
-            $this->_bottom_buttons['csv_reg_report'] = $csv_report;
214
-        }
215
-    }
216
-
217
-
218
-    /**
219
-     * This simply sets up the row class for the table rows.
220
-     * Allows for easier overriding of child methods for setting up sorting.
221
-     *
222
-     * @param EE_Registration $item the current item
223
-     * @return string
224
-     */
225
-    protected function _get_row_class($item): string
226
-    {
227
-        $class = parent::_get_row_class($item);
228
-        if ($this->_has_checkbox_column) {
229
-            $class .= ' has-checkbox-column';
230
-        }
231
-        return $class;
232
-    }
233
-
234
-
235
-    /**
236
-     * Set the $_transaction_details property if not set yet.
237
-     *
238
-     * @param EE_Registration $registration
239
-     * @throws EE_Error
240
-     * @throws InvalidArgumentException
241
-     * @throws ReflectionException
242
-     * @throws InvalidDataTypeException
243
-     * @throws InvalidInterfaceException
244
-     */
245
-    protected function _set_related_details(EE_Registration $registration)
246
-    {
247
-        $transaction                = $registration->transaction();
248
-        $status                     = $transaction->status_ID();
249
-        $this->_transaction_details = [
250
-            'transaction' => $transaction,
251
-            'status'      => $status,
252
-            'id'          => $transaction->ID(),
253
-            'title_attr'  => sprintf(
254
-                esc_html__('View Transaction Details (%s)', 'event_espresso'),
255
-                EEH_Template::pretty_status($status, false, 'sentence')
256
-            ),
257
-        ];
258
-        try {
259
-            $event = $registration->event();
260
-        } catch (EntityNotFoundException $e) {
261
-            $event = null;
262
-        }
263
-        $status               = $event instanceof EE_Event
264
-            ? $event->get_active_status()
265
-            : EE_Datetime::inactive;
266
-        $this->_event_details = [
267
-            'event'      => $event,
268
-            'status'     => $status,
269
-            'id'         => $event instanceof EE_Event
270
-                ? $event->ID()
271
-                : 0,
272
-            'title_attr' => sprintf(
273
-                esc_html__('Edit Event (%s)', 'event_espresso'),
274
-                EEH_Template::pretty_status($status, false, 'sentence')
275
-            ),
276
-        ];
277
-    }
278
-
279
-
280
-    /**
281
-     * @return array
282
-     * @throws EE_Error
283
-     * @throws ReflectionException
284
-     */
285
-    protected function _get_table_filters()
286
-    {
287
-        $filters = [];
288
-        $cur_date     = $this->request->getRequestParam('month_range', '');
289
-        $cur_category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INTEGER);
290
-        $reg_status   = $this->request->getRequestParam('_reg_status', '');
291
-
292
-        $month_filter = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
293
-        $filters[] = "
22
+	/**
23
+	 * @var Registrations_Admin_Page
24
+	 */
25
+	protected EE_Admin_Page $_admin_page;
26
+
27
+	protected RegistrationsListTableUserCapabilities $caps_handler;
28
+
29
+	private array $_status;
30
+
31
+	/**
32
+	 * An array of transaction details for the related transaction to the registration being processed.
33
+	 * This is set via the _set_related_details method.
34
+	 *
35
+	 * @var array
36
+	 */
37
+	protected array $_transaction_details = [];
38
+
39
+	/**
40
+	 * An array of event details for the related event to the registration being processed.
41
+	 * This is set via the _set_related_details method.
42
+	 *
43
+	 * @var array
44
+	 */
45
+	protected array $_event_details = [];
46
+
47
+	private array $filters = [];
48
+
49
+	private int $EVT_ID = 0;
50
+
51
+	private int $DTT_ID = 0;
52
+
53
+	private int $TKT_ID = 0;
54
+
55
+
56
+	/**
57
+	 * @param Registrations_Admin_Page $admin_page
58
+	 */
59
+	public function __construct(Registrations_Admin_Page $admin_page)
60
+	{
61
+		$this->caps_handler = new RegistrationsListTableUserCapabilities(EE_Registry::instance()->CAP);
62
+		$this->request      = $this->request ?? LoaderFactory::getShared(RequestInterface::class);
63
+		$this->setupFilters();
64
+		parent::__construct($admin_page);
65
+		$this->_status = $this->_admin_page->get_registration_status_array();
66
+	}
67
+
68
+
69
+	private function setupFilters()
70
+	{
71
+		// for event filtering
72
+		$this->EVT_ID = $this->request->getRequestParam('event_id', 0, DataType::INTEGER);
73
+		$this->EVT_ID = $this->request->getRequestParam('EVT_ID', $this->EVT_ID, DataType::INTEGER);
74
+		// for datetime filtering
75
+		$this->DTT_ID = $this->request->getRequestParam('datetime_id', 0, DataType::INTEGER);
76
+		$this->DTT_ID = $this->request->getRequestParam('DTT_ID', $this->DTT_ID, DataType::INTEGER);
77
+		// for ticket filtering
78
+		$this->TKT_ID = $this->request->getRequestParam('ticket_id', 0, DataType::INTEGER);
79
+		$this->TKT_ID = $this->request->getRequestParam('TKT_ID', $this->TKT_ID, DataType::INTEGER);
80
+
81
+		$filters = [
82
+			'event_id'    => $this->EVT_ID,
83
+			'datetime_id' => $this->DTT_ID,
84
+			'ticket_id'   => $this->TKT_ID,
85
+		];
86
+		foreach ($filters as $filter_key => $filter_value) {
87
+			if ($filter_value) {
88
+				$this->filters[ $filter_key ] = $filter_value;
89
+			}
90
+		}
91
+
92
+		add_filter(
93
+			'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
94
+			[$this, 'filterExtraQueryArgs'],
95
+			10,
96
+			2
97
+		);
98
+	}
99
+
100
+
101
+	/**
102
+	 * @param array         $extra_query_args
103
+	 * @param EE_Admin_Page $admin_page
104
+	 * @return void
105
+	 * @since 5.0.13.p
106
+	 */
107
+	public function filterExtraQueryArgs(array $extra_query_args, EE_Admin_Page $admin_page): array
108
+	{
109
+		if ($admin_page instanceof Registrations_Admin_Page) {
110
+			foreach ($admin_page->get_views() as $view_details) {
111
+				foreach ($this->filters as $filter_key => $filter_value) {
112
+					$extra_query_args[ $view_details['slug'] ][ $filter_key ] = $filter_value;
113
+				}
114
+			}
115
+		}
116
+		return $extra_query_args;
117
+	}
118
+
119
+
120
+	/**
121
+	 * @return void
122
+	 * @throws EE_Error
123
+	 * @throws ReflectionException
124
+	 */
125
+	protected function _setup_data()
126
+	{
127
+		$this->_data           = $this->_admin_page->get_registrations($this->_per_page);
128
+		$this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true);
129
+	}
130
+
131
+
132
+	/**
133
+	 * @return void
134
+	 */
135
+	protected function _set_properties()
136
+	{
137
+		$this->_wp_list_args = [
138
+			'singular' => esc_html__('registration', 'event_espresso'),
139
+			'plural'   => esc_html__('registrations', 'event_espresso'),
140
+			'ajax'     => true,
141
+			'screen'   => $this->_admin_page->get_current_screen()->id,
142
+		];
143
+
144
+		if ($this->EVT_ID) {
145
+			$this->_columns = [
146
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
147
+				'id'               => esc_html__('ID', 'event_espresso'),
148
+				'ATT_fname'        => esc_html__('Name', 'event_espresso'),
149
+				'ATT_email'        => esc_html__('Email', 'event_espresso'),
150
+				'_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
151
+				'REG_ticket'       => esc_html__('Ticket', 'event_espresso'),
152
+				'_REG_final_price' => esc_html__('Price', 'event_espresso'),
153
+				'_REG_paid'        => esc_html__('REG Paid', 'event_espresso'),
154
+				'TXN_total'        => esc_html__('TXN Paid/Total', 'event_espresso'),
155
+				'actions'          => $this->actionsColumnHeader(),
156
+			];
157
+		} elseif ($this->TKT_ID) {
158
+			$this->_columns = [
159
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
160
+				'id'               => esc_html__('ID', 'event_espresso'),
161
+				'ATT_fname'        => esc_html__('Name', 'event_espresso'),
162
+				'ATT_email'        => esc_html__('Email', 'event_espresso'),
163
+				'_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
164
+				'_REG_final_price' => esc_html__('Price', 'event_espresso'),
165
+				'_REG_paid'        => esc_html__('REG Paid', 'event_espresso'),
166
+				'TXN_total'        => esc_html__('TXN Paid/Total', 'event_espresso'),
167
+				'actions'          => $this->actionsColumnHeader(),
168
+			];
169
+		} else {
170
+			$this->_columns = [
171
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
172
+				'id'               => esc_html__('ID', 'event_espresso'),
173
+				'ATT_fname'        => esc_html__('Name', 'event_espresso'),
174
+				'_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
175
+				'event_name'       => esc_html__('Event', 'event_espresso'),
176
+				'DTT_EVT_start'    => esc_html__('Event Date', 'event_espresso'),
177
+				'REG_ticket'       => esc_html__('Ticket', 'event_espresso'),
178
+				'_REG_final_price' => esc_html__('Price', 'event_espresso'),
179
+				'_REG_paid'        => esc_html__('REG Paid', 'event_espresso'),
180
+				'TXN_total'        => esc_html__('TXN Paid/Total', 'event_espresso'),
181
+				'actions'          => $this->actionsColumnHeader(),
182
+			];
183
+		}
184
+
185
+		$this->_primary_column   = 'id';
186
+		$this->_sortable_columns = [
187
+			'_REG_date'     => ['_REG_date' => true],   // true means its already sorted
188
+			/**
189
+			 * Allows users to change the default sort if they wish.
190
+			 * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
191
+			 * name.
192
+			 */
193
+			'ATT_fname'     => [
194
+				'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
195
+				true,
196
+				$this,
197
+			]
198
+				? ['ATT_lname' => false]
199
+				: ['ATT_fname' => false],
200
+			'event_name'    => ['event_name' => false],
201
+			'DTT_EVT_start' => ['DTT_EVT_start' => false],
202
+			'id'            => ['REG_ID' => false],
203
+		];
204
+		$this->_hidden_columns   = [];
205
+
206
+		$csv_report = RegistrationsCsvReportParams::getRequestParams(
207
+			$this->getReturnUrl(),
208
+			$this->_admin_page->get_request_data(),
209
+			$this->EVT_ID,
210
+			$this->DTT_ID
211
+		);
212
+		if (! empty($csv_report)) {
213
+			$this->_bottom_buttons['csv_reg_report'] = $csv_report;
214
+		}
215
+	}
216
+
217
+
218
+	/**
219
+	 * This simply sets up the row class for the table rows.
220
+	 * Allows for easier overriding of child methods for setting up sorting.
221
+	 *
222
+	 * @param EE_Registration $item the current item
223
+	 * @return string
224
+	 */
225
+	protected function _get_row_class($item): string
226
+	{
227
+		$class = parent::_get_row_class($item);
228
+		if ($this->_has_checkbox_column) {
229
+			$class .= ' has-checkbox-column';
230
+		}
231
+		return $class;
232
+	}
233
+
234
+
235
+	/**
236
+	 * Set the $_transaction_details property if not set yet.
237
+	 *
238
+	 * @param EE_Registration $registration
239
+	 * @throws EE_Error
240
+	 * @throws InvalidArgumentException
241
+	 * @throws ReflectionException
242
+	 * @throws InvalidDataTypeException
243
+	 * @throws InvalidInterfaceException
244
+	 */
245
+	protected function _set_related_details(EE_Registration $registration)
246
+	{
247
+		$transaction                = $registration->transaction();
248
+		$status                     = $transaction->status_ID();
249
+		$this->_transaction_details = [
250
+			'transaction' => $transaction,
251
+			'status'      => $status,
252
+			'id'          => $transaction->ID(),
253
+			'title_attr'  => sprintf(
254
+				esc_html__('View Transaction Details (%s)', 'event_espresso'),
255
+				EEH_Template::pretty_status($status, false, 'sentence')
256
+			),
257
+		];
258
+		try {
259
+			$event = $registration->event();
260
+		} catch (EntityNotFoundException $e) {
261
+			$event = null;
262
+		}
263
+		$status               = $event instanceof EE_Event
264
+			? $event->get_active_status()
265
+			: EE_Datetime::inactive;
266
+		$this->_event_details = [
267
+			'event'      => $event,
268
+			'status'     => $status,
269
+			'id'         => $event instanceof EE_Event
270
+				? $event->ID()
271
+				: 0,
272
+			'title_attr' => sprintf(
273
+				esc_html__('Edit Event (%s)', 'event_espresso'),
274
+				EEH_Template::pretty_status($status, false, 'sentence')
275
+			),
276
+		];
277
+	}
278
+
279
+
280
+	/**
281
+	 * @return array
282
+	 * @throws EE_Error
283
+	 * @throws ReflectionException
284
+	 */
285
+	protected function _get_table_filters()
286
+	{
287
+		$filters = [];
288
+		$cur_date     = $this->request->getRequestParam('month_range', '');
289
+		$cur_category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INTEGER);
290
+		$reg_status   = $this->request->getRequestParam('_reg_status', '');
291
+
292
+		$month_filter = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
293
+		$filters[] = "
294 294
         <span class='ee-list-table-filter ee-reg-filter__month'>
295 295
             <label for='month_range' class='ee-reg-filter__label'>" . esc_html__('Month', 'event_espresso') . "</label>
296 296
             $month_filter
297 297
         </span>";
298 298
 
299
-        $cat_filter = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
300
-        $filters[] = "
299
+		$cat_filter = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
300
+		$filters[] = "
301 301
         <span class='ee-list-table-filter ee-reg-filter__category'>
302 302
             <label for='EVT_CAT' class='ee-reg-filter__label'>" . esc_html__('Category', 'event_espresso') . "</label>
303 303
             $cat_filter
304 304
         </span>";
305 305
 
306
-        $status       = [];
307
-        $status[]     = ['id' => 0, 'text' => esc_html__('Select Status', 'event_espresso')];
308
-        foreach ($this->_status as $key => $value) {
309
-            $status[] = ['id' => $key, 'text' => $value];
310
-        }
311
-        if ($this->_view !== 'incomplete') {
312
-            $status_filter = EEH_Form_Fields::select_input(
313
-                '_reg_status',
314
-                $status,
315
-                $reg_status ? strtoupper($reg_status) : ''
316
-            );
317
-            $filters[] = "
306
+		$status       = [];
307
+		$status[]     = ['id' => 0, 'text' => esc_html__('Select Status', 'event_espresso')];
308
+		foreach ($this->_status as $key => $value) {
309
+			$status[] = ['id' => $key, 'text' => $value];
310
+		}
311
+		if ($this->_view !== 'incomplete') {
312
+			$status_filter = EEH_Form_Fields::select_input(
313
+				'_reg_status',
314
+				$status,
315
+				$reg_status ? strtoupper($reg_status) : ''
316
+			);
317
+			$filters[] = "
318 318
         <span class='ee-list-table-filter ee-reg-filter__status'>
319 319
             <label for='_reg_status' class='ee-reg-filter__label'>" . esc_html__('Status', 'event_espresso') . "</label>
320 320
             $status_filter
321 321
         </span>";
322
-        }
323
-        foreach ($this->filters as $filter_key => $filter_value) {
324
-            // add hidden inputs for each filter with ids like "reg_event_id", "reg_datetime_id", & "reg_ticket_id"
325
-            $filters[] = EEH_Form_Fields::hidden_input($filter_key, $filter_value, "reg_$filter_key");
326
-        }
327
-        return $filters;
328
-    }
329
-
330
-
331
-    /**
332
-     * @return void
333
-     * @throws EE_Error
334
-     * @throws InvalidArgumentException
335
-     * @throws InvalidDataTypeException
336
-     * @throws InvalidInterfaceException
337
-     * @throws ReflectionException
338
-     */
339
-    protected function _add_view_counts()
340
-    {
341
-        $this->_views['all']['count']       = $this->_total_registrations();
342
-        $this->_views['today']['count']     = $this->_total_registrations_today();
343
-        $this->_views['yesterday']['count'] = $this->totalRegistrationsYesterday();
344
-        $this->_views['month']['count']     = $this->_total_registrations_this_month();
345
-        if ($this->caps_handler->userCanTrashRegistrations()) {
346
-            $this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
347
-            $this->_views['trash']['count']      = $this->_total_registrations('trash');
348
-        }
349
-    }
350
-
351
-
352
-    private function addWhereParamsForFilters(array $where = []): array
353
-    {
354
-        if ($this->EVT_ID) {
355
-            $where['EVT_ID'] = $this->EVT_ID;
356
-        }
357
-        if ($this->DTT_ID) {
358
-            $where['Ticket.Datetime.DTT_ID'] = $this->DTT_ID;
359
-        }
360
-        if ($this->TKT_ID) {
361
-            $where['TKT_ID'] = $this->TKT_ID;
362
-        }
363
-        return $where;
364
-    }
365
-
366
-
367
-    /**
368
-     * @param string $view
369
-     * @return int
370
-     * @throws EE_Error
371
-     * @throws ReflectionException
372
-     */
373
-    protected function _total_registrations(string $view = ''): int
374
-    {
375
-        $where = $this->addWhereParamsForFilters();
376
-        switch ($view) {
377
-            case 'trash':
378
-                return EEM_Registration::instance()->count_deleted([$where]);
379
-            case 'incomplete':
380
-                $where['STS_ID'] = RegStatus::INCOMPLETE;
381
-                break;
382
-            default:
383
-                $where['STS_ID'] = ['!=', RegStatus::INCOMPLETE];
384
-        }
385
-        return EEM_Registration::instance()->count([$where]);
386
-    }
387
-
388
-
389
-    /**
390
-     * @return int
391
-     * @throws EE_Error
392
-     * @throws ReflectionException
393
-     */
394
-    protected function _total_registrations_this_month(): int
395
-    {
396
-        $current_time   = current_time('timestamp');
397
-        $year_and_month = date('Y-m', $current_time);
398
-        $days_in_month  = date('t', $current_time);
399
-
400
-        $start_date = "$year_and_month-01";
401
-        $end_date   = "$year_and_month-$days_in_month";
402
-
403
-        return $this->totalRegistrationsForDateRange($start_date, $end_date);
404
-    }
405
-
406
-
407
-    /**
408
-     * @return int
409
-     * @throws EE_Error
410
-     * @throws ReflectionException
411
-     */
412
-    protected function _total_registrations_today(): int
413
-    {
414
-        $today = date('Y-m-d', current_time('timestamp'));
415
-        return $this->totalRegistrationsForDateRange($today, $today);
416
-    }
417
-
418
-
419
-    /**
420
-     * @return int
421
-     * @throws EE_Error
422
-     * @throws ReflectionException
423
-     */
424
-    protected function totalRegistrationsYesterday(): int
425
-    {
426
-        $yesterday = date('Y-m-d', current_time('timestamp') - DAY_IN_SECONDS);
427
-        return $this->totalRegistrationsForDateRange($yesterday, $yesterday);
428
-    }
429
-
430
-
431
-    /**
432
-     * @param string $start_date earlier date string in format 'Y-m-d'
433
-     * @param string $end_date   later date string in format 'Y-m-d'
434
-     * @return int
435
-     * @throws EE_Error
436
-     * @throws ReflectionException
437
-     */
438
-    private function totalRegistrationsForDateRange(string $start_date, string $end_date): int
439
-    {
440
-        $where = $this->addWhereParamsForFilters(
441
-            [
442
-                'REG_date' => [
443
-                    'BETWEEN',
444
-                    [
445
-                        EEM_Registration::instance()->convert_datetime_for_query(
446
-                            'REG_date',
447
-                            "$start_date 00:00:00",
448
-                            'Y-m-d H:i:s'
449
-                        ),
450
-                        EEM_Registration::instance()->convert_datetime_for_query(
451
-                            'REG_date',
452
-                            "$end_date  23:59:59",
453
-                            'Y-m-d H:i:s'
454
-                        ),
455
-                    ],
456
-                ],
457
-                'STS_ID'   => ['!=', RegStatus::INCOMPLETE],
458
-            ]
459
-        );
460
-        return EEM_Registration::instance()->count([$where]);
461
-    }
462
-
463
-
464
-    /**
465
-     * @param EE_Registration $item
466
-     * @return string
467
-     * @throws EE_Error
468
-     * @throws InvalidArgumentException
469
-     * @throws InvalidDataTypeException
470
-     * @throws InvalidInterfaceException
471
-     * @throws ReflectionException
472
-     */
473
-    public function column_cb($item): string
474
-    {
475
-        /** checkbox/lock **/
476
-        $REG_ID        = $item->ID();
477
-        $transaction   = $item->transaction();
478
-        $payment_count = $transaction->count_related('Payment');
479
-
480
-        $content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
481
-        $content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
482
-            ? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
322
+		}
323
+		foreach ($this->filters as $filter_key => $filter_value) {
324
+			// add hidden inputs for each filter with ids like "reg_event_id", "reg_datetime_id", & "reg_ticket_id"
325
+			$filters[] = EEH_Form_Fields::hidden_input($filter_key, $filter_value, "reg_$filter_key");
326
+		}
327
+		return $filters;
328
+	}
329
+
330
+
331
+	/**
332
+	 * @return void
333
+	 * @throws EE_Error
334
+	 * @throws InvalidArgumentException
335
+	 * @throws InvalidDataTypeException
336
+	 * @throws InvalidInterfaceException
337
+	 * @throws ReflectionException
338
+	 */
339
+	protected function _add_view_counts()
340
+	{
341
+		$this->_views['all']['count']       = $this->_total_registrations();
342
+		$this->_views['today']['count']     = $this->_total_registrations_today();
343
+		$this->_views['yesterday']['count'] = $this->totalRegistrationsYesterday();
344
+		$this->_views['month']['count']     = $this->_total_registrations_this_month();
345
+		if ($this->caps_handler->userCanTrashRegistrations()) {
346
+			$this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
347
+			$this->_views['trash']['count']      = $this->_total_registrations('trash');
348
+		}
349
+	}
350
+
351
+
352
+	private function addWhereParamsForFilters(array $where = []): array
353
+	{
354
+		if ($this->EVT_ID) {
355
+			$where['EVT_ID'] = $this->EVT_ID;
356
+		}
357
+		if ($this->DTT_ID) {
358
+			$where['Ticket.Datetime.DTT_ID'] = $this->DTT_ID;
359
+		}
360
+		if ($this->TKT_ID) {
361
+			$where['TKT_ID'] = $this->TKT_ID;
362
+		}
363
+		return $where;
364
+	}
365
+
366
+
367
+	/**
368
+	 * @param string $view
369
+	 * @return int
370
+	 * @throws EE_Error
371
+	 * @throws ReflectionException
372
+	 */
373
+	protected function _total_registrations(string $view = ''): int
374
+	{
375
+		$where = $this->addWhereParamsForFilters();
376
+		switch ($view) {
377
+			case 'trash':
378
+				return EEM_Registration::instance()->count_deleted([$where]);
379
+			case 'incomplete':
380
+				$where['STS_ID'] = RegStatus::INCOMPLETE;
381
+				break;
382
+			default:
383
+				$where['STS_ID'] = ['!=', RegStatus::INCOMPLETE];
384
+		}
385
+		return EEM_Registration::instance()->count([$where]);
386
+	}
387
+
388
+
389
+	/**
390
+	 * @return int
391
+	 * @throws EE_Error
392
+	 * @throws ReflectionException
393
+	 */
394
+	protected function _total_registrations_this_month(): int
395
+	{
396
+		$current_time   = current_time('timestamp');
397
+		$year_and_month = date('Y-m', $current_time);
398
+		$days_in_month  = date('t', $current_time);
399
+
400
+		$start_date = "$year_and_month-01";
401
+		$end_date   = "$year_and_month-$days_in_month";
402
+
403
+		return $this->totalRegistrationsForDateRange($start_date, $end_date);
404
+	}
405
+
406
+
407
+	/**
408
+	 * @return int
409
+	 * @throws EE_Error
410
+	 * @throws ReflectionException
411
+	 */
412
+	protected function _total_registrations_today(): int
413
+	{
414
+		$today = date('Y-m-d', current_time('timestamp'));
415
+		return $this->totalRegistrationsForDateRange($today, $today);
416
+	}
417
+
418
+
419
+	/**
420
+	 * @return int
421
+	 * @throws EE_Error
422
+	 * @throws ReflectionException
423
+	 */
424
+	protected function totalRegistrationsYesterday(): int
425
+	{
426
+		$yesterday = date('Y-m-d', current_time('timestamp') - DAY_IN_SECONDS);
427
+		return $this->totalRegistrationsForDateRange($yesterday, $yesterday);
428
+	}
429
+
430
+
431
+	/**
432
+	 * @param string $start_date earlier date string in format 'Y-m-d'
433
+	 * @param string $end_date   later date string in format 'Y-m-d'
434
+	 * @return int
435
+	 * @throws EE_Error
436
+	 * @throws ReflectionException
437
+	 */
438
+	private function totalRegistrationsForDateRange(string $start_date, string $end_date): int
439
+	{
440
+		$where = $this->addWhereParamsForFilters(
441
+			[
442
+				'REG_date' => [
443
+					'BETWEEN',
444
+					[
445
+						EEM_Registration::instance()->convert_datetime_for_query(
446
+							'REG_date',
447
+							"$start_date 00:00:00",
448
+							'Y-m-d H:i:s'
449
+						),
450
+						EEM_Registration::instance()->convert_datetime_for_query(
451
+							'REG_date',
452
+							"$end_date  23:59:59",
453
+							'Y-m-d H:i:s'
454
+						),
455
+					],
456
+				],
457
+				'STS_ID'   => ['!=', RegStatus::INCOMPLETE],
458
+			]
459
+		);
460
+		return EEM_Registration::instance()->count([$where]);
461
+	}
462
+
463
+
464
+	/**
465
+	 * @param EE_Registration $item
466
+	 * @return string
467
+	 * @throws EE_Error
468
+	 * @throws InvalidArgumentException
469
+	 * @throws InvalidDataTypeException
470
+	 * @throws InvalidInterfaceException
471
+	 * @throws ReflectionException
472
+	 */
473
+	public function column_cb($item): string
474
+	{
475
+		/** checkbox/lock **/
476
+		$REG_ID        = $item->ID();
477
+		$transaction   = $item->transaction();
478
+		$payment_count = $transaction->count_related('Payment');
479
+
480
+		$content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
481
+		$content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
482
+			? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
483 483
                     aria-label="' . $this->lockedRegMessage() . '"></span>'
484
-            : '';
485
-        return $this->columnContent('cb', $content, 'center');
486
-    }
487
-
488
-
489
-    private function lockedRegMessage(): string
490
-    {
491
-        return esc_html__(
492
-            '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.',
493
-            'event_espresso'
494
-        );
495
-    }
496
-
497
-
498
-    /**
499
-     * @param EE_Registration $registration
500
-     * @return string
501
-     * @throws EE_Error
502
-     * @throws InvalidArgumentException
503
-     * @throws InvalidDataTypeException
504
-     * @throws InvalidInterfaceException
505
-     * @throws ReflectionException
506
-     */
507
-    public function column_id(EE_Registration $registration): string
508
-    {
509
-        $content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
510
-        $content .= '<span class="show-on-mobile-view-only">';
511
-        $content .= $this->column_ATT_fname($registration, false);
512
-        $content .= '</span>';
513
-
514
-        return $this->columnContent('id', $content, 'end');
515
-    }
516
-
517
-
518
-    /**
519
-     * @param EE_Registration $registration
520
-     * @param bool            $prep_content
521
-     * @return string
522
-     * @throws EE_Error
523
-     * @throws ReflectionException
524
-     */
525
-    public function column_ATT_fname(EE_Registration $registration, bool $prep_content = true): string
526
-    {
527
-        $status         = esc_attr($registration->status_ID());
528
-        $pretty_status  = EEH_Template::pretty_status($status, false, 'sentence');
529
-        $prime_reg_star = $registration->count() === 1
530
-            ? '<sup><span class="dashicons dashicons-star-filled gold-icon"></span></sup>'
531
-            : '';
532
-
533
-        $group_count = '
484
+			: '';
485
+		return $this->columnContent('cb', $content, 'center');
486
+	}
487
+
488
+
489
+	private function lockedRegMessage(): string
490
+	{
491
+		return esc_html__(
492
+			'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.',
493
+			'event_espresso'
494
+		);
495
+	}
496
+
497
+
498
+	/**
499
+	 * @param EE_Registration $registration
500
+	 * @return string
501
+	 * @throws EE_Error
502
+	 * @throws InvalidArgumentException
503
+	 * @throws InvalidDataTypeException
504
+	 * @throws InvalidInterfaceException
505
+	 * @throws ReflectionException
506
+	 */
507
+	public function column_id(EE_Registration $registration): string
508
+	{
509
+		$content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
510
+		$content .= '<span class="show-on-mobile-view-only">';
511
+		$content .= $this->column_ATT_fname($registration, false);
512
+		$content .= '</span>';
513
+
514
+		return $this->columnContent('id', $content, 'end');
515
+	}
516
+
517
+
518
+	/**
519
+	 * @param EE_Registration $registration
520
+	 * @param bool            $prep_content
521
+	 * @return string
522
+	 * @throws EE_Error
523
+	 * @throws ReflectionException
524
+	 */
525
+	public function column_ATT_fname(EE_Registration $registration, bool $prep_content = true): string
526
+	{
527
+		$status         = esc_attr($registration->status_ID());
528
+		$pretty_status  = EEH_Template::pretty_status($status, false, 'sentence');
529
+		$prime_reg_star = $registration->count() === 1
530
+			? '<sup><span class="dashicons dashicons-star-filled gold-icon"></span></sup>'
531
+			: '';
532
+
533
+		$group_count = '
534 534
             <span class="reg-count-group-size" >
535 535
                 ' . sprintf(
536
-                esc_html__('(%1$s / %2$s)', 'event_espresso'),
537
-                $registration->count(),
538
-                $registration->group_size()
539
-            ) . '
536
+				esc_html__('(%1$s / %2$s)', 'event_espresso'),
537
+				$registration->count(),
538
+				$registration->group_size()
539
+			) . '
540 540
             </span >';
541 541
 
542
-        $content = '
542
+		$content = '
543 543
         <div class="ee-layout-row">
544 544
             <span aria-label="' . $pretty_status . '"
545 545
                   class="ee-status-dot ee-status-bg--' . $status . ' ee-aria-tooltip"
546 546
             ></span>
547 547
             ' . $this->viewRegistrationLink($registration, $status)
548
-            . $prime_reg_star
549
-            . $group_count . '
548
+			. $prime_reg_star
549
+			. $group_count . '
550 550
             <span class="spacer"></span>
551 551
             <span>
552 552
                 ' . sprintf(
553
-                esc_html__('Reg Code: %s', 'event_espresso'),
554
-                $registration->get('REG_code')
555
-            ) . '
553
+				esc_html__('Reg Code: %s', 'event_espresso'),
554
+				$registration->get('REG_code')
555
+			) . '
556 556
             </span>
557 557
         </div>';
558 558
 
559
-        $url_params = ['_REG_ID' => $registration->ID()];
560
-        if ($this->EVT_ID) {
561
-            $url_params['event_id'] = $this->EVT_ID;
562
-        }
563
-        // trash/restore/delete actions
564
-        $actions = $this->trashRegistrationLink($registration, $url_params);
565
-        $actions = $this->restoreRegistrationLink($registration, $url_params, $actions);
566
-        $actions = $this->deleteRegistrationLink($registration, $url_params, $actions);
567
-
568
-        $content .= $this->row_actions($actions);
569
-
570
-        return $prep_content ? $this->columnContent('ATT_fname', $content) : $content;
571
-    }
572
-
573
-
574
-    /**
575
-     * @param EE_Registration $registration
576
-     * @param bool            $prep_content
577
-     * @return string
578
-     * @throws EE_Error
579
-     * @throws ReflectionException
580
-     */
581
-    public function column__REG_date(EE_Registration $registration, bool $prep_content = true): string
582
-    {
583
-        $this->_set_related_details($registration);
584
-        // Build row actions
585
-        $content = $this->viewTransactionLink(
586
-            $registration->transaction(),
587
-            $registration->get_i18n_datetime('REG_date', 'M jS Y g:i a')
588
-        );
589
-        return $prep_content ? $this->columnContent('_REG_date', $content) : $content;
590
-    }
591
-
592
-
593
-    /**
594
-     * @param EE_Registration $registration
595
-     * @return string
596
-     * @throws EE_Error
597
-     * @throws InvalidArgumentException
598
-     * @throws InvalidDataTypeException
599
-     * @throws InvalidInterfaceException
600
-     * @throws ReflectionException
601
-     */
602
-    public function column_event_name(EE_Registration $registration): string
603
-    {
604
-        $this->_set_related_details($registration);
605
-        $edit_event              = $this->editEventLink($registration);
606
-        $actions['event_filter'] = $this->eventFilterLink($registration);
607
-        return $this->columnContent(
608
-            'event_name',
609
-            $edit_event . $this->row_actions($actions)
610
-        );
611
-    }
612
-
613
-
614
-    /**
615
-     * @param EE_Registration $registration
616
-     * @return string
617
-     * @throws EE_Error
618
-     * @throws InvalidArgumentException
619
-     * @throws InvalidDataTypeException
620
-     * @throws InvalidInterfaceException
621
-     * @throws ReflectionException
622
-     */
623
-    public function column_DTT_EVT_start(EE_Registration $registration): string
624
-    {
625
-        $datetime_strings = [];
626
-        $ticket           = $registration->ticket();
627
-        if ($ticket instanceof EE_Ticket) {
628
-            $remove_defaults = ['default_where_conditions' => 'none'];
629
-            $datetimes       = $ticket->datetimes($remove_defaults);
630
-            foreach ($datetimes as $datetime) {
631
-                $datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start', 'M jS Y g:i a');
632
-            }
633
-            $content = $this->generateDisplayForDatetimes($datetime_strings);
634
-        } else {
635
-            $content = esc_html__('There is no ticket on this registration', 'event_espresso');
636
-        }
637
-        return $this->columnContent('DTT_EVT_start', $content);
638
-    }
639
-
640
-
641
-    /**
642
-     * Receives an array of datetime strings to display and converts them to the html container for the column.
643
-     *
644
-     * @param array $datetime_strings
645
-     * @return string
646
-     */
647
-    public function generateDisplayForDatetimes(array $datetime_strings): string
648
-    {
649
-        // get first item for initial visibility
650
-        $content = (string) array_shift($datetime_strings);
651
-        if (! empty($datetime_strings)) {
652
-            $content .= '
559
+		$url_params = ['_REG_ID' => $registration->ID()];
560
+		if ($this->EVT_ID) {
561
+			$url_params['event_id'] = $this->EVT_ID;
562
+		}
563
+		// trash/restore/delete actions
564
+		$actions = $this->trashRegistrationLink($registration, $url_params);
565
+		$actions = $this->restoreRegistrationLink($registration, $url_params, $actions);
566
+		$actions = $this->deleteRegistrationLink($registration, $url_params, $actions);
567
+
568
+		$content .= $this->row_actions($actions);
569
+
570
+		return $prep_content ? $this->columnContent('ATT_fname', $content) : $content;
571
+	}
572
+
573
+
574
+	/**
575
+	 * @param EE_Registration $registration
576
+	 * @param bool            $prep_content
577
+	 * @return string
578
+	 * @throws EE_Error
579
+	 * @throws ReflectionException
580
+	 */
581
+	public function column__REG_date(EE_Registration $registration, bool $prep_content = true): string
582
+	{
583
+		$this->_set_related_details($registration);
584
+		// Build row actions
585
+		$content = $this->viewTransactionLink(
586
+			$registration->transaction(),
587
+			$registration->get_i18n_datetime('REG_date', 'M jS Y g:i a')
588
+		);
589
+		return $prep_content ? $this->columnContent('_REG_date', $content) : $content;
590
+	}
591
+
592
+
593
+	/**
594
+	 * @param EE_Registration $registration
595
+	 * @return string
596
+	 * @throws EE_Error
597
+	 * @throws InvalidArgumentException
598
+	 * @throws InvalidDataTypeException
599
+	 * @throws InvalidInterfaceException
600
+	 * @throws ReflectionException
601
+	 */
602
+	public function column_event_name(EE_Registration $registration): string
603
+	{
604
+		$this->_set_related_details($registration);
605
+		$edit_event              = $this->editEventLink($registration);
606
+		$actions['event_filter'] = $this->eventFilterLink($registration);
607
+		return $this->columnContent(
608
+			'event_name',
609
+			$edit_event . $this->row_actions($actions)
610
+		);
611
+	}
612
+
613
+
614
+	/**
615
+	 * @param EE_Registration $registration
616
+	 * @return string
617
+	 * @throws EE_Error
618
+	 * @throws InvalidArgumentException
619
+	 * @throws InvalidDataTypeException
620
+	 * @throws InvalidInterfaceException
621
+	 * @throws ReflectionException
622
+	 */
623
+	public function column_DTT_EVT_start(EE_Registration $registration): string
624
+	{
625
+		$datetime_strings = [];
626
+		$ticket           = $registration->ticket();
627
+		if ($ticket instanceof EE_Ticket) {
628
+			$remove_defaults = ['default_where_conditions' => 'none'];
629
+			$datetimes       = $ticket->datetimes($remove_defaults);
630
+			foreach ($datetimes as $datetime) {
631
+				$datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start', 'M jS Y g:i a');
632
+			}
633
+			$content = $this->generateDisplayForDatetimes($datetime_strings);
634
+		} else {
635
+			$content = esc_html__('There is no ticket on this registration', 'event_espresso');
636
+		}
637
+		return $this->columnContent('DTT_EVT_start', $content);
638
+	}
639
+
640
+
641
+	/**
642
+	 * Receives an array of datetime strings to display and converts them to the html container for the column.
643
+	 *
644
+	 * @param array $datetime_strings
645
+	 * @return string
646
+	 */
647
+	public function generateDisplayForDatetimes(array $datetime_strings): string
648
+	{
649
+		// get first item for initial visibility
650
+		$content = (string) array_shift($datetime_strings);
651
+		if (! empty($datetime_strings)) {
652
+			$content .= '
653 653
                 <div class="ee-registration-event-datetimes-container-wrap">
654 654
                     <div class="ee-registration-event-datetimes-container__control">
655 655
                         <span class="tiny-text">' . esc_html__('Click to view additional dates', 'event_espresso') . '</span>
@@ -663,637 +663,637 @@  discard block
 block discarded – undo
663 663
                         ' . implode("", $datetime_strings) . '
664 664
                     </div>
665 665
                 </div>';
666
-        }
667
-        return $content;
668
-    }
669
-
670
-
671
-    /**
672
-     * @param EE_Registration $registration
673
-     * @return string
674
-     * @throws EE_Error
675
-     * @throws InvalidArgumentException
676
-     * @throws InvalidDataTypeException
677
-     * @throws InvalidInterfaceException
678
-     * @throws ReflectionException
679
-     */
680
-    public function column_ATT_email(EE_Registration $registration): string
681
-    {
682
-        $attendee = $registration->get_first_related('Attendee');
683
-        $content  = ! $attendee instanceof EE_Attendee
684
-            ? esc_html__('No attached contact record.', 'event_espresso')
685
-            : $attendee->email();
686
-        return $this->columnContent('ATT_email', $content);
687
-    }
688
-
689
-
690
-    /**
691
-     * @param EE_Registration $registration
692
-     * @return string
693
-     * @throws EE_Error
694
-     * @throws ReflectionException
695
-     */
696
-    public function column__REG_count(EE_Registration $registration): string
697
-    {
698
-        $content = sprintf(
699
-            esc_html__('%1$s / %2$s', 'event_espresso'),
700
-            $registration->count(),
701
-            $registration->group_size()
702
-        );
703
-        return $this->columnContent('_REG_count', $content);
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_ticket(EE_Registration $registration): string
714
-    {
715
-        $ticket = $registration->ticket();
716
-        $ticket_name = $this->ticketName($ticket);
717
-        $actions['ticket_filter'] = $this->ticketFilterLink($ticket);
718
-        return $this->columnContent(
719
-            'REG_ticket',
720
-            $ticket_name . $this->row_actions($actions)
721
-        );
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_final_price(EE_Registration $registration): string
732
-    {
733
-        // free ticket?
734
-        $content = $registration->final_price() > 0
735
-            ? '<span class="reg-overview-paid-event-spn">' . $registration->pretty_final_price() . '</span>'
736
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
737
-        return $this->columnContent( '_REG_final_price', $content, 'end' );
738
-    }
739
-
740
-
741
-    /**
742
-     * @param EE_Registration $registration
743
-     * @return string
744
-     * @throws EE_Error
745
-     * @throws ReflectionException
746
-     */
747
-    public function column__REG_paid(EE_Registration $registration): string
748
-    {
749
-        $payment_method      = $registration->payment_method();
750
-        $payment_method_name = $payment_method instanceof EE_Payment_Method
751
-            ? $payment_method->admin_name()
752
-            : esc_html__('Unknown', 'event_espresso');
753
-
754
-        $payment_status = RegStatus::PENDING_PAYMENT;
755
-        $content = '<span>';
756
-        $icon = '';
757
-        $label = esc_attr__('pending payment', 'event_espresso');
758
-        if ($registration->paid() == $registration->final_price()) {
759
-            $icon = '<span class="dashicons dashicons-yes green-icon"></span> ';
760
-            $label = esc_attr__('paid in full', 'event_espresso');
761
-            $payment_status = RegStatus::APPROVED;
762
-        }
763
-        if ($registration->paid() > $registration->final_price()) {
764
-            $icon = '<span class="dashicons dashicons-warning orange-icon"></span> ';
765
-            $label = esc_attr__('overpaid', 'event_espresso');
766
-            $payment_status = EEM_Transaction::overpaid_status_code;
767
-        }
768
-        $content .= '
666
+		}
667
+		return $content;
668
+	}
669
+
670
+
671
+	/**
672
+	 * @param EE_Registration $registration
673
+	 * @return string
674
+	 * @throws EE_Error
675
+	 * @throws InvalidArgumentException
676
+	 * @throws InvalidDataTypeException
677
+	 * @throws InvalidInterfaceException
678
+	 * @throws ReflectionException
679
+	 */
680
+	public function column_ATT_email(EE_Registration $registration): string
681
+	{
682
+		$attendee = $registration->get_first_related('Attendee');
683
+		$content  = ! $attendee instanceof EE_Attendee
684
+			? esc_html__('No attached contact record.', 'event_espresso')
685
+			: $attendee->email();
686
+		return $this->columnContent('ATT_email', $content);
687
+	}
688
+
689
+
690
+	/**
691
+	 * @param EE_Registration $registration
692
+	 * @return string
693
+	 * @throws EE_Error
694
+	 * @throws ReflectionException
695
+	 */
696
+	public function column__REG_count(EE_Registration $registration): string
697
+	{
698
+		$content = sprintf(
699
+			esc_html__('%1$s / %2$s', 'event_espresso'),
700
+			$registration->count(),
701
+			$registration->group_size()
702
+		);
703
+		return $this->columnContent('_REG_count', $content);
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_ticket(EE_Registration $registration): string
714
+	{
715
+		$ticket = $registration->ticket();
716
+		$ticket_name = $this->ticketName($ticket);
717
+		$actions['ticket_filter'] = $this->ticketFilterLink($ticket);
718
+		return $this->columnContent(
719
+			'REG_ticket',
720
+			$ticket_name . $this->row_actions($actions)
721
+		);
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_final_price(EE_Registration $registration): string
732
+	{
733
+		// free ticket?
734
+		$content = $registration->final_price() > 0
735
+			? '<span class="reg-overview-paid-event-spn">' . $registration->pretty_final_price() . '</span>'
736
+			: '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
737
+		return $this->columnContent( '_REG_final_price', $content, 'end' );
738
+	}
739
+
740
+
741
+	/**
742
+	 * @param EE_Registration $registration
743
+	 * @return string
744
+	 * @throws EE_Error
745
+	 * @throws ReflectionException
746
+	 */
747
+	public function column__REG_paid(EE_Registration $registration): string
748
+	{
749
+		$payment_method      = $registration->payment_method();
750
+		$payment_method_name = $payment_method instanceof EE_Payment_Method
751
+			? $payment_method->admin_name()
752
+			: esc_html__('Unknown', 'event_espresso');
753
+
754
+		$payment_status = RegStatus::PENDING_PAYMENT;
755
+		$content = '<span>';
756
+		$icon = '';
757
+		$label = esc_attr__('pending payment', 'event_espresso');
758
+		if ($registration->paid() == $registration->final_price()) {
759
+			$icon = '<span class="dashicons dashicons-yes green-icon"></span> ';
760
+			$label = esc_attr__('paid in full', 'event_espresso');
761
+			$payment_status = RegStatus::APPROVED;
762
+		}
763
+		if ($registration->paid() > $registration->final_price()) {
764
+			$icon = '<span class="dashicons dashicons-warning orange-icon"></span> ';
765
+			$label = esc_attr__('overpaid', 'event_espresso');
766
+			$payment_status = EEM_Transaction::overpaid_status_code;
767
+		}
768
+		$content .= '
769 769
             <span class="reg-overview-paid-event-spn ee-aria-tooltip ee-status-color--' . $payment_status . '"
770 770
                   aria-label="' . $label . '"
771 771
             >
772 772
                 ' . $icon . $registration->pretty_paid('no_currency_code') . '
773 773
             </span>
774 774
             </span>';
775
-        if ($registration->paid() > 0) {
776
-            $content .= '
775
+		if ($registration->paid() > 0) {
776
+			$content .= '
777 777
             <span class="ee-status-text-small">
778 778
                 ' . sprintf(
779
-                        esc_html__('...via %s', 'event_espresso'),
780
-                        $payment_method_name
781
-                    ) . '
779
+						esc_html__('...via %s', 'event_espresso'),
780
+						$payment_method_name
781
+					) . '
782 782
             </span>';
783
-        }
784
-        return $this->columnContent('_REG_paid', $content, 'end', 'stack');
785
-    }
786
-
787
-
788
-    /**
789
-     * @param EE_Registration $registration
790
-     * @return string
791
-     * @throws EE_Error
792
-     * @throws EntityNotFoundException
793
-     * @throws InvalidArgumentException
794
-     * @throws InvalidDataTypeException
795
-     * @throws InvalidInterfaceException
796
-     * @throws ReflectionException
797
-     */
798
-    public function column_TXN_total(EE_Registration $registration): string
799
-    {
800
-        $content      = '';
801
-        if ($registration->count() === 1) {
802
-            $transaction = $registration->transaction();
803
-            $content     = '
783
+		}
784
+		return $this->columnContent('_REG_paid', $content, 'end', 'stack');
785
+	}
786
+
787
+
788
+	/**
789
+	 * @param EE_Registration $registration
790
+	 * @return string
791
+	 * @throws EE_Error
792
+	 * @throws EntityNotFoundException
793
+	 * @throws InvalidArgumentException
794
+	 * @throws InvalidDataTypeException
795
+	 * @throws InvalidInterfaceException
796
+	 * @throws ReflectionException
797
+	 */
798
+	public function column_TXN_total(EE_Registration $registration): string
799
+	{
800
+		$content      = '';
801
+		if ($registration->count() === 1) {
802
+			$transaction = $registration->transaction();
803
+			$content     = '
804 804
             <span class="ee-status-color--' . $transaction->status_ID() . '">
805 805
                 ' . $transaction->pretty_paid('no_currency_code') . '
806 806
                 <span class="separator">/</span>
807 807
                 ' . $transaction->pretty_total('no_currency_code') . '
808 808
             </span>';
809 809
 
810
-            $content .= '<span class="row-actions">' . $this->viewTransactionLink($transaction) . '</span>';
811
-        }
812
-        return $this->columnContent('TXN_total', $content, 'end', 'stack');
813
-    }
814
-
815
-
816
-    /**
817
-     * @param EE_Registration $registration
818
-     * @return string
819
-     * @throws EE_Error
820
-     * @throws InvalidArgumentException
821
-     * @throws InvalidDataTypeException
822
-     * @throws InvalidInterfaceException
823
-     * @throws ReflectionException
824
-     */
825
-    public function column_actions(EE_Registration $registration): string
826
-    {
827
-        $attendee = $registration->attendee();
828
-        $this->_set_related_details($registration);
829
-
830
-        // Build and filter row actions
831
-        $actions = apply_filters(
832
-            'FHEE__EE_Registrations_List_Table__column_actions__actions',
833
-            [
834
-                'view_lnk'               => $this->viewRegistrationAction($registration),
835
-                'edit_lnk'               => $this->editContactAction($registration, $attendee),
836
-                'resend_reg_lnk'         => $this->resendRegistrationMessageAction($registration, $attendee),
837
-                'view_txn_lnk'           => $this->viewTransactionAction($registration->transaction()),
838
-                'dl_invoice_lnk'         => $this->viewTransactionInvoiceAction($registration, $attendee),
839
-                'filtered_messages_link' => $this->viewNotificationsAction($registration),
840
-            ],
841
-            $registration,
842
-            $this
843
-        );
844
-
845
-        $content = $this->_action_string(
846
-            implode('', $actions),
847
-            $registration,
848
-            'div',
849
-            'reg-overview-actions ee-list-table-actions'
850
-        );
851
-
852
-        return $this->columnContent('actions', $this->actionsModalMenu($content));
853
-    }
854
-
855
-
856
-    /**
857
-     * @throws EE_Error
858
-     * @throws ReflectionException
859
-     */
860
-    protected function viewRegistrationUrl(EE_Registration $registration): string
861
-    {
862
-        return EE_Admin_Page::add_query_args_and_nonce(
863
-            [
864
-                'action'  => 'view_registration',
865
-                '_REG_ID' => $registration->ID(),
866
-            ],
867
-            REG_ADMIN_URL
868
-        );
869
-    }
870
-
871
-
872
-    /**
873
-     * @throws EE_Error
874
-     * @throws ReflectionException
875
-     */
876
-    protected function viewRegistrationLink(
877
-        EE_Registration $registration,
878
-        string $status
879
-    ): string {
880
-        $attendee      = $registration->attendee();
881
-        $attendee_name = $attendee instanceof EE_Attendee
882
-            ? $attendee->full_name()
883
-            : '';
884
-        return $this->caps_handler->userCanReadRegistration($registration)
885
-            ? '
810
+			$content .= '<span class="row-actions">' . $this->viewTransactionLink($transaction) . '</span>';
811
+		}
812
+		return $this->columnContent('TXN_total', $content, 'end', 'stack');
813
+	}
814
+
815
+
816
+	/**
817
+	 * @param EE_Registration $registration
818
+	 * @return string
819
+	 * @throws EE_Error
820
+	 * @throws InvalidArgumentException
821
+	 * @throws InvalidDataTypeException
822
+	 * @throws InvalidInterfaceException
823
+	 * @throws ReflectionException
824
+	 */
825
+	public function column_actions(EE_Registration $registration): string
826
+	{
827
+		$attendee = $registration->attendee();
828
+		$this->_set_related_details($registration);
829
+
830
+		// Build and filter row actions
831
+		$actions = apply_filters(
832
+			'FHEE__EE_Registrations_List_Table__column_actions__actions',
833
+			[
834
+				'view_lnk'               => $this->viewRegistrationAction($registration),
835
+				'edit_lnk'               => $this->editContactAction($registration, $attendee),
836
+				'resend_reg_lnk'         => $this->resendRegistrationMessageAction($registration, $attendee),
837
+				'view_txn_lnk'           => $this->viewTransactionAction($registration->transaction()),
838
+				'dl_invoice_lnk'         => $this->viewTransactionInvoiceAction($registration, $attendee),
839
+				'filtered_messages_link' => $this->viewNotificationsAction($registration),
840
+			],
841
+			$registration,
842
+			$this
843
+		);
844
+
845
+		$content = $this->_action_string(
846
+			implode('', $actions),
847
+			$registration,
848
+			'div',
849
+			'reg-overview-actions ee-list-table-actions'
850
+		);
851
+
852
+		return $this->columnContent('actions', $this->actionsModalMenu($content));
853
+	}
854
+
855
+
856
+	/**
857
+	 * @throws EE_Error
858
+	 * @throws ReflectionException
859
+	 */
860
+	protected function viewRegistrationUrl(EE_Registration $registration): string
861
+	{
862
+		return EE_Admin_Page::add_query_args_and_nonce(
863
+			[
864
+				'action'  => 'view_registration',
865
+				'_REG_ID' => $registration->ID(),
866
+			],
867
+			REG_ADMIN_URL
868
+		);
869
+	}
870
+
871
+
872
+	/**
873
+	 * @throws EE_Error
874
+	 * @throws ReflectionException
875
+	 */
876
+	protected function viewRegistrationLink(
877
+		EE_Registration $registration,
878
+		string $status
879
+	): string {
880
+		$attendee      = $registration->attendee();
881
+		$attendee_name = $attendee instanceof EE_Attendee
882
+			? $attendee->full_name()
883
+			: '';
884
+		return $this->caps_handler->userCanReadRegistration($registration)
885
+			? '
886 886
             <a  href="' . $this->viewRegistrationUrl($registration) . '"
887 887
                 class="row-title ee-status-color--' . $status . ' ee-aria-tooltip"
888 888
                 aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
889 889
             >
890 890
                 ' . $attendee_name . '
891 891
             </a>'
892
-            : $attendee_name;
893
-    }
894
-
895
-
896
-    /**
897
-     * @throws EE_Error
898
-     * @throws ReflectionException
899
-     */
900
-    protected function viewRegistrationAction(EE_Registration $registration): string
901
-    {
902
-        return $this->caps_handler->userCanReadRegistration($registration)
903
-            ? '
892
+			: $attendee_name;
893
+	}
894
+
895
+
896
+	/**
897
+	 * @throws EE_Error
898
+	 * @throws ReflectionException
899
+	 */
900
+	protected function viewRegistrationAction(EE_Registration $registration): string
901
+	{
902
+		return $this->caps_handler->userCanReadRegistration($registration)
903
+			? '
904 904
             <a  href="' . $this->viewRegistrationUrl($registration) . '"
905 905
                 class="ee-aria-tooltip button button--icon-only"
906 906
                 aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
907 907
             >
908 908
                 <span class="dashicons dashicons-clipboard"></span>
909 909
             </a>'
910
-            : '';
911
-    }
912
-
913
-
914
-    protected function editContactAction(EE_Registration $registration, ?EE_Attendee $attendee = null): string
915
-    {
916
-        if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanEditContacts()) {
917
-            $edit_link_url = EE_Admin_Page::add_query_args_and_nonce(
918
-                [
919
-                    'action' => 'edit_attendee',
920
-                    'post'   => $registration->attendee_ID(),
921
-                ],
922
-                REG_ADMIN_URL
923
-            );
924
-            return '
910
+			: '';
911
+	}
912
+
913
+
914
+	protected function editContactAction(EE_Registration $registration, ?EE_Attendee $attendee = null): string
915
+	{
916
+		if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanEditContacts()) {
917
+			$edit_link_url = EE_Admin_Page::add_query_args_and_nonce(
918
+				[
919
+					'action' => 'edit_attendee',
920
+					'post'   => $registration->attendee_ID(),
921
+				],
922
+				REG_ADMIN_URL
923
+			);
924
+			return '
925 925
                 <a href="' . $edit_link_url . '"
926 926
                    aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso') . '"
927 927
                    class="ee-aria-tooltip button button--secondary button--icon-only"
928 928
                 >
929 929
                     <span class="dashicons dashicons-admin-users"></span>
930 930
                 </a>';
931
-        }
932
-        return '';
933
-    }
934
-
935
-
936
-    /**
937
-     * @throws EE_Error
938
-     * @throws ReflectionException
939
-     */
940
-    protected function resendRegistrationMessageAction(
941
-        EE_Registration $registration,
942
-        ?EE_Attendee $attendee = null
943
-    ): string {
944
-        if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanResendMessage($registration)) {
945
-            $resend_reg_link_url = EE_Admin_Page::add_query_args_and_nonce(
946
-                [
947
-                    'action'  => 'resend_registration',
948
-                    '_REG_ID' => $registration->ID(),
949
-                ],
950
-                REG_ADMIN_URL,
951
-                true
952
-            );
953
-            return '
931
+		}
932
+		return '';
933
+	}
934
+
935
+
936
+	/**
937
+	 * @throws EE_Error
938
+	 * @throws ReflectionException
939
+	 */
940
+	protected function resendRegistrationMessageAction(
941
+		EE_Registration $registration,
942
+		?EE_Attendee $attendee = null
943
+	): string {
944
+		if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanResendMessage($registration)) {
945
+			$resend_reg_link_url = EE_Admin_Page::add_query_args_and_nonce(
946
+				[
947
+					'action'  => 'resend_registration',
948
+					'_REG_ID' => $registration->ID(),
949
+				],
950
+				REG_ADMIN_URL,
951
+				true
952
+			);
953
+			return '
954 954
 			    <a href="' . $resend_reg_link_url . '" aria-label="'
955
-                . esc_attr__('Resend Registration Details', 'event_espresso')
956
-                . '" class="ee-aria-tooltip button button--icon-only">
955
+				. esc_attr__('Resend Registration Details', 'event_espresso')
956
+				. '" class="ee-aria-tooltip button button--icon-only">
957 957
 			        <span class="dashicons dashicons-email-alt"></span>
958 958
 			    </a>';
959
-        }
960
-        return '';
961
-    }
962
-
963
-
964
-    /**
965
-     * @param EE_Transaction $transaction
966
-     * @return string
967
-     * @throws EE_Error
968
-     * @throws ReflectionException
969
-     */
970
-    protected function viewTransactionUrl(EE_Transaction $transaction): string
971
-    {
972
-        return EE_Admin_Page::add_query_args_and_nonce(
973
-            [
974
-                'action' => 'view_transaction',
975
-                'TXN_ID' => $transaction->ID(),
976
-            ],
977
-            TXN_ADMIN_URL
978
-        );
979
-    }
980
-
981
-
982
-    /**
983
-     * @param EE_Transaction $transaction
984
-     * @param string         $link_text
985
-     * @return string
986
-     * @throws EE_Error
987
-     * @throws ReflectionException
988
-     * @since 5.0.18.p
989
-     */
990
-    protected function viewTransactionLink(EE_Transaction $transaction, string $link_text = ''): string
991
-    {
992
-        if ($this->caps_handler->userCanViewTransaction()) {
993
-            $link_text = $link_text ?: '<span class="dashicons dashicons-cart"></span> '
994
-                . esc_html__('View Transaction', 'event_espresso');
995
-            return '
959
+		}
960
+		return '';
961
+	}
962
+
963
+
964
+	/**
965
+	 * @param EE_Transaction $transaction
966
+	 * @return string
967
+	 * @throws EE_Error
968
+	 * @throws ReflectionException
969
+	 */
970
+	protected function viewTransactionUrl(EE_Transaction $transaction): string
971
+	{
972
+		return EE_Admin_Page::add_query_args_and_nonce(
973
+			[
974
+				'action' => 'view_transaction',
975
+				'TXN_ID' => $transaction->ID(),
976
+			],
977
+			TXN_ADMIN_URL
978
+		);
979
+	}
980
+
981
+
982
+	/**
983
+	 * @param EE_Transaction $transaction
984
+	 * @param string         $link_text
985
+	 * @return string
986
+	 * @throws EE_Error
987
+	 * @throws ReflectionException
988
+	 * @since 5.0.18.p
989
+	 */
990
+	protected function viewTransactionLink(EE_Transaction $transaction, string $link_text = ''): string
991
+	{
992
+		if ($this->caps_handler->userCanViewTransaction()) {
993
+			$link_text = $link_text ?: '<span class="dashicons dashicons-cart"></span> '
994
+				. esc_html__('View Transaction', 'event_espresso');
995
+			return '
996 996
             <a class="ee-reg-list-txn-link ee-aria-tooltip ee-status-color--' . $transaction->status_ID() . '"
997 997
                 href="' . $this->viewTransactionUrl($transaction) . '"
998 998
                 aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
999 999
             >
1000 1000
                 ' . $link_text . '
1001 1001
             </a>';
1002
-        }
1003
-        return $link_text;
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * @param EE_Transaction $transaction
1009
-     * @return string
1010
-     * @throws EE_Error
1011
-     * @throws ReflectionException
1012
-     */
1013
-    protected function viewTransactionAction(EE_Transaction $transaction): string
1014
-    {
1015
-        if ($this->caps_handler->userCanViewTransaction()) {
1016
-            return '
1002
+		}
1003
+		return $link_text;
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * @param EE_Transaction $transaction
1009
+	 * @return string
1010
+	 * @throws EE_Error
1011
+	 * @throws ReflectionException
1012
+	 */
1013
+	protected function viewTransactionAction(EE_Transaction $transaction): string
1014
+	{
1015
+		if ($this->caps_handler->userCanViewTransaction()) {
1016
+			return '
1017 1017
                 <a class="ee-aria-tooltip button button--icon-only"
1018 1018
                    href="' . $this->viewTransactionUrl($transaction) . '"
1019 1019
                    aria-label="' . sprintf(
1020
-                    esc_html__('View Transaction Details (%s)', 'event_espresso'),
1021
-                    EEH_Template::pretty_status($transaction->status_ID(), false, 'sentence')
1022
-                ) . '"
1020
+					esc_html__('View Transaction Details (%s)', 'event_espresso'),
1021
+					EEH_Template::pretty_status($transaction->status_ID(), false, 'sentence')
1022
+				) . '"
1023 1023
                 >
1024 1024
                     <span class="dashicons dashicons-cart"></span>
1025 1025
                 </a>';
1026
-        }
1027
-        return '';
1028
-    }
1029
-
1030
-
1031
-    /**
1032
-     * @throws EE_Error
1033
-     * @throws ReflectionException
1034
-     */
1035
-    protected function viewTransactionInvoiceAction(
1036
-        EE_Registration $registration,
1037
-        ?EE_Attendee $attendee = null
1038
-    ): string {
1039
-        // only show invoice link if message type is active.
1040
-        if (
1041
-            $attendee instanceof EE_Attendee
1042
-            && $registration->is_primary_registrant()
1043
-            && EEH_MSG_Template::is_mt_active('invoice')
1044
-        ) {
1045
-            return '
1026
+		}
1027
+		return '';
1028
+	}
1029
+
1030
+
1031
+	/**
1032
+	 * @throws EE_Error
1033
+	 * @throws ReflectionException
1034
+	 */
1035
+	protected function viewTransactionInvoiceAction(
1036
+		EE_Registration $registration,
1037
+		?EE_Attendee $attendee = null
1038
+	): string {
1039
+		// only show invoice link if message type is active.
1040
+		if (
1041
+			$attendee instanceof EE_Attendee
1042
+			&& $registration->is_primary_registrant()
1043
+			&& EEH_MSG_Template::is_mt_active('invoice')
1044
+		) {
1045
+			return '
1046 1046
                 <a aria-label="' . esc_attr__('View Transaction Invoice', 'event_espresso')
1047
-                . '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
1047
+				. '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
1048 1048
                     <span class="dashicons dashicons-media-spreadsheet"></span>
1049 1049
                 </a>';
1050
-        }
1051
-        return '';
1052
-    }
1053
-
1054
-
1055
-    /**
1056
-     * @throws ReflectionException
1057
-     * @throws EE_Error
1058
-     */
1059
-    protected function viewNotificationsAction(EE_Registration $registration): string
1060
-    {
1061
-        // message list table link (filtered by REG_ID
1062
-        return $this->caps_handler->userCanReadGlobalMessages()
1063
-            ? EEH_MSG_Template::get_message_action_link(
1064
-                'see_notifications_for',
1065
-                null,
1066
-                ['_REG_ID' => $registration->ID()]
1067
-            )
1068
-            : '';
1069
-    }
1070
-
1071
-
1072
-    /**
1073
-     * @throws EE_Error
1074
-     * @throws ReflectionException
1075
-     */
1076
-    protected function trashRegistrationLink(
1077
-        EE_Registration $registration,
1078
-        array $url_params
1079
-    ): array {
1080
-        $actions = [];
1081
-        // can't trash what's already trashed
1082
-        if ($this->_view === 'trash') {
1083
-            return $actions;
1084
-        }
1085
-
1086
-        // check caps
1087
-        if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1088
-            return $actions;
1089
-        }
1090
-
1091
-        // don't delete registrations that have payments applied
1092
-        $transaction   = $registration->transaction();
1093
-        $payment_count = $transaction instanceof EE_Transaction
1094
-            ? $transaction->count_related('Payment')
1095
-            : 0;
1096
-
1097
-        if ($payment_count > 0) {
1098
-            return $actions;
1099
-        }
1100
-
1101
-        $url_params['action'] = 'trash_registrations';
1102
-        $trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1103
-        $actions['trash']     = '
1050
+		}
1051
+		return '';
1052
+	}
1053
+
1054
+
1055
+	/**
1056
+	 * @throws ReflectionException
1057
+	 * @throws EE_Error
1058
+	 */
1059
+	protected function viewNotificationsAction(EE_Registration $registration): string
1060
+	{
1061
+		// message list table link (filtered by REG_ID
1062
+		return $this->caps_handler->userCanReadGlobalMessages()
1063
+			? EEH_MSG_Template::get_message_action_link(
1064
+				'see_notifications_for',
1065
+				null,
1066
+				['_REG_ID' => $registration->ID()]
1067
+			)
1068
+			: '';
1069
+	}
1070
+
1071
+
1072
+	/**
1073
+	 * @throws EE_Error
1074
+	 * @throws ReflectionException
1075
+	 */
1076
+	protected function trashRegistrationLink(
1077
+		EE_Registration $registration,
1078
+		array $url_params
1079
+	): array {
1080
+		$actions = [];
1081
+		// can't trash what's already trashed
1082
+		if ($this->_view === 'trash') {
1083
+			return $actions;
1084
+		}
1085
+
1086
+		// check caps
1087
+		if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1088
+			return $actions;
1089
+		}
1090
+
1091
+		// don't delete registrations that have payments applied
1092
+		$transaction   = $registration->transaction();
1093
+		$payment_count = $transaction instanceof EE_Transaction
1094
+			? $transaction->count_related('Payment')
1095
+			: 0;
1096
+
1097
+		if ($payment_count > 0) {
1098
+			return $actions;
1099
+		}
1100
+
1101
+		$url_params['action'] = 'trash_registrations';
1102
+		$trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1103
+		$actions['trash']     = '
1104 1104
             <a class="ee-aria-tooltip"
1105 1105
                 href="' . $trash_link_url . '"
1106 1106
                 aria-label="' . esc_attr__('Trash Registration', 'event_espresso') . '"
1107 1107
             >
1108 1108
                 ' . esc_html__('Trash', 'event_espresso') . '
1109 1109
             </a>';
1110
-        return $actions;
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     * @throws EE_Error
1116
-     * @throws ReflectionException
1117
-     */
1118
-    protected function restoreRegistrationLink(
1119
-        EE_Registration $registration,
1120
-        array $url_params,
1121
-        array $actions
1122
-    ): array {
1123
-        // can't restore what's not trashed
1124
-        if ($this->_view !== 'trash') {
1125
-            return $actions;
1126
-        }
1127
-
1128
-        // restore registration link
1129
-        if ($this->caps_handler->userCanRestoreRegistration($registration)) {
1130
-            $url_params['action'] = 'restore_registrations';
1131
-            $restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1132
-            $actions['restore']   = '
1110
+		return $actions;
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 * @throws EE_Error
1116
+	 * @throws ReflectionException
1117
+	 */
1118
+	protected function restoreRegistrationLink(
1119
+		EE_Registration $registration,
1120
+		array $url_params,
1121
+		array $actions
1122
+	): array {
1123
+		// can't restore what's not trashed
1124
+		if ($this->_view !== 'trash') {
1125
+			return $actions;
1126
+		}
1127
+
1128
+		// restore registration link
1129
+		if ($this->caps_handler->userCanRestoreRegistration($registration)) {
1130
+			$url_params['action'] = 'restore_registrations';
1131
+			$restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1132
+			$actions['restore']   = '
1133 1133
                 <a class="ee-aria-tooltip"
1134 1134
                     href="' . $restore_link_url . '"
1135 1135
                     aria-label="' . esc_attr__('Restore Registration', 'event_espresso') . '"
1136 1136
                 >
1137 1137
                     ' . esc_html__('Restore', 'event_espresso') . '
1138 1138
                 </a>';
1139
-        }
1140
-
1141
-        return $actions;
1142
-    }
1143
-
1144
-
1145
-    /**
1146
-     * @throws EE_Error
1147
-     * @throws ReflectionException
1148
-     */
1149
-    protected function deleteRegistrationLink(
1150
-        EE_Registration $registration,
1151
-        array $url_params,
1152
-        array $actions
1153
-    ): array {
1154
-        if ($this->_view === 'trash' && $this->caps_handler->userCanDeleteRegistration($registration)) {
1155
-            $url_params['action'] = 'delete_registrations';
1156
-            $delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1157
-            $actions['delete']    = '
1139
+		}
1140
+
1141
+		return $actions;
1142
+	}
1143
+
1144
+
1145
+	/**
1146
+	 * @throws EE_Error
1147
+	 * @throws ReflectionException
1148
+	 */
1149
+	protected function deleteRegistrationLink(
1150
+		EE_Registration $registration,
1151
+		array $url_params,
1152
+		array $actions
1153
+	): array {
1154
+		if ($this->_view === 'trash' && $this->caps_handler->userCanDeleteRegistration($registration)) {
1155
+			$url_params['action'] = 'delete_registrations';
1156
+			$delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1157
+			$actions['delete']    = '
1158 1158
                 <a class="ee-aria-tooltip"
1159 1159
                     href="' . $delete_link_url . '"
1160 1160
                     aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso') . '"
1161 1161
                 >
1162 1162
                     ' . esc_html__('Delete', 'event_espresso') . '
1163 1163
                 </a>';
1164
-        }
1165
-        return $actions;
1166
-    }
1167
-
1168
-
1169
-    protected function editEventLink(EE_Registration $registration): string
1170
-    {
1171
-        $EVT_ID     = $registration->event_ID();
1172
-        $event_name = $this->eventName($registration);
1173
-        if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1174
-            return $event_name;
1175
-        }
1176
-        $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
1177
-            ['action' => 'edit', 'post' => $EVT_ID],
1178
-            EVENTS_ADMIN_URL
1179
-        );
1180
-        return '
1164
+		}
1165
+		return $actions;
1166
+	}
1167
+
1168
+
1169
+	protected function editEventLink(EE_Registration $registration): string
1170
+	{
1171
+		$EVT_ID     = $registration->event_ID();
1172
+		$event_name = $this->eventName($registration);
1173
+		if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1174
+			return $event_name;
1175
+		}
1176
+		$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
1177
+			['action' => 'edit', 'post' => $EVT_ID],
1178
+			EVENTS_ADMIN_URL
1179
+		);
1180
+		return '
1181 1181
             <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'] . '"
1182 1182
                 href="' . $edit_event_url . '"
1183 1183
                 aria-label="' . esc_attr($this->_event_details['title_attr']) . '"
1184 1184
             >
1185 1185
                 ' . $event_name . '
1186 1186
             </a>';
1187
-    }
1187
+	}
1188 1188
 
1189 1189
 
1190
-    protected function eventName(EE_Registration $registration): string
1191
-    {
1192
-        $event_name = $registration->event_name();
1193
-        $event_name = $event_name ?: esc_html__("No Associated Event", 'event_espresso');
1194
-        return wp_trim_words($event_name, 30, '...');
1195
-    }
1190
+	protected function eventName(EE_Registration $registration): string
1191
+	{
1192
+		$event_name = $registration->event_name();
1193
+		$event_name = $event_name ?: esc_html__("No Associated Event", 'event_espresso');
1194
+		return wp_trim_words($event_name, 30, '...');
1195
+	}
1196 1196
 
1197 1197
 
1198
-    protected function eventFilterLink(EE_Registration $registration): string
1199
-    {
1200
-        $event_filter_url = EE_Admin_Page::add_query_args_and_nonce(
1201
-            ['event_id' => $registration->event_ID()],
1202
-            REG_ADMIN_URL
1203
-        );
1204
-        return '
1198
+	protected function eventFilterLink(EE_Registration $registration): string
1199
+	{
1200
+		$event_filter_url = EE_Admin_Page::add_query_args_and_nonce(
1201
+			['event_id' => $registration->event_ID()],
1202
+			REG_ADMIN_URL
1203
+		);
1204
+		return '
1205 1205
             <a  class="ee-aria-tooltip ee-event-filter-link"
1206 1206
                 href="' . $event_filter_url . '"
1207 1207
                 aria-label="' . sprintf(
1208
-                    esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1209
-                    $this->eventName($registration)
1210
-                ) . '"
1208
+					esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1209
+					$this->eventName($registration)
1210
+				) . '"
1211 1211
             >
1212 1212
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1213
-                . esc_html__('View Registrations', 'event_espresso') . '
1213
+				. esc_html__('View Registrations', 'event_espresso') . '
1214 1214
             </a>';
1215
-    }
1216
-
1217
-
1218
-    /**
1219
-     * @param EE_Ticket $ticket
1220
-     * @return string
1221
-     * @throws EE_Error
1222
-     * @throws ReflectionException
1223
-     * @since 5.0.18.p
1224
-     */
1225
-    protected function ticketName(EE_Ticket $ticket): string
1226
-    {
1227
-        return '<span class="TKT_name ee-status-color--' . $ticket->ticket_status() . '">' . $ticket->name() . '</span>';
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * @param EE_Ticket $ticket
1233
-     * @return string
1234
-     * @throws EE_Error
1235
-     * @throws ReflectionException
1236
-     * @since 5.0.18.p
1237
-     */
1238
-    protected function ticketFilterLink(EE_Ticket $ticket): string
1239
-    {
1240
-        $ticket_filter_url = EE_Admin_Page::add_query_args_and_nonce(['ticket_id' => $ticket->ID()], REG_ADMIN_URL);
1241
-        return '
1215
+	}
1216
+
1217
+
1218
+	/**
1219
+	 * @param EE_Ticket $ticket
1220
+	 * @return string
1221
+	 * @throws EE_Error
1222
+	 * @throws ReflectionException
1223
+	 * @since 5.0.18.p
1224
+	 */
1225
+	protected function ticketName(EE_Ticket $ticket): string
1226
+	{
1227
+		return '<span class="TKT_name ee-status-color--' . $ticket->ticket_status() . '">' . $ticket->name() . '</span>';
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * @param EE_Ticket $ticket
1233
+	 * @return string
1234
+	 * @throws EE_Error
1235
+	 * @throws ReflectionException
1236
+	 * @since 5.0.18.p
1237
+	 */
1238
+	protected function ticketFilterLink(EE_Ticket $ticket): string
1239
+	{
1240
+		$ticket_filter_url = EE_Admin_Page::add_query_args_and_nonce(['ticket_id' => $ticket->ID()], REG_ADMIN_URL);
1241
+		return '
1242 1242
             <a  class="ee-aria-tooltip ee-ticket-filter-link"
1243 1243
                 href="' . $ticket_filter_url . '"
1244 1244
                 aria-label="' . sprintf(
1245
-                esc_attr__('Filter this list to only show registrations for ticket %s', 'event_espresso'),
1246
-                $ticket->name()
1247
-            ) . '"
1245
+				esc_attr__('Filter this list to only show registrations for ticket %s', 'event_espresso'),
1246
+				$ticket->name()
1247
+			) . '"
1248 1248
             >
1249 1249
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1250
-                . esc_html__('View Registrations', 'event_espresso') . '
1250
+				. esc_html__('View Registrations', 'event_espresso') . '
1251 1251
             </a>';
1252
-    }
1253
-
1254
-
1255
-    /**
1256
-     * @param EE_Registration $registration
1257
-     * @return string
1258
-     * @throws EE_Error
1259
-     * @throws ReflectionException
1260
-     * @deprecated 5.0.18.p
1261
-     */
1262
-    public function column_TXN_paid(EE_Registration $registration): string
1263
-    {
1264
-        $transaction = $registration->transaction();
1265
-        $content = $transaction->pretty_paid();
1266
-        if ($transaction->paid() >= $transaction->total()) {
1267
-            $content .= '<span class="dashicons dashicons-yes green-icon"></span>';
1268
-        }
1269
-        $content .= $this->viewTransactionLink($transaction);
1270
-        return $this->columnContent('TXN_paid', $content, 'end');
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * @param EE_Registration $registration
1276
-     * @return string
1277
-     * @throws EE_Error
1278
-     * @throws ReflectionException
1279
-     * @deprecated 5.0.18.p
1280
-     */
1281
-    public function column_PRC_amount(EE_Registration $registration): string
1282
-    {
1283
-        $ticket = $registration->ticket();
1284
-
1285
-        $content = $this->EVT_ID && $ticket instanceof EE_Ticket
1286
-            ? '<div class="TKT_name">' . $ticket->name() . '</div>'
1287
-            : '';
1288
-
1289
-        $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
1290
-        $content        .= $registration->final_price() > 0
1291
-            ? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
1252
+	}
1253
+
1254
+
1255
+	/**
1256
+	 * @param EE_Registration $registration
1257
+	 * @return string
1258
+	 * @throws EE_Error
1259
+	 * @throws ReflectionException
1260
+	 * @deprecated 5.0.18.p
1261
+	 */
1262
+	public function column_TXN_paid(EE_Registration $registration): string
1263
+	{
1264
+		$transaction = $registration->transaction();
1265
+		$content = $transaction->pretty_paid();
1266
+		if ($transaction->paid() >= $transaction->total()) {
1267
+			$content .= '<span class="dashicons dashicons-yes green-icon"></span>';
1268
+		}
1269
+		$content .= $this->viewTransactionLink($transaction);
1270
+		return $this->columnContent('TXN_paid', $content, 'end');
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * @param EE_Registration $registration
1276
+	 * @return string
1277
+	 * @throws EE_Error
1278
+	 * @throws ReflectionException
1279
+	 * @deprecated 5.0.18.p
1280
+	 */
1281
+	public function column_PRC_amount(EE_Registration $registration): string
1282
+	{
1283
+		$ticket = $registration->ticket();
1284
+
1285
+		$content = $this->EVT_ID && $ticket instanceof EE_Ticket
1286
+			? '<div class="TKT_name">' . $ticket->name() . '</div>'
1287
+			: '';
1288
+
1289
+		$payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
1290
+		$content        .= $registration->final_price() > 0
1291
+			? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
1292 1292
                 ' . $registration->pretty_final_price() . '
1293 1293
                </span>'
1294
-            // free event
1295
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
1294
+			// free event
1295
+			: '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
1296 1296
 
1297
-        return $this->columnContent('PRC_amount', $content, 'end');
1298
-    }
1297
+		return $this->columnContent('PRC_amount', $content, 'end');
1298
+	}
1299 1299
 }
Please login to merge, or discard this patch.
Spacing   +77 added lines, -77 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
         ];
86 86
         foreach ($filters as $filter_key => $filter_value) {
87 87
             if ($filter_value) {
88
-                $this->filters[ $filter_key ] = $filter_value;
88
+                $this->filters[$filter_key] = $filter_value;
89 89
             }
90 90
         }
91 91
 
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
         if ($admin_page instanceof Registrations_Admin_Page) {
110 110
             foreach ($admin_page->get_views() as $view_details) {
111 111
                 foreach ($this->filters as $filter_key => $filter_value) {
112
-                    $extra_query_args[ $view_details['slug'] ][ $filter_key ] = $filter_value;
112
+                    $extra_query_args[$view_details['slug']][$filter_key] = $filter_value;
113 113
                 }
114 114
             }
115 115
         }
@@ -184,7 +184,7 @@  discard block
 block discarded – undo
184 184
 
185 185
         $this->_primary_column   = 'id';
186 186
         $this->_sortable_columns = [
187
-            '_REG_date'     => ['_REG_date' => true],   // true means its already sorted
187
+            '_REG_date'     => ['_REG_date' => true], // true means its already sorted
188 188
             /**
189 189
              * Allows users to change the default sort if they wish.
190 190
              * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
@@ -201,7 +201,7 @@  discard block
 block discarded – undo
201 201
             'DTT_EVT_start' => ['DTT_EVT_start' => false],
202 202
             'id'            => ['REG_ID' => false],
203 203
         ];
204
-        $this->_hidden_columns   = [];
204
+        $this->_hidden_columns = [];
205 205
 
206 206
         $csv_report = RegistrationsCsvReportParams::getRequestParams(
207 207
             $this->getReturnUrl(),
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
             $this->EVT_ID,
210 210
             $this->DTT_ID
211 211
         );
212
-        if (! empty($csv_report)) {
212
+        if ( ! empty($csv_report)) {
213 213
             $this->_bottom_buttons['csv_reg_report'] = $csv_report;
214 214
         }
215 215
     }
@@ -292,14 +292,14 @@  discard block
 block discarded – undo
292 292
         $month_filter = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
293 293
         $filters[] = "
294 294
         <span class='ee-list-table-filter ee-reg-filter__month'>
295
-            <label for='month_range' class='ee-reg-filter__label'>" . esc_html__('Month', 'event_espresso') . "</label>
295
+            <label for='month_range' class='ee-reg-filter__label'>" . esc_html__('Month', 'event_espresso')."</label>
296 296
             $month_filter
297 297
         </span>";
298 298
 
299 299
         $cat_filter = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
300 300
         $filters[] = "
301 301
         <span class='ee-list-table-filter ee-reg-filter__category'>
302
-            <label for='EVT_CAT' class='ee-reg-filter__label'>" . esc_html__('Category', 'event_espresso') . "</label>
302
+            <label for='EVT_CAT' class='ee-reg-filter__label'>" . esc_html__('Category', 'event_espresso')."</label>
303 303
             $cat_filter
304 304
         </span>";
305 305
 
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
             );
317 317
             $filters[] = "
318 318
         <span class='ee-list-table-filter ee-reg-filter__status'>
319
-            <label for='_reg_status' class='ee-reg-filter__label'>" . esc_html__('Status', 'event_espresso') . "</label>
319
+            <label for='_reg_status' class='ee-reg-filter__label'>" . esc_html__('Status', 'event_espresso')."</label>
320 320
             $status_filter
321 321
         </span>";
322 322
         }
@@ -477,10 +477,10 @@  discard block
 block discarded – undo
477 477
         $transaction   = $item->transaction();
478 478
         $payment_count = $transaction->count_related('Payment');
479 479
 
480
-        $content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
480
+        $content = '<input type="checkbox" name="_REG_ID[]" value="'.$REG_ID.'" />';
481 481
         $content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
482 482
             ? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
483
-                    aria-label="' . $this->lockedRegMessage() . '"></span>'
483
+                    aria-label="' . $this->lockedRegMessage().'"></span>'
484 484
             : '';
485 485
         return $this->columnContent('cb', $content, 'center');
486 486
     }
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
      */
507 507
     public function column_id(EE_Registration $registration): string
508 508
     {
509
-        $content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
509
+        $content = '<span class="ee-entity-id">'.$registration->ID().'</span>';
510 510
         $content .= '<span class="show-on-mobile-view-only">';
511 511
         $content .= $this->column_ATT_fname($registration, false);
512 512
         $content .= '</span>';
@@ -536,23 +536,23 @@  discard block
 block discarded – undo
536 536
                 esc_html__('(%1$s / %2$s)', 'event_espresso'),
537 537
                 $registration->count(),
538 538
                 $registration->group_size()
539
-            ) . '
539
+            ).'
540 540
             </span >';
541 541
 
542 542
         $content = '
543 543
         <div class="ee-layout-row">
544
-            <span aria-label="' . $pretty_status . '"
545
-                  class="ee-status-dot ee-status-bg--' . $status . ' ee-aria-tooltip"
544
+            <span aria-label="' . $pretty_status.'"
545
+                  class="ee-status-dot ee-status-bg--' . $status.' ee-aria-tooltip"
546 546
             ></span>
547 547
             ' . $this->viewRegistrationLink($registration, $status)
548 548
             . $prime_reg_star
549
-            . $group_count . '
549
+            . $group_count.'
550 550
             <span class="spacer"></span>
551 551
             <span>
552 552
                 ' . sprintf(
553 553
                 esc_html__('Reg Code: %s', 'event_espresso'),
554 554
                 $registration->get('REG_code')
555
-            ) . '
555
+            ).'
556 556
             </span>
557 557
         </div>';
558 558
 
@@ -606,7 +606,7 @@  discard block
 block discarded – undo
606 606
         $actions['event_filter'] = $this->eventFilterLink($registration);
607 607
         return $this->columnContent(
608 608
             'event_name',
609
-            $edit_event . $this->row_actions($actions)
609
+            $edit_event.$this->row_actions($actions)
610 610
         );
611 611
     }
612 612
 
@@ -648,19 +648,19 @@  discard block
 block discarded – undo
648 648
     {
649 649
         // get first item for initial visibility
650 650
         $content = (string) array_shift($datetime_strings);
651
-        if (! empty($datetime_strings)) {
651
+        if ( ! empty($datetime_strings)) {
652 652
             $content .= '
653 653
                 <div class="ee-registration-event-datetimes-container-wrap">
654 654
                     <div class="ee-registration-event-datetimes-container__control">
655
-                        <span class="tiny-text">' . esc_html__('Click to view additional dates', 'event_espresso') . '</span>
656
-                        <button aria-label="' . esc_attr__('Click to view additional dates', 'event_espresso') . '"
655
+                        <span class="tiny-text">' . esc_html__('Click to view additional dates', 'event_espresso').'</span>
656
+                        <button aria-label="' . esc_attr__('Click to view additional dates', 'event_espresso').'"
657 657
                               class="ee-aria-tooltip button button--secondary button--tiny button--icon-only ee-js ee-more-datetimes-toggle"
658 658
                         >
659 659
                            <span class="dashicons dashicons-admin-collapse"></span>
660 660
                         </button>
661 661
                     </div>
662 662
                     <div class="ee-registration-event-datetimes-container more-items hidden">
663
-                        ' . implode("", $datetime_strings) . '
663
+                        ' . implode("", $datetime_strings).'
664 664
                     </div>
665 665
                 </div>';
666 666
         }
@@ -717,7 +717,7 @@  discard block
 block discarded – undo
717 717
         $actions['ticket_filter'] = $this->ticketFilterLink($ticket);
718 718
         return $this->columnContent(
719 719
             'REG_ticket',
720
-            $ticket_name . $this->row_actions($actions)
720
+            $ticket_name.$this->row_actions($actions)
721 721
         );
722 722
     }
723 723
 
@@ -732,9 +732,9 @@  discard block
 block discarded – undo
732 732
     {
733 733
         // free ticket?
734 734
         $content = $registration->final_price() > 0
735
-            ? '<span class="reg-overview-paid-event-spn">' . $registration->pretty_final_price() . '</span>'
736
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
737
-        return $this->columnContent( '_REG_final_price', $content, 'end' );
735
+            ? '<span class="reg-overview-paid-event-spn">'.$registration->pretty_final_price().'</span>'
736
+            : '<span class="reg-overview-free-event-spn">'.esc_html__('free', 'event_espresso').'</span>';
737
+        return $this->columnContent('_REG_final_price', $content, 'end');
738 738
     }
739 739
 
740 740
 
@@ -766,10 +766,10 @@  discard block
 block discarded – undo
766 766
             $payment_status = EEM_Transaction::overpaid_status_code;
767 767
         }
768 768
         $content .= '
769
-            <span class="reg-overview-paid-event-spn ee-aria-tooltip ee-status-color--' . $payment_status . '"
770
-                  aria-label="' . $label . '"
769
+            <span class="reg-overview-paid-event-spn ee-aria-tooltip ee-status-color--' . $payment_status.'"
770
+                  aria-label="' . $label.'"
771 771
             >
772
-                ' . $icon . $registration->pretty_paid('no_currency_code') . '
772
+                ' . $icon.$registration->pretty_paid('no_currency_code').'
773 773
             </span>
774 774
             </span>';
775 775
         if ($registration->paid() > 0) {
@@ -778,7 +778,7 @@  discard block
 block discarded – undo
778 778
                 ' . sprintf(
779 779
                         esc_html__('...via %s', 'event_espresso'),
780 780
                         $payment_method_name
781
-                    ) . '
781
+                    ).'
782 782
             </span>';
783 783
         }
784 784
         return $this->columnContent('_REG_paid', $content, 'end', 'stack');
@@ -797,17 +797,17 @@  discard block
 block discarded – undo
797 797
      */
798 798
     public function column_TXN_total(EE_Registration $registration): string
799 799
     {
800
-        $content      = '';
800
+        $content = '';
801 801
         if ($registration->count() === 1) {
802 802
             $transaction = $registration->transaction();
803 803
             $content     = '
804
-            <span class="ee-status-color--' . $transaction->status_ID() . '">
805
-                ' . $transaction->pretty_paid('no_currency_code') . '
804
+            <span class="ee-status-color--' . $transaction->status_ID().'">
805
+                ' . $transaction->pretty_paid('no_currency_code').'
806 806
                 <span class="separator">/</span>
807
-                ' . $transaction->pretty_total('no_currency_code') . '
807
+                ' . $transaction->pretty_total('no_currency_code').'
808 808
             </span>';
809 809
 
810
-            $content .= '<span class="row-actions">' . $this->viewTransactionLink($transaction) . '</span>';
810
+            $content .= '<span class="row-actions">'.$this->viewTransactionLink($transaction).'</span>';
811 811
         }
812 812
         return $this->columnContent('TXN_total', $content, 'end', 'stack');
813 813
     }
@@ -883,11 +883,11 @@  discard block
 block discarded – undo
883 883
             : '';
884 884
         return $this->caps_handler->userCanReadRegistration($registration)
885 885
             ? '
886
-            <a  href="' . $this->viewRegistrationUrl($registration) . '"
887
-                class="row-title ee-status-color--' . $status . ' ee-aria-tooltip"
888
-                aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
886
+            <a  href="' . $this->viewRegistrationUrl($registration).'"
887
+                class="row-title ee-status-color--' . $status.' ee-aria-tooltip"
888
+                aria-label="' . esc_attr__('View Registration Details', 'event_espresso').'"
889 889
             >
890
-                ' . $attendee_name . '
890
+                ' . $attendee_name.'
891 891
             </a>'
892 892
             : $attendee_name;
893 893
     }
@@ -901,9 +901,9 @@  discard block
 block discarded – undo
901 901
     {
902 902
         return $this->caps_handler->userCanReadRegistration($registration)
903 903
             ? '
904
-            <a  href="' . $this->viewRegistrationUrl($registration) . '"
904
+            <a  href="' . $this->viewRegistrationUrl($registration).'"
905 905
                 class="ee-aria-tooltip button button--icon-only"
906
-                aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
906
+                aria-label="' . esc_attr__('View Registration Details', 'event_espresso').'"
907 907
             >
908 908
                 <span class="dashicons dashicons-clipboard"></span>
909 909
             </a>'
@@ -922,8 +922,8 @@  discard block
 block discarded – undo
922 922
                 REG_ADMIN_URL
923 923
             );
924 924
             return '
925
-                <a href="' . $edit_link_url . '"
926
-                   aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso') . '"
925
+                <a href="' . $edit_link_url.'"
926
+                   aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso').'"
927 927
                    class="ee-aria-tooltip button button--secondary button--icon-only"
928 928
                 >
929 929
                     <span class="dashicons dashicons-admin-users"></span>
@@ -951,7 +951,7 @@  discard block
 block discarded – undo
951 951
                 true
952 952
             );
953 953
             return '
954
-			    <a href="' . $resend_reg_link_url . '" aria-label="'
954
+			    <a href="' . $resend_reg_link_url.'" aria-label="'
955 955
                 . esc_attr__('Resend Registration Details', 'event_espresso')
956 956
                 . '" class="ee-aria-tooltip button button--icon-only">
957 957
 			        <span class="dashicons dashicons-email-alt"></span>
@@ -993,11 +993,11 @@  discard block
 block discarded – undo
993 993
             $link_text = $link_text ?: '<span class="dashicons dashicons-cart"></span> '
994 994
                 . esc_html__('View Transaction', 'event_espresso');
995 995
             return '
996
-            <a class="ee-reg-list-txn-link ee-aria-tooltip ee-status-color--' . $transaction->status_ID() . '"
997
-                href="' . $this->viewTransactionUrl($transaction) . '"
998
-                aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
996
+            <a class="ee-reg-list-txn-link ee-aria-tooltip ee-status-color--' . $transaction->status_ID().'"
997
+                href="' . $this->viewTransactionUrl($transaction).'"
998
+                aria-label="' . esc_attr__('View Transaction', 'event_espresso').'"
999 999
             >
1000
-                ' . $link_text . '
1000
+                ' . $link_text.'
1001 1001
             </a>';
1002 1002
         }
1003 1003
         return $link_text;
@@ -1015,11 +1015,11 @@  discard block
 block discarded – undo
1015 1015
         if ($this->caps_handler->userCanViewTransaction()) {
1016 1016
             return '
1017 1017
                 <a class="ee-aria-tooltip button button--icon-only"
1018
-                   href="' . $this->viewTransactionUrl($transaction) . '"
1018
+                   href="' . $this->viewTransactionUrl($transaction).'"
1019 1019
                    aria-label="' . sprintf(
1020 1020
                     esc_html__('View Transaction Details (%s)', 'event_espresso'),
1021 1021
                     EEH_Template::pretty_status($transaction->status_ID(), false, 'sentence')
1022
-                ) . '"
1022
+                ).'"
1023 1023
                 >
1024 1024
                     <span class="dashicons dashicons-cart"></span>
1025 1025
                 </a>';
@@ -1044,7 +1044,7 @@  discard block
 block discarded – undo
1044 1044
         ) {
1045 1045
             return '
1046 1046
                 <a aria-label="' . esc_attr__('View Transaction Invoice', 'event_espresso')
1047
-                . '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
1047
+                . '" target="_blank" href="'.$registration->invoice_url().'" class="ee-aria-tooltip button button--icon-only">
1048 1048
                     <span class="dashicons dashicons-media-spreadsheet"></span>
1049 1049
                 </a>';
1050 1050
         }
@@ -1084,7 +1084,7 @@  discard block
 block discarded – undo
1084 1084
         }
1085 1085
 
1086 1086
         // check caps
1087
-        if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1087
+        if ( ! $this->caps_handler->userCanTrashRegistration($registration)) {
1088 1088
             return $actions;
1089 1089
         }
1090 1090
 
@@ -1102,10 +1102,10 @@  discard block
 block discarded – undo
1102 1102
         $trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1103 1103
         $actions['trash']     = '
1104 1104
             <a class="ee-aria-tooltip"
1105
-                href="' . $trash_link_url . '"
1106
-                aria-label="' . esc_attr__('Trash Registration', 'event_espresso') . '"
1105
+                href="' . $trash_link_url.'"
1106
+                aria-label="' . esc_attr__('Trash Registration', 'event_espresso').'"
1107 1107
             >
1108
-                ' . esc_html__('Trash', 'event_espresso') . '
1108
+                ' . esc_html__('Trash', 'event_espresso').'
1109 1109
             </a>';
1110 1110
         return $actions;
1111 1111
     }
@@ -1131,10 +1131,10 @@  discard block
 block discarded – undo
1131 1131
             $restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1132 1132
             $actions['restore']   = '
1133 1133
                 <a class="ee-aria-tooltip"
1134
-                    href="' . $restore_link_url . '"
1135
-                    aria-label="' . esc_attr__('Restore Registration', 'event_espresso') . '"
1134
+                    href="' . $restore_link_url.'"
1135
+                    aria-label="' . esc_attr__('Restore Registration', 'event_espresso').'"
1136 1136
                 >
1137
-                    ' . esc_html__('Restore', 'event_espresso') . '
1137
+                    ' . esc_html__('Restore', 'event_espresso').'
1138 1138
                 </a>';
1139 1139
         }
1140 1140
 
@@ -1156,10 +1156,10 @@  discard block
 block discarded – undo
1156 1156
             $delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1157 1157
             $actions['delete']    = '
1158 1158
                 <a class="ee-aria-tooltip"
1159
-                    href="' . $delete_link_url . '"
1160
-                    aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso') . '"
1159
+                    href="' . $delete_link_url.'"
1160
+                    aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso').'"
1161 1161
                 >
1162
-                    ' . esc_html__('Delete', 'event_espresso') . '
1162
+                    ' . esc_html__('Delete', 'event_espresso').'
1163 1163
                 </a>';
1164 1164
         }
1165 1165
         return $actions;
@@ -1170,7 +1170,7 @@  discard block
 block discarded – undo
1170 1170
     {
1171 1171
         $EVT_ID     = $registration->event_ID();
1172 1172
         $event_name = $this->eventName($registration);
1173
-        if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1173
+        if ( ! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1174 1174
             return $event_name;
1175 1175
         }
1176 1176
         $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
@@ -1178,11 +1178,11 @@  discard block
 block discarded – undo
1178 1178
             EVENTS_ADMIN_URL
1179 1179
         );
1180 1180
         return '
1181
-            <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'] . '"
1182
-                href="' . $edit_event_url . '"
1183
-                aria-label="' . esc_attr($this->_event_details['title_attr']) . '"
1181
+            <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'].'"
1182
+                href="' . $edit_event_url.'"
1183
+                aria-label="' . esc_attr($this->_event_details['title_attr']).'"
1184 1184
             >
1185
-                ' . $event_name . '
1185
+                ' . $event_name.'
1186 1186
             </a>';
1187 1187
     }
1188 1188
 
@@ -1203,14 +1203,14 @@  discard block
 block discarded – undo
1203 1203
         );
1204 1204
         return '
1205 1205
             <a  class="ee-aria-tooltip ee-event-filter-link"
1206
-                href="' . $event_filter_url . '"
1206
+                href="' . $event_filter_url.'"
1207 1207
                 aria-label="' . sprintf(
1208 1208
                     esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1209 1209
                     $this->eventName($registration)
1210
-                ) . '"
1210
+                ).'"
1211 1211
             >
1212 1212
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1213
-                . esc_html__('View Registrations', 'event_espresso') . '
1213
+                . esc_html__('View Registrations', 'event_espresso').'
1214 1214
             </a>';
1215 1215
     }
1216 1216
 
@@ -1224,7 +1224,7 @@  discard block
 block discarded – undo
1224 1224
      */
1225 1225
     protected function ticketName(EE_Ticket $ticket): string
1226 1226
     {
1227
-        return '<span class="TKT_name ee-status-color--' . $ticket->ticket_status() . '">' . $ticket->name() . '</span>';
1227
+        return '<span class="TKT_name ee-status-color--'.$ticket->ticket_status().'">'.$ticket->name().'</span>';
1228 1228
     }
1229 1229
 
1230 1230
 
@@ -1240,14 +1240,14 @@  discard block
 block discarded – undo
1240 1240
         $ticket_filter_url = EE_Admin_Page::add_query_args_and_nonce(['ticket_id' => $ticket->ID()], REG_ADMIN_URL);
1241 1241
         return '
1242 1242
             <a  class="ee-aria-tooltip ee-ticket-filter-link"
1243
-                href="' . $ticket_filter_url . '"
1243
+                href="' . $ticket_filter_url.'"
1244 1244
                 aria-label="' . sprintf(
1245 1245
                 esc_attr__('Filter this list to only show registrations for ticket %s', 'event_espresso'),
1246 1246
                 $ticket->name()
1247
-            ) . '"
1247
+            ).'"
1248 1248
             >
1249 1249
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1250
-                . esc_html__('View Registrations', 'event_espresso') . '
1250
+                . esc_html__('View Registrations', 'event_espresso').'
1251 1251
             </a>';
1252 1252
     }
1253 1253
 
@@ -1283,16 +1283,16 @@  discard block
 block discarded – undo
1283 1283
         $ticket = $registration->ticket();
1284 1284
 
1285 1285
         $content = $this->EVT_ID && $ticket instanceof EE_Ticket
1286
-            ? '<div class="TKT_name">' . $ticket->name() . '</div>'
1286
+            ? '<div class="TKT_name">'.$ticket->name().'</div>'
1287 1287
             : '';
1288 1288
 
1289 1289
         $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
1290
-        $content        .= $registration->final_price() > 0
1291
-            ? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
1292
-                ' . $registration->pretty_final_price() . '
1290
+        $content .= $registration->final_price() > 0
1291
+            ? '<span class="reg-overview-paid-event-spn ee-status-color--'.$payment_status.'">
1292
+                ' . $registration->pretty_final_price().'
1293 1293
                </span>'
1294 1294
             // free event
1295
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
1295
+            : '<span class="reg-overview-free-event-spn">'.esc_html__('free', 'event_espresso').'</span>';
1296 1296
 
1297 1297
         return $this->columnContent('PRC_amount', $content, 'end');
1298 1298
     }
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 1 patch
Indentation   +3807 added lines, -3807 removed lines patch added patch discarded remove patch
@@ -23,2237 +23,2237 @@  discard block
 block discarded – undo
23 23
  */
24 24
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
25 25
 {
26
-    /**
27
-     * @var EE_Registration
28
-     */
29
-    private $_registration;
30
-
31
-    /**
32
-     * @var EE_Event
33
-     */
34
-    private $_reg_event;
35
-
36
-    private array $session_data = [];
37
-
38
-    /**
39
-     * @var array
40
-     */
41
-    private static $_reg_status;
42
-
43
-    /**
44
-     * Form for displaying the custom questions for this registration.
45
-     * This gets used a few times throughout the request so its best to cache it
46
-     *
47
-     * @var EE_Registration_Custom_Questions_Form
48
-     */
49
-    protected $_reg_custom_questions_form;
50
-
51
-    /**
52
-     * @var EEM_Registration $registration_model
53
-     */
54
-    private $registration_model;
55
-
56
-    /**
57
-     * @var EEM_Attendee $attendee_model
58
-     */
59
-    private $attendee_model;
60
-
61
-    /**
62
-     * @var EEM_Event $event_model
63
-     */
64
-    private $event_model;
65
-
66
-    /**
67
-     * @var EEM_Status $status_model
68
-     */
69
-    private $status_model;
70
-
71
-
72
-    /**
73
-     * @param bool $routing
74
-     * @throws InvalidArgumentException
75
-     * @throws InvalidDataTypeException
76
-     * @throws InvalidInterfaceException
77
-     * @throws ReflectionException
78
-     */
79
-    public function __construct($routing = true)
80
-    {
81
-        parent::__construct($routing);
82
-        $this->cpt_editpost_route = 'edit_attendee';
83
-        add_action('wp_loaded', [$this, 'wp_loaded']);
84
-    }
85
-
86
-
87
-    /**
88
-     * @return EEM_Registration
89
-     * @throws InvalidArgumentException
90
-     * @throws InvalidDataTypeException
91
-     * @throws InvalidInterfaceException
92
-     * @since 4.10.2.p
93
-     */
94
-    protected function getRegistrationModel()
95
-    {
96
-        if (! $this->registration_model instanceof EEM_Registration) {
97
-            $this->registration_model = $this->loader->getShared('EEM_Registration');
98
-        }
99
-        return $this->registration_model;
100
-    }
101
-
102
-
103
-    /**
104
-     * @return EEM_Attendee
105
-     * @throws InvalidArgumentException
106
-     * @throws InvalidDataTypeException
107
-     * @throws InvalidInterfaceException
108
-     * @since 4.10.2.p
109
-     */
110
-    protected function getAttendeeModel()
111
-    {
112
-        if (! $this->attendee_model instanceof EEM_Attendee) {
113
-            $this->attendee_model = $this->loader->getShared('EEM_Attendee');
114
-        }
115
-        return $this->attendee_model;
116
-    }
117
-
118
-
119
-    /**
120
-     * @return EEM_Event
121
-     * @throws InvalidArgumentException
122
-     * @throws InvalidDataTypeException
123
-     * @throws InvalidInterfaceException
124
-     * @since 4.10.2.p
125
-     */
126
-    protected function getEventModel()
127
-    {
128
-        if (! $this->event_model instanceof EEM_Event) {
129
-            $this->event_model = $this->loader->getShared('EEM_Event');
130
-        }
131
-        return $this->event_model;
132
-    }
133
-
134
-
135
-    /**
136
-     * @return EEM_Status
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     * @since 4.10.2.p
141
-     */
142
-    protected function getStatusModel()
143
-    {
144
-        if (! $this->status_model instanceof EEM_Status) {
145
-            $this->status_model = $this->loader->getShared('EEM_Status');
146
-        }
147
-        return $this->status_model;
148
-    }
149
-
150
-
151
-    public function wp_loaded()
152
-    {
153
-        // when adding a new registration...
154
-        $action = $this->request->getRequestParam('action');
155
-        if ($action === 'new_registration') {
156
-            EE_System::do_not_cache();
157
-            if ($this->request->getRequestParam('processing_registration', 0, 'int') !== 1) {
158
-                // and it's NOT the attendee information reg step
159
-                // force cookie expiration by setting time to last week
160
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
161
-                // and update the global
162
-                $_COOKIE['ee_registration_added'] = 0;
163
-            }
164
-        }
165
-    }
166
-
167
-
168
-    protected function _init_page_props()
169
-    {
170
-        $this->page_slug        = REG_PG_SLUG;
171
-        $this->_admin_base_url  = REG_ADMIN_URL;
172
-        $this->_admin_base_path = REG_ADMIN;
173
-        $this->page_label       = esc_html__('Registrations', 'event_espresso');
174
-        $this->_cpt_routes      = [
175
-            'add_new_attendee' => 'espresso_attendees',
176
-            'edit_attendee'    => 'espresso_attendees',
177
-            'insert_attendee'  => 'espresso_attendees',
178
-            'update_attendee'  => 'espresso_attendees',
179
-        ];
180
-        $this->_cpt_model_names = [
181
-            'add_new_attendee' => 'EEM_Attendee',
182
-            'edit_attendee'    => 'EEM_Attendee',
183
-        ];
184
-        $this->_cpt_edit_routes = [
185
-            'espresso_attendees' => 'edit_attendee',
186
-        ];
187
-        $this->_pagenow_map     = [
188
-            'add_new_attendee' => 'post-new.php',
189
-            'edit_attendee'    => 'post.php',
190
-            'trash'            => 'post.php',
191
-        ];
192
-        add_action('edit_form_after_title', [$this, 'after_title_form_fields'], 10);
193
-        // add filters so that the comment urls don't take users to a confusing 404 page
194
-        add_filter('get_comment_link', [$this, 'clear_comment_link'], 10, 2);
195
-    }
196
-
197
-
198
-    /**
199
-     * @param string     $link    The comment permalink with '#comment-$id' appended.
200
-     * @param WP_Comment $comment The current comment object.
201
-     * @return string
202
-     */
203
-    public function clear_comment_link($link, WP_Comment $comment)
204
-    {
205
-        // gotta make sure this only happens on this route
206
-        $post_type = get_post_type($comment->comment_post_ID);
207
-        if ($post_type === EspressoPostType::ATTENDEES) {
208
-            return '#commentsdiv';
209
-        }
210
-        return $link;
211
-    }
212
-
213
-
214
-    protected function _ajax_hooks()
215
-    {
216
-    }
217
-
218
-
219
-    protected function _define_page_props()
220
-    {
221
-        $this->_admin_page_title = $this->page_label;
222
-        $this->_labels           = [
223
-            'buttons'                      => [
224
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
225
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
226
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
227
-                'csv_reg_report'      => esc_html__('Registrations CSV Report', 'event_espresso'),
228
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
229
-                'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
230
-            ],
231
-            'publishbox'                   => [
232
-                'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
233
-                'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
234
-            ],
235
-            'hide_add_button_on_cpt_route' => [
236
-                'edit_attendee' => true,
237
-            ],
238
-        ];
239
-    }
240
-
241
-
242
-    /**
243
-     * grab url requests and route them
244
-     *
245
-     * @return void
246
-     * @throws EE_Error
247
-     */
248
-    public function _set_page_routes()
249
-    {
250
-        $this->_get_registration_status_array();
251
-        $REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
252
-        $REG_ID             = $this->request->getRequestParam('reg_status_change_form[REG_ID]', $REG_ID, 'int');
253
-        $ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
254
-        $ATT_ID             = $this->request->getRequestParam('post', $ATT_ID, 'int');
255
-        $this->_page_routes = [
256
-            'default'                             => [
257
-                'func'       => [$this, '_registrations_overview_list_table'],
258
-                'capability' => 'ee_read_registrations',
259
-            ],
260
-            'view_registration'                   => [
261
-                'func'       => [$this, '_registration_details'],
262
-                'capability' => 'ee_read_registration',
263
-                'obj_id'     => $REG_ID,
264
-            ],
265
-            'edit_registration'                   => [
266
-                'func'               => '_update_attendee_registration_form',
267
-                'noheader'           => true,
268
-                'headers_sent_route' => 'view_registration',
269
-                'capability'         => 'ee_edit_registration',
270
-                'obj_id'             => $REG_ID,
271
-                '_REG_ID'            => $REG_ID,
272
-            ],
273
-            'trash_registrations'                 => [
274
-                'func'       => '_trash_or_restore_registrations',
275
-                'args'       => ['trash' => true],
276
-                'noheader'   => true,
277
-                'capability' => 'ee_delete_registrations',
278
-            ],
279
-            'restore_registrations'               => [
280
-                'func'       => '_trash_or_restore_registrations',
281
-                'args'       => ['trash' => false],
282
-                'noheader'   => true,
283
-                'capability' => 'ee_delete_registrations',
284
-            ],
285
-            'delete_registrations'                => [
286
-                'func'       => '_delete_registrations',
287
-                'noheader'   => true,
288
-                'capability' => 'ee_delete_registrations',
289
-            ],
290
-            'new_registration'                    => [
291
-                'func'       => 'new_registration',
292
-                'capability' => 'ee_edit_registrations',
293
-            ],
294
-            'process_reg_step'                    => [
295
-                'func'       => 'process_reg_step',
296
-                'noheader'   => true,
297
-                'capability' => 'ee_edit_registrations',
298
-            ],
299
-            'redirect_to_txn'                     => [
300
-                'func'       => 'redirect_to_txn',
301
-                'noheader'   => true,
302
-                'capability' => 'ee_edit_registrations',
303
-            ],
304
-            'change_reg_status'                   => [
305
-                'func'       => '_change_reg_status',
306
-                'noheader'   => true,
307
-                'capability' => 'ee_edit_registration',
308
-                'obj_id'     => $REG_ID,
309
-            ],
310
-            'approve_registration'                => [
311
-                'func'       => 'approve_registration',
312
-                'noheader'   => true,
313
-                'capability' => 'ee_edit_registration',
314
-                'obj_id'     => $REG_ID,
315
-            ],
316
-            'approve_and_notify_registration'     => [
317
-                'func'       => 'approve_registration',
318
-                'noheader'   => true,
319
-                'args'       => [true],
320
-                'capability' => 'ee_edit_registration',
321
-                'obj_id'     => $REG_ID,
322
-            ],
323
-            'approve_registrations'               => [
324
-                'func'       => 'bulk_action_on_registrations',
325
-                'noheader'   => true,
326
-                'capability' => 'ee_edit_registrations',
327
-                'args'       => ['approve'],
328
-            ],
329
-            'approve_and_notify_registrations'    => [
330
-                'func'       => 'bulk_action_on_registrations',
331
-                'noheader'   => true,
332
-                'capability' => 'ee_edit_registrations',
333
-                'args'       => ['approve', true],
334
-            ],
335
-            'decline_registration'                => [
336
-                'func'       => 'decline_registration',
337
-                'noheader'   => true,
338
-                'capability' => 'ee_edit_registration',
339
-                'obj_id'     => $REG_ID,
340
-            ],
341
-            'decline_and_notify_registration'     => [
342
-                'func'       => 'decline_registration',
343
-                'noheader'   => true,
344
-                'args'       => [true],
345
-                'capability' => 'ee_edit_registration',
346
-                'obj_id'     => $REG_ID,
347
-            ],
348
-            'decline_registrations'               => [
349
-                'func'       => 'bulk_action_on_registrations',
350
-                'noheader'   => true,
351
-                'capability' => 'ee_edit_registrations',
352
-                'args'       => ['decline'],
353
-            ],
354
-            'decline_and_notify_registrations'    => [
355
-                'func'       => 'bulk_action_on_registrations',
356
-                'noheader'   => true,
357
-                'capability' => 'ee_edit_registrations',
358
-                'args'       => ['decline', true],
359
-            ],
360
-            'pending_registration'                => [
361
-                'func'       => 'pending_registration',
362
-                'noheader'   => true,
363
-                'capability' => 'ee_edit_registration',
364
-                'obj_id'     => $REG_ID,
365
-            ],
366
-            'pending_and_notify_registration'     => [
367
-                'func'       => 'pending_registration',
368
-                'noheader'   => true,
369
-                'args'       => [true],
370
-                'capability' => 'ee_edit_registration',
371
-                'obj_id'     => $REG_ID,
372
-            ],
373
-            'pending_registrations'               => [
374
-                'func'       => 'bulk_action_on_registrations',
375
-                'noheader'   => true,
376
-                'capability' => 'ee_edit_registrations',
377
-                'args'       => ['pending'],
378
-            ],
379
-            'pending_and_notify_registrations'    => [
380
-                'func'       => 'bulk_action_on_registrations',
381
-                'noheader'   => true,
382
-                'capability' => 'ee_edit_registrations',
383
-                'args'       => ['pending', true],
384
-            ],
385
-            'no_approve_registration'             => [
386
-                'func'       => 'not_approve_registration',
387
-                'noheader'   => true,
388
-                'capability' => 'ee_edit_registration',
389
-                'obj_id'     => $REG_ID,
390
-            ],
391
-            'no_approve_and_notify_registration'  => [
392
-                'func'       => 'not_approve_registration',
393
-                'noheader'   => true,
394
-                'args'       => [true],
395
-                'capability' => 'ee_edit_registration',
396
-                'obj_id'     => $REG_ID,
397
-            ],
398
-            'no_approve_registrations'            => [
399
-                'func'       => 'bulk_action_on_registrations',
400
-                'noheader'   => true,
401
-                'capability' => 'ee_edit_registrations',
402
-                'args'       => ['not_approve'],
403
-            ],
404
-            'no_approve_and_notify_registrations' => [
405
-                'func'       => 'bulk_action_on_registrations',
406
-                'noheader'   => true,
407
-                'capability' => 'ee_edit_registrations',
408
-                'args'       => ['not_approve', true],
409
-            ],
410
-            'cancel_registration'                 => [
411
-                'func'       => 'cancel_registration',
412
-                'noheader'   => true,
413
-                'capability' => 'ee_edit_registration',
414
-                'obj_id'     => $REG_ID,
415
-            ],
416
-            'cancel_and_notify_registration'      => [
417
-                'func'       => 'cancel_registration',
418
-                'noheader'   => true,
419
-                'args'       => [true],
420
-                'capability' => 'ee_edit_registration',
421
-                'obj_id'     => $REG_ID,
422
-            ],
423
-            'cancel_registrations'                => [
424
-                'func'       => 'bulk_action_on_registrations',
425
-                'noheader'   => true,
426
-                'capability' => 'ee_edit_registrations',
427
-                'args'       => ['cancel'],
428
-            ],
429
-            'cancel_and_notify_registrations'     => [
430
-                'func'       => 'bulk_action_on_registrations',
431
-                'noheader'   => true,
432
-                'capability' => 'ee_edit_registrations',
433
-                'args'       => ['cancel', true],
434
-            ],
435
-            'wait_list_registration'              => [
436
-                'func'       => 'wait_list_registration',
437
-                'noheader'   => true,
438
-                'capability' => 'ee_edit_registration',
439
-                'obj_id'     => $REG_ID,
440
-            ],
441
-            'wait_list_and_notify_registration'   => [
442
-                'func'       => 'wait_list_registration',
443
-                'noheader'   => true,
444
-                'args'       => [true],
445
-                'capability' => 'ee_edit_registration',
446
-                'obj_id'     => $REG_ID,
447
-            ],
448
-            'contact_list'                        => [
449
-                'func'       => '_attendee_contact_list_table',
450
-                'capability' => 'ee_read_contacts',
451
-            ],
452
-            'add_new_attendee'                    => [
453
-                'func' => '_create_new_cpt_item',
454
-                'args' => [
455
-                    'new_attendee' => true,
456
-                    'capability'   => 'ee_edit_contacts',
457
-                ],
458
-            ],
459
-            'edit_attendee'                       => [
460
-                'func'       => '_edit_cpt_item',
461
-                'capability' => 'ee_edit_contacts',
462
-                'obj_id'     => $ATT_ID,
463
-            ],
464
-            'duplicate_attendee'                  => [
465
-                'func'       => '_duplicate_attendee',
466
-                'noheader'   => true,
467
-                'capability' => 'ee_edit_contacts',
468
-                'obj_id'     => $ATT_ID,
469
-            ],
470
-            'insert_attendee'                     => [
471
-                'func'       => '_insert_or_update_attendee',
472
-                'args'       => [
473
-                    'new_attendee' => true,
474
-                ],
475
-                'noheader'   => true,
476
-                'capability' => 'ee_edit_contacts',
477
-            ],
478
-            'update_attendee'                     => [
479
-                'func'       => '_insert_or_update_attendee',
480
-                'args'       => [
481
-                    'new_attendee' => false,
482
-                ],
483
-                'noheader'   => true,
484
-                'capability' => 'ee_edit_contacts',
485
-                'obj_id'     => $ATT_ID,
486
-            ],
487
-            'trash_attendees'                     => [
488
-                'func'       => '_trash_or_restore_attendees',
489
-                'args'       => [
490
-                    'trash' => 'true',
491
-                ],
492
-                'noheader'   => true,
493
-                'capability' => 'ee_delete_contacts',
494
-            ],
495
-            'trash_attendee'                      => [
496
-                'func'       => '_trash_or_restore_attendees',
497
-                'args'       => [
498
-                    'trash' => true,
499
-                ],
500
-                'noheader'   => true,
501
-                'capability' => 'ee_delete_contacts',
502
-                'obj_id'     => $ATT_ID,
503
-            ],
504
-            'restore_attendees'                   => [
505
-                'func'       => '_trash_or_restore_attendees',
506
-                'args'       => [
507
-                    'trash' => false,
508
-                ],
509
-                'noheader'   => true,
510
-                'capability' => 'ee_delete_contacts',
511
-                'obj_id'     => $ATT_ID,
512
-            ],
513
-            'delete_attendee'                  => [
514
-                'func'       => [$this, 'deleteAttendees'],
515
-                'capability' => 'ee_delete_contacts',
516
-                'obj_id'     => $ATT_ID,
517
-                'noheader'   => true,
518
-            ],
519
-            'delete_attendees'                 => [
520
-                'func'       => [$this, 'deleteAttendees'],
521
-                'capability' => 'ee_delete_contacts',
522
-                'noheader'   => true,
523
-            ],
524
-            'resend_registration'                 => [
525
-                'func'       => '_resend_registration',
526
-                'noheader'   => true,
527
-                'capability' => 'ee_send_message',
528
-            ],
529
-            'registrations_report'                => [
530
-                'func'       => [$this, '_registrations_report'],
531
-                'noheader'   => true,
532
-                'capability' => 'ee_read_registrations',
533
-            ],
534
-            'contact_list_export'                 => [
535
-                'func'       => '_contact_list_export',
536
-                'noheader'   => true,
537
-                'capability' => 'export',
538
-            ],
539
-            'contact_list_report'                 => [
540
-                'func'       => '_contact_list_report',
541
-                'noheader'   => true,
542
-                'capability' => 'ee_read_contacts',
543
-            ],
544
-        ];
545
-    }
546
-
547
-
548
-    protected function _set_page_config()
549
-    {
550
-        $REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
551
-        $ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
552
-        $this->_page_config = [
553
-            'default'           => [
554
-                'nav'           => [
555
-                    'label' => esc_html__('Overview', 'event_espresso'),
556
-                    'icon'  => 'dashicons-list-view',
557
-                    'order' => 5,
558
-                ],
559
-                'help_tabs'     => [
560
-                    'registrations_overview_help_tab'                       => [
561
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
562
-                        'filename' => 'registrations_overview',
563
-                    ],
564
-                    'registrations_overview_table_column_headings_help_tab' => [
565
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
566
-                        'filename' => 'registrations_overview_table_column_headings',
567
-                    ],
568
-                    'registrations_overview_filters_help_tab'               => [
569
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
570
-                        'filename' => 'registrations_overview_filters',
571
-                    ],
572
-                    'registrations_overview_views_help_tab'                 => [
573
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
574
-                        'filename' => 'registrations_overview_views',
575
-                    ],
576
-                    'registrations_regoverview_other_help_tab'              => [
577
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
578
-                        'filename' => 'registrations_overview_other',
579
-                    ],
580
-                ],
581
-                'list_table'    => 'EE_Registrations_List_Table',
582
-                'require_nonce' => false,
583
-            ],
584
-            'view_registration' => [
585
-                'nav'           => [
586
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
587
-                    'icon'       => 'dashicons-clipboard',
588
-                    'order'      => 15,
589
-                    'url'        => $REG_ID
590
-                        ? add_query_arg(['_REG_ID' => $REG_ID], $this->_current_page_view_url)
591
-                        : $this->_admin_base_url,
592
-                    'persistent' => false,
593
-                ],
594
-                'help_tabs'     => [
595
-                    'registrations_details_help_tab'                    => [
596
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
597
-                        'filename' => 'registrations_details',
598
-                    ],
599
-                    'registrations_details_table_help_tab'              => [
600
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
601
-                        'filename' => 'registrations_details_table',
602
-                    ],
603
-                    'registrations_details_form_answers_help_tab'       => [
604
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
605
-                        'filename' => 'registrations_details_form_answers',
606
-                    ],
607
-                    'registrations_details_registrant_details_help_tab' => [
608
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
609
-                        'filename' => 'registrations_details_registrant_details',
610
-                    ],
611
-                ],
612
-                'metaboxes'     => array_merge(
613
-                    $this->_default_espresso_metaboxes,
614
-                    ['_registration_details_metaboxes']
615
-                ),
616
-                'require_nonce' => false,
617
-            ],
618
-            'new_registration'  => [
619
-                'nav'           => [
620
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
621
-                    'icon'       => 'dashicons-plus-alt',
622
-                    'url'        => '#',
623
-                    'order'      => 15,
624
-                    'persistent' => false,
625
-                ],
626
-                'metaboxes'     => $this->_default_espresso_metaboxes,
627
-                'labels'        => [
628
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
629
-                ],
630
-                'require_nonce' => false,
631
-            ],
632
-            'add_new_attendee'  => [
633
-                'nav'           => [
634
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
635
-                    'icon'       => 'dashicons-plus-alt',
636
-                    'order'      => 15,
637
-                    'persistent' => false,
638
-                ],
639
-                'metaboxes'     => array_merge(
640
-                    $this->_default_espresso_metaboxes,
641
-                    ['_publish_post_box', 'attendee_editor_metaboxes']
642
-                ),
643
-                'require_nonce' => false,
644
-            ],
645
-            'edit_attendee'     => [
646
-                'nav'           => [
647
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
648
-                    'icon'       => 'dashicons-edit-large',
649
-                    'order'      => 15,
650
-                    'persistent' => false,
651
-                    'url'        => $ATT_ID
652
-                        ? add_query_arg(['ATT_ID' => $ATT_ID], $this->_current_page_view_url)
653
-                        : $this->_admin_base_url,
654
-                ],
655
-                'metaboxes'     => array_merge(
656
-                    $this->_default_espresso_metaboxes,
657
-                    ['attendee_editor_metaboxes']
658
-                ),
659
-                'require_nonce' => false,
660
-            ],
661
-            'contact_list'      => [
662
-                'nav'           => [
663
-                    'label' => esc_html__('Contact List', 'event_espresso'),
664
-                    'icon'  => 'dashicons-id-alt',
665
-                    'order' => 20,
666
-                ],
667
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
668
-                'help_tabs'     => [
669
-                    'registrations_contact_list_help_tab'                       => [
670
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
671
-                        'filename' => 'registrations_contact_list',
672
-                    ],
673
-                    'registrations_contact-list_table_column_headings_help_tab' => [
674
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
675
-                        'filename' => 'registrations_contact_list_table_column_headings',
676
-                    ],
677
-                    'registrations_contact_list_views_help_tab'                 => [
678
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
679
-                        'filename' => 'registrations_contact_list_views',
680
-                    ],
681
-                    'registrations_contact_list_other_help_tab'                 => [
682
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
683
-                        'filename' => 'registrations_contact_list_other',
684
-                    ],
685
-                ],
686
-                'metaboxes'     => [],
687
-                'require_nonce' => false,
688
-            ],
689
-            // override default cpt routes
690
-            'create_new'        => '',
691
-            'edit'              => '',
692
-        ];
693
-    }
694
-
695
-
696
-    /**
697
-     * The below methods aren't used by this class currently
698
-     */
699
-    protected function _add_screen_options()
700
-    {
701
-    }
702
-
703
-
704
-    protected function _add_feature_pointers()
705
-    {
706
-    }
707
-
708
-
709
-    public function admin_init()
710
-    {
711
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
712
-            'click "Update Registration Questions" to save your changes',
713
-            'event_espresso'
714
-        );
715
-    }
716
-
717
-
718
-    public function admin_notices()
719
-    {
720
-    }
721
-
722
-
723
-    public function admin_footer_scripts()
724
-    {
725
-    }
726
-
727
-
728
-    /**
729
-     * get list of registration statuses
730
-     *
731
-     * @return void
732
-     * @throws EE_Error
733
-     * @throws ReflectionException
734
-     */
735
-    private function _get_registration_status_array()
736
-    {
737
-        self::$_reg_status = EEM_Registration::reg_status_array([], true);
738
-    }
739
-
740
-
741
-    /**
742
-     * @throws InvalidArgumentException
743
-     * @throws InvalidDataTypeException
744
-     * @throws InvalidInterfaceException
745
-     * @since 4.10.2.p
746
-     */
747
-    protected function _add_screen_options_default()
748
-    {
749
-        $this->_per_page_screen_option();
750
-    }
751
-
752
-
753
-    /**
754
-     * @throws InvalidArgumentException
755
-     * @throws InvalidDataTypeException
756
-     * @throws InvalidInterfaceException
757
-     * @since 4.10.2.p
758
-     */
759
-    protected function _add_screen_options_contact_list()
760
-    {
761
-        $page_title              = $this->_admin_page_title;
762
-        $this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
763
-        $this->_per_page_screen_option();
764
-        $this->_admin_page_title = $page_title;
765
-    }
766
-
767
-
768
-    public function load_scripts_styles()
769
-    {
770
-        // style
771
-        wp_register_style(
772
-            'espresso_reg',
773
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
774
-            ['ee-admin-css'],
775
-            EVENT_ESPRESSO_VERSION
776
-        );
777
-        wp_enqueue_style('espresso_reg');
778
-        // script
779
-        wp_register_script(
780
-            'espresso_reg',
781
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
782
-            ['jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'],
783
-            EVENT_ESPRESSO_VERSION,
784
-            true
785
-        );
786
-        wp_enqueue_script('espresso_reg');
787
-    }
788
-
789
-
790
-    /**
791
-     * @throws EE_Error
792
-     * @throws InvalidArgumentException
793
-     * @throws InvalidDataTypeException
794
-     * @throws InvalidInterfaceException
795
-     * @throws ReflectionException
796
-     * @since 4.10.2.p
797
-     */
798
-    public function load_scripts_styles_edit_attendee()
799
-    {
800
-        // stuff to only show up on our attendee edit details page.
801
-        $attendee_details_translations = [
802
-            'att_publish_text' => sprintf(
803
-            /* translators: The date and time */
804
-                wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
805
-                '<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
806
-            ),
807
-        ];
808
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
809
-        wp_enqueue_script('jquery-validate');
810
-    }
811
-
812
-
813
-    /**
814
-     * @throws EE_Error
815
-     * @throws InvalidArgumentException
816
-     * @throws InvalidDataTypeException
817
-     * @throws InvalidInterfaceException
818
-     * @throws ReflectionException
819
-     * @since 4.10.2.p
820
-     */
821
-    public function load_scripts_styles_view_registration()
822
-    {
823
-        $this->_set_registration_object();
824
-        // styles
825
-        wp_enqueue_style('espresso-ui-theme');
826
-        // scripts
827
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
828
-        $this->_reg_custom_questions_form->wp_enqueue_scripts();
829
-    }
830
-
831
-
832
-    public function load_scripts_styles_contact_list()
833
-    {
834
-        wp_dequeue_style('espresso_reg');
835
-        wp_register_style(
836
-            'espresso_att',
837
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
838
-            ['ee-admin-css'],
839
-            EVENT_ESPRESSO_VERSION
840
-        );
841
-        wp_enqueue_style('espresso_att');
842
-    }
843
-
844
-
845
-    public function load_scripts_styles_new_registration()
846
-    {
847
-        wp_register_script(
848
-            'ee-spco-for-admin',
849
-            REG_ASSETS_URL . 'spco_for_admin.js',
850
-            ['underscore', 'jquery'],
851
-            EVENT_ESPRESSO_VERSION,
852
-            true
853
-        );
854
-        wp_enqueue_script('ee-spco-for-admin');
855
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
856
-        EE_Form_Section_Proper::wp_enqueue_scripts();
857
-        EED_Ticket_Selector::load_tckt_slctr_assets();
858
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
859
-    }
860
-
861
-
862
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
863
-    {
864
-        add_filter('FHEE_load_EE_messages', '__return_true');
865
-    }
866
-
867
-
868
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
869
-    {
870
-        add_filter('FHEE_load_EE_messages', '__return_true');
871
-    }
872
-
873
-
874
-    /**
875
-     * @throws EE_Error
876
-     * @throws InvalidArgumentException
877
-     * @throws InvalidDataTypeException
878
-     * @throws InvalidInterfaceException
879
-     * @throws ReflectionException
880
-     * @since 4.10.2.p
881
-     */
882
-    protected function _set_list_table_views_default()
883
-    {
884
-        // for notification related bulk actions we need to make sure only active messengers have an option.
885
-        EED_Messages::set_autoloaders();
886
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
887
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
888
-        $active_mts               = $message_resource_manager->list_of_active_message_types();
889
-        // key= bulk_action_slug, value= message type.
890
-        $match_array = [
891
-            'approve_registrations'    => 'registration',
892
-            'decline_registrations'    => 'declined_registration',
893
-            'pending_registrations'    => 'pending_approval',
894
-            'no_approve_registrations' => 'not_approved_registration',
895
-            'cancel_registrations'     => 'cancelled_registration',
896
-        ];
897
-        $can_send    = $this->capabilities->current_user_can(
898
-            'ee_send_message',
899
-            'batch_send_messages'
900
-        );
901
-        /** setup reg status bulk actions **/
902
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
903
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
904
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
905
-                'Approve and Notify Registrations',
906
-                'event_espresso'
907
-            );
908
-        }
909
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
910
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
911
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
912
-                'Decline and Notify Registrations',
913
-                'event_espresso'
914
-            );
915
-        }
916
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
917
-            'Set Registrations to Pending Payment',
918
-            'event_espresso'
919
-        );
920
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
921
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
922
-                'Set Registrations to Pending Payment and Notify',
923
-                'event_espresso'
924
-            );
925
-        }
926
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
927
-            'Set Registrations to Awaiting Review',
928
-            'event_espresso'
929
-        );
930
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
931
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
932
-                'Set Registrations to Awaiting Review and Notify',
933
-                'event_espresso'
934
-            );
935
-        }
936
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
937
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
938
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
939
-                'Cancel Registrations and Notify',
940
-                'event_espresso'
941
-            );
942
-        }
943
-        $def_reg_status_actions = apply_filters(
944
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
945
-            $def_reg_status_actions,
946
-            $active_mts,
947
-            $can_send
948
-        );
949
-
950
-        $current_time = current_time('timestamp');
951
-        $this->_views = [
952
-            'all'   => [
953
-                'slug'        => 'all',
954
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
955
-                'count'       => 0,
956
-                'bulk_action' => array_merge(
957
-                    $def_reg_status_actions,
958
-                    [
959
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
960
-                    ]
961
-                ),
962
-            ],
963
-            'today' => [
964
-                'slug'        => 'today',
965
-                'label'       => sprintf(
966
-                    esc_html__('Today - %s', 'event_espresso'),
967
-                    date('M d, Y', $current_time)
968
-                ),
969
-                'count'       => 0,
970
-                'bulk_action' => array_merge(
971
-                    $def_reg_status_actions,
972
-                    [
973
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
974
-                    ]
975
-                ),
976
-            ],
977
-            'yesterday' => [
978
-                'slug'        => 'yesterday',
979
-                'label'       => sprintf(
980
-                    esc_html__('Yesterday - %s', 'event_espresso'),
981
-                    date('M d, Y', $current_time - DAY_IN_SECONDS)
982
-                ),
983
-                'count'       => 0,
984
-                'bulk_action' => array_merge(
985
-                    $def_reg_status_actions,
986
-                    [
987
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
988
-                    ]
989
-                ),
990
-            ],
991
-            'month' => [
992
-                'slug'        => 'month',
993
-                'label'       => esc_html__('This Month', 'event_espresso'),
994
-                'count'       => 0,
995
-                'bulk_action' => array_merge(
996
-                    $def_reg_status_actions,
997
-                    [
998
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
999
-                    ]
1000
-                ),
1001
-            ],
1002
-        ];
1003
-        if (
1004
-            $this->capabilities->current_user_can(
1005
-                'ee_delete_registrations',
1006
-                'espresso_registrations_delete_registration'
1007
-            )
1008
-        ) {
1009
-            $this->_views['incomplete'] = [
1010
-                'slug'        => 'incomplete',
1011
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
1012
-                'count'       => 0,
1013
-                'bulk_action' => [
1014
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
1015
-                ],
1016
-            ];
1017
-            $this->_views['trash']      = [
1018
-                'slug'        => 'trash',
1019
-                'label'       => esc_html__('Trash', 'event_espresso'),
1020
-                'count'       => 0,
1021
-                'bulk_action' => [
1022
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
1023
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
1024
-                ],
1025
-            ];
1026
-        }
1027
-    }
1028
-
1029
-
1030
-    protected function _set_list_table_views_contact_list()
1031
-    {
1032
-        $this->_views = [
1033
-            'in_use' => [
1034
-                'slug'        => 'in_use',
1035
-                'label'       => esc_html__('In Use', 'event_espresso'),
1036
-                'count'       => 0,
1037
-                'bulk_action' => [
1038
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1039
-                ],
1040
-            ],
1041
-        ];
1042
-        if (
1043
-            $this->capabilities->current_user_can(
1044
-                'ee_delete_contacts',
1045
-                'espresso_registrations_trash_attendees'
1046
-            )
1047
-        ) {
1048
-            $this->_views['trash'] = [
1049
-                'slug'        => 'trash',
1050
-                'label'       => esc_html__('Trash', 'event_espresso'),
1051
-                'count'       => 0,
1052
-                'bulk_action' => [
1053
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1054
-                    'delete_attendees' => esc_html__('Permanently Delete', 'event_espresso'),
1055
-                ],
1056
-            ];
1057
-        }
1058
-    }
1059
-
1060
-
1061
-    /**
1062
-     * @return array
1063
-     * @throws EE_Error
1064
-     */
1065
-    protected function _registration_legend_items()
1066
-    {
1067
-        $fc_items = [
1068
-            'star-icon'        => [
1069
-                'class' => 'dashicons dashicons-star-filled gold-icon',
1070
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1071
-            ],
1072
-            'view_details'     => [
1073
-                'class' => 'dashicons dashicons-clipboard',
1074
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1075
-            ],
1076
-            'edit_attendee'    => [
1077
-                'class' => 'dashicons dashicons-admin-users',
1078
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1079
-            ],
1080
-            'view_transaction' => [
1081
-                'class' => 'dashicons dashicons-cart',
1082
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1083
-            ],
1084
-            'view_invoice'     => [
1085
-                'class' => 'dashicons dashicons-media-spreadsheet',
1086
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1087
-            ],
1088
-        ];
1089
-        if (
1090
-            $this->capabilities->current_user_can(
1091
-                'ee_send_message',
1092
-                'espresso_registrations_resend_registration'
1093
-            )
1094
-        ) {
1095
-            $fc_items['resend_registration'] = [
1096
-                'class' => 'dashicons dashicons-email-alt',
1097
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1098
-            ];
1099
-        } else {
1100
-            $fc_items['blank'] = ['class' => 'blank', 'desc' => ''];
1101
-        }
1102
-        if (
1103
-            $this->capabilities->current_user_can(
1104
-                'ee_read_global_messages',
1105
-                'view_filtered_messages'
1106
-            )
1107
-        ) {
1108
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1109
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1110
-                $fc_items['view_related_messages'] = [
1111
-                    'class' => $related_for_icon['css_class'],
1112
-                    'desc'  => $related_for_icon['label'],
1113
-                ];
1114
-            }
1115
-        }
1116
-        $sc_items = [
1117
-            'approved_status'   => [
1118
-                'class' => 'ee-status-legend ee-status-bg--' . RegStatus::APPROVED,
1119
-                'desc'  => EEH_Template::pretty_status(
1120
-                    RegStatus::APPROVED,
1121
-                    false,
1122
-                    'sentence'
1123
-                ),
1124
-            ],
1125
-            'pending_status'    => [
1126
-                'class' => 'ee-status-legend ee-status-bg--' . RegStatus::PENDING_PAYMENT,
1127
-                'desc'  => EEH_Template::pretty_status(
1128
-                    RegStatus::PENDING_PAYMENT,
1129
-                    false,
1130
-                    'sentence'
1131
-                ),
1132
-            ],
1133
-            'wait_list'         => [
1134
-                'class' => 'ee-status-legend ee-status-bg--' . RegStatus::WAIT_LIST,
1135
-                'desc'  => EEH_Template::pretty_status(
1136
-                    RegStatus::WAIT_LIST,
1137
-                    false,
1138
-                    'sentence'
1139
-                ),
1140
-            ],
1141
-            'incomplete_status' => [
1142
-                'class' => 'ee-status-legend ee-status-bg--' . RegStatus::INCOMPLETE,
1143
-                'desc'  => EEH_Template::pretty_status(
1144
-                    RegStatus::INCOMPLETE,
1145
-                    false,
1146
-                    'sentence'
1147
-                ),
1148
-            ],
1149
-            'not_approved'      => [
1150
-                'class' => 'ee-status-legend ee-status-bg--' . RegStatus::AWAITING_REVIEW,
1151
-                'desc'  => EEH_Template::pretty_status(
1152
-                    RegStatus::AWAITING_REVIEW,
1153
-                    false,
1154
-                    'sentence'
1155
-                ),
1156
-            ],
1157
-            'declined_status'   => [
1158
-                'class' => 'ee-status-legend ee-status-bg--' . RegStatus::DECLINED,
1159
-                'desc'  => EEH_Template::pretty_status(
1160
-                    RegStatus::DECLINED,
1161
-                    false,
1162
-                    'sentence'
1163
-                ),
1164
-            ],
1165
-            'cancelled_status'  => [
1166
-                'class' => 'ee-status-legend ee-status-bg--' . RegStatus::CANCELLED,
1167
-                'desc'  => EEH_Template::pretty_status(
1168
-                    RegStatus::CANCELLED,
1169
-                    false,
1170
-                    'sentence'
1171
-                ),
1172
-            ],
1173
-        ];
1174
-        return array_merge($fc_items, $sc_items);
1175
-    }
1176
-
1177
-
1178
-
1179
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1180
-
1181
-
1182
-    /**
1183
-     * @throws DomainException
1184
-     * @throws EE_Error
1185
-     * @throws InvalidArgumentException
1186
-     * @throws InvalidDataTypeException
1187
-     * @throws InvalidInterfaceException
1188
-     */
1189
-    protected function _registrations_overview_list_table()
1190
-    {
1191
-        $this->appendAddNewRegistrationButtonToPageTitle();
1192
-        $header_text                  = '';
1193
-        $admin_page_header_decorators = [
1194
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1195
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1196
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1197
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1198
-        ];
1199
-        foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1200
-            $filter_header_decorator = $this->loader->getNew($admin_page_header_decorator);
1201
-            $header_text             = $filter_header_decorator->getHeaderText($header_text);
1202
-        }
1203
-        $this->_template_args['before_list_table'] = $header_text;
1204
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_registration_legend_items());
1205
-        $this->display_admin_list_table_page_with_no_sidebar();
1206
-    }
1207
-
1208
-
1209
-    /**
1210
-     * @throws EE_Error
1211
-     * @throws InvalidArgumentException
1212
-     * @throws InvalidDataTypeException
1213
-     * @throws InvalidInterfaceException
1214
-     */
1215
-    private function appendAddNewRegistrationButtonToPageTitle()
1216
-    {
1217
-        $EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
1218
-        if (
1219
-            $EVT_ID
1220
-            && $this->capabilities->current_user_can(
1221
-                'ee_edit_registrations',
1222
-                'espresso_registrations_new_registration',
1223
-                $EVT_ID
1224
-            )
1225
-        ) {
1226
-            $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1227
-                    'new_registration',
1228
-                    'add-registrant',
1229
-                    ['event_id' => $EVT_ID],
1230
-                    'add-new-h2'
1231
-                );
1232
-        }
1233
-    }
1234
-
1235
-
1236
-    /**
1237
-     * This sets the _registration property for the registration details screen
1238
-     *
1239
-     * @return void
1240
-     * @throws EE_Error
1241
-     * @throws InvalidArgumentException
1242
-     * @throws InvalidDataTypeException
1243
-     * @throws InvalidInterfaceException
1244
-     * @throws ReflectionException
1245
-     */
1246
-    private function _set_registration_object()
1247
-    {
1248
-        // get out if we've already set the object
1249
-        if ($this->_registration instanceof EE_Registration) {
1250
-            return;
1251
-        }
1252
-        $REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
1253
-        if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1254
-            return;
1255
-        }
1256
-        $error_msg = sprintf(
1257
-            esc_html__(
1258
-                'An error occurred and the details for Registration ID #%s could not be retrieved.',
1259
-                'event_espresso'
1260
-            ),
1261
-            $REG_ID
1262
-        );
1263
-        EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1264
-        $this->_registration = null;
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     * Used to retrieve registrations for the list table.
1270
-     *
1271
-     * @param int  $per_page
1272
-     * @param bool $count
1273
-     * @param bool $this_month
1274
-     * @param bool $today
1275
-     * @param bool $yesterday
1276
-     * @return EE_Registration[]|int
1277
-     * @throws EE_Error
1278
-     * @throws ReflectionException
1279
-     */
1280
-    public function get_registrations(
1281
-        int $per_page = 10,
1282
-        bool $count = false,
1283
-        bool $this_month = false,
1284
-        bool $today = false,
1285
-        bool $yesterday = false
1286
-    ) {
1287
-        if ($this_month) {
1288
-            $this->request->setRequestParam('status', 'month');
1289
-        }
1290
-        if ($today) {
1291
-            $this->request->setRequestParam('status', 'today');
1292
-        }
1293
-        if ($yesterday) {
1294
-            $this->request->setRequestParam('status', 'yesterday');
1295
-        }
1296
-        $query_params = $this->_get_registration_query_parameters([], $per_page, $count);
1297
-        /**
1298
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1299
-         *
1300
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1301
-         * @see  https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1302
-         *                      or if you have the development copy of EE you can view this at the path:
1303
-         *                      /docs/G--Model-System/model-query-params.md
1304
-         */
1305
-        $query_params['group_by'] = '';
1306
-
1307
-        return $count
1308
-            ? $this->getRegistrationModel()->count($query_params)
1309
-            /** @type EE_Registration[] */
1310
-            : $this->getRegistrationModel()->get_all($query_params);
1311
-    }
1312
-
1313
-
1314
-    /**
1315
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1316
-     * Note: this listens to values on the request for some query parameters.
1317
-     *
1318
-     * @param array $request
1319
-     * @param int   $per_page
1320
-     * @param bool  $count
1321
-     * @return array
1322
-     * @throws EE_Error
1323
-     * @throws InvalidArgumentException
1324
-     * @throws InvalidDataTypeException
1325
-     * @throws InvalidInterfaceException
1326
-     */
1327
-    protected function _get_registration_query_parameters(
1328
-        array $request = [],
1329
-        int $per_page = 10,
1330
-        bool $count = false
1331
-    ): array {
1332
-        /** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1333
-        $list_table_query_builder = $this->loader->getNew(
1334
-            'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1335
-            [null, null, $request]
1336
-        );
1337
-        return $list_table_query_builder->getQueryParams($per_page, $count);
1338
-    }
1339
-
1340
-
1341
-    public function get_registration_status_array(): array
1342
-    {
1343
-        return self::$_reg_status;
1344
-    }
1345
-
1346
-
1347
-
1348
-
1349
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1350
-    /**
1351
-     * generates HTML for the View Registration Details Admin page
1352
-     *
1353
-     * @return void
1354
-     * @throws DomainException
1355
-     * @throws EE_Error
1356
-     * @throws InvalidArgumentException
1357
-     * @throws InvalidDataTypeException
1358
-     * @throws InvalidInterfaceException
1359
-     * @throws EntityNotFoundException
1360
-     * @throws ReflectionException
1361
-     */
1362
-    protected function _registration_details()
1363
-    {
1364
-        $this->_template_args = [];
1365
-        $this->_set_registration_object();
1366
-        if (is_object($this->_registration)) {
1367
-            $transaction        = $this->_registration->transaction()
1368
-                ? $this->_registration->transaction()
1369
-                : EE_Transaction::new_instance();
1370
-            $this->session_data = $transaction->session_data();
1371
-            $event_id           = $this->_registration->event_ID();
1372
-            $this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1373
-            $this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1374
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1375
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1376
-            $this->_template_args['grand_total']           = $transaction->total();
1377
-            $this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1378
-            // link back to overview
1379
-            $this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1380
-            $this->_template_args['registration']                = $this->_registration;
1381
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1382
-                [
1383
-                    'action'   => 'default',
1384
-                    'event_id' => $event_id,
1385
-                ],
1386
-                REG_ADMIN_URL
1387
-            );
1388
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1389
-                [
1390
-                    'action' => 'default',
1391
-                    'EVT_ID' => $event_id,
1392
-                    'page'   => 'espresso_transactions',
1393
-                ],
1394
-                admin_url('admin.php')
1395
-            );
1396
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1397
-                [
1398
-                    'page'   => 'espresso_events',
1399
-                    'action' => 'edit',
1400
-                    'post'   => $event_id,
1401
-                ],
1402
-                admin_url('admin.php')
1403
-            );
1404
-            // next and previous links
1405
-            $next_reg                                      = $this->_registration->next(
1406
-                null,
1407
-                [],
1408
-                'REG_ID'
1409
-            );
1410
-            $this->_template_args['next_registration']     = $next_reg
1411
-                ? $this->_next_link(
1412
-                    EE_Admin_Page::add_query_args_and_nonce(
1413
-                        [
1414
-                            'action'  => 'view_registration',
1415
-                            '_REG_ID' => $next_reg['REG_ID'],
1416
-                        ],
1417
-                        REG_ADMIN_URL
1418
-                    ),
1419
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1420
-                )
1421
-                : '';
1422
-            $previous_reg                                  = $this->_registration->previous(
1423
-                null,
1424
-                [],
1425
-                'REG_ID'
1426
-            );
1427
-            $this->_template_args['previous_registration'] = $previous_reg
1428
-                ? $this->_previous_link(
1429
-                    EE_Admin_Page::add_query_args_and_nonce(
1430
-                        [
1431
-                            'action'  => 'view_registration',
1432
-                            '_REG_ID' => $previous_reg['REG_ID'],
1433
-                        ],
1434
-                        REG_ADMIN_URL
1435
-                    ),
1436
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1437
-                )
1438
-                : '';
1439
-            // grab header
1440
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1441
-            $this->_template_args['REG_ID']            = $this->_registration->ID();
1442
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1443
-                $template_path,
1444
-                $this->_template_args,
1445
-                true
1446
-            );
1447
-        } else {
1448
-            $this->_template_args['admin_page_header'] = '';
1449
-            $this->_display_espresso_notices();
1450
-        }
1451
-        // the details template wrapper
1452
-        $this->display_admin_page_with_sidebar();
1453
-    }
1454
-
1455
-
1456
-    /**
1457
-     * @throws EE_Error
1458
-     * @throws InvalidArgumentException
1459
-     * @throws InvalidDataTypeException
1460
-     * @throws InvalidInterfaceException
1461
-     * @throws ReflectionException
1462
-     * @since 4.10.2.p
1463
-     */
1464
-    protected function _registration_details_metaboxes()
1465
-    {
1466
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1467
-        $this->_set_registration_object();
1468
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1469
-        $this->addMetaBox(
1470
-            'edit-reg-status-mbox',
1471
-            esc_html__('Registration Status', 'event_espresso'),
1472
-            [$this, 'set_reg_status_buttons_metabox'],
1473
-            $this->_wp_page_slug
1474
-        );
1475
-        $this->addMetaBox(
1476
-            'edit-reg-details-mbox',
1477
-            '<span>' . esc_html__('Registration Details', 'event_espresso')
1478
-            . '&nbsp;<span class="dashicons dashicons-clipboard"></span></span>',
1479
-            [$this, '_reg_details_meta_box'],
1480
-            $this->_wp_page_slug
1481
-        );
1482
-        if (
1483
-            $attendee instanceof EE_Attendee
1484
-            && $this->capabilities->current_user_can(
1485
-                'ee_read_registration',
1486
-                'edit-reg-questions-mbox',
1487
-                $this->_registration->ID()
1488
-            )
1489
-        ) {
1490
-            $this->addMetaBox(
1491
-                'edit-reg-questions-mbox',
1492
-                esc_html__('Registration Form Answers', 'event_espresso'),
1493
-                [$this, '_reg_questions_meta_box'],
1494
-                $this->_wp_page_slug
1495
-            );
1496
-        }
1497
-        $this->addMetaBox(
1498
-            'edit-reg-registrant-mbox',
1499
-            esc_html__('Contact Details', 'event_espresso'),
1500
-            [$this, '_reg_registrant_side_meta_box'],
1501
-            $this->_wp_page_slug,
1502
-            'side'
1503
-        );
1504
-        if ($this->_registration->group_size() > 1) {
1505
-            $this->addMetaBox(
1506
-                'edit-reg-attendees-mbox',
1507
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1508
-                [$this, '_reg_attendees_meta_box'],
1509
-                $this->_wp_page_slug
1510
-            );
1511
-        }
1512
-    }
1513
-
1514
-
1515
-    /**
1516
-     * set_reg_status_buttons_metabox
1517
-     *
1518
-     * @return void
1519
-     * @throws EE_Error
1520
-     * @throws EntityNotFoundException
1521
-     * @throws InvalidArgumentException
1522
-     * @throws InvalidDataTypeException
1523
-     * @throws InvalidInterfaceException
1524
-     * @throws ReflectionException
1525
-     */
1526
-    public function set_reg_status_buttons_metabox()
1527
-    {
1528
-        $this->_set_registration_object();
1529
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1530
-        $output                 = $change_reg_status_form->form_open(
1531
-            self::add_query_args_and_nonce(
1532
-                [
1533
-                    'action' => 'change_reg_status',
1534
-                ],
1535
-                REG_ADMIN_URL
1536
-            )
1537
-        );
1538
-        $output                 .= $change_reg_status_form->get_html();
1539
-        $output                 .= $change_reg_status_form->form_close();
1540
-        echo wp_kses($output, AllowedTags::getWithFormTags());
1541
-    }
1542
-
1543
-
1544
-    /**
1545
-     * @return EE_Form_Section_Proper
1546
-     * @throws EE_Error
1547
-     * @throws InvalidArgumentException
1548
-     * @throws InvalidDataTypeException
1549
-     * @throws InvalidInterfaceException
1550
-     * @throws EntityNotFoundException
1551
-     * @throws ReflectionException
1552
-     */
1553
-    protected function _generate_reg_status_change_form()
1554
-    {
1555
-        $reg_status_change_form_array = [
1556
-            'name'            => 'reg_status_change_form',
1557
-            'html_id'         => 'reg-status-change-form',
1558
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1559
-            'subsections'     => [
1560
-                'return' => new EE_Hidden_Input(
1561
-                    [
1562
-                        'name'    => 'return',
1563
-                        'default' => 'view_registration',
1564
-                    ]
1565
-                ),
1566
-                'REG_ID' => new EE_Hidden_Input(
1567
-                    [
1568
-                        'name'    => 'REG_ID',
1569
-                        'default' => $this->_registration->ID(),
1570
-                    ]
1571
-                ),
1572
-            ],
1573
-        ];
1574
-        if (
1575
-            $this->capabilities->current_user_can(
1576
-                'ee_edit_registration',
1577
-                'toggle_registration_status',
1578
-                $this->_registration->ID()
1579
-            )
1580
-        ) {
1581
-            $reg_status_change_form_array['subsections']['reg_status']         = new EE_Select_Input(
1582
-                $this->_get_reg_statuses(),
1583
-                [
1584
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1585
-                    'default'         => $this->_registration->status_ID(),
1586
-                    'html_class'      => 'ee-input-width--small',
1587
-                ]
1588
-            );
1589
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1590
-                [
1591
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1592
-                    'default'         => false,
1593
-                    'html_help_text'  => esc_html__(
1594
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1595
-                        'event_espresso'
1596
-                    ),
1597
-                ]
1598
-            );
1599
-            $reg_status_change_form_array['subsections']['submit']             = new EE_Submit_Input(
1600
-                [
1601
-                    'html_class'      => 'button--primary',
1602
-                    'html_label_text' => '&nbsp;',
1603
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1604
-                ]
1605
-            );
1606
-        }
1607
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1608
-    }
1609
-
1610
-
1611
-    /**
1612
-     * Returns an array of all the buttons for the various statuses and switch status actions
1613
-     *
1614
-     * @return array
1615
-     * @throws EE_Error
1616
-     * @throws InvalidArgumentException
1617
-     * @throws InvalidDataTypeException
1618
-     * @throws InvalidInterfaceException
1619
-     * @throws EntityNotFoundException
1620
-     * @throws ReflectionException
1621
-     */
1622
-    protected function _get_reg_statuses()
1623
-    {
1624
-        $reg_status_array = $this->getRegistrationModel()->reg_status_array();
1625
-        unset($reg_status_array[ RegStatus::INCOMPLETE ]);
1626
-        // get current reg status
1627
-        $current_status = $this->_registration->status_ID();
1628
-        // is registration for free event? This will determine whether to display the pending payment option
1629
-        if (
1630
-            $current_status !== RegStatus::PENDING_PAYMENT
1631
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1632
-        ) {
1633
-            unset($reg_status_array[ RegStatus::PENDING_PAYMENT ]);
1634
-        }
1635
-        return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1641
-     *
1642
-     * @param bool $status REG status given for changing registrations to.
1643
-     * @param bool $notify Whether to send messages notifications or not.
1644
-     * @return array (array with reg_id(s) updated and whether update was successful.
1645
-     * @throws DomainException
1646
-     * @throws EE_Error
1647
-     * @throws EntityNotFoundException
1648
-     * @throws InvalidArgumentException
1649
-     * @throws InvalidDataTypeException
1650
-     * @throws InvalidInterfaceException
1651
-     * @throws ReflectionException
1652
-     * @throws RuntimeException
1653
-     */
1654
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1655
-    {
1656
-        $REG_IDs = $this->request->requestParamIsSet('reg_status_change_form')
1657
-            ? $this->request->getRequestParam('reg_status_change_form[REG_ID]', [], 'int', true)
1658
-            : $this->request->getRequestParam('_REG_ID', [], 'int', true);
1659
-        // sanitize $REG_IDs
1660
-        $REG_IDs = array_map('absint', $REG_IDs);
1661
-        // and remove empty entries
1662
-        $REG_IDs = array_filter($REG_IDs);
1663
-
1664
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1665
-
1666
-        /**
1667
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1668
-         * Currently this value is used downstream by the _process_resend_registration method.
1669
-         *
1670
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1671
-         * @param bool                     $status           The status registrations were changed to.
1672
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1673
-         * @param Registrations_Admin_Page $admin_page
1674
-         */
1675
-        $REG_ID = apply_filters(
1676
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1677
-            $result['REG_ID'],
1678
-            $status,
1679
-            $result['success'],
1680
-            $this
1681
-        );
1682
-        $this->request->setRequestParam('_REG_ID', $REG_ID);
1683
-
1684
-        // notify?
1685
-        if (
1686
-            $notify
1687
-            && $result['success']
1688
-            && ! empty($REG_ID)
1689
-            && $this->capabilities->current_user_can(
1690
-                'ee_send_message',
1691
-                'espresso_registrations_resend_registration'
1692
-            )
1693
-        ) {
1694
-            $this->_process_resend_registration();
1695
-        }
1696
-        return $result;
1697
-    }
1698
-
1699
-
1700
-    /**
1701
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1702
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1703
-     *
1704
-     * @param array  $REG_IDs
1705
-     * @param string $status
1706
-     * @param bool   $notify Used to indicate whether notification was requested or not.  This determines the context
1707
-     *                       slug sent with setting the registration status.
1708
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1709
-     * @throws EE_Error
1710
-     * @throws InvalidArgumentException
1711
-     * @throws InvalidDataTypeException
1712
-     * @throws InvalidInterfaceException
1713
-     * @throws ReflectionException
1714
-     * @throws RuntimeException
1715
-     * @throws EntityNotFoundException
1716
-     * @throws DomainException
1717
-     */
1718
-    protected function _set_registration_status($REG_IDs = [], $status = '', $notify = false)
1719
-    {
1720
-        $success = false;
1721
-        // typecast $REG_IDs
1722
-        $REG_IDs = (array) $REG_IDs;
1723
-        if (! empty($REG_IDs)) {
1724
-            $success = true;
1725
-            // set default status if none is passed
1726
-            $status         = $status ?: RegStatus::PENDING_PAYMENT;
1727
-            $status_context = $notify
1728
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1729
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1730
-            // loop through REG_ID's and change status
1731
-            foreach ($REG_IDs as $REG_ID) {
1732
-                $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1733
-                if ($registration instanceof EE_Registration) {
1734
-                    $registration->set_status(
1735
-                        $status,
1736
-                        false,
1737
-                        new Context(
1738
-                            $status_context,
1739
-                            esc_html__(
1740
-                                'Manually triggered status change on a Registration Admin Page route.',
1741
-                                'event_espresso'
1742
-                            )
1743
-                        )
1744
-                    );
1745
-                    $result = $registration->save();
1746
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1747
-                    $success = $result !== false ? $success : false;
1748
-                }
1749
-            }
1750
-        }
1751
-
1752
-        // return $success and processed registrations
1753
-        return ['REG_ID' => $REG_IDs, 'success' => $success];
1754
-    }
1755
-
1756
-
1757
-    /**
1758
-     * Common logic for setting up success message and redirecting to appropriate route
1759
-     *
1760
-     * @param string $STS_ID status id for the registration changed to
1761
-     * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1762
-     * @return void
1763
-     * @throws DomainException
1764
-     * @throws EE_Error
1765
-     * @throws EntityNotFoundException
1766
-     * @throws InvalidArgumentException
1767
-     * @throws InvalidDataTypeException
1768
-     * @throws InvalidInterfaceException
1769
-     * @throws ReflectionException
1770
-     * @throws RuntimeException
1771
-     */
1772
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1773
-    {
1774
-        $result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1775
-            : ['success' => false];
1776
-        $success = isset($result['success']) && $result['success'];
1777
-        // setup success message
1778
-        if ($success) {
1779
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1780
-                $msg = sprintf(
1781
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1782
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1783
-                );
1784
-            } else {
1785
-                $msg = sprintf(
1786
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1787
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1788
-                );
1789
-            }
1790
-            EE_Error::add_success($msg);
1791
-        } else {
1792
-            EE_Error::add_error(
1793
-                esc_html__(
1794
-                    'Something went wrong, and the status was not changed',
1795
-                    'event_espresso'
1796
-                ),
1797
-                __FILE__,
1798
-                __LINE__,
1799
-                __FUNCTION__
1800
-            );
1801
-        }
1802
-        $return = $this->request->getRequestParam('return');
1803
-        $route  = $return === 'view_registration'
1804
-            ? ['action' => 'view_registration', '_REG_ID' => reset($result['REG_ID'])]
1805
-            : ['action' => 'default'];
1806
-        $route  = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1807
-        $this->_redirect_after_action($success, '', '', $route, true);
1808
-    }
1809
-
1810
-
1811
-    /**
1812
-     * incoming reg status change from reg details page.
1813
-     *
1814
-     * @return void
1815
-     * @throws EE_Error
1816
-     * @throws EntityNotFoundException
1817
-     * @throws InvalidArgumentException
1818
-     * @throws InvalidDataTypeException
1819
-     * @throws InvalidInterfaceException
1820
-     * @throws ReflectionException
1821
-     * @throws RuntimeException
1822
-     * @throws DomainException
1823
-     */
1824
-    protected function _change_reg_status()
1825
-    {
1826
-        $this->request->setRequestParam('return', 'view_registration');
1827
-        // set notify based on whether the send notifications toggle is set or not
1828
-        $notify     = $this->request->getRequestParam('reg_status_change_form[send_notifications]', false, 'bool');
1829
-        $reg_status = $this->request->getRequestParam('reg_status_change_form[reg_status]', '');
1830
-        $this->request->setRequestParam('reg_status_change_form[reg_status]', $reg_status);
1831
-        switch ($reg_status) {
1832
-            case RegStatus::APPROVED:
1833
-            case EEH_Template::pretty_status(RegStatus::APPROVED, false, 'sentence'):
1834
-                $this->approve_registration($notify);
1835
-                break;
1836
-            case RegStatus::PENDING_PAYMENT:
1837
-            case EEH_Template::pretty_status(RegStatus::PENDING_PAYMENT, false, 'sentence'):
1838
-                $this->pending_registration($notify);
1839
-                break;
1840
-            case RegStatus::AWAITING_REVIEW:
1841
-            case EEH_Template::pretty_status(RegStatus::AWAITING_REVIEW, false, 'sentence'):
1842
-                $this->not_approve_registration($notify);
1843
-                break;
1844
-            case RegStatus::DECLINED:
1845
-            case EEH_Template::pretty_status(RegStatus::DECLINED, false, 'sentence'):
1846
-                $this->decline_registration($notify);
1847
-                break;
1848
-            case RegStatus::CANCELLED:
1849
-            case EEH_Template::pretty_status(RegStatus::CANCELLED, false, 'sentence'):
1850
-                $this->cancel_registration($notify);
1851
-                break;
1852
-            case RegStatus::WAIT_LIST:
1853
-            case EEH_Template::pretty_status(RegStatus::WAIT_LIST, false, 'sentence'):
1854
-                $this->wait_list_registration($notify);
1855
-                break;
1856
-            case RegStatus::INCOMPLETE:
1857
-            default:
1858
-                $this->request->unSetRequestParam('return');
1859
-                $this->_reg_status_change_return('');
1860
-                break;
1861
-        }
1862
-    }
1863
-
1864
-
1865
-    /**
1866
-     * Callback for bulk action routes.
1867
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1868
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
1869
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1870
-     * when an action is happening on just a single registration).
1871
-     *
1872
-     * @param      $action
1873
-     * @param bool $notify
1874
-     */
1875
-    protected function bulk_action_on_registrations($action, $notify = false)
1876
-    {
1877
-        do_action(
1878
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1879
-            $this,
1880
-            $action,
1881
-            $notify
1882
-        );
1883
-        $method = $action . '_registration';
1884
-        if (method_exists($this, $method)) {
1885
-            $this->$method($notify);
1886
-        }
1887
-    }
1888
-
1889
-
1890
-    /**
1891
-     * approve_registration
1892
-     *
1893
-     * @param bool $notify whether or not to notify the registrant about their approval.
1894
-     * @return void
1895
-     * @throws EE_Error
1896
-     * @throws EntityNotFoundException
1897
-     * @throws InvalidArgumentException
1898
-     * @throws InvalidDataTypeException
1899
-     * @throws InvalidInterfaceException
1900
-     * @throws ReflectionException
1901
-     * @throws RuntimeException
1902
-     * @throws DomainException
1903
-     */
1904
-    protected function approve_registration($notify = false)
1905
-    {
1906
-        $this->_reg_status_change_return(RegStatus::APPROVED, $notify);
1907
-    }
1908
-
1909
-
1910
-    /**
1911
-     * decline_registration
1912
-     *
1913
-     * @param bool $notify whether or not to notify the registrant about their status change.
1914
-     * @return void
1915
-     * @throws EE_Error
1916
-     * @throws EntityNotFoundException
1917
-     * @throws InvalidArgumentException
1918
-     * @throws InvalidDataTypeException
1919
-     * @throws InvalidInterfaceException
1920
-     * @throws ReflectionException
1921
-     * @throws RuntimeException
1922
-     * @throws DomainException
1923
-     */
1924
-    protected function decline_registration($notify = false)
1925
-    {
1926
-        $this->_reg_status_change_return(RegStatus::DECLINED, $notify);
1927
-    }
1928
-
1929
-
1930
-    /**
1931
-     * cancel_registration
1932
-     *
1933
-     * @param bool $notify whether or not to notify the registrant about their status change.
1934
-     * @return void
1935
-     * @throws EE_Error
1936
-     * @throws EntityNotFoundException
1937
-     * @throws InvalidArgumentException
1938
-     * @throws InvalidDataTypeException
1939
-     * @throws InvalidInterfaceException
1940
-     * @throws ReflectionException
1941
-     * @throws RuntimeException
1942
-     * @throws DomainException
1943
-     */
1944
-    protected function cancel_registration($notify = false)
1945
-    {
1946
-        $this->_reg_status_change_return(RegStatus::CANCELLED, $notify);
1947
-    }
1948
-
1949
-
1950
-    /**
1951
-     * not_approve_registration
1952
-     *
1953
-     * @param bool $notify whether or not to notify the registrant about their status change.
1954
-     * @return void
1955
-     * @throws EE_Error
1956
-     * @throws EntityNotFoundException
1957
-     * @throws InvalidArgumentException
1958
-     * @throws InvalidDataTypeException
1959
-     * @throws InvalidInterfaceException
1960
-     * @throws ReflectionException
1961
-     * @throws RuntimeException
1962
-     * @throws DomainException
1963
-     */
1964
-    protected function not_approve_registration($notify = false)
1965
-    {
1966
-        $this->_reg_status_change_return(RegStatus::AWAITING_REVIEW, $notify);
1967
-    }
1968
-
1969
-
1970
-    /**
1971
-     * decline_registration
1972
-     *
1973
-     * @param bool $notify whether or not to notify the registrant about their status change.
1974
-     * @return void
1975
-     * @throws EE_Error
1976
-     * @throws EntityNotFoundException
1977
-     * @throws InvalidArgumentException
1978
-     * @throws InvalidDataTypeException
1979
-     * @throws InvalidInterfaceException
1980
-     * @throws ReflectionException
1981
-     * @throws RuntimeException
1982
-     * @throws DomainException
1983
-     */
1984
-    protected function pending_registration($notify = false)
1985
-    {
1986
-        $this->_reg_status_change_return(RegStatus::PENDING_PAYMENT, $notify);
1987
-    }
1988
-
1989
-
1990
-    /**
1991
-     * waitlist_registration
1992
-     *
1993
-     * @param bool $notify whether or not to notify the registrant about their status change.
1994
-     * @return void
1995
-     * @throws EE_Error
1996
-     * @throws EntityNotFoundException
1997
-     * @throws InvalidArgumentException
1998
-     * @throws InvalidDataTypeException
1999
-     * @throws InvalidInterfaceException
2000
-     * @throws ReflectionException
2001
-     * @throws RuntimeException
2002
-     * @throws DomainException
2003
-     */
2004
-    protected function wait_list_registration($notify = false)
2005
-    {
2006
-        $this->_reg_status_change_return(RegStatus::WAIT_LIST, $notify);
2007
-    }
2008
-
2009
-
2010
-    /**
2011
-     * generates HTML for the Registration main meta box
2012
-     *
2013
-     * @return void
2014
-     * @throws DomainException
2015
-     * @throws EE_Error
2016
-     * @throws InvalidArgumentException
2017
-     * @throws InvalidDataTypeException
2018
-     * @throws InvalidInterfaceException
2019
-     * @throws ReflectionException
2020
-     * @throws EntityNotFoundException
2021
-     */
2022
-    public function _reg_details_meta_box()
2023
-    {
2024
-        EEH_Autoloader::register_line_item_display_autoloaders();
2025
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2026
-        EE_Registry::instance()->load_helper('Line_Item');
2027
-        $transaction        = $this->_registration->transaction()
2028
-            ? $this->_registration->transaction()
2029
-            : EE_Transaction::new_instance();
2030
-        $this->session_data = $transaction->session_data();
2031
-        $filters            = new EE_Line_Item_Filter_Collection();
2032
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2033
-        $filters->add(new EE_Non_Zero_Line_Item_Filter());
2034
-        $line_item_filter_processor              = new EE_Line_Item_Filter_Processor(
2035
-            $filters,
2036
-            $transaction->total_line_item()
2037
-        );
2038
-        $filtered_line_item_tree                 = $line_item_filter_processor->process();
2039
-        $line_item_display                       = new EE_Line_Item_Display(
2040
-            'reg_admin_table',
2041
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2042
-        );
2043
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2044
-            $filtered_line_item_tree,
2045
-            ['EE_Registration' => $this->_registration]
2046
-        );
2047
-        $attendee                                = $this->_registration->attendee();
2048
-        if (
2049
-            $this->capabilities->current_user_can(
2050
-                'ee_read_transaction',
2051
-                'espresso_transactions_view_transaction'
2052
-            )
2053
-        ) {
2054
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2055
-                EE_Admin_Page::add_query_args_and_nonce(
2056
-                    [
2057
-                        'action' => 'view_transaction',
2058
-                        'TXN_ID' => $transaction->ID(),
2059
-                    ],
2060
-                    TXN_ADMIN_URL
2061
-                ),
2062
-                esc_html__(' View Transaction', 'event_espresso'),
2063
-                'button button--secondary right',
2064
-                'dashicons dashicons-cart'
2065
-            );
2066
-        } else {
2067
-            $this->_template_args['view_transaction_button'] = '';
2068
-        }
2069
-        if (
2070
-            $attendee instanceof EE_Attendee
2071
-            && $this->capabilities->current_user_can(
2072
-                'ee_send_message',
2073
-                'espresso_registrations_resend_registration'
2074
-            )
2075
-        ) {
2076
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2077
-                EE_Admin_Page::add_query_args_and_nonce(
2078
-                    [
2079
-                        'action'      => 'resend_registration',
2080
-                        '_REG_ID'     => $this->_registration->ID(),
2081
-                        'redirect_to' => 'view_registration',
2082
-                    ],
2083
-                    REG_ADMIN_URL
2084
-                ),
2085
-                esc_html__(' Resend Registration', 'event_espresso'),
2086
-                'button button--secondary right',
2087
-                'dashicons dashicons-email-alt'
2088
-            );
2089
-        } else {
2090
-            $this->_template_args['resend_registration_button'] = '';
2091
-        }
2092
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2093
-        $payment                               = $transaction->get_first_related('Payment');
2094
-        $payment                               = ! $payment instanceof EE_Payment
2095
-            ? EE_Payment::new_instance()
2096
-            : $payment;
2097
-        $payment_method                        = $payment->get_first_related('Payment_Method');
2098
-        $payment_method                        = ! $payment_method instanceof EE_Payment_Method
2099
-            ? EE_Payment_Method::new_instance()
2100
-            : $payment_method;
2101
-        $reg_details        = [
2102
-            'payment_method'       => $payment_method->name(),
2103
-            'response_msg'         => $payment->gateway_response(),
2104
-            'registration_id'      => $this->_registration->get('REG_code'),
2105
-            'registration_session' => $this->_registration->session_ID(),
2106
-            'ip_address'           => $this->session_data['ip_address'] ?? '',
2107
-            'user_agent'           => $this->session_data['user_agent'] ?? '',
2108
-        ];
2109
-        if (isset($reg_details['registration_id'])) {
2110
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2111
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2112
-                'Registration ID',
2113
-                'event_espresso'
2114
-            );
2115
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2116
-        }
2117
-        if (isset($reg_details['payment_method'])) {
2118
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2119
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2120
-                'Most Recent Payment Method',
2121
-                'event_espresso'
2122
-            );
2123
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2124
-            $this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2125
-            $this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2126
-                'Payment method response',
2127
-                'event_espresso'
2128
-            );
2129
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2130
-        }
2131
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2132
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2133
-            'Registration Session',
2134
-            'event_espresso'
2135
-        );
2136
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2137
-        $this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2138
-        $this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2139
-            'Registration placed from IP',
2140
-            'event_espresso'
2141
-        );
2142
-        $this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2143
-        $this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2144
-        $this->_template_args['reg_details']['user_agent']['label']           = esc_html__(
2145
-            'Registrant User Agent',
2146
-            'event_espresso'
2147
-        );
2148
-        $this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2149
-        $this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2150
-            [
2151
-                'action'   => 'default',
2152
-                'event_id' => $this->_registration->event_ID(),
2153
-            ],
2154
-            REG_ADMIN_URL
2155
-        );
2156
-
2157
-        $this->_template_args['REG_ID']   = $this->_registration->ID();
2158
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2159
-
2160
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2161
-        EEH_Template::display_template($template_path, $this->_template_args); // already escaped
2162
-    }
2163
-
2164
-
2165
-    /**
2166
-     * generates HTML for the Registration Questions meta box.
2167
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2168
-     * otherwise uses new forms system
2169
-     *
2170
-     * @return void
2171
-     * @throws DomainException
2172
-     * @throws EE_Error
2173
-     * @throws InvalidArgumentException
2174
-     * @throws InvalidDataTypeException
2175
-     * @throws InvalidInterfaceException
2176
-     * @throws ReflectionException
2177
-     */
2178
-    public function _reg_questions_meta_box()
2179
-    {
2180
-        // allow someone to override this method entirely
2181
-        if (
2182
-            apply_filters(
2183
-                'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2184
-                true,
2185
-                $this,
2186
-                $this->_registration
2187
-            )
2188
-        ) {
2189
-            $form = $this->_get_reg_custom_questions_form(
2190
-                $this->_registration->ID()
2191
-            );
2192
-
2193
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2194
-                ? $form->get_html_and_js()
2195
-                : '';
2196
-
2197
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2198
-            $this->_template_args['REG_ID']                    = $this->_registration->ID();
2199
-            $template_path                                     =
2200
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2201
-            EEH_Template::display_template($template_path, $this->_template_args);
2202
-        }
2203
-    }
2204
-
2205
-
2206
-    /**
2207
-     * form_before_question_group
2208
-     *
2209
-     * @param string $output
2210
-     * @return        string
2211
-     * @deprecated    as of 4.8.32.rc.000
2212
-     */
2213
-    public function form_before_question_group($output)
2214
-    {
2215
-        EE_Error::doing_it_wrong(
2216
-            __CLASS__ . '::' . __FUNCTION__,
2217
-            esc_html__(
2218
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2219
-                'event_espresso'
2220
-            ),
2221
-            '4.8.32.rc.000'
2222
-        );
2223
-        return '
26
+	/**
27
+	 * @var EE_Registration
28
+	 */
29
+	private $_registration;
30
+
31
+	/**
32
+	 * @var EE_Event
33
+	 */
34
+	private $_reg_event;
35
+
36
+	private array $session_data = [];
37
+
38
+	/**
39
+	 * @var array
40
+	 */
41
+	private static $_reg_status;
42
+
43
+	/**
44
+	 * Form for displaying the custom questions for this registration.
45
+	 * This gets used a few times throughout the request so its best to cache it
46
+	 *
47
+	 * @var EE_Registration_Custom_Questions_Form
48
+	 */
49
+	protected $_reg_custom_questions_form;
50
+
51
+	/**
52
+	 * @var EEM_Registration $registration_model
53
+	 */
54
+	private $registration_model;
55
+
56
+	/**
57
+	 * @var EEM_Attendee $attendee_model
58
+	 */
59
+	private $attendee_model;
60
+
61
+	/**
62
+	 * @var EEM_Event $event_model
63
+	 */
64
+	private $event_model;
65
+
66
+	/**
67
+	 * @var EEM_Status $status_model
68
+	 */
69
+	private $status_model;
70
+
71
+
72
+	/**
73
+	 * @param bool $routing
74
+	 * @throws InvalidArgumentException
75
+	 * @throws InvalidDataTypeException
76
+	 * @throws InvalidInterfaceException
77
+	 * @throws ReflectionException
78
+	 */
79
+	public function __construct($routing = true)
80
+	{
81
+		parent::__construct($routing);
82
+		$this->cpt_editpost_route = 'edit_attendee';
83
+		add_action('wp_loaded', [$this, 'wp_loaded']);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @return EEM_Registration
89
+	 * @throws InvalidArgumentException
90
+	 * @throws InvalidDataTypeException
91
+	 * @throws InvalidInterfaceException
92
+	 * @since 4.10.2.p
93
+	 */
94
+	protected function getRegistrationModel()
95
+	{
96
+		if (! $this->registration_model instanceof EEM_Registration) {
97
+			$this->registration_model = $this->loader->getShared('EEM_Registration');
98
+		}
99
+		return $this->registration_model;
100
+	}
101
+
102
+
103
+	/**
104
+	 * @return EEM_Attendee
105
+	 * @throws InvalidArgumentException
106
+	 * @throws InvalidDataTypeException
107
+	 * @throws InvalidInterfaceException
108
+	 * @since 4.10.2.p
109
+	 */
110
+	protected function getAttendeeModel()
111
+	{
112
+		if (! $this->attendee_model instanceof EEM_Attendee) {
113
+			$this->attendee_model = $this->loader->getShared('EEM_Attendee');
114
+		}
115
+		return $this->attendee_model;
116
+	}
117
+
118
+
119
+	/**
120
+	 * @return EEM_Event
121
+	 * @throws InvalidArgumentException
122
+	 * @throws InvalidDataTypeException
123
+	 * @throws InvalidInterfaceException
124
+	 * @since 4.10.2.p
125
+	 */
126
+	protected function getEventModel()
127
+	{
128
+		if (! $this->event_model instanceof EEM_Event) {
129
+			$this->event_model = $this->loader->getShared('EEM_Event');
130
+		}
131
+		return $this->event_model;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @return EEM_Status
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 * @since 4.10.2.p
141
+	 */
142
+	protected function getStatusModel()
143
+	{
144
+		if (! $this->status_model instanceof EEM_Status) {
145
+			$this->status_model = $this->loader->getShared('EEM_Status');
146
+		}
147
+		return $this->status_model;
148
+	}
149
+
150
+
151
+	public function wp_loaded()
152
+	{
153
+		// when adding a new registration...
154
+		$action = $this->request->getRequestParam('action');
155
+		if ($action === 'new_registration') {
156
+			EE_System::do_not_cache();
157
+			if ($this->request->getRequestParam('processing_registration', 0, 'int') !== 1) {
158
+				// and it's NOT the attendee information reg step
159
+				// force cookie expiration by setting time to last week
160
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
161
+				// and update the global
162
+				$_COOKIE['ee_registration_added'] = 0;
163
+			}
164
+		}
165
+	}
166
+
167
+
168
+	protected function _init_page_props()
169
+	{
170
+		$this->page_slug        = REG_PG_SLUG;
171
+		$this->_admin_base_url  = REG_ADMIN_URL;
172
+		$this->_admin_base_path = REG_ADMIN;
173
+		$this->page_label       = esc_html__('Registrations', 'event_espresso');
174
+		$this->_cpt_routes      = [
175
+			'add_new_attendee' => 'espresso_attendees',
176
+			'edit_attendee'    => 'espresso_attendees',
177
+			'insert_attendee'  => 'espresso_attendees',
178
+			'update_attendee'  => 'espresso_attendees',
179
+		];
180
+		$this->_cpt_model_names = [
181
+			'add_new_attendee' => 'EEM_Attendee',
182
+			'edit_attendee'    => 'EEM_Attendee',
183
+		];
184
+		$this->_cpt_edit_routes = [
185
+			'espresso_attendees' => 'edit_attendee',
186
+		];
187
+		$this->_pagenow_map     = [
188
+			'add_new_attendee' => 'post-new.php',
189
+			'edit_attendee'    => 'post.php',
190
+			'trash'            => 'post.php',
191
+		];
192
+		add_action('edit_form_after_title', [$this, 'after_title_form_fields'], 10);
193
+		// add filters so that the comment urls don't take users to a confusing 404 page
194
+		add_filter('get_comment_link', [$this, 'clear_comment_link'], 10, 2);
195
+	}
196
+
197
+
198
+	/**
199
+	 * @param string     $link    The comment permalink with '#comment-$id' appended.
200
+	 * @param WP_Comment $comment The current comment object.
201
+	 * @return string
202
+	 */
203
+	public function clear_comment_link($link, WP_Comment $comment)
204
+	{
205
+		// gotta make sure this only happens on this route
206
+		$post_type = get_post_type($comment->comment_post_ID);
207
+		if ($post_type === EspressoPostType::ATTENDEES) {
208
+			return '#commentsdiv';
209
+		}
210
+		return $link;
211
+	}
212
+
213
+
214
+	protected function _ajax_hooks()
215
+	{
216
+	}
217
+
218
+
219
+	protected function _define_page_props()
220
+	{
221
+		$this->_admin_page_title = $this->page_label;
222
+		$this->_labels           = [
223
+			'buttons'                      => [
224
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
225
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
226
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
227
+				'csv_reg_report'      => esc_html__('Registrations CSV Report', 'event_espresso'),
228
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
229
+				'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
230
+			],
231
+			'publishbox'                   => [
232
+				'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
233
+				'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
234
+			],
235
+			'hide_add_button_on_cpt_route' => [
236
+				'edit_attendee' => true,
237
+			],
238
+		];
239
+	}
240
+
241
+
242
+	/**
243
+	 * grab url requests and route them
244
+	 *
245
+	 * @return void
246
+	 * @throws EE_Error
247
+	 */
248
+	public function _set_page_routes()
249
+	{
250
+		$this->_get_registration_status_array();
251
+		$REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
252
+		$REG_ID             = $this->request->getRequestParam('reg_status_change_form[REG_ID]', $REG_ID, 'int');
253
+		$ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
254
+		$ATT_ID             = $this->request->getRequestParam('post', $ATT_ID, 'int');
255
+		$this->_page_routes = [
256
+			'default'                             => [
257
+				'func'       => [$this, '_registrations_overview_list_table'],
258
+				'capability' => 'ee_read_registrations',
259
+			],
260
+			'view_registration'                   => [
261
+				'func'       => [$this, '_registration_details'],
262
+				'capability' => 'ee_read_registration',
263
+				'obj_id'     => $REG_ID,
264
+			],
265
+			'edit_registration'                   => [
266
+				'func'               => '_update_attendee_registration_form',
267
+				'noheader'           => true,
268
+				'headers_sent_route' => 'view_registration',
269
+				'capability'         => 'ee_edit_registration',
270
+				'obj_id'             => $REG_ID,
271
+				'_REG_ID'            => $REG_ID,
272
+			],
273
+			'trash_registrations'                 => [
274
+				'func'       => '_trash_or_restore_registrations',
275
+				'args'       => ['trash' => true],
276
+				'noheader'   => true,
277
+				'capability' => 'ee_delete_registrations',
278
+			],
279
+			'restore_registrations'               => [
280
+				'func'       => '_trash_or_restore_registrations',
281
+				'args'       => ['trash' => false],
282
+				'noheader'   => true,
283
+				'capability' => 'ee_delete_registrations',
284
+			],
285
+			'delete_registrations'                => [
286
+				'func'       => '_delete_registrations',
287
+				'noheader'   => true,
288
+				'capability' => 'ee_delete_registrations',
289
+			],
290
+			'new_registration'                    => [
291
+				'func'       => 'new_registration',
292
+				'capability' => 'ee_edit_registrations',
293
+			],
294
+			'process_reg_step'                    => [
295
+				'func'       => 'process_reg_step',
296
+				'noheader'   => true,
297
+				'capability' => 'ee_edit_registrations',
298
+			],
299
+			'redirect_to_txn'                     => [
300
+				'func'       => 'redirect_to_txn',
301
+				'noheader'   => true,
302
+				'capability' => 'ee_edit_registrations',
303
+			],
304
+			'change_reg_status'                   => [
305
+				'func'       => '_change_reg_status',
306
+				'noheader'   => true,
307
+				'capability' => 'ee_edit_registration',
308
+				'obj_id'     => $REG_ID,
309
+			],
310
+			'approve_registration'                => [
311
+				'func'       => 'approve_registration',
312
+				'noheader'   => true,
313
+				'capability' => 'ee_edit_registration',
314
+				'obj_id'     => $REG_ID,
315
+			],
316
+			'approve_and_notify_registration'     => [
317
+				'func'       => 'approve_registration',
318
+				'noheader'   => true,
319
+				'args'       => [true],
320
+				'capability' => 'ee_edit_registration',
321
+				'obj_id'     => $REG_ID,
322
+			],
323
+			'approve_registrations'               => [
324
+				'func'       => 'bulk_action_on_registrations',
325
+				'noheader'   => true,
326
+				'capability' => 'ee_edit_registrations',
327
+				'args'       => ['approve'],
328
+			],
329
+			'approve_and_notify_registrations'    => [
330
+				'func'       => 'bulk_action_on_registrations',
331
+				'noheader'   => true,
332
+				'capability' => 'ee_edit_registrations',
333
+				'args'       => ['approve', true],
334
+			],
335
+			'decline_registration'                => [
336
+				'func'       => 'decline_registration',
337
+				'noheader'   => true,
338
+				'capability' => 'ee_edit_registration',
339
+				'obj_id'     => $REG_ID,
340
+			],
341
+			'decline_and_notify_registration'     => [
342
+				'func'       => 'decline_registration',
343
+				'noheader'   => true,
344
+				'args'       => [true],
345
+				'capability' => 'ee_edit_registration',
346
+				'obj_id'     => $REG_ID,
347
+			],
348
+			'decline_registrations'               => [
349
+				'func'       => 'bulk_action_on_registrations',
350
+				'noheader'   => true,
351
+				'capability' => 'ee_edit_registrations',
352
+				'args'       => ['decline'],
353
+			],
354
+			'decline_and_notify_registrations'    => [
355
+				'func'       => 'bulk_action_on_registrations',
356
+				'noheader'   => true,
357
+				'capability' => 'ee_edit_registrations',
358
+				'args'       => ['decline', true],
359
+			],
360
+			'pending_registration'                => [
361
+				'func'       => 'pending_registration',
362
+				'noheader'   => true,
363
+				'capability' => 'ee_edit_registration',
364
+				'obj_id'     => $REG_ID,
365
+			],
366
+			'pending_and_notify_registration'     => [
367
+				'func'       => 'pending_registration',
368
+				'noheader'   => true,
369
+				'args'       => [true],
370
+				'capability' => 'ee_edit_registration',
371
+				'obj_id'     => $REG_ID,
372
+			],
373
+			'pending_registrations'               => [
374
+				'func'       => 'bulk_action_on_registrations',
375
+				'noheader'   => true,
376
+				'capability' => 'ee_edit_registrations',
377
+				'args'       => ['pending'],
378
+			],
379
+			'pending_and_notify_registrations'    => [
380
+				'func'       => 'bulk_action_on_registrations',
381
+				'noheader'   => true,
382
+				'capability' => 'ee_edit_registrations',
383
+				'args'       => ['pending', true],
384
+			],
385
+			'no_approve_registration'             => [
386
+				'func'       => 'not_approve_registration',
387
+				'noheader'   => true,
388
+				'capability' => 'ee_edit_registration',
389
+				'obj_id'     => $REG_ID,
390
+			],
391
+			'no_approve_and_notify_registration'  => [
392
+				'func'       => 'not_approve_registration',
393
+				'noheader'   => true,
394
+				'args'       => [true],
395
+				'capability' => 'ee_edit_registration',
396
+				'obj_id'     => $REG_ID,
397
+			],
398
+			'no_approve_registrations'            => [
399
+				'func'       => 'bulk_action_on_registrations',
400
+				'noheader'   => true,
401
+				'capability' => 'ee_edit_registrations',
402
+				'args'       => ['not_approve'],
403
+			],
404
+			'no_approve_and_notify_registrations' => [
405
+				'func'       => 'bulk_action_on_registrations',
406
+				'noheader'   => true,
407
+				'capability' => 'ee_edit_registrations',
408
+				'args'       => ['not_approve', true],
409
+			],
410
+			'cancel_registration'                 => [
411
+				'func'       => 'cancel_registration',
412
+				'noheader'   => true,
413
+				'capability' => 'ee_edit_registration',
414
+				'obj_id'     => $REG_ID,
415
+			],
416
+			'cancel_and_notify_registration'      => [
417
+				'func'       => 'cancel_registration',
418
+				'noheader'   => true,
419
+				'args'       => [true],
420
+				'capability' => 'ee_edit_registration',
421
+				'obj_id'     => $REG_ID,
422
+			],
423
+			'cancel_registrations'                => [
424
+				'func'       => 'bulk_action_on_registrations',
425
+				'noheader'   => true,
426
+				'capability' => 'ee_edit_registrations',
427
+				'args'       => ['cancel'],
428
+			],
429
+			'cancel_and_notify_registrations'     => [
430
+				'func'       => 'bulk_action_on_registrations',
431
+				'noheader'   => true,
432
+				'capability' => 'ee_edit_registrations',
433
+				'args'       => ['cancel', true],
434
+			],
435
+			'wait_list_registration'              => [
436
+				'func'       => 'wait_list_registration',
437
+				'noheader'   => true,
438
+				'capability' => 'ee_edit_registration',
439
+				'obj_id'     => $REG_ID,
440
+			],
441
+			'wait_list_and_notify_registration'   => [
442
+				'func'       => 'wait_list_registration',
443
+				'noheader'   => true,
444
+				'args'       => [true],
445
+				'capability' => 'ee_edit_registration',
446
+				'obj_id'     => $REG_ID,
447
+			],
448
+			'contact_list'                        => [
449
+				'func'       => '_attendee_contact_list_table',
450
+				'capability' => 'ee_read_contacts',
451
+			],
452
+			'add_new_attendee'                    => [
453
+				'func' => '_create_new_cpt_item',
454
+				'args' => [
455
+					'new_attendee' => true,
456
+					'capability'   => 'ee_edit_contacts',
457
+				],
458
+			],
459
+			'edit_attendee'                       => [
460
+				'func'       => '_edit_cpt_item',
461
+				'capability' => 'ee_edit_contacts',
462
+				'obj_id'     => $ATT_ID,
463
+			],
464
+			'duplicate_attendee'                  => [
465
+				'func'       => '_duplicate_attendee',
466
+				'noheader'   => true,
467
+				'capability' => 'ee_edit_contacts',
468
+				'obj_id'     => $ATT_ID,
469
+			],
470
+			'insert_attendee'                     => [
471
+				'func'       => '_insert_or_update_attendee',
472
+				'args'       => [
473
+					'new_attendee' => true,
474
+				],
475
+				'noheader'   => true,
476
+				'capability' => 'ee_edit_contacts',
477
+			],
478
+			'update_attendee'                     => [
479
+				'func'       => '_insert_or_update_attendee',
480
+				'args'       => [
481
+					'new_attendee' => false,
482
+				],
483
+				'noheader'   => true,
484
+				'capability' => 'ee_edit_contacts',
485
+				'obj_id'     => $ATT_ID,
486
+			],
487
+			'trash_attendees'                     => [
488
+				'func'       => '_trash_or_restore_attendees',
489
+				'args'       => [
490
+					'trash' => 'true',
491
+				],
492
+				'noheader'   => true,
493
+				'capability' => 'ee_delete_contacts',
494
+			],
495
+			'trash_attendee'                      => [
496
+				'func'       => '_trash_or_restore_attendees',
497
+				'args'       => [
498
+					'trash' => true,
499
+				],
500
+				'noheader'   => true,
501
+				'capability' => 'ee_delete_contacts',
502
+				'obj_id'     => $ATT_ID,
503
+			],
504
+			'restore_attendees'                   => [
505
+				'func'       => '_trash_or_restore_attendees',
506
+				'args'       => [
507
+					'trash' => false,
508
+				],
509
+				'noheader'   => true,
510
+				'capability' => 'ee_delete_contacts',
511
+				'obj_id'     => $ATT_ID,
512
+			],
513
+			'delete_attendee'                  => [
514
+				'func'       => [$this, 'deleteAttendees'],
515
+				'capability' => 'ee_delete_contacts',
516
+				'obj_id'     => $ATT_ID,
517
+				'noheader'   => true,
518
+			],
519
+			'delete_attendees'                 => [
520
+				'func'       => [$this, 'deleteAttendees'],
521
+				'capability' => 'ee_delete_contacts',
522
+				'noheader'   => true,
523
+			],
524
+			'resend_registration'                 => [
525
+				'func'       => '_resend_registration',
526
+				'noheader'   => true,
527
+				'capability' => 'ee_send_message',
528
+			],
529
+			'registrations_report'                => [
530
+				'func'       => [$this, '_registrations_report'],
531
+				'noheader'   => true,
532
+				'capability' => 'ee_read_registrations',
533
+			],
534
+			'contact_list_export'                 => [
535
+				'func'       => '_contact_list_export',
536
+				'noheader'   => true,
537
+				'capability' => 'export',
538
+			],
539
+			'contact_list_report'                 => [
540
+				'func'       => '_contact_list_report',
541
+				'noheader'   => true,
542
+				'capability' => 'ee_read_contacts',
543
+			],
544
+		];
545
+	}
546
+
547
+
548
+	protected function _set_page_config()
549
+	{
550
+		$REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
551
+		$ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
552
+		$this->_page_config = [
553
+			'default'           => [
554
+				'nav'           => [
555
+					'label' => esc_html__('Overview', 'event_espresso'),
556
+					'icon'  => 'dashicons-list-view',
557
+					'order' => 5,
558
+				],
559
+				'help_tabs'     => [
560
+					'registrations_overview_help_tab'                       => [
561
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
562
+						'filename' => 'registrations_overview',
563
+					],
564
+					'registrations_overview_table_column_headings_help_tab' => [
565
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
566
+						'filename' => 'registrations_overview_table_column_headings',
567
+					],
568
+					'registrations_overview_filters_help_tab'               => [
569
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
570
+						'filename' => 'registrations_overview_filters',
571
+					],
572
+					'registrations_overview_views_help_tab'                 => [
573
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
574
+						'filename' => 'registrations_overview_views',
575
+					],
576
+					'registrations_regoverview_other_help_tab'              => [
577
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
578
+						'filename' => 'registrations_overview_other',
579
+					],
580
+				],
581
+				'list_table'    => 'EE_Registrations_List_Table',
582
+				'require_nonce' => false,
583
+			],
584
+			'view_registration' => [
585
+				'nav'           => [
586
+					'label'      => esc_html__('REG Details', 'event_espresso'),
587
+					'icon'       => 'dashicons-clipboard',
588
+					'order'      => 15,
589
+					'url'        => $REG_ID
590
+						? add_query_arg(['_REG_ID' => $REG_ID], $this->_current_page_view_url)
591
+						: $this->_admin_base_url,
592
+					'persistent' => false,
593
+				],
594
+				'help_tabs'     => [
595
+					'registrations_details_help_tab'                    => [
596
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
597
+						'filename' => 'registrations_details',
598
+					],
599
+					'registrations_details_table_help_tab'              => [
600
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
601
+						'filename' => 'registrations_details_table',
602
+					],
603
+					'registrations_details_form_answers_help_tab'       => [
604
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
605
+						'filename' => 'registrations_details_form_answers',
606
+					],
607
+					'registrations_details_registrant_details_help_tab' => [
608
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
609
+						'filename' => 'registrations_details_registrant_details',
610
+					],
611
+				],
612
+				'metaboxes'     => array_merge(
613
+					$this->_default_espresso_metaboxes,
614
+					['_registration_details_metaboxes']
615
+				),
616
+				'require_nonce' => false,
617
+			],
618
+			'new_registration'  => [
619
+				'nav'           => [
620
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
621
+					'icon'       => 'dashicons-plus-alt',
622
+					'url'        => '#',
623
+					'order'      => 15,
624
+					'persistent' => false,
625
+				],
626
+				'metaboxes'     => $this->_default_espresso_metaboxes,
627
+				'labels'        => [
628
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
629
+				],
630
+				'require_nonce' => false,
631
+			],
632
+			'add_new_attendee'  => [
633
+				'nav'           => [
634
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
635
+					'icon'       => 'dashicons-plus-alt',
636
+					'order'      => 15,
637
+					'persistent' => false,
638
+				],
639
+				'metaboxes'     => array_merge(
640
+					$this->_default_espresso_metaboxes,
641
+					['_publish_post_box', 'attendee_editor_metaboxes']
642
+				),
643
+				'require_nonce' => false,
644
+			],
645
+			'edit_attendee'     => [
646
+				'nav'           => [
647
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
648
+					'icon'       => 'dashicons-edit-large',
649
+					'order'      => 15,
650
+					'persistent' => false,
651
+					'url'        => $ATT_ID
652
+						? add_query_arg(['ATT_ID' => $ATT_ID], $this->_current_page_view_url)
653
+						: $this->_admin_base_url,
654
+				],
655
+				'metaboxes'     => array_merge(
656
+					$this->_default_espresso_metaboxes,
657
+					['attendee_editor_metaboxes']
658
+				),
659
+				'require_nonce' => false,
660
+			],
661
+			'contact_list'      => [
662
+				'nav'           => [
663
+					'label' => esc_html__('Contact List', 'event_espresso'),
664
+					'icon'  => 'dashicons-id-alt',
665
+					'order' => 20,
666
+				],
667
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
668
+				'help_tabs'     => [
669
+					'registrations_contact_list_help_tab'                       => [
670
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
671
+						'filename' => 'registrations_contact_list',
672
+					],
673
+					'registrations_contact-list_table_column_headings_help_tab' => [
674
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
675
+						'filename' => 'registrations_contact_list_table_column_headings',
676
+					],
677
+					'registrations_contact_list_views_help_tab'                 => [
678
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
679
+						'filename' => 'registrations_contact_list_views',
680
+					],
681
+					'registrations_contact_list_other_help_tab'                 => [
682
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
683
+						'filename' => 'registrations_contact_list_other',
684
+					],
685
+				],
686
+				'metaboxes'     => [],
687
+				'require_nonce' => false,
688
+			],
689
+			// override default cpt routes
690
+			'create_new'        => '',
691
+			'edit'              => '',
692
+		];
693
+	}
694
+
695
+
696
+	/**
697
+	 * The below methods aren't used by this class currently
698
+	 */
699
+	protected function _add_screen_options()
700
+	{
701
+	}
702
+
703
+
704
+	protected function _add_feature_pointers()
705
+	{
706
+	}
707
+
708
+
709
+	public function admin_init()
710
+	{
711
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
712
+			'click "Update Registration Questions" to save your changes',
713
+			'event_espresso'
714
+		);
715
+	}
716
+
717
+
718
+	public function admin_notices()
719
+	{
720
+	}
721
+
722
+
723
+	public function admin_footer_scripts()
724
+	{
725
+	}
726
+
727
+
728
+	/**
729
+	 * get list of registration statuses
730
+	 *
731
+	 * @return void
732
+	 * @throws EE_Error
733
+	 * @throws ReflectionException
734
+	 */
735
+	private function _get_registration_status_array()
736
+	{
737
+		self::$_reg_status = EEM_Registration::reg_status_array([], true);
738
+	}
739
+
740
+
741
+	/**
742
+	 * @throws InvalidArgumentException
743
+	 * @throws InvalidDataTypeException
744
+	 * @throws InvalidInterfaceException
745
+	 * @since 4.10.2.p
746
+	 */
747
+	protected function _add_screen_options_default()
748
+	{
749
+		$this->_per_page_screen_option();
750
+	}
751
+
752
+
753
+	/**
754
+	 * @throws InvalidArgumentException
755
+	 * @throws InvalidDataTypeException
756
+	 * @throws InvalidInterfaceException
757
+	 * @since 4.10.2.p
758
+	 */
759
+	protected function _add_screen_options_contact_list()
760
+	{
761
+		$page_title              = $this->_admin_page_title;
762
+		$this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
763
+		$this->_per_page_screen_option();
764
+		$this->_admin_page_title = $page_title;
765
+	}
766
+
767
+
768
+	public function load_scripts_styles()
769
+	{
770
+		// style
771
+		wp_register_style(
772
+			'espresso_reg',
773
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
774
+			['ee-admin-css'],
775
+			EVENT_ESPRESSO_VERSION
776
+		);
777
+		wp_enqueue_style('espresso_reg');
778
+		// script
779
+		wp_register_script(
780
+			'espresso_reg',
781
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
782
+			['jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'],
783
+			EVENT_ESPRESSO_VERSION,
784
+			true
785
+		);
786
+		wp_enqueue_script('espresso_reg');
787
+	}
788
+
789
+
790
+	/**
791
+	 * @throws EE_Error
792
+	 * @throws InvalidArgumentException
793
+	 * @throws InvalidDataTypeException
794
+	 * @throws InvalidInterfaceException
795
+	 * @throws ReflectionException
796
+	 * @since 4.10.2.p
797
+	 */
798
+	public function load_scripts_styles_edit_attendee()
799
+	{
800
+		// stuff to only show up on our attendee edit details page.
801
+		$attendee_details_translations = [
802
+			'att_publish_text' => sprintf(
803
+			/* translators: The date and time */
804
+				wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
805
+				'<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
806
+			),
807
+		];
808
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
809
+		wp_enqueue_script('jquery-validate');
810
+	}
811
+
812
+
813
+	/**
814
+	 * @throws EE_Error
815
+	 * @throws InvalidArgumentException
816
+	 * @throws InvalidDataTypeException
817
+	 * @throws InvalidInterfaceException
818
+	 * @throws ReflectionException
819
+	 * @since 4.10.2.p
820
+	 */
821
+	public function load_scripts_styles_view_registration()
822
+	{
823
+		$this->_set_registration_object();
824
+		// styles
825
+		wp_enqueue_style('espresso-ui-theme');
826
+		// scripts
827
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
828
+		$this->_reg_custom_questions_form->wp_enqueue_scripts();
829
+	}
830
+
831
+
832
+	public function load_scripts_styles_contact_list()
833
+	{
834
+		wp_dequeue_style('espresso_reg');
835
+		wp_register_style(
836
+			'espresso_att',
837
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
838
+			['ee-admin-css'],
839
+			EVENT_ESPRESSO_VERSION
840
+		);
841
+		wp_enqueue_style('espresso_att');
842
+	}
843
+
844
+
845
+	public function load_scripts_styles_new_registration()
846
+	{
847
+		wp_register_script(
848
+			'ee-spco-for-admin',
849
+			REG_ASSETS_URL . 'spco_for_admin.js',
850
+			['underscore', 'jquery'],
851
+			EVENT_ESPRESSO_VERSION,
852
+			true
853
+		);
854
+		wp_enqueue_script('ee-spco-for-admin');
855
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
856
+		EE_Form_Section_Proper::wp_enqueue_scripts();
857
+		EED_Ticket_Selector::load_tckt_slctr_assets();
858
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
859
+	}
860
+
861
+
862
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
863
+	{
864
+		add_filter('FHEE_load_EE_messages', '__return_true');
865
+	}
866
+
867
+
868
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
869
+	{
870
+		add_filter('FHEE_load_EE_messages', '__return_true');
871
+	}
872
+
873
+
874
+	/**
875
+	 * @throws EE_Error
876
+	 * @throws InvalidArgumentException
877
+	 * @throws InvalidDataTypeException
878
+	 * @throws InvalidInterfaceException
879
+	 * @throws ReflectionException
880
+	 * @since 4.10.2.p
881
+	 */
882
+	protected function _set_list_table_views_default()
883
+	{
884
+		// for notification related bulk actions we need to make sure only active messengers have an option.
885
+		EED_Messages::set_autoloaders();
886
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
887
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
888
+		$active_mts               = $message_resource_manager->list_of_active_message_types();
889
+		// key= bulk_action_slug, value= message type.
890
+		$match_array = [
891
+			'approve_registrations'    => 'registration',
892
+			'decline_registrations'    => 'declined_registration',
893
+			'pending_registrations'    => 'pending_approval',
894
+			'no_approve_registrations' => 'not_approved_registration',
895
+			'cancel_registrations'     => 'cancelled_registration',
896
+		];
897
+		$can_send    = $this->capabilities->current_user_can(
898
+			'ee_send_message',
899
+			'batch_send_messages'
900
+		);
901
+		/** setup reg status bulk actions **/
902
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
903
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
904
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
905
+				'Approve and Notify Registrations',
906
+				'event_espresso'
907
+			);
908
+		}
909
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
910
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
911
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
912
+				'Decline and Notify Registrations',
913
+				'event_espresso'
914
+			);
915
+		}
916
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
917
+			'Set Registrations to Pending Payment',
918
+			'event_espresso'
919
+		);
920
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
921
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
922
+				'Set Registrations to Pending Payment and Notify',
923
+				'event_espresso'
924
+			);
925
+		}
926
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
927
+			'Set Registrations to Awaiting Review',
928
+			'event_espresso'
929
+		);
930
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
931
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
932
+				'Set Registrations to Awaiting Review and Notify',
933
+				'event_espresso'
934
+			);
935
+		}
936
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
937
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
938
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
939
+				'Cancel Registrations and Notify',
940
+				'event_espresso'
941
+			);
942
+		}
943
+		$def_reg_status_actions = apply_filters(
944
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
945
+			$def_reg_status_actions,
946
+			$active_mts,
947
+			$can_send
948
+		);
949
+
950
+		$current_time = current_time('timestamp');
951
+		$this->_views = [
952
+			'all'   => [
953
+				'slug'        => 'all',
954
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
955
+				'count'       => 0,
956
+				'bulk_action' => array_merge(
957
+					$def_reg_status_actions,
958
+					[
959
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
960
+					]
961
+				),
962
+			],
963
+			'today' => [
964
+				'slug'        => 'today',
965
+				'label'       => sprintf(
966
+					esc_html__('Today - %s', 'event_espresso'),
967
+					date('M d, Y', $current_time)
968
+				),
969
+				'count'       => 0,
970
+				'bulk_action' => array_merge(
971
+					$def_reg_status_actions,
972
+					[
973
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
974
+					]
975
+				),
976
+			],
977
+			'yesterday' => [
978
+				'slug'        => 'yesterday',
979
+				'label'       => sprintf(
980
+					esc_html__('Yesterday - %s', 'event_espresso'),
981
+					date('M d, Y', $current_time - DAY_IN_SECONDS)
982
+				),
983
+				'count'       => 0,
984
+				'bulk_action' => array_merge(
985
+					$def_reg_status_actions,
986
+					[
987
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
988
+					]
989
+				),
990
+			],
991
+			'month' => [
992
+				'slug'        => 'month',
993
+				'label'       => esc_html__('This Month', 'event_espresso'),
994
+				'count'       => 0,
995
+				'bulk_action' => array_merge(
996
+					$def_reg_status_actions,
997
+					[
998
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
999
+					]
1000
+				),
1001
+			],
1002
+		];
1003
+		if (
1004
+			$this->capabilities->current_user_can(
1005
+				'ee_delete_registrations',
1006
+				'espresso_registrations_delete_registration'
1007
+			)
1008
+		) {
1009
+			$this->_views['incomplete'] = [
1010
+				'slug'        => 'incomplete',
1011
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
1012
+				'count'       => 0,
1013
+				'bulk_action' => [
1014
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
1015
+				],
1016
+			];
1017
+			$this->_views['trash']      = [
1018
+				'slug'        => 'trash',
1019
+				'label'       => esc_html__('Trash', 'event_espresso'),
1020
+				'count'       => 0,
1021
+				'bulk_action' => [
1022
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
1023
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
1024
+				],
1025
+			];
1026
+		}
1027
+	}
1028
+
1029
+
1030
+	protected function _set_list_table_views_contact_list()
1031
+	{
1032
+		$this->_views = [
1033
+			'in_use' => [
1034
+				'slug'        => 'in_use',
1035
+				'label'       => esc_html__('In Use', 'event_espresso'),
1036
+				'count'       => 0,
1037
+				'bulk_action' => [
1038
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1039
+				],
1040
+			],
1041
+		];
1042
+		if (
1043
+			$this->capabilities->current_user_can(
1044
+				'ee_delete_contacts',
1045
+				'espresso_registrations_trash_attendees'
1046
+			)
1047
+		) {
1048
+			$this->_views['trash'] = [
1049
+				'slug'        => 'trash',
1050
+				'label'       => esc_html__('Trash', 'event_espresso'),
1051
+				'count'       => 0,
1052
+				'bulk_action' => [
1053
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1054
+					'delete_attendees' => esc_html__('Permanently Delete', 'event_espresso'),
1055
+				],
1056
+			];
1057
+		}
1058
+	}
1059
+
1060
+
1061
+	/**
1062
+	 * @return array
1063
+	 * @throws EE_Error
1064
+	 */
1065
+	protected function _registration_legend_items()
1066
+	{
1067
+		$fc_items = [
1068
+			'star-icon'        => [
1069
+				'class' => 'dashicons dashicons-star-filled gold-icon',
1070
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1071
+			],
1072
+			'view_details'     => [
1073
+				'class' => 'dashicons dashicons-clipboard',
1074
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1075
+			],
1076
+			'edit_attendee'    => [
1077
+				'class' => 'dashicons dashicons-admin-users',
1078
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1079
+			],
1080
+			'view_transaction' => [
1081
+				'class' => 'dashicons dashicons-cart',
1082
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1083
+			],
1084
+			'view_invoice'     => [
1085
+				'class' => 'dashicons dashicons-media-spreadsheet',
1086
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1087
+			],
1088
+		];
1089
+		if (
1090
+			$this->capabilities->current_user_can(
1091
+				'ee_send_message',
1092
+				'espresso_registrations_resend_registration'
1093
+			)
1094
+		) {
1095
+			$fc_items['resend_registration'] = [
1096
+				'class' => 'dashicons dashicons-email-alt',
1097
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1098
+			];
1099
+		} else {
1100
+			$fc_items['blank'] = ['class' => 'blank', 'desc' => ''];
1101
+		}
1102
+		if (
1103
+			$this->capabilities->current_user_can(
1104
+				'ee_read_global_messages',
1105
+				'view_filtered_messages'
1106
+			)
1107
+		) {
1108
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1109
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1110
+				$fc_items['view_related_messages'] = [
1111
+					'class' => $related_for_icon['css_class'],
1112
+					'desc'  => $related_for_icon['label'],
1113
+				];
1114
+			}
1115
+		}
1116
+		$sc_items = [
1117
+			'approved_status'   => [
1118
+				'class' => 'ee-status-legend ee-status-bg--' . RegStatus::APPROVED,
1119
+				'desc'  => EEH_Template::pretty_status(
1120
+					RegStatus::APPROVED,
1121
+					false,
1122
+					'sentence'
1123
+				),
1124
+			],
1125
+			'pending_status'    => [
1126
+				'class' => 'ee-status-legend ee-status-bg--' . RegStatus::PENDING_PAYMENT,
1127
+				'desc'  => EEH_Template::pretty_status(
1128
+					RegStatus::PENDING_PAYMENT,
1129
+					false,
1130
+					'sentence'
1131
+				),
1132
+			],
1133
+			'wait_list'         => [
1134
+				'class' => 'ee-status-legend ee-status-bg--' . RegStatus::WAIT_LIST,
1135
+				'desc'  => EEH_Template::pretty_status(
1136
+					RegStatus::WAIT_LIST,
1137
+					false,
1138
+					'sentence'
1139
+				),
1140
+			],
1141
+			'incomplete_status' => [
1142
+				'class' => 'ee-status-legend ee-status-bg--' . RegStatus::INCOMPLETE,
1143
+				'desc'  => EEH_Template::pretty_status(
1144
+					RegStatus::INCOMPLETE,
1145
+					false,
1146
+					'sentence'
1147
+				),
1148
+			],
1149
+			'not_approved'      => [
1150
+				'class' => 'ee-status-legend ee-status-bg--' . RegStatus::AWAITING_REVIEW,
1151
+				'desc'  => EEH_Template::pretty_status(
1152
+					RegStatus::AWAITING_REVIEW,
1153
+					false,
1154
+					'sentence'
1155
+				),
1156
+			],
1157
+			'declined_status'   => [
1158
+				'class' => 'ee-status-legend ee-status-bg--' . RegStatus::DECLINED,
1159
+				'desc'  => EEH_Template::pretty_status(
1160
+					RegStatus::DECLINED,
1161
+					false,
1162
+					'sentence'
1163
+				),
1164
+			],
1165
+			'cancelled_status'  => [
1166
+				'class' => 'ee-status-legend ee-status-bg--' . RegStatus::CANCELLED,
1167
+				'desc'  => EEH_Template::pretty_status(
1168
+					RegStatus::CANCELLED,
1169
+					false,
1170
+					'sentence'
1171
+				),
1172
+			],
1173
+		];
1174
+		return array_merge($fc_items, $sc_items);
1175
+	}
1176
+
1177
+
1178
+
1179
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1180
+
1181
+
1182
+	/**
1183
+	 * @throws DomainException
1184
+	 * @throws EE_Error
1185
+	 * @throws InvalidArgumentException
1186
+	 * @throws InvalidDataTypeException
1187
+	 * @throws InvalidInterfaceException
1188
+	 */
1189
+	protected function _registrations_overview_list_table()
1190
+	{
1191
+		$this->appendAddNewRegistrationButtonToPageTitle();
1192
+		$header_text                  = '';
1193
+		$admin_page_header_decorators = [
1194
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1195
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1196
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1197
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1198
+		];
1199
+		foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1200
+			$filter_header_decorator = $this->loader->getNew($admin_page_header_decorator);
1201
+			$header_text             = $filter_header_decorator->getHeaderText($header_text);
1202
+		}
1203
+		$this->_template_args['before_list_table'] = $header_text;
1204
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_registration_legend_items());
1205
+		$this->display_admin_list_table_page_with_no_sidebar();
1206
+	}
1207
+
1208
+
1209
+	/**
1210
+	 * @throws EE_Error
1211
+	 * @throws InvalidArgumentException
1212
+	 * @throws InvalidDataTypeException
1213
+	 * @throws InvalidInterfaceException
1214
+	 */
1215
+	private function appendAddNewRegistrationButtonToPageTitle()
1216
+	{
1217
+		$EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
1218
+		if (
1219
+			$EVT_ID
1220
+			&& $this->capabilities->current_user_can(
1221
+				'ee_edit_registrations',
1222
+				'espresso_registrations_new_registration',
1223
+				$EVT_ID
1224
+			)
1225
+		) {
1226
+			$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1227
+					'new_registration',
1228
+					'add-registrant',
1229
+					['event_id' => $EVT_ID],
1230
+					'add-new-h2'
1231
+				);
1232
+		}
1233
+	}
1234
+
1235
+
1236
+	/**
1237
+	 * This sets the _registration property for the registration details screen
1238
+	 *
1239
+	 * @return void
1240
+	 * @throws EE_Error
1241
+	 * @throws InvalidArgumentException
1242
+	 * @throws InvalidDataTypeException
1243
+	 * @throws InvalidInterfaceException
1244
+	 * @throws ReflectionException
1245
+	 */
1246
+	private function _set_registration_object()
1247
+	{
1248
+		// get out if we've already set the object
1249
+		if ($this->_registration instanceof EE_Registration) {
1250
+			return;
1251
+		}
1252
+		$REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
1253
+		if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1254
+			return;
1255
+		}
1256
+		$error_msg = sprintf(
1257
+			esc_html__(
1258
+				'An error occurred and the details for Registration ID #%s could not be retrieved.',
1259
+				'event_espresso'
1260
+			),
1261
+			$REG_ID
1262
+		);
1263
+		EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1264
+		$this->_registration = null;
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 * Used to retrieve registrations for the list table.
1270
+	 *
1271
+	 * @param int  $per_page
1272
+	 * @param bool $count
1273
+	 * @param bool $this_month
1274
+	 * @param bool $today
1275
+	 * @param bool $yesterday
1276
+	 * @return EE_Registration[]|int
1277
+	 * @throws EE_Error
1278
+	 * @throws ReflectionException
1279
+	 */
1280
+	public function get_registrations(
1281
+		int $per_page = 10,
1282
+		bool $count = false,
1283
+		bool $this_month = false,
1284
+		bool $today = false,
1285
+		bool $yesterday = false
1286
+	) {
1287
+		if ($this_month) {
1288
+			$this->request->setRequestParam('status', 'month');
1289
+		}
1290
+		if ($today) {
1291
+			$this->request->setRequestParam('status', 'today');
1292
+		}
1293
+		if ($yesterday) {
1294
+			$this->request->setRequestParam('status', 'yesterday');
1295
+		}
1296
+		$query_params = $this->_get_registration_query_parameters([], $per_page, $count);
1297
+		/**
1298
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1299
+		 *
1300
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1301
+		 * @see  https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1302
+		 *                      or if you have the development copy of EE you can view this at the path:
1303
+		 *                      /docs/G--Model-System/model-query-params.md
1304
+		 */
1305
+		$query_params['group_by'] = '';
1306
+
1307
+		return $count
1308
+			? $this->getRegistrationModel()->count($query_params)
1309
+			/** @type EE_Registration[] */
1310
+			: $this->getRegistrationModel()->get_all($query_params);
1311
+	}
1312
+
1313
+
1314
+	/**
1315
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1316
+	 * Note: this listens to values on the request for some query parameters.
1317
+	 *
1318
+	 * @param array $request
1319
+	 * @param int   $per_page
1320
+	 * @param bool  $count
1321
+	 * @return array
1322
+	 * @throws EE_Error
1323
+	 * @throws InvalidArgumentException
1324
+	 * @throws InvalidDataTypeException
1325
+	 * @throws InvalidInterfaceException
1326
+	 */
1327
+	protected function _get_registration_query_parameters(
1328
+		array $request = [],
1329
+		int $per_page = 10,
1330
+		bool $count = false
1331
+	): array {
1332
+		/** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1333
+		$list_table_query_builder = $this->loader->getNew(
1334
+			'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1335
+			[null, null, $request]
1336
+		);
1337
+		return $list_table_query_builder->getQueryParams($per_page, $count);
1338
+	}
1339
+
1340
+
1341
+	public function get_registration_status_array(): array
1342
+	{
1343
+		return self::$_reg_status;
1344
+	}
1345
+
1346
+
1347
+
1348
+
1349
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1350
+	/**
1351
+	 * generates HTML for the View Registration Details Admin page
1352
+	 *
1353
+	 * @return void
1354
+	 * @throws DomainException
1355
+	 * @throws EE_Error
1356
+	 * @throws InvalidArgumentException
1357
+	 * @throws InvalidDataTypeException
1358
+	 * @throws InvalidInterfaceException
1359
+	 * @throws EntityNotFoundException
1360
+	 * @throws ReflectionException
1361
+	 */
1362
+	protected function _registration_details()
1363
+	{
1364
+		$this->_template_args = [];
1365
+		$this->_set_registration_object();
1366
+		if (is_object($this->_registration)) {
1367
+			$transaction        = $this->_registration->transaction()
1368
+				? $this->_registration->transaction()
1369
+				: EE_Transaction::new_instance();
1370
+			$this->session_data = $transaction->session_data();
1371
+			$event_id           = $this->_registration->event_ID();
1372
+			$this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1373
+			$this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1374
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1375
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1376
+			$this->_template_args['grand_total']           = $transaction->total();
1377
+			$this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1378
+			// link back to overview
1379
+			$this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1380
+			$this->_template_args['registration']                = $this->_registration;
1381
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1382
+				[
1383
+					'action'   => 'default',
1384
+					'event_id' => $event_id,
1385
+				],
1386
+				REG_ADMIN_URL
1387
+			);
1388
+			$this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1389
+				[
1390
+					'action' => 'default',
1391
+					'EVT_ID' => $event_id,
1392
+					'page'   => 'espresso_transactions',
1393
+				],
1394
+				admin_url('admin.php')
1395
+			);
1396
+			$this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1397
+				[
1398
+					'page'   => 'espresso_events',
1399
+					'action' => 'edit',
1400
+					'post'   => $event_id,
1401
+				],
1402
+				admin_url('admin.php')
1403
+			);
1404
+			// next and previous links
1405
+			$next_reg                                      = $this->_registration->next(
1406
+				null,
1407
+				[],
1408
+				'REG_ID'
1409
+			);
1410
+			$this->_template_args['next_registration']     = $next_reg
1411
+				? $this->_next_link(
1412
+					EE_Admin_Page::add_query_args_and_nonce(
1413
+						[
1414
+							'action'  => 'view_registration',
1415
+							'_REG_ID' => $next_reg['REG_ID'],
1416
+						],
1417
+						REG_ADMIN_URL
1418
+					),
1419
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1420
+				)
1421
+				: '';
1422
+			$previous_reg                                  = $this->_registration->previous(
1423
+				null,
1424
+				[],
1425
+				'REG_ID'
1426
+			);
1427
+			$this->_template_args['previous_registration'] = $previous_reg
1428
+				? $this->_previous_link(
1429
+					EE_Admin_Page::add_query_args_and_nonce(
1430
+						[
1431
+							'action'  => 'view_registration',
1432
+							'_REG_ID' => $previous_reg['REG_ID'],
1433
+						],
1434
+						REG_ADMIN_URL
1435
+					),
1436
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1437
+				)
1438
+				: '';
1439
+			// grab header
1440
+			$template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1441
+			$this->_template_args['REG_ID']            = $this->_registration->ID();
1442
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1443
+				$template_path,
1444
+				$this->_template_args,
1445
+				true
1446
+			);
1447
+		} else {
1448
+			$this->_template_args['admin_page_header'] = '';
1449
+			$this->_display_espresso_notices();
1450
+		}
1451
+		// the details template wrapper
1452
+		$this->display_admin_page_with_sidebar();
1453
+	}
1454
+
1455
+
1456
+	/**
1457
+	 * @throws EE_Error
1458
+	 * @throws InvalidArgumentException
1459
+	 * @throws InvalidDataTypeException
1460
+	 * @throws InvalidInterfaceException
1461
+	 * @throws ReflectionException
1462
+	 * @since 4.10.2.p
1463
+	 */
1464
+	protected function _registration_details_metaboxes()
1465
+	{
1466
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1467
+		$this->_set_registration_object();
1468
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1469
+		$this->addMetaBox(
1470
+			'edit-reg-status-mbox',
1471
+			esc_html__('Registration Status', 'event_espresso'),
1472
+			[$this, 'set_reg_status_buttons_metabox'],
1473
+			$this->_wp_page_slug
1474
+		);
1475
+		$this->addMetaBox(
1476
+			'edit-reg-details-mbox',
1477
+			'<span>' . esc_html__('Registration Details', 'event_espresso')
1478
+			. '&nbsp;<span class="dashicons dashicons-clipboard"></span></span>',
1479
+			[$this, '_reg_details_meta_box'],
1480
+			$this->_wp_page_slug
1481
+		);
1482
+		if (
1483
+			$attendee instanceof EE_Attendee
1484
+			&& $this->capabilities->current_user_can(
1485
+				'ee_read_registration',
1486
+				'edit-reg-questions-mbox',
1487
+				$this->_registration->ID()
1488
+			)
1489
+		) {
1490
+			$this->addMetaBox(
1491
+				'edit-reg-questions-mbox',
1492
+				esc_html__('Registration Form Answers', 'event_espresso'),
1493
+				[$this, '_reg_questions_meta_box'],
1494
+				$this->_wp_page_slug
1495
+			);
1496
+		}
1497
+		$this->addMetaBox(
1498
+			'edit-reg-registrant-mbox',
1499
+			esc_html__('Contact Details', 'event_espresso'),
1500
+			[$this, '_reg_registrant_side_meta_box'],
1501
+			$this->_wp_page_slug,
1502
+			'side'
1503
+		);
1504
+		if ($this->_registration->group_size() > 1) {
1505
+			$this->addMetaBox(
1506
+				'edit-reg-attendees-mbox',
1507
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1508
+				[$this, '_reg_attendees_meta_box'],
1509
+				$this->_wp_page_slug
1510
+			);
1511
+		}
1512
+	}
1513
+
1514
+
1515
+	/**
1516
+	 * set_reg_status_buttons_metabox
1517
+	 *
1518
+	 * @return void
1519
+	 * @throws EE_Error
1520
+	 * @throws EntityNotFoundException
1521
+	 * @throws InvalidArgumentException
1522
+	 * @throws InvalidDataTypeException
1523
+	 * @throws InvalidInterfaceException
1524
+	 * @throws ReflectionException
1525
+	 */
1526
+	public function set_reg_status_buttons_metabox()
1527
+	{
1528
+		$this->_set_registration_object();
1529
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1530
+		$output                 = $change_reg_status_form->form_open(
1531
+			self::add_query_args_and_nonce(
1532
+				[
1533
+					'action' => 'change_reg_status',
1534
+				],
1535
+				REG_ADMIN_URL
1536
+			)
1537
+		);
1538
+		$output                 .= $change_reg_status_form->get_html();
1539
+		$output                 .= $change_reg_status_form->form_close();
1540
+		echo wp_kses($output, AllowedTags::getWithFormTags());
1541
+	}
1542
+
1543
+
1544
+	/**
1545
+	 * @return EE_Form_Section_Proper
1546
+	 * @throws EE_Error
1547
+	 * @throws InvalidArgumentException
1548
+	 * @throws InvalidDataTypeException
1549
+	 * @throws InvalidInterfaceException
1550
+	 * @throws EntityNotFoundException
1551
+	 * @throws ReflectionException
1552
+	 */
1553
+	protected function _generate_reg_status_change_form()
1554
+	{
1555
+		$reg_status_change_form_array = [
1556
+			'name'            => 'reg_status_change_form',
1557
+			'html_id'         => 'reg-status-change-form',
1558
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1559
+			'subsections'     => [
1560
+				'return' => new EE_Hidden_Input(
1561
+					[
1562
+						'name'    => 'return',
1563
+						'default' => 'view_registration',
1564
+					]
1565
+				),
1566
+				'REG_ID' => new EE_Hidden_Input(
1567
+					[
1568
+						'name'    => 'REG_ID',
1569
+						'default' => $this->_registration->ID(),
1570
+					]
1571
+				),
1572
+			],
1573
+		];
1574
+		if (
1575
+			$this->capabilities->current_user_can(
1576
+				'ee_edit_registration',
1577
+				'toggle_registration_status',
1578
+				$this->_registration->ID()
1579
+			)
1580
+		) {
1581
+			$reg_status_change_form_array['subsections']['reg_status']         = new EE_Select_Input(
1582
+				$this->_get_reg_statuses(),
1583
+				[
1584
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1585
+					'default'         => $this->_registration->status_ID(),
1586
+					'html_class'      => 'ee-input-width--small',
1587
+				]
1588
+			);
1589
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1590
+				[
1591
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1592
+					'default'         => false,
1593
+					'html_help_text'  => esc_html__(
1594
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1595
+						'event_espresso'
1596
+					),
1597
+				]
1598
+			);
1599
+			$reg_status_change_form_array['subsections']['submit']             = new EE_Submit_Input(
1600
+				[
1601
+					'html_class'      => 'button--primary',
1602
+					'html_label_text' => '&nbsp;',
1603
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1604
+				]
1605
+			);
1606
+		}
1607
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1608
+	}
1609
+
1610
+
1611
+	/**
1612
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1613
+	 *
1614
+	 * @return array
1615
+	 * @throws EE_Error
1616
+	 * @throws InvalidArgumentException
1617
+	 * @throws InvalidDataTypeException
1618
+	 * @throws InvalidInterfaceException
1619
+	 * @throws EntityNotFoundException
1620
+	 * @throws ReflectionException
1621
+	 */
1622
+	protected function _get_reg_statuses()
1623
+	{
1624
+		$reg_status_array = $this->getRegistrationModel()->reg_status_array();
1625
+		unset($reg_status_array[ RegStatus::INCOMPLETE ]);
1626
+		// get current reg status
1627
+		$current_status = $this->_registration->status_ID();
1628
+		// is registration for free event? This will determine whether to display the pending payment option
1629
+		if (
1630
+			$current_status !== RegStatus::PENDING_PAYMENT
1631
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1632
+		) {
1633
+			unset($reg_status_array[ RegStatus::PENDING_PAYMENT ]);
1634
+		}
1635
+		return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1641
+	 *
1642
+	 * @param bool $status REG status given for changing registrations to.
1643
+	 * @param bool $notify Whether to send messages notifications or not.
1644
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1645
+	 * @throws DomainException
1646
+	 * @throws EE_Error
1647
+	 * @throws EntityNotFoundException
1648
+	 * @throws InvalidArgumentException
1649
+	 * @throws InvalidDataTypeException
1650
+	 * @throws InvalidInterfaceException
1651
+	 * @throws ReflectionException
1652
+	 * @throws RuntimeException
1653
+	 */
1654
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1655
+	{
1656
+		$REG_IDs = $this->request->requestParamIsSet('reg_status_change_form')
1657
+			? $this->request->getRequestParam('reg_status_change_form[REG_ID]', [], 'int', true)
1658
+			: $this->request->getRequestParam('_REG_ID', [], 'int', true);
1659
+		// sanitize $REG_IDs
1660
+		$REG_IDs = array_map('absint', $REG_IDs);
1661
+		// and remove empty entries
1662
+		$REG_IDs = array_filter($REG_IDs);
1663
+
1664
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1665
+
1666
+		/**
1667
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1668
+		 * Currently this value is used downstream by the _process_resend_registration method.
1669
+		 *
1670
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1671
+		 * @param bool                     $status           The status registrations were changed to.
1672
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1673
+		 * @param Registrations_Admin_Page $admin_page
1674
+		 */
1675
+		$REG_ID = apply_filters(
1676
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1677
+			$result['REG_ID'],
1678
+			$status,
1679
+			$result['success'],
1680
+			$this
1681
+		);
1682
+		$this->request->setRequestParam('_REG_ID', $REG_ID);
1683
+
1684
+		// notify?
1685
+		if (
1686
+			$notify
1687
+			&& $result['success']
1688
+			&& ! empty($REG_ID)
1689
+			&& $this->capabilities->current_user_can(
1690
+				'ee_send_message',
1691
+				'espresso_registrations_resend_registration'
1692
+			)
1693
+		) {
1694
+			$this->_process_resend_registration();
1695
+		}
1696
+		return $result;
1697
+	}
1698
+
1699
+
1700
+	/**
1701
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1702
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1703
+	 *
1704
+	 * @param array  $REG_IDs
1705
+	 * @param string $status
1706
+	 * @param bool   $notify Used to indicate whether notification was requested or not.  This determines the context
1707
+	 *                       slug sent with setting the registration status.
1708
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1709
+	 * @throws EE_Error
1710
+	 * @throws InvalidArgumentException
1711
+	 * @throws InvalidDataTypeException
1712
+	 * @throws InvalidInterfaceException
1713
+	 * @throws ReflectionException
1714
+	 * @throws RuntimeException
1715
+	 * @throws EntityNotFoundException
1716
+	 * @throws DomainException
1717
+	 */
1718
+	protected function _set_registration_status($REG_IDs = [], $status = '', $notify = false)
1719
+	{
1720
+		$success = false;
1721
+		// typecast $REG_IDs
1722
+		$REG_IDs = (array) $REG_IDs;
1723
+		if (! empty($REG_IDs)) {
1724
+			$success = true;
1725
+			// set default status if none is passed
1726
+			$status         = $status ?: RegStatus::PENDING_PAYMENT;
1727
+			$status_context = $notify
1728
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1729
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1730
+			// loop through REG_ID's and change status
1731
+			foreach ($REG_IDs as $REG_ID) {
1732
+				$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1733
+				if ($registration instanceof EE_Registration) {
1734
+					$registration->set_status(
1735
+						$status,
1736
+						false,
1737
+						new Context(
1738
+							$status_context,
1739
+							esc_html__(
1740
+								'Manually triggered status change on a Registration Admin Page route.',
1741
+								'event_espresso'
1742
+							)
1743
+						)
1744
+					);
1745
+					$result = $registration->save();
1746
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1747
+					$success = $result !== false ? $success : false;
1748
+				}
1749
+			}
1750
+		}
1751
+
1752
+		// return $success and processed registrations
1753
+		return ['REG_ID' => $REG_IDs, 'success' => $success];
1754
+	}
1755
+
1756
+
1757
+	/**
1758
+	 * Common logic for setting up success message and redirecting to appropriate route
1759
+	 *
1760
+	 * @param string $STS_ID status id for the registration changed to
1761
+	 * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1762
+	 * @return void
1763
+	 * @throws DomainException
1764
+	 * @throws EE_Error
1765
+	 * @throws EntityNotFoundException
1766
+	 * @throws InvalidArgumentException
1767
+	 * @throws InvalidDataTypeException
1768
+	 * @throws InvalidInterfaceException
1769
+	 * @throws ReflectionException
1770
+	 * @throws RuntimeException
1771
+	 */
1772
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1773
+	{
1774
+		$result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1775
+			: ['success' => false];
1776
+		$success = isset($result['success']) && $result['success'];
1777
+		// setup success message
1778
+		if ($success) {
1779
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1780
+				$msg = sprintf(
1781
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1782
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1783
+				);
1784
+			} else {
1785
+				$msg = sprintf(
1786
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1787
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1788
+				);
1789
+			}
1790
+			EE_Error::add_success($msg);
1791
+		} else {
1792
+			EE_Error::add_error(
1793
+				esc_html__(
1794
+					'Something went wrong, and the status was not changed',
1795
+					'event_espresso'
1796
+				),
1797
+				__FILE__,
1798
+				__LINE__,
1799
+				__FUNCTION__
1800
+			);
1801
+		}
1802
+		$return = $this->request->getRequestParam('return');
1803
+		$route  = $return === 'view_registration'
1804
+			? ['action' => 'view_registration', '_REG_ID' => reset($result['REG_ID'])]
1805
+			: ['action' => 'default'];
1806
+		$route  = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1807
+		$this->_redirect_after_action($success, '', '', $route, true);
1808
+	}
1809
+
1810
+
1811
+	/**
1812
+	 * incoming reg status change from reg details page.
1813
+	 *
1814
+	 * @return void
1815
+	 * @throws EE_Error
1816
+	 * @throws EntityNotFoundException
1817
+	 * @throws InvalidArgumentException
1818
+	 * @throws InvalidDataTypeException
1819
+	 * @throws InvalidInterfaceException
1820
+	 * @throws ReflectionException
1821
+	 * @throws RuntimeException
1822
+	 * @throws DomainException
1823
+	 */
1824
+	protected function _change_reg_status()
1825
+	{
1826
+		$this->request->setRequestParam('return', 'view_registration');
1827
+		// set notify based on whether the send notifications toggle is set or not
1828
+		$notify     = $this->request->getRequestParam('reg_status_change_form[send_notifications]', false, 'bool');
1829
+		$reg_status = $this->request->getRequestParam('reg_status_change_form[reg_status]', '');
1830
+		$this->request->setRequestParam('reg_status_change_form[reg_status]', $reg_status);
1831
+		switch ($reg_status) {
1832
+			case RegStatus::APPROVED:
1833
+			case EEH_Template::pretty_status(RegStatus::APPROVED, false, 'sentence'):
1834
+				$this->approve_registration($notify);
1835
+				break;
1836
+			case RegStatus::PENDING_PAYMENT:
1837
+			case EEH_Template::pretty_status(RegStatus::PENDING_PAYMENT, false, 'sentence'):
1838
+				$this->pending_registration($notify);
1839
+				break;
1840
+			case RegStatus::AWAITING_REVIEW:
1841
+			case EEH_Template::pretty_status(RegStatus::AWAITING_REVIEW, false, 'sentence'):
1842
+				$this->not_approve_registration($notify);
1843
+				break;
1844
+			case RegStatus::DECLINED:
1845
+			case EEH_Template::pretty_status(RegStatus::DECLINED, false, 'sentence'):
1846
+				$this->decline_registration($notify);
1847
+				break;
1848
+			case RegStatus::CANCELLED:
1849
+			case EEH_Template::pretty_status(RegStatus::CANCELLED, false, 'sentence'):
1850
+				$this->cancel_registration($notify);
1851
+				break;
1852
+			case RegStatus::WAIT_LIST:
1853
+			case EEH_Template::pretty_status(RegStatus::WAIT_LIST, false, 'sentence'):
1854
+				$this->wait_list_registration($notify);
1855
+				break;
1856
+			case RegStatus::INCOMPLETE:
1857
+			default:
1858
+				$this->request->unSetRequestParam('return');
1859
+				$this->_reg_status_change_return('');
1860
+				break;
1861
+		}
1862
+	}
1863
+
1864
+
1865
+	/**
1866
+	 * Callback for bulk action routes.
1867
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1868
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
1869
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1870
+	 * when an action is happening on just a single registration).
1871
+	 *
1872
+	 * @param      $action
1873
+	 * @param bool $notify
1874
+	 */
1875
+	protected function bulk_action_on_registrations($action, $notify = false)
1876
+	{
1877
+		do_action(
1878
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1879
+			$this,
1880
+			$action,
1881
+			$notify
1882
+		);
1883
+		$method = $action . '_registration';
1884
+		if (method_exists($this, $method)) {
1885
+			$this->$method($notify);
1886
+		}
1887
+	}
1888
+
1889
+
1890
+	/**
1891
+	 * approve_registration
1892
+	 *
1893
+	 * @param bool $notify whether or not to notify the registrant about their approval.
1894
+	 * @return void
1895
+	 * @throws EE_Error
1896
+	 * @throws EntityNotFoundException
1897
+	 * @throws InvalidArgumentException
1898
+	 * @throws InvalidDataTypeException
1899
+	 * @throws InvalidInterfaceException
1900
+	 * @throws ReflectionException
1901
+	 * @throws RuntimeException
1902
+	 * @throws DomainException
1903
+	 */
1904
+	protected function approve_registration($notify = false)
1905
+	{
1906
+		$this->_reg_status_change_return(RegStatus::APPROVED, $notify);
1907
+	}
1908
+
1909
+
1910
+	/**
1911
+	 * decline_registration
1912
+	 *
1913
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1914
+	 * @return void
1915
+	 * @throws EE_Error
1916
+	 * @throws EntityNotFoundException
1917
+	 * @throws InvalidArgumentException
1918
+	 * @throws InvalidDataTypeException
1919
+	 * @throws InvalidInterfaceException
1920
+	 * @throws ReflectionException
1921
+	 * @throws RuntimeException
1922
+	 * @throws DomainException
1923
+	 */
1924
+	protected function decline_registration($notify = false)
1925
+	{
1926
+		$this->_reg_status_change_return(RegStatus::DECLINED, $notify);
1927
+	}
1928
+
1929
+
1930
+	/**
1931
+	 * cancel_registration
1932
+	 *
1933
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1934
+	 * @return void
1935
+	 * @throws EE_Error
1936
+	 * @throws EntityNotFoundException
1937
+	 * @throws InvalidArgumentException
1938
+	 * @throws InvalidDataTypeException
1939
+	 * @throws InvalidInterfaceException
1940
+	 * @throws ReflectionException
1941
+	 * @throws RuntimeException
1942
+	 * @throws DomainException
1943
+	 */
1944
+	protected function cancel_registration($notify = false)
1945
+	{
1946
+		$this->_reg_status_change_return(RegStatus::CANCELLED, $notify);
1947
+	}
1948
+
1949
+
1950
+	/**
1951
+	 * not_approve_registration
1952
+	 *
1953
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1954
+	 * @return void
1955
+	 * @throws EE_Error
1956
+	 * @throws EntityNotFoundException
1957
+	 * @throws InvalidArgumentException
1958
+	 * @throws InvalidDataTypeException
1959
+	 * @throws InvalidInterfaceException
1960
+	 * @throws ReflectionException
1961
+	 * @throws RuntimeException
1962
+	 * @throws DomainException
1963
+	 */
1964
+	protected function not_approve_registration($notify = false)
1965
+	{
1966
+		$this->_reg_status_change_return(RegStatus::AWAITING_REVIEW, $notify);
1967
+	}
1968
+
1969
+
1970
+	/**
1971
+	 * decline_registration
1972
+	 *
1973
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1974
+	 * @return void
1975
+	 * @throws EE_Error
1976
+	 * @throws EntityNotFoundException
1977
+	 * @throws InvalidArgumentException
1978
+	 * @throws InvalidDataTypeException
1979
+	 * @throws InvalidInterfaceException
1980
+	 * @throws ReflectionException
1981
+	 * @throws RuntimeException
1982
+	 * @throws DomainException
1983
+	 */
1984
+	protected function pending_registration($notify = false)
1985
+	{
1986
+		$this->_reg_status_change_return(RegStatus::PENDING_PAYMENT, $notify);
1987
+	}
1988
+
1989
+
1990
+	/**
1991
+	 * waitlist_registration
1992
+	 *
1993
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1994
+	 * @return void
1995
+	 * @throws EE_Error
1996
+	 * @throws EntityNotFoundException
1997
+	 * @throws InvalidArgumentException
1998
+	 * @throws InvalidDataTypeException
1999
+	 * @throws InvalidInterfaceException
2000
+	 * @throws ReflectionException
2001
+	 * @throws RuntimeException
2002
+	 * @throws DomainException
2003
+	 */
2004
+	protected function wait_list_registration($notify = false)
2005
+	{
2006
+		$this->_reg_status_change_return(RegStatus::WAIT_LIST, $notify);
2007
+	}
2008
+
2009
+
2010
+	/**
2011
+	 * generates HTML for the Registration main meta box
2012
+	 *
2013
+	 * @return void
2014
+	 * @throws DomainException
2015
+	 * @throws EE_Error
2016
+	 * @throws InvalidArgumentException
2017
+	 * @throws InvalidDataTypeException
2018
+	 * @throws InvalidInterfaceException
2019
+	 * @throws ReflectionException
2020
+	 * @throws EntityNotFoundException
2021
+	 */
2022
+	public function _reg_details_meta_box()
2023
+	{
2024
+		EEH_Autoloader::register_line_item_display_autoloaders();
2025
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2026
+		EE_Registry::instance()->load_helper('Line_Item');
2027
+		$transaction        = $this->_registration->transaction()
2028
+			? $this->_registration->transaction()
2029
+			: EE_Transaction::new_instance();
2030
+		$this->session_data = $transaction->session_data();
2031
+		$filters            = new EE_Line_Item_Filter_Collection();
2032
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2033
+		$filters->add(new EE_Non_Zero_Line_Item_Filter());
2034
+		$line_item_filter_processor              = new EE_Line_Item_Filter_Processor(
2035
+			$filters,
2036
+			$transaction->total_line_item()
2037
+		);
2038
+		$filtered_line_item_tree                 = $line_item_filter_processor->process();
2039
+		$line_item_display                       = new EE_Line_Item_Display(
2040
+			'reg_admin_table',
2041
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2042
+		);
2043
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2044
+			$filtered_line_item_tree,
2045
+			['EE_Registration' => $this->_registration]
2046
+		);
2047
+		$attendee                                = $this->_registration->attendee();
2048
+		if (
2049
+			$this->capabilities->current_user_can(
2050
+				'ee_read_transaction',
2051
+				'espresso_transactions_view_transaction'
2052
+			)
2053
+		) {
2054
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2055
+				EE_Admin_Page::add_query_args_and_nonce(
2056
+					[
2057
+						'action' => 'view_transaction',
2058
+						'TXN_ID' => $transaction->ID(),
2059
+					],
2060
+					TXN_ADMIN_URL
2061
+				),
2062
+				esc_html__(' View Transaction', 'event_espresso'),
2063
+				'button button--secondary right',
2064
+				'dashicons dashicons-cart'
2065
+			);
2066
+		} else {
2067
+			$this->_template_args['view_transaction_button'] = '';
2068
+		}
2069
+		if (
2070
+			$attendee instanceof EE_Attendee
2071
+			&& $this->capabilities->current_user_can(
2072
+				'ee_send_message',
2073
+				'espresso_registrations_resend_registration'
2074
+			)
2075
+		) {
2076
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2077
+				EE_Admin_Page::add_query_args_and_nonce(
2078
+					[
2079
+						'action'      => 'resend_registration',
2080
+						'_REG_ID'     => $this->_registration->ID(),
2081
+						'redirect_to' => 'view_registration',
2082
+					],
2083
+					REG_ADMIN_URL
2084
+				),
2085
+				esc_html__(' Resend Registration', 'event_espresso'),
2086
+				'button button--secondary right',
2087
+				'dashicons dashicons-email-alt'
2088
+			);
2089
+		} else {
2090
+			$this->_template_args['resend_registration_button'] = '';
2091
+		}
2092
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2093
+		$payment                               = $transaction->get_first_related('Payment');
2094
+		$payment                               = ! $payment instanceof EE_Payment
2095
+			? EE_Payment::new_instance()
2096
+			: $payment;
2097
+		$payment_method                        = $payment->get_first_related('Payment_Method');
2098
+		$payment_method                        = ! $payment_method instanceof EE_Payment_Method
2099
+			? EE_Payment_Method::new_instance()
2100
+			: $payment_method;
2101
+		$reg_details        = [
2102
+			'payment_method'       => $payment_method->name(),
2103
+			'response_msg'         => $payment->gateway_response(),
2104
+			'registration_id'      => $this->_registration->get('REG_code'),
2105
+			'registration_session' => $this->_registration->session_ID(),
2106
+			'ip_address'           => $this->session_data['ip_address'] ?? '',
2107
+			'user_agent'           => $this->session_data['user_agent'] ?? '',
2108
+		];
2109
+		if (isset($reg_details['registration_id'])) {
2110
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2111
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2112
+				'Registration ID',
2113
+				'event_espresso'
2114
+			);
2115
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2116
+		}
2117
+		if (isset($reg_details['payment_method'])) {
2118
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2119
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2120
+				'Most Recent Payment Method',
2121
+				'event_espresso'
2122
+			);
2123
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2124
+			$this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2125
+			$this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2126
+				'Payment method response',
2127
+				'event_espresso'
2128
+			);
2129
+			$this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2130
+		}
2131
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2132
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2133
+			'Registration Session',
2134
+			'event_espresso'
2135
+		);
2136
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2137
+		$this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2138
+		$this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2139
+			'Registration placed from IP',
2140
+			'event_espresso'
2141
+		);
2142
+		$this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2143
+		$this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2144
+		$this->_template_args['reg_details']['user_agent']['label']           = esc_html__(
2145
+			'Registrant User Agent',
2146
+			'event_espresso'
2147
+		);
2148
+		$this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2149
+		$this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2150
+			[
2151
+				'action'   => 'default',
2152
+				'event_id' => $this->_registration->event_ID(),
2153
+			],
2154
+			REG_ADMIN_URL
2155
+		);
2156
+
2157
+		$this->_template_args['REG_ID']   = $this->_registration->ID();
2158
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2159
+
2160
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2161
+		EEH_Template::display_template($template_path, $this->_template_args); // already escaped
2162
+	}
2163
+
2164
+
2165
+	/**
2166
+	 * generates HTML for the Registration Questions meta box.
2167
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2168
+	 * otherwise uses new forms system
2169
+	 *
2170
+	 * @return void
2171
+	 * @throws DomainException
2172
+	 * @throws EE_Error
2173
+	 * @throws InvalidArgumentException
2174
+	 * @throws InvalidDataTypeException
2175
+	 * @throws InvalidInterfaceException
2176
+	 * @throws ReflectionException
2177
+	 */
2178
+	public function _reg_questions_meta_box()
2179
+	{
2180
+		// allow someone to override this method entirely
2181
+		if (
2182
+			apply_filters(
2183
+				'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2184
+				true,
2185
+				$this,
2186
+				$this->_registration
2187
+			)
2188
+		) {
2189
+			$form = $this->_get_reg_custom_questions_form(
2190
+				$this->_registration->ID()
2191
+			);
2192
+
2193
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2194
+				? $form->get_html_and_js()
2195
+				: '';
2196
+
2197
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2198
+			$this->_template_args['REG_ID']                    = $this->_registration->ID();
2199
+			$template_path                                     =
2200
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2201
+			EEH_Template::display_template($template_path, $this->_template_args);
2202
+		}
2203
+	}
2204
+
2205
+
2206
+	/**
2207
+	 * form_before_question_group
2208
+	 *
2209
+	 * @param string $output
2210
+	 * @return        string
2211
+	 * @deprecated    as of 4.8.32.rc.000
2212
+	 */
2213
+	public function form_before_question_group($output)
2214
+	{
2215
+		EE_Error::doing_it_wrong(
2216
+			__CLASS__ . '::' . __FUNCTION__,
2217
+			esc_html__(
2218
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2219
+				'event_espresso'
2220
+			),
2221
+			'4.8.32.rc.000'
2222
+		);
2223
+		return '
2224 2224
 	<table class="form-table ee-width-100">
2225 2225
 		<tbody>
2226 2226
 			';
2227
-    }
2228
-
2229
-
2230
-    /**
2231
-     * form_after_question_group
2232
-     *
2233
-     * @param string $output
2234
-     * @return        string
2235
-     * @deprecated    as of 4.8.32.rc.000
2236
-     */
2237
-    public function form_after_question_group($output)
2238
-    {
2239
-        EE_Error::doing_it_wrong(
2240
-            __CLASS__ . '::' . __FUNCTION__,
2241
-            esc_html__(
2242
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2243
-                'event_espresso'
2244
-            ),
2245
-            '4.8.32.rc.000'
2246
-        );
2247
-        return '
2227
+	}
2228
+
2229
+
2230
+	/**
2231
+	 * form_after_question_group
2232
+	 *
2233
+	 * @param string $output
2234
+	 * @return        string
2235
+	 * @deprecated    as of 4.8.32.rc.000
2236
+	 */
2237
+	public function form_after_question_group($output)
2238
+	{
2239
+		EE_Error::doing_it_wrong(
2240
+			__CLASS__ . '::' . __FUNCTION__,
2241
+			esc_html__(
2242
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2243
+				'event_espresso'
2244
+			),
2245
+			'4.8.32.rc.000'
2246
+		);
2247
+		return '
2248 2248
 			<tr class="hide-if-no-js">
2249 2249
 				<th> </th>
2250 2250
 				<td class="reg-admin-edit-attendee-question-td">
2251 2251
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" aria-label="'
2252
-               . esc_attr__('click to edit question', 'event_espresso')
2253
-               . '">
2252
+			   . esc_attr__('click to edit question', 'event_espresso')
2253
+			   . '">
2254 2254
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2255
-               . esc_html__('edit the above question group', 'event_espresso')
2256
-               . '</span>
2255
+			   . esc_html__('edit the above question group', 'event_espresso')
2256
+			   . '</span>
2257 2257
 						<div class="dashicons dashicons-edit"></div>
2258 2258
 					</a>
2259 2259
 				</td>
@@ -2261,644 +2261,644 @@  discard block
 block discarded – undo
2261 2261
 		</tbody>
2262 2262
 	</table>
2263 2263
 ';
2264
-    }
2265
-
2266
-
2267
-    /**
2268
-     * form_form_field_label_wrap
2269
-     *
2270
-     * @param string $label
2271
-     * @return        string
2272
-     * @deprecated    as of 4.8.32.rc.000
2273
-     */
2274
-    public function form_form_field_label_wrap($label)
2275
-    {
2276
-        EE_Error::doing_it_wrong(
2277
-            __CLASS__ . '::' . __FUNCTION__,
2278
-            esc_html__(
2279
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2280
-                'event_espresso'
2281
-            ),
2282
-            '4.8.32.rc.000'
2283
-        );
2284
-        return '
2264
+	}
2265
+
2266
+
2267
+	/**
2268
+	 * form_form_field_label_wrap
2269
+	 *
2270
+	 * @param string $label
2271
+	 * @return        string
2272
+	 * @deprecated    as of 4.8.32.rc.000
2273
+	 */
2274
+	public function form_form_field_label_wrap($label)
2275
+	{
2276
+		EE_Error::doing_it_wrong(
2277
+			__CLASS__ . '::' . __FUNCTION__,
2278
+			esc_html__(
2279
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2280
+				'event_espresso'
2281
+			),
2282
+			'4.8.32.rc.000'
2283
+		);
2284
+		return '
2285 2285
 			<tr>
2286 2286
 				<th>
2287 2287
 					' . $label . '
2288 2288
 				</th>';
2289
-    }
2290
-
2291
-
2292
-    /**
2293
-     * form_form_field_input__wrap
2294
-     *
2295
-     * @param string $input
2296
-     * @return        string
2297
-     * @deprecated    as of 4.8.32.rc.000
2298
-     */
2299
-    public function form_form_field_input__wrap($input)
2300
-    {
2301
-        EE_Error::doing_it_wrong(
2302
-            __CLASS__ . '::' . __FUNCTION__,
2303
-            esc_html__(
2304
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2305
-                'event_espresso'
2306
-            ),
2307
-            '4.8.32.rc.000'
2308
-        );
2309
-        return '
2289
+	}
2290
+
2291
+
2292
+	/**
2293
+	 * form_form_field_input__wrap
2294
+	 *
2295
+	 * @param string $input
2296
+	 * @return        string
2297
+	 * @deprecated    as of 4.8.32.rc.000
2298
+	 */
2299
+	public function form_form_field_input__wrap($input)
2300
+	{
2301
+		EE_Error::doing_it_wrong(
2302
+			__CLASS__ . '::' . __FUNCTION__,
2303
+			esc_html__(
2304
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2305
+				'event_espresso'
2306
+			),
2307
+			'4.8.32.rc.000'
2308
+		);
2309
+		return '
2310 2310
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2311 2311
 					' . $input . '
2312 2312
 				</td>
2313 2313
 			</tr>';
2314
-    }
2315
-
2316
-
2317
-    /**
2318
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2319
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2320
-     * to display the page
2321
-     *
2322
-     * @return void
2323
-     * @throws EE_Error
2324
-     * @throws InvalidArgumentException
2325
-     * @throws InvalidDataTypeException
2326
-     * @throws InvalidInterfaceException
2327
-     * @throws ReflectionException
2328
-     */
2329
-    protected function _update_attendee_registration_form()
2330
-    {
2331
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2332
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2333
-            $REG_ID  = $this->request->getRequestParam('_REG_ID', 0, 'int');
2334
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2335
-            if ($success) {
2336
-                $what  = esc_html__('Registration Form', 'event_espresso');
2337
-                $route = $REG_ID
2338
-                    ? ['action' => 'view_registration', '_REG_ID' => $REG_ID]
2339
-                    : ['action' => 'default'];
2340
-                $this->_redirect_after_action(true, $what, esc_html__('updated', 'event_espresso'), $route);
2341
-            }
2342
-        }
2343
-    }
2344
-
2345
-
2346
-    /**
2347
-     * Gets the form for saving registrations custom questions (if done
2348
-     * previously retrieves the cached form object, which may have validation errors in it)
2349
-     *
2350
-     * @param int $REG_ID
2351
-     * @return EE_Registration_Custom_Questions_Form
2352
-     * @throws EE_Error
2353
-     * @throws InvalidArgumentException
2354
-     * @throws InvalidDataTypeException
2355
-     * @throws InvalidInterfaceException
2356
-     * @throws ReflectionException
2357
-     */
2358
-    protected function _get_reg_custom_questions_form($REG_ID)
2359
-    {
2360
-        if (! $this->_reg_custom_questions_form) {
2361
-            require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2362
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2363
-                $this->getRegistrationModel()->get_one_by_ID($REG_ID)
2364
-            );
2365
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2366
-        }
2367
-        return $this->_reg_custom_questions_form;
2368
-    }
2369
-
2370
-
2371
-    /**
2372
-     * Saves
2373
-     *
2374
-     * @param bool $REG_ID
2375
-     * @return bool
2376
-     * @throws EE_Error
2377
-     * @throws InvalidArgumentException
2378
-     * @throws InvalidDataTypeException
2379
-     * @throws InvalidInterfaceException
2380
-     * @throws ReflectionException
2381
-     */
2382
-    private function _save_reg_custom_questions_form($REG_ID = 0)
2383
-    {
2384
-        if (! $REG_ID) {
2385
-            EE_Error::add_error(
2386
-                esc_html__(
2387
-                    'An error occurred. No registration ID was received.',
2388
-                    'event_espresso'
2389
-                ),
2390
-                __FILE__,
2391
-                __FUNCTION__,
2392
-                __LINE__
2393
-            );
2394
-        }
2395
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2396
-        $form->receive_form_submission($this->request->requestParams());
2397
-        $success = false;
2398
-        if ($form->is_valid()) {
2399
-            foreach ($form->subforms() as $question_group_form) {
2400
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2401
-                    $where_conditions    = [
2402
-                        'QST_ID' => $question_id,
2403
-                        'REG_ID' => $REG_ID,
2404
-                    ];
2405
-                    $possibly_new_values = [
2406
-                        'ANS_value' => $input->normalized_value(),
2407
-                    ];
2408
-                    $answer              = EEM_Answer::instance()->get_one([$where_conditions]);
2409
-                    if ($answer instanceof EE_Answer) {
2410
-                        $success = $answer->save($possibly_new_values);
2411
-                    } else {
2412
-                        // insert it then
2413
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2414
-                        $answer      = EE_Answer::new_instance($cols_n_vals);
2415
-                        $success     = $answer->save();
2416
-                    }
2417
-                }
2418
-            }
2419
-        } else {
2420
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2421
-        }
2422
-        return $success;
2423
-    }
2424
-
2425
-
2426
-    /**
2427
-     * generates HTML for the Registration main meta box
2428
-     *
2429
-     * @return void
2430
-     * @throws DomainException
2431
-     * @throws EE_Error
2432
-     * @throws InvalidArgumentException
2433
-     * @throws InvalidDataTypeException
2434
-     * @throws InvalidInterfaceException
2435
-     * @throws ReflectionException
2436
-     */
2437
-    public function _reg_attendees_meta_box()
2438
-    {
2439
-        $REG = $this->getRegistrationModel();
2440
-        // get all other registrations on this transaction, and cache
2441
-        // the attendees for them so we don't have to run another query using force_join
2442
-        $registrations                           = $REG->get_all(
2443
-            [
2444
-                [
2445
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2446
-                    'REG_ID' => ['!=', $this->_registration->ID()],
2447
-                ],
2448
-                'force_join'               => ['Attendee'],
2449
-                'default_where_conditions' => 'other_models_only',
2450
-            ]
2451
-        );
2452
-        $this->_template_args['attendees']       = [];
2453
-        $this->_template_args['attendee_notice'] = '';
2454
-        if (
2455
-            empty($registrations)
2456
-            || (is_array($registrations)
2457
-                && ! EEH_Array::get_one_item_from_array($registrations))
2458
-        ) {
2459
-            EE_Error::add_error(
2460
-                esc_html__(
2461
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2462
-                    'event_espresso'
2463
-                ),
2464
-                __FILE__,
2465
-                __FUNCTION__,
2466
-                __LINE__
2467
-            );
2468
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2469
-        } else {
2470
-            $att_nmbr = 1;
2471
-            foreach ($registrations as $registration) {
2472
-                /* @var $registration EE_Registration */
2473
-                $attendee                                                      = $registration->attendee()
2474
-                    ? $registration->attendee()
2475
-                    : $this->getAttendeeModel()->create_default_object();
2476
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID']      = $registration->status_ID();
2477
-                $this->_template_args['attendees'][ $att_nmbr ]['fname']       = $attendee->fname();
2478
-                $this->_template_args['attendees'][ $att_nmbr ]['lname']       = $attendee->lname();
2479
-                $this->_template_args['attendees'][ $att_nmbr ]['email']       = $attendee->email();
2480
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2481
-                $this->_template_args['attendees'][ $att_nmbr ]['address']     = implode(
2482
-                    ', ',
2483
-                    $attendee->full_address_as_array()
2484
-                );
2485
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link']    = self::add_query_args_and_nonce(
2486
-                    [
2487
-                        'action' => 'edit_attendee',
2488
-                        'post'   => $attendee->ID(),
2489
-                    ],
2490
-                    REG_ADMIN_URL
2491
-                );
2492
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name']  =
2493
-                    $registration->event_obj() instanceof EE_Event
2494
-                        ? $registration->event_obj()->name()
2495
-                        : '';
2496
-                $att_nmbr++;
2497
-            }
2498
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2499
-        }
2500
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2501
-        EEH_Template::display_template($template_path, $this->_template_args);
2502
-    }
2503
-
2504
-
2505
-    /**
2506
-     * generates HTML for the Edit Registration side meta box
2507
-     *
2508
-     * @return void
2509
-     * @throws DomainException
2510
-     * @throws EE_Error
2511
-     * @throws InvalidArgumentException
2512
-     * @throws InvalidDataTypeException
2513
-     * @throws InvalidInterfaceException
2514
-     * @throws ReflectionException
2515
-     */
2516
-    public function _reg_registrant_side_meta_box()
2517
-    {
2518
-        /*@var $attendee EE_Attendee */
2519
-        $att_check = $this->_registration->attendee();
2520
-        $attendee  = $att_check instanceof EE_Attendee
2521
-            ? $att_check
2522
-            : $this->getAttendeeModel()->create_default_object();
2523
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2524
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2525
-        // primary registration object (that way we know if we need to show create button or not)
2526
-        if (! $this->_registration->is_primary_registrant()) {
2527
-            $primary_registration = $this->_registration->get_primary_registration();
2528
-            $primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2529
-                : null;
2530
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2531
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2532
-                // custom attendee object so let's not worry about the primary reg.
2533
-                $primary_registration = null;
2534
-            }
2535
-        } else {
2536
-            $primary_registration = null;
2537
-        }
2538
-        $this->_template_args['ATT_ID']            = $attendee->ID();
2539
-        $this->_template_args['fname']             = $attendee->fname();
2540
-        $this->_template_args['lname']             = $attendee->lname();
2541
-        $this->_template_args['email']             = $attendee->email();
2542
-        $this->_template_args['phone']             = $attendee->phone();
2543
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2544
-        // edit link
2545
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(
2546
-            [
2547
-                'action' => 'edit_attendee',
2548
-                'post'   => $attendee->ID(),
2549
-            ],
2550
-            REG_ADMIN_URL
2551
-        );
2552
-        $this->_template_args['att_edit_title'] = esc_html__('View details for this contact.', 'event_espresso');
2553
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2554
-        // create link
2555
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2556
-            ? EE_Admin_Page::add_query_args_and_nonce(
2557
-                [
2558
-                    'action'  => 'duplicate_attendee',
2559
-                    '_REG_ID' => $this->_registration->ID(),
2560
-                ],
2561
-                REG_ADMIN_URL
2562
-            ) : '';
2563
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2564
-        $this->_template_args['att_check']    = $att_check;
2565
-        $template_path                        =
2566
-            REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2567
-        EEH_Template::display_template($template_path, $this->_template_args);
2568
-    }
2569
-
2570
-
2571
-    /**
2572
-     * trash or restore registrations
2573
-     *
2574
-     * @param boolean $trash whether to archive or restore
2575
-     * @return void
2576
-     * @throws DomainException
2577
-     * @throws EE_Error
2578
-     * @throws EntityNotFoundException
2579
-     * @throws InvalidArgumentException
2580
-     * @throws InvalidDataTypeException
2581
-     * @throws InvalidInterfaceException
2582
-     * @throws ReflectionException
2583
-     * @throws RuntimeException
2584
-     * @throws UnexpectedEntityException
2585
-     */
2586
-    protected function _trash_or_restore_registrations(bool $trash = true)
2587
-    {
2588
-        // if empty _REG_ID then get out because there's nothing to do
2589
-        $REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2590
-        if (empty($REG_IDs)) {
2591
-            EE_Error::add_error(
2592
-                sprintf(
2593
-                    esc_html__(
2594
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2595
-                        'event_espresso'
2596
-                    ),
2597
-                    $trash ? 'trash' : 'restore'
2598
-                ),
2599
-                __FILE__,
2600
-                __LINE__,
2601
-                __FUNCTION__
2602
-            );
2603
-            $this->_redirect_after_action(false, '', '', [], true);
2604
-        }
2605
-        $success        = 0;
2606
-        $overwrite_msgs = false;
2607
-        // Checkboxes
2608
-        $reg_count = count($REG_IDs);
2609
-        // cycle thru checkboxes
2610
-        foreach ($REG_IDs as $REG_ID) {
2611
-            /** @var EE_Registration $REG */
2612
-            $REG = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2613
-            if ($trash) {
2614
-                $payments = $REG->registration_payments();
2615
-                if (! empty($payments)) {
2616
-                    $name           = $REG->attendee() instanceof EE_Attendee
2617
-                        ? $REG->attendee()->full_name()
2618
-                        : esc_html__('Unknown Attendee', 'event_espresso');
2619
-                    $overwrite_msgs = true;
2620
-                    EE_Error::add_error(
2621
-                        sprintf(
2622
-                            esc_html__(
2623
-                                'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2624
-                                'event_espresso'
2625
-                            ),
2626
-                            $name
2627
-                        ),
2628
-                        __FILE__,
2629
-                        __FUNCTION__,
2630
-                        __LINE__
2631
-                    );
2632
-                    // can't trash this registration because it has payments.
2633
-                    continue;
2634
-                }
2635
-            }
2636
-            $updated = $trash ? $REG->delete() : $REG->restore();
2637
-            if ($updated) {
2638
-                $success++;
2639
-            }
2640
-        }
2641
-        $this->_redirect_after_action(
2642
-            $success === $reg_count, // were ALL registrations affected?
2643
-            $success > 1
2644
-                ? esc_html__('Registrations', 'event_espresso')
2645
-                : esc_html__('Registration', 'event_espresso'),
2646
-            $trash
2647
-                ? esc_html__('moved to the trash', 'event_espresso')
2648
-                : esc_html__('restored', 'event_espresso'),
2649
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2650
-            $overwrite_msgs
2651
-        );
2652
-    }
2653
-
2654
-
2655
-    /**
2656
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2657
-     * registration but also.
2658
-     * 1. Removing relations to EE_Attendee
2659
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2660
-     * ALSO trashed.
2661
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2662
-     * 4. Removing relationships between all tickets and the related registrations
2663
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2664
-     * 6. Deleting permanently any related Check-ins.
2665
-     *
2666
-     * @return void
2667
-     * @throws EE_Error
2668
-     * @throws InvalidArgumentException
2669
-     * @throws InvalidDataTypeException
2670
-     * @throws InvalidInterfaceException
2671
-     * @throws ReflectionException
2672
-     */
2673
-    protected function _delete_registrations()
2674
-    {
2675
-        $REG_MDL = $this->getRegistrationModel();
2676
-        $success = 0;
2677
-        // Checkboxes
2678
-        $REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2679
-
2680
-        if (! empty($REG_IDs)) {
2681
-            // if array has more than one element than success message should be plural
2682
-            $success = count($REG_IDs) > 1 ? 2 : 1;
2683
-            // cycle thru checkboxes
2684
-            foreach ($REG_IDs as $REG_ID) {
2685
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2686
-                if (! $REG instanceof EE_Registration) {
2687
-                    continue;
2688
-                }
2689
-                $deleted = $this->_delete_registration($REG);
2690
-                if (! $deleted) {
2691
-                    $success = 0;
2692
-                }
2693
-            }
2694
-        }
2695
-
2696
-        $what        = $success > 1
2697
-            ? esc_html__('Registrations', 'event_espresso')
2698
-            : esc_html__('Registration', 'event_espresso');
2699
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2700
-        $this->_redirect_after_action(
2701
-            $success,
2702
-            $what,
2703
-            $action_desc,
2704
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2705
-            true
2706
-        );
2707
-    }
2708
-
2709
-
2710
-    /**
2711
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2712
-     * models get affected.
2713
-     *
2714
-     * @param EE_Registration $REG registration to be deleted permanently
2715
-     * @return bool true = successful deletion, false = fail.
2716
-     * @throws EE_Error
2717
-     * @throws InvalidArgumentException
2718
-     * @throws InvalidDataTypeException
2719
-     * @throws InvalidInterfaceException
2720
-     * @throws ReflectionException
2721
-     */
2722
-    protected function _delete_registration(EE_Registration $REG)
2723
-    {
2724
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2725
-        // registrations on the transaction that are NOT trashed.
2726
-        $TXN = $REG->transaction();
2727
-        if (! $TXN instanceof EE_Transaction) {
2728
-            EE_Error::add_error(
2729
-                sprintf(
2730
-                    esc_html__(
2731
-                        'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2732
-                        'event_espresso'
2733
-                    ),
2734
-                    $REG->id()
2735
-                ),
2736
-                __FILE__,
2737
-                __FUNCTION__,
2738
-                __LINE__
2739
-            );
2740
-            return false;
2741
-        }
2742
-        $REGS        = $TXN->get_many_related('Registration');
2743
-        $all_trashed = true;
2744
-        foreach ($REGS as $registration) {
2745
-            if (! $registration->get('REG_deleted')) {
2746
-                $all_trashed = false;
2747
-            }
2748
-        }
2749
-        if (! $all_trashed) {
2750
-            EE_Error::add_error(
2751
-                esc_html__(
2752
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2753
-                    'event_espresso'
2754
-                ),
2755
-                __FILE__,
2756
-                __FUNCTION__,
2757
-                __LINE__
2758
-            );
2759
-            return false;
2760
-        }
2761
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2762
-        // separately from THIS one).
2763
-        foreach ($REGS as $registration) {
2764
-            // delete related answers
2765
-            $registration->delete_related_permanently('Answer');
2766
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2767
-            $attendee = $registration->get_first_related('Attendee');
2768
-            if ($attendee instanceof EE_Attendee) {
2769
-                $registration->_remove_relation_to($attendee, 'Attendee');
2770
-            }
2771
-            // now remove relationships to tickets on this registration.
2772
-            $registration->_remove_relations('Ticket');
2773
-            // now delete permanently the checkins related to this registration.
2774
-            $registration->delete_related_permanently('Checkin');
2775
-            if ($registration->ID() === $REG->ID()) {
2776
-                continue;
2777
-            } //we don't want to delete permanently the existing registration just yet.
2778
-            // remove relation to transaction for these registrations if NOT the existing registrations
2779
-            $registration->_remove_relations('Transaction');
2780
-            // delete permanently any related messages.
2781
-            $registration->delete_related_permanently('Message');
2782
-            // now delete this registration permanently
2783
-            $registration->delete_permanently();
2784
-        }
2785
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2786
-        // (the transaction and line items should be all that's left).
2787
-        // delete the line items related to the transaction for this registration.
2788
-        $TXN->delete_related_permanently('Line_Item');
2789
-        // we need to remove all the relationships on the transaction
2790
-        $TXN->delete_related_permanently('Payment');
2791
-        $TXN->delete_related_permanently('Extra_Meta');
2792
-        $TXN->delete_related_permanently('Message');
2793
-        // now we can delete this REG permanently (and the transaction of course)
2794
-        $REG->delete_related_permanently('Transaction');
2795
-        return $REG->delete_permanently();
2796
-    }
2797
-
2798
-
2799
-    /**
2800
-     *    generates HTML for the Register New Attendee Admin page
2801
-     *
2802
-     * @throws DomainException
2803
-     * @throws EE_Error
2804
-     * @throws InvalidArgumentException
2805
-     * @throws InvalidDataTypeException
2806
-     * @throws InvalidInterfaceException
2807
-     * @throws ReflectionException
2808
-     */
2809
-    public function new_registration()
2810
-    {
2811
-        if (! $this->_set_reg_event()) {
2812
-            throw new EE_Error(
2813
-                esc_html__(
2814
-                    'Unable to continue with registering because there is no Event ID in the request',
2815
-                    'event_espresso'
2816
-                )
2817
-            );
2818
-        }
2819
-        /** @var CurrentPage $current_page */
2820
-        $current_page = $this->loader->getShared(CurrentPage::class);
2821
-        $current_page->setEspressoPage(true);
2822
-        // gotta start with a clean slate if we're not coming here via ajax
2823
-        if (
2824
-            ! $this->request->isAjax()
2825
-            && (
2826
-                ! $this->request->requestParamIsSet('processing_registration')
2827
-                || $this->request->requestParamIsSet('step_error')
2828
-            )
2829
-        ) {
2830
-            $this->clearSession(__CLASS__, __FUNCTION__);
2831
-        }
2832
-        $this->_template_args['event_name'] = '';
2833
-        // event name
2834
-        if ($this->_reg_event) {
2835
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2836
-            $edit_event_url                     = self::add_query_args_and_nonce(
2837
-                [
2838
-                    'action' => 'edit',
2839
-                    'post'   => $this->_reg_event->ID(),
2840
-                ],
2841
-                EVENTS_ADMIN_URL
2842
-            );
2843
-            $edit_event_lnk                     = '<a href="'
2844
-                                                  . $edit_event_url
2845
-                                                  . '" aria-label="'
2846
-                                                  . esc_attr__('Edit ', 'event_espresso')
2847
-                                                  . $this->_reg_event->name()
2848
-                                                  . '">'
2849
-                                                  . esc_html__('Edit Event', 'event_espresso')
2850
-                                                  . '</a>';
2851
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2852
-                                                   . $edit_event_lnk
2853
-                                                   . '</span>';
2854
-        }
2855
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2856
-        if ($this->request->isAjax()) {
2857
-            $this->_return_json();
2858
-        }
2859
-        // grab header
2860
-        $template_path                              =
2861
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2862
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2863
-            $template_path,
2864
-            $this->_template_args,
2865
-            true
2866
-        );
2867
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2868
-        // the details template wrapper
2869
-        $this->display_admin_page_with_sidebar();
2870
-    }
2871
-
2872
-
2873
-    /**
2874
-     * This returns the content for a registration step
2875
-     *
2876
-     * @return string html
2877
-     * @throws DomainException
2878
-     * @throws EE_Error
2879
-     * @throws InvalidArgumentException
2880
-     * @throws InvalidDataTypeException
2881
-     * @throws InvalidInterfaceException
2882
-     * @throws ReflectionException
2883
-     */
2884
-    protected function _get_registration_step_content()
2885
-    {
2886
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2887
-            $warning_msg = sprintf(
2888
-                esc_html__(
2889
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2890
-                    'event_espresso'
2891
-                ),
2892
-                '<br />',
2893
-                '<h3 class="important-notice">',
2894
-                '</h3>',
2895
-                '<div class="float-right">',
2896
-                '<span id="redirect_timer" class="important-notice">30</span>',
2897
-                '</div>',
2898
-                '<b>',
2899
-                '</b>'
2900
-            );
2901
-            return '
2314
+	}
2315
+
2316
+
2317
+	/**
2318
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2319
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2320
+	 * to display the page
2321
+	 *
2322
+	 * @return void
2323
+	 * @throws EE_Error
2324
+	 * @throws InvalidArgumentException
2325
+	 * @throws InvalidDataTypeException
2326
+	 * @throws InvalidInterfaceException
2327
+	 * @throws ReflectionException
2328
+	 */
2329
+	protected function _update_attendee_registration_form()
2330
+	{
2331
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2332
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2333
+			$REG_ID  = $this->request->getRequestParam('_REG_ID', 0, 'int');
2334
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2335
+			if ($success) {
2336
+				$what  = esc_html__('Registration Form', 'event_espresso');
2337
+				$route = $REG_ID
2338
+					? ['action' => 'view_registration', '_REG_ID' => $REG_ID]
2339
+					: ['action' => 'default'];
2340
+				$this->_redirect_after_action(true, $what, esc_html__('updated', 'event_espresso'), $route);
2341
+			}
2342
+		}
2343
+	}
2344
+
2345
+
2346
+	/**
2347
+	 * Gets the form for saving registrations custom questions (if done
2348
+	 * previously retrieves the cached form object, which may have validation errors in it)
2349
+	 *
2350
+	 * @param int $REG_ID
2351
+	 * @return EE_Registration_Custom_Questions_Form
2352
+	 * @throws EE_Error
2353
+	 * @throws InvalidArgumentException
2354
+	 * @throws InvalidDataTypeException
2355
+	 * @throws InvalidInterfaceException
2356
+	 * @throws ReflectionException
2357
+	 */
2358
+	protected function _get_reg_custom_questions_form($REG_ID)
2359
+	{
2360
+		if (! $this->_reg_custom_questions_form) {
2361
+			require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2362
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2363
+				$this->getRegistrationModel()->get_one_by_ID($REG_ID)
2364
+			);
2365
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2366
+		}
2367
+		return $this->_reg_custom_questions_form;
2368
+	}
2369
+
2370
+
2371
+	/**
2372
+	 * Saves
2373
+	 *
2374
+	 * @param bool $REG_ID
2375
+	 * @return bool
2376
+	 * @throws EE_Error
2377
+	 * @throws InvalidArgumentException
2378
+	 * @throws InvalidDataTypeException
2379
+	 * @throws InvalidInterfaceException
2380
+	 * @throws ReflectionException
2381
+	 */
2382
+	private function _save_reg_custom_questions_form($REG_ID = 0)
2383
+	{
2384
+		if (! $REG_ID) {
2385
+			EE_Error::add_error(
2386
+				esc_html__(
2387
+					'An error occurred. No registration ID was received.',
2388
+					'event_espresso'
2389
+				),
2390
+				__FILE__,
2391
+				__FUNCTION__,
2392
+				__LINE__
2393
+			);
2394
+		}
2395
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2396
+		$form->receive_form_submission($this->request->requestParams());
2397
+		$success = false;
2398
+		if ($form->is_valid()) {
2399
+			foreach ($form->subforms() as $question_group_form) {
2400
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2401
+					$where_conditions    = [
2402
+						'QST_ID' => $question_id,
2403
+						'REG_ID' => $REG_ID,
2404
+					];
2405
+					$possibly_new_values = [
2406
+						'ANS_value' => $input->normalized_value(),
2407
+					];
2408
+					$answer              = EEM_Answer::instance()->get_one([$where_conditions]);
2409
+					if ($answer instanceof EE_Answer) {
2410
+						$success = $answer->save($possibly_new_values);
2411
+					} else {
2412
+						// insert it then
2413
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2414
+						$answer      = EE_Answer::new_instance($cols_n_vals);
2415
+						$success     = $answer->save();
2416
+					}
2417
+				}
2418
+			}
2419
+		} else {
2420
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2421
+		}
2422
+		return $success;
2423
+	}
2424
+
2425
+
2426
+	/**
2427
+	 * generates HTML for the Registration main meta box
2428
+	 *
2429
+	 * @return void
2430
+	 * @throws DomainException
2431
+	 * @throws EE_Error
2432
+	 * @throws InvalidArgumentException
2433
+	 * @throws InvalidDataTypeException
2434
+	 * @throws InvalidInterfaceException
2435
+	 * @throws ReflectionException
2436
+	 */
2437
+	public function _reg_attendees_meta_box()
2438
+	{
2439
+		$REG = $this->getRegistrationModel();
2440
+		// get all other registrations on this transaction, and cache
2441
+		// the attendees for them so we don't have to run another query using force_join
2442
+		$registrations                           = $REG->get_all(
2443
+			[
2444
+				[
2445
+					'TXN_ID' => $this->_registration->transaction_ID(),
2446
+					'REG_ID' => ['!=', $this->_registration->ID()],
2447
+				],
2448
+				'force_join'               => ['Attendee'],
2449
+				'default_where_conditions' => 'other_models_only',
2450
+			]
2451
+		);
2452
+		$this->_template_args['attendees']       = [];
2453
+		$this->_template_args['attendee_notice'] = '';
2454
+		if (
2455
+			empty($registrations)
2456
+			|| (is_array($registrations)
2457
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2458
+		) {
2459
+			EE_Error::add_error(
2460
+				esc_html__(
2461
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2462
+					'event_espresso'
2463
+				),
2464
+				__FILE__,
2465
+				__FUNCTION__,
2466
+				__LINE__
2467
+			);
2468
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2469
+		} else {
2470
+			$att_nmbr = 1;
2471
+			foreach ($registrations as $registration) {
2472
+				/* @var $registration EE_Registration */
2473
+				$attendee                                                      = $registration->attendee()
2474
+					? $registration->attendee()
2475
+					: $this->getAttendeeModel()->create_default_object();
2476
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID']      = $registration->status_ID();
2477
+				$this->_template_args['attendees'][ $att_nmbr ]['fname']       = $attendee->fname();
2478
+				$this->_template_args['attendees'][ $att_nmbr ]['lname']       = $attendee->lname();
2479
+				$this->_template_args['attendees'][ $att_nmbr ]['email']       = $attendee->email();
2480
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2481
+				$this->_template_args['attendees'][ $att_nmbr ]['address']     = implode(
2482
+					', ',
2483
+					$attendee->full_address_as_array()
2484
+				);
2485
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link']    = self::add_query_args_and_nonce(
2486
+					[
2487
+						'action' => 'edit_attendee',
2488
+						'post'   => $attendee->ID(),
2489
+					],
2490
+					REG_ADMIN_URL
2491
+				);
2492
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name']  =
2493
+					$registration->event_obj() instanceof EE_Event
2494
+						? $registration->event_obj()->name()
2495
+						: '';
2496
+				$att_nmbr++;
2497
+			}
2498
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2499
+		}
2500
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2501
+		EEH_Template::display_template($template_path, $this->_template_args);
2502
+	}
2503
+
2504
+
2505
+	/**
2506
+	 * generates HTML for the Edit Registration side meta box
2507
+	 *
2508
+	 * @return void
2509
+	 * @throws DomainException
2510
+	 * @throws EE_Error
2511
+	 * @throws InvalidArgumentException
2512
+	 * @throws InvalidDataTypeException
2513
+	 * @throws InvalidInterfaceException
2514
+	 * @throws ReflectionException
2515
+	 */
2516
+	public function _reg_registrant_side_meta_box()
2517
+	{
2518
+		/*@var $attendee EE_Attendee */
2519
+		$att_check = $this->_registration->attendee();
2520
+		$attendee  = $att_check instanceof EE_Attendee
2521
+			? $att_check
2522
+			: $this->getAttendeeModel()->create_default_object();
2523
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2524
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2525
+		// primary registration object (that way we know if we need to show create button or not)
2526
+		if (! $this->_registration->is_primary_registrant()) {
2527
+			$primary_registration = $this->_registration->get_primary_registration();
2528
+			$primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2529
+				: null;
2530
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2531
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2532
+				// custom attendee object so let's not worry about the primary reg.
2533
+				$primary_registration = null;
2534
+			}
2535
+		} else {
2536
+			$primary_registration = null;
2537
+		}
2538
+		$this->_template_args['ATT_ID']            = $attendee->ID();
2539
+		$this->_template_args['fname']             = $attendee->fname();
2540
+		$this->_template_args['lname']             = $attendee->lname();
2541
+		$this->_template_args['email']             = $attendee->email();
2542
+		$this->_template_args['phone']             = $attendee->phone();
2543
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2544
+		// edit link
2545
+		$this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(
2546
+			[
2547
+				'action' => 'edit_attendee',
2548
+				'post'   => $attendee->ID(),
2549
+			],
2550
+			REG_ADMIN_URL
2551
+		);
2552
+		$this->_template_args['att_edit_title'] = esc_html__('View details for this contact.', 'event_espresso');
2553
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2554
+		// create link
2555
+		$this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2556
+			? EE_Admin_Page::add_query_args_and_nonce(
2557
+				[
2558
+					'action'  => 'duplicate_attendee',
2559
+					'_REG_ID' => $this->_registration->ID(),
2560
+				],
2561
+				REG_ADMIN_URL
2562
+			) : '';
2563
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2564
+		$this->_template_args['att_check']    = $att_check;
2565
+		$template_path                        =
2566
+			REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2567
+		EEH_Template::display_template($template_path, $this->_template_args);
2568
+	}
2569
+
2570
+
2571
+	/**
2572
+	 * trash or restore registrations
2573
+	 *
2574
+	 * @param boolean $trash whether to archive or restore
2575
+	 * @return void
2576
+	 * @throws DomainException
2577
+	 * @throws EE_Error
2578
+	 * @throws EntityNotFoundException
2579
+	 * @throws InvalidArgumentException
2580
+	 * @throws InvalidDataTypeException
2581
+	 * @throws InvalidInterfaceException
2582
+	 * @throws ReflectionException
2583
+	 * @throws RuntimeException
2584
+	 * @throws UnexpectedEntityException
2585
+	 */
2586
+	protected function _trash_or_restore_registrations(bool $trash = true)
2587
+	{
2588
+		// if empty _REG_ID then get out because there's nothing to do
2589
+		$REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2590
+		if (empty($REG_IDs)) {
2591
+			EE_Error::add_error(
2592
+				sprintf(
2593
+					esc_html__(
2594
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2595
+						'event_espresso'
2596
+					),
2597
+					$trash ? 'trash' : 'restore'
2598
+				),
2599
+				__FILE__,
2600
+				__LINE__,
2601
+				__FUNCTION__
2602
+			);
2603
+			$this->_redirect_after_action(false, '', '', [], true);
2604
+		}
2605
+		$success        = 0;
2606
+		$overwrite_msgs = false;
2607
+		// Checkboxes
2608
+		$reg_count = count($REG_IDs);
2609
+		// cycle thru checkboxes
2610
+		foreach ($REG_IDs as $REG_ID) {
2611
+			/** @var EE_Registration $REG */
2612
+			$REG = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2613
+			if ($trash) {
2614
+				$payments = $REG->registration_payments();
2615
+				if (! empty($payments)) {
2616
+					$name           = $REG->attendee() instanceof EE_Attendee
2617
+						? $REG->attendee()->full_name()
2618
+						: esc_html__('Unknown Attendee', 'event_espresso');
2619
+					$overwrite_msgs = true;
2620
+					EE_Error::add_error(
2621
+						sprintf(
2622
+							esc_html__(
2623
+								'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2624
+								'event_espresso'
2625
+							),
2626
+							$name
2627
+						),
2628
+						__FILE__,
2629
+						__FUNCTION__,
2630
+						__LINE__
2631
+					);
2632
+					// can't trash this registration because it has payments.
2633
+					continue;
2634
+				}
2635
+			}
2636
+			$updated = $trash ? $REG->delete() : $REG->restore();
2637
+			if ($updated) {
2638
+				$success++;
2639
+			}
2640
+		}
2641
+		$this->_redirect_after_action(
2642
+			$success === $reg_count, // were ALL registrations affected?
2643
+			$success > 1
2644
+				? esc_html__('Registrations', 'event_espresso')
2645
+				: esc_html__('Registration', 'event_espresso'),
2646
+			$trash
2647
+				? esc_html__('moved to the trash', 'event_espresso')
2648
+				: esc_html__('restored', 'event_espresso'),
2649
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2650
+			$overwrite_msgs
2651
+		);
2652
+	}
2653
+
2654
+
2655
+	/**
2656
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2657
+	 * registration but also.
2658
+	 * 1. Removing relations to EE_Attendee
2659
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2660
+	 * ALSO trashed.
2661
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2662
+	 * 4. Removing relationships between all tickets and the related registrations
2663
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2664
+	 * 6. Deleting permanently any related Check-ins.
2665
+	 *
2666
+	 * @return void
2667
+	 * @throws EE_Error
2668
+	 * @throws InvalidArgumentException
2669
+	 * @throws InvalidDataTypeException
2670
+	 * @throws InvalidInterfaceException
2671
+	 * @throws ReflectionException
2672
+	 */
2673
+	protected function _delete_registrations()
2674
+	{
2675
+		$REG_MDL = $this->getRegistrationModel();
2676
+		$success = 0;
2677
+		// Checkboxes
2678
+		$REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2679
+
2680
+		if (! empty($REG_IDs)) {
2681
+			// if array has more than one element than success message should be plural
2682
+			$success = count($REG_IDs) > 1 ? 2 : 1;
2683
+			// cycle thru checkboxes
2684
+			foreach ($REG_IDs as $REG_ID) {
2685
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2686
+				if (! $REG instanceof EE_Registration) {
2687
+					continue;
2688
+				}
2689
+				$deleted = $this->_delete_registration($REG);
2690
+				if (! $deleted) {
2691
+					$success = 0;
2692
+				}
2693
+			}
2694
+		}
2695
+
2696
+		$what        = $success > 1
2697
+			? esc_html__('Registrations', 'event_espresso')
2698
+			: esc_html__('Registration', 'event_espresso');
2699
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2700
+		$this->_redirect_after_action(
2701
+			$success,
2702
+			$what,
2703
+			$action_desc,
2704
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2705
+			true
2706
+		);
2707
+	}
2708
+
2709
+
2710
+	/**
2711
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2712
+	 * models get affected.
2713
+	 *
2714
+	 * @param EE_Registration $REG registration to be deleted permanently
2715
+	 * @return bool true = successful deletion, false = fail.
2716
+	 * @throws EE_Error
2717
+	 * @throws InvalidArgumentException
2718
+	 * @throws InvalidDataTypeException
2719
+	 * @throws InvalidInterfaceException
2720
+	 * @throws ReflectionException
2721
+	 */
2722
+	protected function _delete_registration(EE_Registration $REG)
2723
+	{
2724
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2725
+		// registrations on the transaction that are NOT trashed.
2726
+		$TXN = $REG->transaction();
2727
+		if (! $TXN instanceof EE_Transaction) {
2728
+			EE_Error::add_error(
2729
+				sprintf(
2730
+					esc_html__(
2731
+						'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2732
+						'event_espresso'
2733
+					),
2734
+					$REG->id()
2735
+				),
2736
+				__FILE__,
2737
+				__FUNCTION__,
2738
+				__LINE__
2739
+			);
2740
+			return false;
2741
+		}
2742
+		$REGS        = $TXN->get_many_related('Registration');
2743
+		$all_trashed = true;
2744
+		foreach ($REGS as $registration) {
2745
+			if (! $registration->get('REG_deleted')) {
2746
+				$all_trashed = false;
2747
+			}
2748
+		}
2749
+		if (! $all_trashed) {
2750
+			EE_Error::add_error(
2751
+				esc_html__(
2752
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2753
+					'event_espresso'
2754
+				),
2755
+				__FILE__,
2756
+				__FUNCTION__,
2757
+				__LINE__
2758
+			);
2759
+			return false;
2760
+		}
2761
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2762
+		// separately from THIS one).
2763
+		foreach ($REGS as $registration) {
2764
+			// delete related answers
2765
+			$registration->delete_related_permanently('Answer');
2766
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2767
+			$attendee = $registration->get_first_related('Attendee');
2768
+			if ($attendee instanceof EE_Attendee) {
2769
+				$registration->_remove_relation_to($attendee, 'Attendee');
2770
+			}
2771
+			// now remove relationships to tickets on this registration.
2772
+			$registration->_remove_relations('Ticket');
2773
+			// now delete permanently the checkins related to this registration.
2774
+			$registration->delete_related_permanently('Checkin');
2775
+			if ($registration->ID() === $REG->ID()) {
2776
+				continue;
2777
+			} //we don't want to delete permanently the existing registration just yet.
2778
+			// remove relation to transaction for these registrations if NOT the existing registrations
2779
+			$registration->_remove_relations('Transaction');
2780
+			// delete permanently any related messages.
2781
+			$registration->delete_related_permanently('Message');
2782
+			// now delete this registration permanently
2783
+			$registration->delete_permanently();
2784
+		}
2785
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2786
+		// (the transaction and line items should be all that's left).
2787
+		// delete the line items related to the transaction for this registration.
2788
+		$TXN->delete_related_permanently('Line_Item');
2789
+		// we need to remove all the relationships on the transaction
2790
+		$TXN->delete_related_permanently('Payment');
2791
+		$TXN->delete_related_permanently('Extra_Meta');
2792
+		$TXN->delete_related_permanently('Message');
2793
+		// now we can delete this REG permanently (and the transaction of course)
2794
+		$REG->delete_related_permanently('Transaction');
2795
+		return $REG->delete_permanently();
2796
+	}
2797
+
2798
+
2799
+	/**
2800
+	 *    generates HTML for the Register New Attendee Admin page
2801
+	 *
2802
+	 * @throws DomainException
2803
+	 * @throws EE_Error
2804
+	 * @throws InvalidArgumentException
2805
+	 * @throws InvalidDataTypeException
2806
+	 * @throws InvalidInterfaceException
2807
+	 * @throws ReflectionException
2808
+	 */
2809
+	public function new_registration()
2810
+	{
2811
+		if (! $this->_set_reg_event()) {
2812
+			throw new EE_Error(
2813
+				esc_html__(
2814
+					'Unable to continue with registering because there is no Event ID in the request',
2815
+					'event_espresso'
2816
+				)
2817
+			);
2818
+		}
2819
+		/** @var CurrentPage $current_page */
2820
+		$current_page = $this->loader->getShared(CurrentPage::class);
2821
+		$current_page->setEspressoPage(true);
2822
+		// gotta start with a clean slate if we're not coming here via ajax
2823
+		if (
2824
+			! $this->request->isAjax()
2825
+			&& (
2826
+				! $this->request->requestParamIsSet('processing_registration')
2827
+				|| $this->request->requestParamIsSet('step_error')
2828
+			)
2829
+		) {
2830
+			$this->clearSession(__CLASS__, __FUNCTION__);
2831
+		}
2832
+		$this->_template_args['event_name'] = '';
2833
+		// event name
2834
+		if ($this->_reg_event) {
2835
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2836
+			$edit_event_url                     = self::add_query_args_and_nonce(
2837
+				[
2838
+					'action' => 'edit',
2839
+					'post'   => $this->_reg_event->ID(),
2840
+				],
2841
+				EVENTS_ADMIN_URL
2842
+			);
2843
+			$edit_event_lnk                     = '<a href="'
2844
+												  . $edit_event_url
2845
+												  . '" aria-label="'
2846
+												  . esc_attr__('Edit ', 'event_espresso')
2847
+												  . $this->_reg_event->name()
2848
+												  . '">'
2849
+												  . esc_html__('Edit Event', 'event_espresso')
2850
+												  . '</a>';
2851
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2852
+												   . $edit_event_lnk
2853
+												   . '</span>';
2854
+		}
2855
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2856
+		if ($this->request->isAjax()) {
2857
+			$this->_return_json();
2858
+		}
2859
+		// grab header
2860
+		$template_path                              =
2861
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2862
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2863
+			$template_path,
2864
+			$this->_template_args,
2865
+			true
2866
+		);
2867
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2868
+		// the details template wrapper
2869
+		$this->display_admin_page_with_sidebar();
2870
+	}
2871
+
2872
+
2873
+	/**
2874
+	 * This returns the content for a registration step
2875
+	 *
2876
+	 * @return string html
2877
+	 * @throws DomainException
2878
+	 * @throws EE_Error
2879
+	 * @throws InvalidArgumentException
2880
+	 * @throws InvalidDataTypeException
2881
+	 * @throws InvalidInterfaceException
2882
+	 * @throws ReflectionException
2883
+	 */
2884
+	protected function _get_registration_step_content()
2885
+	{
2886
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2887
+			$warning_msg = sprintf(
2888
+				esc_html__(
2889
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2890
+					'event_espresso'
2891
+				),
2892
+				'<br />',
2893
+				'<h3 class="important-notice">',
2894
+				'</h3>',
2895
+				'<div class="float-right">',
2896
+				'<span id="redirect_timer" class="important-notice">30</span>',
2897
+				'</div>',
2898
+				'<b>',
2899
+				'</b>'
2900
+			);
2901
+			return '
2902 2902
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2903 2903
 	<script >
2904 2904
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2911,958 +2911,958 @@  discard block
 block discarded – undo
2911 2911
 	        }
2912 2912
 	    }, 800 );
2913 2913
 	</script >';
2914
-        }
2915
-        $template_args = [
2916
-            'title'                    => '',
2917
-            'content'                  => '',
2918
-            'step_button_text'         => '',
2919
-            'show_notification_toggle' => false,
2920
-        ];
2921
-        // to indicate we're processing a new registration
2922
-        $hidden_fields = [
2923
-            'processing_registration' => [
2924
-                'type'  => 'hidden',
2925
-                'value' => 0,
2926
-            ],
2927
-            'event_id'                => [
2928
-                'type'  => 'hidden',
2929
-                'value' => $this->_reg_event->ID(),
2930
-            ],
2931
-        ];
2932
-        // if the cart is empty then we know we're at step one, so we'll display the ticket selector
2933
-        $cart = $this->getCart();
2934
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2935
-        switch ($step) {
2936
-            case 'ticket':
2937
-                $hidden_fields['processing_registration']['value'] = 1;
2938
-                $template_args['title']                            = esc_html__(
2939
-                    'Step One: Select the Ticket for this registration',
2940
-                    'event_espresso'
2941
-                );
2942
-                $template_args['content']                          =
2943
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2944
-                $template_args['content']                          .= '</div>';
2945
-                $template_args['step_button_text']                 = esc_html__(
2946
-                    'Add Tickets and Continue to Registrant Details',
2947
-                    'event_espresso'
2948
-                );
2949
-                $template_args['show_notification_toggle']         = false;
2950
-                break;
2951
-            case 'questions':
2952
-                $hidden_fields['processing_registration']['value'] = 2;
2953
-                $template_args['title']                            = esc_html__(
2954
-                    'Step Two: Add Registrant Details for this Registration',
2955
-                    'event_espresso'
2956
-                );
2957
-                // in theory, we should be able to run EED_SPCO at this point
2958
-                // because the cart should have been set up properly by the first process_reg_step run.
2959
-                $template_args['content']                  =
2960
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
2961
-                $template_args['step_button_text']         = esc_html__(
2962
-                    'Save Registration and Continue to Details',
2963
-                    'event_espresso'
2964
-                );
2965
-                $template_args['show_notification_toggle'] = true;
2966
-                break;
2967
-        }
2968
-        // we come back to the process_registration_step route.
2969
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2970
-        return EEH_Template::display_template(
2971
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2972
-            $template_args,
2973
-            true
2974
-        );
2975
-    }
2976
-
2977
-
2978
-    /**
2979
-     * set_reg_event
2980
-     *
2981
-     * @return bool
2982
-     * @throws EE_Error
2983
-     * @throws InvalidArgumentException
2984
-     * @throws InvalidDataTypeException
2985
-     * @throws InvalidInterfaceException
2986
-     * @throws ReflectionException
2987
-     */
2988
-    private function _set_reg_event()
2989
-    {
2990
-        if (is_object($this->_reg_event)) {
2991
-            return true;
2992
-        }
2993
-
2994
-        $EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
2995
-        if (! $EVT_ID) {
2996
-            return false;
2997
-        }
2998
-        $this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2999
-        return true;
3000
-    }
3001
-
3002
-
3003
-    /**
3004
-     * process_reg_step
3005
-     *
3006
-     * @return void
3007
-     * @throws DomainException
3008
-     * @throws EE_Error
3009
-     * @throws InvalidArgumentException
3010
-     * @throws InvalidDataTypeException
3011
-     * @throws InvalidInterfaceException
3012
-     * @throws ReflectionException
3013
-     * @throws RuntimeException
3014
-     */
3015
-    public function process_reg_step()
3016
-    {
3017
-        EE_System::do_not_cache();
3018
-        $this->_set_reg_event();
3019
-        /** @var CurrentPage $current_page */
3020
-        $current_page = $this->loader->getShared(CurrentPage::class);
3021
-        $current_page->setEspressoPage(true);
3022
-        $this->request->setRequestParam('uts', time());
3023
-        // what step are we on?
3024
-        $cart = $this->getCart();
3025
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3026
-        // if doing ajax then we need to verify the nonce
3027
-        if ($this->request->isAjax()) {
3028
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
3029
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3030
-        }
3031
-        switch ($step) {
3032
-            case 'ticket':
3033
-                // process ticket selection
3034
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3035
-                if ($success) {
3036
-                    EE_Error::add_success(
3037
-                        esc_html__(
3038
-                            'Tickets Selected. Now complete the registration.',
3039
-                            'event_espresso'
3040
-                        )
3041
-                    );
3042
-                } else {
3043
-                    $this->request->setRequestParam('step_error', true);
3044
-                    $query_args['step_error'] = $this->request->getRequestParam('step_error', true, 'bool');
3045
-                }
3046
-                if ($this->request->isAjax()) {
3047
-                    $this->new_registration(); // display next step
3048
-                } else {
3049
-                    $query_args = [
3050
-                        'action'                  => 'new_registration',
3051
-                        'processing_registration' => 1,
3052
-                        'event_id'                => $this->_reg_event->ID(),
3053
-                        'uts'                     => time(),
3054
-                    ];
3055
-                    $this->_redirect_after_action(
3056
-                        false,
3057
-                        '',
3058
-                        '',
3059
-                        $query_args,
3060
-                        true
3061
-                    );
3062
-                }
3063
-                break;
3064
-            case 'questions':
3065
-                if (! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3066
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3067
-                }
3068
-                // process registration
3069
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3070
-                if ($cart instanceof EE_Cart) {
3071
-                    $grand_total = $cart->get_grand_total();
3072
-                    if ($grand_total instanceof EE_Line_Item) {
3073
-                        $grand_total->save_this_and_descendants_to_txn();
3074
-                    }
3075
-                }
3076
-                if (! $transaction instanceof EE_Transaction) {
3077
-                    $query_args = [
3078
-                        'action'                  => 'new_registration',
3079
-                        'processing_registration' => 2,
3080
-                        'event_id'                => $this->_reg_event->ID(),
3081
-                        'uts'                     => time(),
3082
-                    ];
3083
-                    if ($this->request->isAjax()) {
3084
-                        // display registration form again because there are errors (maybe validation?)
3085
-                        $this->new_registration();
3086
-                        return;
3087
-                    }
3088
-                    $this->_redirect_after_action(
3089
-                        false,
3090
-                        '',
3091
-                        '',
3092
-                        $query_args,
3093
-                        true
3094
-                    );
3095
-                    return;
3096
-                }
3097
-                // maybe update status, and make sure to save transaction if not done already
3098
-                if (! $transaction->update_status_based_on_total_paid()) {
3099
-                    $transaction->save();
3100
-                }
3101
-                $this->clearSession(__CLASS__, __FUNCTION__);
3102
-                $query_args = [
3103
-                    'action'        => 'redirect_to_txn',
3104
-                    'TXN_ID'        => $transaction->ID(),
3105
-                    'EVT_ID'        => $this->_reg_event->ID(),
3106
-                    'event_name'    => urlencode($this->_reg_event->name()),
3107
-                    'redirect_from' => 'new_registration',
3108
-                ];
3109
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3110
-                break;
3111
-        }
3112
-        // what are you looking here for?  Should be nothing to do at this point.
3113
-    }
3114
-
3115
-
3116
-    /**
3117
-     * redirect_to_txn
3118
-     *
3119
-     * @return void
3120
-     * @throws EE_Error
3121
-     * @throws InvalidArgumentException
3122
-     * @throws InvalidDataTypeException
3123
-     * @throws InvalidInterfaceException
3124
-     * @throws ReflectionException
3125
-     */
3126
-    public function redirect_to_txn()
3127
-    {
3128
-        EE_System::do_not_cache();
3129
-        $this->clearSession(__CLASS__, __FUNCTION__);
3130
-        $query_args = [
3131
-            'action' => 'view_transaction',
3132
-            'TXN_ID' => $this->request->getRequestParam('TXN_ID', 0, 'int'),
3133
-            'page'   => 'espresso_transactions',
3134
-        ];
3135
-        if ($this->request->requestParamIsSet('EVT_ID') && $this->request->requestParamIsSet('redirect_from')) {
3136
-            $query_args['EVT_ID']        = $this->request->getRequestParam('EVT_ID', 0, 'int');
3137
-            $query_args['event_name']    = urlencode($this->request->getRequestParam('event_name'));
3138
-            $query_args['redirect_from'] = $this->request->getRequestParam('redirect_from');
3139
-        }
3140
-        EE_Error::add_success(
3141
-            esc_html__(
3142
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3143
-                'event_espresso'
3144
-            )
3145
-        );
3146
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3147
-    }
3148
-
3149
-
3150
-    /**
3151
-     * generates HTML for the Attendee Contact List
3152
-     *
3153
-     * @return void
3154
-     * @throws DomainException
3155
-     * @throws EE_Error
3156
-     */
3157
-    protected function _attendee_contact_list_table()
3158
-    {
3159
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3160
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3161
-        $this->display_admin_list_table_page_with_no_sidebar();
3162
-    }
3163
-
3164
-
3165
-    /**
3166
-     * get_attendees
3167
-     *
3168
-     * @param      $per_page
3169
-     * @param bool $count whether to return count or data.
3170
-     * @param bool $trash
3171
-     * @return array|int
3172
-     * @throws EE_Error
3173
-     * @throws InvalidArgumentException
3174
-     * @throws InvalidDataTypeException
3175
-     * @throws InvalidInterfaceException
3176
-     * @throws ReflectionException
3177
-     */
3178
-    public function get_attendees($per_page, $count = false, $trash = false)
3179
-    {
3180
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3181
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3182
-        $orderby = $this->request->getRequestParam('orderby');
3183
-        switch ($orderby) {
3184
-            case 'ATT_ID':
3185
-            case 'ATT_fname':
3186
-            case 'ATT_email':
3187
-            case 'ATT_city':
3188
-            case 'STA_ID':
3189
-            case 'CNT_ID':
3190
-                break;
3191
-            case 'Registration_Count':
3192
-                $orderby = 'Registration_Count';
3193
-                break;
3194
-            default:
3195
-                $orderby = 'ATT_lname';
3196
-        }
3197
-        $sort         = $this->request->getRequestParam('order', 'ASC');
3198
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
3199
-        $per_page     = absint($per_page) ? $per_page : 10;
3200
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
3201
-        $_where       = [];
3202
-        $search_term  = $this->request->getRequestParam('s');
3203
-        if ($search_term) {
3204
-            $search_term  = '%' . $search_term . '%';
3205
-            $_where['OR'] = [
3206
-                'Registration.Event.EVT_name'       => ['LIKE', $search_term],
3207
-                'Registration.Event.EVT_desc'       => ['LIKE', $search_term],
3208
-                'Registration.Event.EVT_short_desc' => ['LIKE', $search_term],
3209
-                'ATT_fname'                         => ['LIKE', $search_term],
3210
-                'ATT_lname'                         => ['LIKE', $search_term],
3211
-                'ATT_short_bio'                     => ['LIKE', $search_term],
3212
-                'ATT_email'                         => ['LIKE', $search_term],
3213
-                'ATT_address'                       => ['LIKE', $search_term],
3214
-                'ATT_address2'                      => ['LIKE', $search_term],
3215
-                'ATT_city'                          => ['LIKE', $search_term],
3216
-                'Country.CNT_name'                  => ['LIKE', $search_term],
3217
-                'State.STA_name'                    => ['LIKE', $search_term],
3218
-                'ATT_phone'                         => ['LIKE', $search_term],
3219
-                'Registration.REG_final_price'      => ['LIKE', $search_term],
3220
-                'Registration.REG_code'             => ['LIKE', $search_term],
3221
-                'Registration.REG_group_size'       => ['LIKE', $search_term],
3222
-            ];
3223
-        }
3224
-        $offset     = ($current_page - 1) * $per_page;
3225
-        $limit      = $count ? null : [$offset, $per_page];
3226
-        $query_args = [
3227
-            $_where,
3228
-            'extra_selects' => ['Registration_Count' => ['Registration.REG_ID', 'count', '%d']],
3229
-            'limit'         => $limit,
3230
-        ];
3231
-        if (! $count) {
3232
-            $query_args['order_by'] = [$orderby => $sort];
3233
-        }
3234
-        $query_args[0]['status'] = $trash ? ['!=', 'publish'] : ['IN', ['publish']];
3235
-        return $count
3236
-            ? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3237
-            : $this->getAttendeeModel()->get_all($query_args);
3238
-    }
3239
-
3240
-
3241
-    /**
3242
-     * This is just taking care of resending the registration confirmation
3243
-     *
3244
-     * @return void
3245
-     * @throws EE_Error
3246
-     * @throws InvalidArgumentException
3247
-     * @throws InvalidDataTypeException
3248
-     * @throws InvalidInterfaceException
3249
-     * @throws ReflectionException
3250
-     */
3251
-    protected function _resend_registration()
3252
-    {
3253
-        $this->_process_resend_registration();
3254
-        $REG_ID      = $this->request->getRequestParam('_REG_ID', 0, 'int');
3255
-        $redirect_to = $this->request->getRequestParam('redirect_to');
3256
-        $query_args  = $redirect_to
3257
-            ? ['action' => $redirect_to, '_REG_ID' => $REG_ID]
3258
-            : ['action' => 'default'];
3259
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3260
-    }
3261
-
3262
-
3263
-    /**
3264
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3265
-     * to use when selecting registrations
3266
-     *
3267
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3268
-     *                                                     the query parameters from the request
3269
-     * @return void ends the request with a redirect or download
3270
-     */
3271
-    public function _registrations_report_base(string $method_name_for_getting_query_params)
3272
-    {
3273
-        $EVT_ID = $this->request->requestParamIsSet('EVT_ID')
3274
-            ? $this->request->getRequestParam('EVT_ID', 0, DataType::INT)
3275
-            : null;
3276
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3277
-            $return_url    = $this->request->getRequestParam('return_url', '', DataType::URL);
3278
-            $filters       = $this->request->getRequestParam('filters', [], DataType::STRING, true);
3279
-            $report_params = $this->$method_name_for_getting_query_params($filters);
3280
-            $report_params = $this->convertDatetimeObjectsToStrings($report_params);
3281
-            $use_filters   = $this->request->getRequestParam('use_filters', false, DataType::BOOL);
3282
-            wp_redirect(
3283
-                EE_Admin_Page::add_query_args_and_nonce(
3284
-                    [
3285
-                        'page'        => EED_Batch::PAGE_SLUG,
3286
-                        'batch'       => EED_Batch::batch_file_job,
3287
-                        'EVT_ID'      => $EVT_ID,
3288
-                        'filters'     => urlencode(serialize($report_params)),
3289
-                        'use_filters' => urlencode($use_filters),
3290
-                        'job_handler' => urlencode('EventEspresso\core\libraries\batch\JobHandlers\RegistrationsReport'),
3291
-                        'return_url'  => urlencode($return_url),
3292
-                    ]
3293
-                )
3294
-            );
3295
-        } else {
3296
-            // Pull the current request params
3297
-            $request_args = $this->request->requestParams();
3298
-            $request_args = $this->convertDatetimeObjectsToStrings($request_args);
3299
-            // Set the required request_args to be passed to the export
3300
-            $required_request_args = [
3301
-                'export' => 'report',
3302
-                'action' => 'registrations_report_for_event',
3303
-                'EVT_ID' => $EVT_ID,
3304
-            ];
3305
-            // Merge required request args, overriding any currently set
3306
-            $request_args = array_merge($request_args, $required_request_args);
3307
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3308
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3309
-                $EE_Export = EE_Export::instance($request_args);
3310
-                $EE_Export->export();
3311
-            }
3312
-        }
3313
-    }
3314
-
3315
-
3316
-    /**
3317
-     * recursively convert Datetime objects in query params array to strings using MySQL format
3318
-     *
3319
-     * @param array $query_params
3320
-     * @return array
3321
-     * @since 5.0.19.p
3322
-     */
3323
-    private function convertDatetimeObjectsToStrings(array $query_params): array
3324
-    {
3325
-        foreach ($query_params as $key => $value) {
3326
-            if (is_array($value)) {
3327
-                $query_params[$key] = $this->convertDatetimeObjectsToStrings($value);
3328
-            } elseif ($value instanceof DateTime) {
3329
-                $query_params[$key] = $value->format('Y-m-d H:i:s');
3330
-            }
3331
-        }
3332
-        return $query_params;
3333
-    }
3334
-
3335
-
3336
-    /**
3337
-     * Creates a registration report using only query parameters in the request
3338
-     *
3339
-     * @return void
3340
-     */
3341
-    public function _registrations_report()
3342
-    {
3343
-        $this->_registrations_report_base('_get_registration_query_parameters');
3344
-    }
3345
-
3346
-
3347
-    public function _contact_list_export()
3348
-    {
3349
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3350
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3351
-            $EE_Export = EE_Export::instance($this->request->requestParams());
3352
-            $EE_Export->export_attendees();
3353
-        }
3354
-    }
3355
-
3356
-
3357
-    public function _contact_list_report()
3358
-    {
3359
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3360
-            wp_redirect(
3361
-                EE_Admin_Page::add_query_args_and_nonce(
3362
-                    [
3363
-                        'page'        => EED_Batch::PAGE_SLUG,
3364
-                        'batch'       => EED_Batch::batch_file_job,
3365
-                        'job_handler' => urlencode('EventEspresso\core\libraries\batch\JobHandlers\AttendeesReport'),
3366
-                        'return_url'  => urlencode($this->request->getRequestParam('return_url', '', DataType::URL)),
3367
-                    ]
3368
-                )
3369
-            );
3370
-        } else {
3371
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3372
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3373
-                $EE_Export = EE_Export::instance($this->request->requestParams());
3374
-                $EE_Export->report_attendees();
3375
-            }
3376
-        }
3377
-    }
3378
-
3379
-
3380
-
3381
-
3382
-
3383
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3384
-    /**
3385
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3386
-     *
3387
-     * @return void
3388
-     * @throws EE_Error
3389
-     * @throws InvalidArgumentException
3390
-     * @throws InvalidDataTypeException
3391
-     * @throws InvalidInterfaceException
3392
-     * @throws ReflectionException
3393
-     */
3394
-    protected function _duplicate_attendee()
3395
-    {
3396
-        $REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
3397
-        $action = $this->request->getRequestParam('return', 'default');
3398
-        // verify we have necessary info
3399
-        if (! $REG_ID) {
3400
-            EE_Error::add_error(
3401
-                esc_html__(
3402
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3403
-                    'event_espresso'
3404
-                ),
3405
-                __FILE__,
3406
-                __LINE__,
3407
-                __FUNCTION__
3408
-            );
3409
-            $query_args = ['action' => $action];
3410
-            $this->_redirect_after_action('', '', '', $query_args, true);
3411
-        }
3412
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3413
-        $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
3414
-        if (! $registration instanceof EE_Registration) {
3415
-            throw new RuntimeException(
3416
-                sprintf(
3417
-                    esc_html__(
3418
-                        'Unable to create the contact because a valid registration could not be retrieved for REG ID: %1$d',
3419
-                        'event_espresso'
3420
-                    ),
3421
-                    $REG_ID
3422
-                )
3423
-            );
3424
-        }
3425
-        $attendee = $registration->attendee();
3426
-        // remove relation of existing attendee on registration
3427
-        $registration->_remove_relation_to($attendee, 'Attendee');
3428
-        // new attendee
3429
-        $new_attendee = clone $attendee;
3430
-        $new_attendee->set('ATT_ID', 0);
3431
-        $new_attendee->save();
3432
-        // add new attendee to reg
3433
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3434
-        EE_Error::add_success(
3435
-            esc_html__(
3436
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3437
-                'event_espresso'
3438
-            )
3439
-        );
3440
-        // redirect to edit page for attendee
3441
-        $query_args = ['post' => $new_attendee->ID(), 'action' => 'edit_attendee'];
3442
-        $this->_redirect_after_action('', '', '', $query_args, true);
3443
-    }
3444
-
3445
-
3446
-    /**
3447
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3448
-     *
3449
-     * @param int     $post_id
3450
-     * @param WP_Post $post
3451
-     * @throws DomainException
3452
-     * @throws EE_Error
3453
-     * @throws InvalidArgumentException
3454
-     * @throws InvalidDataTypeException
3455
-     * @throws InvalidInterfaceException
3456
-     * @throws LogicException
3457
-     * @throws InvalidFormSubmissionException
3458
-     * @throws ReflectionException
3459
-     */
3460
-    protected function _insert_update_cpt_item($post_id, $post)
3461
-    {
3462
-        $success  = true;
3463
-        $attendee = $post instanceof WP_Post && $post->post_type === EspressoPostType::ATTENDEES
3464
-            ? $this->getAttendeeModel()->get_one_by_ID($post_id)
3465
-            : null;
3466
-        // for attendee updates
3467
-        if ($attendee instanceof EE_Attendee) {
3468
-            // note we should only be UPDATING attendees at this point.
3469
-            $fname          = $this->request->getRequestParam('ATT_fname', '');
3470
-            $lname          = $this->request->getRequestParam('ATT_lname', '');
3471
-            $updated_fields = [
3472
-                'ATT_fname'     => $fname,
3473
-                'ATT_lname'     => $lname,
3474
-                'ATT_full_name' => "{$fname} {$lname}",
3475
-                'ATT_address'   => $this->request->getRequestParam('ATT_address', ''),
3476
-                'ATT_address2'  => $this->request->getRequestParam('ATT_address2', ''),
3477
-                'ATT_city'      => $this->request->getRequestParam('ATT_city', ''),
3478
-                'STA_ID'        => $this->request->getRequestParam('STA_ID', ''),
3479
-                'CNT_ISO'       => $this->request->getRequestParam('CNT_ISO', ''),
3480
-                'ATT_zip'       => $this->request->getRequestParam('ATT_zip', ''),
3481
-            ];
3482
-            foreach ($updated_fields as $field => $value) {
3483
-                $attendee->set($field, $value);
3484
-            }
3485
-
3486
-            // process contact details metabox form handler (which will also save the attendee)
3487
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3488
-            $success              = $contact_details_form->process($this->request->requestParams());
3489
-
3490
-            $attendee_update_callbacks = apply_filters(
3491
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3492
-                []
3493
-            );
3494
-            foreach ($attendee_update_callbacks as $a_callback) {
3495
-                if (false === call_user_func_array($a_callback, [$attendee, $this->request->requestParams()])) {
3496
-                    throw new EE_Error(
3497
-                        sprintf(
3498
-                            esc_html__(
3499
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3500
-                                'event_espresso'
3501
-                            ),
3502
-                            $a_callback
3503
-                        )
3504
-                    );
3505
-                }
3506
-            }
3507
-        }
3508
-
3509
-        if ($success === false) {
3510
-            EE_Error::add_error(
3511
-                esc_html__(
3512
-                    'Something went wrong with updating the meta table data for the registration.',
3513
-                    'event_espresso'
3514
-                ),
3515
-                __FILE__,
3516
-                __FUNCTION__,
3517
-                __LINE__
3518
-            );
3519
-        }
3520
-    }
3521
-
3522
-
3523
-    public function trash_cpt_item($post_id)
3524
-    {
3525
-    }
3526
-
3527
-
3528
-    public function delete_cpt_item($post_id)
3529
-    {
3530
-    }
3531
-
3532
-
3533
-    public function restore_cpt_item($post_id)
3534
-    {
3535
-    }
3536
-
3537
-
3538
-    protected function _restore_cpt_item($post_id, $revision_id)
3539
-    {
3540
-    }
3541
-
3542
-
3543
-    /**
3544
-     * @throws EE_Error
3545
-     * @throws ReflectionException
3546
-     * @since 4.10.2.p
3547
-     */
3548
-    public function attendee_editor_metaboxes()
3549
-    {
3550
-        $this->verify_cpt_object();
3551
-        remove_meta_box(
3552
-            'postexcerpt',
3553
-            $this->_cpt_routes[ $this->_req_action ],
3554
-            'normal'
3555
-        );
3556
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal');
3557
-        if (post_type_supports(EspressoPostType::ATTENDEES, 'excerpt')) {
3558
-            $this->addMetaBox(
3559
-                'postexcerpt',
3560
-                esc_html__('Short Biography', 'event_espresso'),
3561
-                'post_excerpt_meta_box',
3562
-                $this->_cpt_routes[ $this->_req_action ]
3563
-            );
3564
-        }
3565
-        if (post_type_supports(EspressoPostType::ATTENDEES, 'comments')) {
3566
-            $this->addMetaBox(
3567
-                'commentsdiv',
3568
-                esc_html__('Notes on the Contact', 'event_espresso'),
3569
-                'post_comment_meta_box',
3570
-                $this->_cpt_routes[ $this->_req_action ],
3571
-                'normal',
3572
-                'core'
3573
-            );
3574
-        }
3575
-        $this->addMetaBox(
3576
-            'attendee_contact_info',
3577
-            esc_html__('Contact Info', 'event_espresso'),
3578
-            [$this, 'attendee_contact_info'],
3579
-            $this->_cpt_routes[ $this->_req_action ],
3580
-            'side',
3581
-            'core'
3582
-        );
3583
-        $this->addMetaBox(
3584
-            'attendee_details_address',
3585
-            esc_html__('Address Details', 'event_espresso'),
3586
-            [$this, 'attendee_address_details'],
3587
-            $this->_cpt_routes[ $this->_req_action ],
3588
-            'normal',
3589
-            'core'
3590
-        );
3591
-        $this->addMetaBox(
3592
-            'attendee_registrations',
3593
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3594
-            [$this, 'attendee_registrations_meta_box'],
3595
-            $this->_cpt_routes[ $this->_req_action ]
3596
-        );
3597
-    }
3598
-
3599
-
3600
-    /**
3601
-     * Metabox for attendee contact info
3602
-     *
3603
-     * @param WP_Post $post wp post object
3604
-     * @return void attendee contact info ( and form )
3605
-     * @throws EE_Error
3606
-     * @throws InvalidArgumentException
3607
-     * @throws InvalidDataTypeException
3608
-     * @throws InvalidInterfaceException
3609
-     * @throws LogicException
3610
-     * @throws DomainException
3611
-     */
3612
-    public function attendee_contact_info($post)
3613
-    {
3614
-        // get attendee object ( should already have it )
3615
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3616
-        $form->enqueueStylesAndScripts();
3617
-        echo wp_kses($form->display(), AllowedTags::getWithFormTags());
3618
-    }
3619
-
3620
-
3621
-    /**
3622
-     * Return form handler for the contact details metabox
3623
-     *
3624
-     * @param EE_Attendee $attendee
3625
-     * @return AttendeeContactDetailsMetaboxFormHandler
3626
-     * @throws DomainException
3627
-     * @throws InvalidArgumentException
3628
-     * @throws InvalidDataTypeException
3629
-     * @throws InvalidInterfaceException
3630
-     */
3631
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3632
-    {
3633
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3634
-    }
3635
-
3636
-
3637
-    /**
3638
-     * Metabox for attendee details
3639
-     *
3640
-     * @param WP_Post $post wp post object
3641
-     * @throws EE_Error
3642
-     * @throws ReflectionException
3643
-     */
3644
-    public function attendee_address_details($post)
3645
-    {
3646
-        // get attendee object (should already have it)
3647
-        $this->_template_args['attendee']     = $this->_cpt_model_obj;
3648
-        $this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3649
-            new EE_Question_Form_Input(
3650
-                EE_Question::new_instance(
3651
-                    [
3652
-                        'QST_ID'           => 0,
3653
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3654
-                        'QST_system'       => 'admin-state',
3655
-                    ]
3656
-                ),
3657
-                EE_Answer::new_instance(
3658
-                    [
3659
-                        'ANS_ID'    => 0,
3660
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3661
-                    ]
3662
-                ),
3663
-                [
3664
-                    'input_id'       => 'STA_ID',
3665
-                    'input_name'     => 'STA_ID',
3666
-                    'input_prefix'   => '',
3667
-                    'append_qstn_id' => false,
3668
-                ]
3669
-            )
3670
-        );
3671
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3672
-            new EE_Question_Form_Input(
3673
-                EE_Question::new_instance(
3674
-                    [
3675
-                        'QST_ID'           => 0,
3676
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3677
-                        'QST_system'       => 'admin-country',
3678
-                    ]
3679
-                ),
3680
-                EE_Answer::new_instance(
3681
-                    [
3682
-                        'ANS_ID'    => 0,
3683
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3684
-                    ]
3685
-                ),
3686
-                [
3687
-                    'input_id'       => 'CNT_ISO',
3688
-                    'input_name'     => 'CNT_ISO',
3689
-                    'input_prefix'   => '',
3690
-                    'append_qstn_id' => false,
3691
-                ]
3692
-            )
3693
-        );
3694
-        $template                             =
3695
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3696
-        EEH_Template::display_template($template, $this->_template_args);
3697
-    }
3698
-
3699
-
3700
-    /**
3701
-     * _attendee_details
3702
-     *
3703
-     * @param $post
3704
-     * @return void
3705
-     * @throws DomainException
3706
-     * @throws EE_Error
3707
-     * @throws InvalidArgumentException
3708
-     * @throws InvalidDataTypeException
3709
-     * @throws InvalidInterfaceException
3710
-     * @throws ReflectionException
3711
-     */
3712
-    public function attendee_registrations_meta_box($post)
3713
-    {
3714
-        $this->_template_args['attendee']      = $this->_cpt_model_obj;
3715
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3716
-        $template                              =
3717
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3718
-        EEH_Template::display_template($template, $this->_template_args);
3719
-    }
3720
-
3721
-
3722
-    /**
3723
-     * add in the form fields for the attendee edit
3724
-     *
3725
-     * @param WP_Post $post wp post object
3726
-     * @return void echos html for new form.
3727
-     * @throws DomainException
3728
-     */
3729
-    public function after_title_form_fields($post)
3730
-    {
3731
-        if ($post->post_type === EspressoPostType::ATTENDEES) {
3732
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3733
-            $template_args['attendee'] = $this->_cpt_model_obj;
3734
-            EEH_Template::display_template($template, $template_args);
3735
-        }
3736
-    }
3737
-
3738
-
3739
-    /**
3740
-     * _trash_or_restore_attendee
3741
-     *
3742
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3743
-     * @return void
3744
-     * @throws EE_Error
3745
-     * @throws InvalidArgumentException
3746
-     * @throws InvalidDataTypeException
3747
-     * @throws InvalidInterfaceException
3748
-     * @throws ReflectionException
3749
-     */
3750
-    protected function _trash_or_restore_attendees($trash = true)
3751
-    {
3752
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3753
-        $status = $trash ? 'trash' : 'publish';
3754
-        // Checkboxes
3755
-        if ($this->request->requestParamIsSet('ATT_IDs')) {
3756
-            $ATT_IDs = $this->request->getRequestParam('ATT_IDs', [], 'int', true);
3757
-            // if array has more than one element than success message should be plural
3758
-            $success = count($ATT_IDs) > 1 ? 2 : 1;
3759
-            // cycle thru checkboxes
3760
-            foreach ($ATT_IDs as $ATT_ID) {
3761
-                $updated = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID);
3762
-                if (! $updated) {
3763
-                    $success = 0;
3764
-                }
3765
-            }
3766
-        } else {
3767
-            // grab single id and delete
3768
-            $ATT_ID = $this->request->getRequestParam('ATT_ID', 0, 'int');
3769
-            // update attendee
3770
-            $success = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID) ? 1 : 0;
3771
-        }
3772
-        $what        = $success > 1
3773
-            ? esc_html__('Contacts', 'event_espresso')
3774
-            : esc_html__('Contact', 'event_espresso');
3775
-        $action_desc = $trash
3776
-            ? esc_html__('moved to the trash', 'event_espresso')
3777
-            : esc_html__('restored', 'event_espresso');
3778
-        $this->_redirect_after_action($success, $what, $action_desc, ['action' => 'contact_list']);
3779
-    }
3780
-
3781
-
3782
-    /**
3783
-     * @return void
3784
-     * @throws EE_Error
3785
-     * @throws ReflectionException
3786
-     * @since  :VID:
3787
-     */
3788
-    protected function deleteAttendees()
3789
-    {
3790
-        $success = 0;
3791
-        $att_ids = $this->getAttIdsFromRequest();
3792
-        foreach ($att_ids as $att_id) {
3793
-            $attendee = $this->getAttendeeModel()->get_one_by_ID($att_id);
3794
-            if ($attendee instanceof EE_Attendee) {
3795
-                $deleted = $attendee->delete_permanently();
3796
-                if($deleted) {
3797
-                    $success++;
3798
-                }
3799
-            }
3800
-        }
3801
-        $what = $success > 1
3802
-            ? esc_html__('Contacts', 'event_espresso')
3803
-            : esc_html__('Contact', 'event_espresso');
3804
-
3805
-        $this->_redirect_after_action(
3806
-            $success,
3807
-            $what,
3808
-            esc_html__('deleted', 'event_espresso'),
3809
-            [
3810
-                'action' => 'contact_list',
3811
-                'status' => 'trash',
3812
-            ],
3813
-            $success == 0 ? true : false
3814
-        );
3815
-    }
3816
-
3817
-
3818
-    /**
3819
-     * @return array
3820
-     * @since  :VID:
3821
-     */
3822
-    private function getAttIdsFromRequest(): array
3823
-    {
3824
-        if ($this->request->requestParamIsSet('ATT_IDs')) {
3825
-            return $this->request->getRequestParam('ATT_IDs', [], 'int', true);
3826
-        } else {
3827
-            return $this->request->getRequestParam('ATT_ID', [], 'int', true);
3828
-        }
3829
-    }
3830
-
3831
-
3832
-    /**
3833
-     * @return EE_Session|null
3834
-     * @since 5.0.20.p
3835
-     */
3836
-    private function getSession(): ?EE_Session
3837
-    {
3838
-        return EE_Registry::instance()->SSN;
3839
-    }
3840
-
3841
-
3842
-    /**
3843
-     * @param string $class
3844
-     * @param string $function
3845
-     * @return void
3846
-     * @throws EE_Error
3847
-     * @throws ReflectionException
3848
-     * @since 5.0.20.p
3849
-     */
3850
-    private function clearSession(string $class, string $function)
3851
-    {
3852
-        $session = $this->getSession();
3853
-        if ($session instanceof EE_Session) {
3854
-            $session->clear_session($class, $function);
3855
-        }
3856
-    }
3857
-
3858
-
3859
-    /**
3860
-     * @return EE_Cart|null
3861
-     * @since 5.0.20.p
3862
-     */
3863
-    private function getCart(): ?EE_Cart
3864
-    {
3865
-        $session = $this->getSession();
3866
-        return $session instanceof EE_Session ? $session->cart() : null;
3867
-    }
2914
+		}
2915
+		$template_args = [
2916
+			'title'                    => '',
2917
+			'content'                  => '',
2918
+			'step_button_text'         => '',
2919
+			'show_notification_toggle' => false,
2920
+		];
2921
+		// to indicate we're processing a new registration
2922
+		$hidden_fields = [
2923
+			'processing_registration' => [
2924
+				'type'  => 'hidden',
2925
+				'value' => 0,
2926
+			],
2927
+			'event_id'                => [
2928
+				'type'  => 'hidden',
2929
+				'value' => $this->_reg_event->ID(),
2930
+			],
2931
+		];
2932
+		// if the cart is empty then we know we're at step one, so we'll display the ticket selector
2933
+		$cart = $this->getCart();
2934
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2935
+		switch ($step) {
2936
+			case 'ticket':
2937
+				$hidden_fields['processing_registration']['value'] = 1;
2938
+				$template_args['title']                            = esc_html__(
2939
+					'Step One: Select the Ticket for this registration',
2940
+					'event_espresso'
2941
+				);
2942
+				$template_args['content']                          =
2943
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2944
+				$template_args['content']                          .= '</div>';
2945
+				$template_args['step_button_text']                 = esc_html__(
2946
+					'Add Tickets and Continue to Registrant Details',
2947
+					'event_espresso'
2948
+				);
2949
+				$template_args['show_notification_toggle']         = false;
2950
+				break;
2951
+			case 'questions':
2952
+				$hidden_fields['processing_registration']['value'] = 2;
2953
+				$template_args['title']                            = esc_html__(
2954
+					'Step Two: Add Registrant Details for this Registration',
2955
+					'event_espresso'
2956
+				);
2957
+				// in theory, we should be able to run EED_SPCO at this point
2958
+				// because the cart should have been set up properly by the first process_reg_step run.
2959
+				$template_args['content']                  =
2960
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
2961
+				$template_args['step_button_text']         = esc_html__(
2962
+					'Save Registration and Continue to Details',
2963
+					'event_espresso'
2964
+				);
2965
+				$template_args['show_notification_toggle'] = true;
2966
+				break;
2967
+		}
2968
+		// we come back to the process_registration_step route.
2969
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2970
+		return EEH_Template::display_template(
2971
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2972
+			$template_args,
2973
+			true
2974
+		);
2975
+	}
2976
+
2977
+
2978
+	/**
2979
+	 * set_reg_event
2980
+	 *
2981
+	 * @return bool
2982
+	 * @throws EE_Error
2983
+	 * @throws InvalidArgumentException
2984
+	 * @throws InvalidDataTypeException
2985
+	 * @throws InvalidInterfaceException
2986
+	 * @throws ReflectionException
2987
+	 */
2988
+	private function _set_reg_event()
2989
+	{
2990
+		if (is_object($this->_reg_event)) {
2991
+			return true;
2992
+		}
2993
+
2994
+		$EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
2995
+		if (! $EVT_ID) {
2996
+			return false;
2997
+		}
2998
+		$this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2999
+		return true;
3000
+	}
3001
+
3002
+
3003
+	/**
3004
+	 * process_reg_step
3005
+	 *
3006
+	 * @return void
3007
+	 * @throws DomainException
3008
+	 * @throws EE_Error
3009
+	 * @throws InvalidArgumentException
3010
+	 * @throws InvalidDataTypeException
3011
+	 * @throws InvalidInterfaceException
3012
+	 * @throws ReflectionException
3013
+	 * @throws RuntimeException
3014
+	 */
3015
+	public function process_reg_step()
3016
+	{
3017
+		EE_System::do_not_cache();
3018
+		$this->_set_reg_event();
3019
+		/** @var CurrentPage $current_page */
3020
+		$current_page = $this->loader->getShared(CurrentPage::class);
3021
+		$current_page->setEspressoPage(true);
3022
+		$this->request->setRequestParam('uts', time());
3023
+		// what step are we on?
3024
+		$cart = $this->getCart();
3025
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3026
+		// if doing ajax then we need to verify the nonce
3027
+		if ($this->request->isAjax()) {
3028
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
3029
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3030
+		}
3031
+		switch ($step) {
3032
+			case 'ticket':
3033
+				// process ticket selection
3034
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3035
+				if ($success) {
3036
+					EE_Error::add_success(
3037
+						esc_html__(
3038
+							'Tickets Selected. Now complete the registration.',
3039
+							'event_espresso'
3040
+						)
3041
+					);
3042
+				} else {
3043
+					$this->request->setRequestParam('step_error', true);
3044
+					$query_args['step_error'] = $this->request->getRequestParam('step_error', true, 'bool');
3045
+				}
3046
+				if ($this->request->isAjax()) {
3047
+					$this->new_registration(); // display next step
3048
+				} else {
3049
+					$query_args = [
3050
+						'action'                  => 'new_registration',
3051
+						'processing_registration' => 1,
3052
+						'event_id'                => $this->_reg_event->ID(),
3053
+						'uts'                     => time(),
3054
+					];
3055
+					$this->_redirect_after_action(
3056
+						false,
3057
+						'',
3058
+						'',
3059
+						$query_args,
3060
+						true
3061
+					);
3062
+				}
3063
+				break;
3064
+			case 'questions':
3065
+				if (! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3066
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3067
+				}
3068
+				// process registration
3069
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3070
+				if ($cart instanceof EE_Cart) {
3071
+					$grand_total = $cart->get_grand_total();
3072
+					if ($grand_total instanceof EE_Line_Item) {
3073
+						$grand_total->save_this_and_descendants_to_txn();
3074
+					}
3075
+				}
3076
+				if (! $transaction instanceof EE_Transaction) {
3077
+					$query_args = [
3078
+						'action'                  => 'new_registration',
3079
+						'processing_registration' => 2,
3080
+						'event_id'                => $this->_reg_event->ID(),
3081
+						'uts'                     => time(),
3082
+					];
3083
+					if ($this->request->isAjax()) {
3084
+						// display registration form again because there are errors (maybe validation?)
3085
+						$this->new_registration();
3086
+						return;
3087
+					}
3088
+					$this->_redirect_after_action(
3089
+						false,
3090
+						'',
3091
+						'',
3092
+						$query_args,
3093
+						true
3094
+					);
3095
+					return;
3096
+				}
3097
+				// maybe update status, and make sure to save transaction if not done already
3098
+				if (! $transaction->update_status_based_on_total_paid()) {
3099
+					$transaction->save();
3100
+				}
3101
+				$this->clearSession(__CLASS__, __FUNCTION__);
3102
+				$query_args = [
3103
+					'action'        => 'redirect_to_txn',
3104
+					'TXN_ID'        => $transaction->ID(),
3105
+					'EVT_ID'        => $this->_reg_event->ID(),
3106
+					'event_name'    => urlencode($this->_reg_event->name()),
3107
+					'redirect_from' => 'new_registration',
3108
+				];
3109
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3110
+				break;
3111
+		}
3112
+		// what are you looking here for?  Should be nothing to do at this point.
3113
+	}
3114
+
3115
+
3116
+	/**
3117
+	 * redirect_to_txn
3118
+	 *
3119
+	 * @return void
3120
+	 * @throws EE_Error
3121
+	 * @throws InvalidArgumentException
3122
+	 * @throws InvalidDataTypeException
3123
+	 * @throws InvalidInterfaceException
3124
+	 * @throws ReflectionException
3125
+	 */
3126
+	public function redirect_to_txn()
3127
+	{
3128
+		EE_System::do_not_cache();
3129
+		$this->clearSession(__CLASS__, __FUNCTION__);
3130
+		$query_args = [
3131
+			'action' => 'view_transaction',
3132
+			'TXN_ID' => $this->request->getRequestParam('TXN_ID', 0, 'int'),
3133
+			'page'   => 'espresso_transactions',
3134
+		];
3135
+		if ($this->request->requestParamIsSet('EVT_ID') && $this->request->requestParamIsSet('redirect_from')) {
3136
+			$query_args['EVT_ID']        = $this->request->getRequestParam('EVT_ID', 0, 'int');
3137
+			$query_args['event_name']    = urlencode($this->request->getRequestParam('event_name'));
3138
+			$query_args['redirect_from'] = $this->request->getRequestParam('redirect_from');
3139
+		}
3140
+		EE_Error::add_success(
3141
+			esc_html__(
3142
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3143
+				'event_espresso'
3144
+			)
3145
+		);
3146
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3147
+	}
3148
+
3149
+
3150
+	/**
3151
+	 * generates HTML for the Attendee Contact List
3152
+	 *
3153
+	 * @return void
3154
+	 * @throws DomainException
3155
+	 * @throws EE_Error
3156
+	 */
3157
+	protected function _attendee_contact_list_table()
3158
+	{
3159
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3160
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3161
+		$this->display_admin_list_table_page_with_no_sidebar();
3162
+	}
3163
+
3164
+
3165
+	/**
3166
+	 * get_attendees
3167
+	 *
3168
+	 * @param      $per_page
3169
+	 * @param bool $count whether to return count or data.
3170
+	 * @param bool $trash
3171
+	 * @return array|int
3172
+	 * @throws EE_Error
3173
+	 * @throws InvalidArgumentException
3174
+	 * @throws InvalidDataTypeException
3175
+	 * @throws InvalidInterfaceException
3176
+	 * @throws ReflectionException
3177
+	 */
3178
+	public function get_attendees($per_page, $count = false, $trash = false)
3179
+	{
3180
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3181
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3182
+		$orderby = $this->request->getRequestParam('orderby');
3183
+		switch ($orderby) {
3184
+			case 'ATT_ID':
3185
+			case 'ATT_fname':
3186
+			case 'ATT_email':
3187
+			case 'ATT_city':
3188
+			case 'STA_ID':
3189
+			case 'CNT_ID':
3190
+				break;
3191
+			case 'Registration_Count':
3192
+				$orderby = 'Registration_Count';
3193
+				break;
3194
+			default:
3195
+				$orderby = 'ATT_lname';
3196
+		}
3197
+		$sort         = $this->request->getRequestParam('order', 'ASC');
3198
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
3199
+		$per_page     = absint($per_page) ? $per_page : 10;
3200
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
3201
+		$_where       = [];
3202
+		$search_term  = $this->request->getRequestParam('s');
3203
+		if ($search_term) {
3204
+			$search_term  = '%' . $search_term . '%';
3205
+			$_where['OR'] = [
3206
+				'Registration.Event.EVT_name'       => ['LIKE', $search_term],
3207
+				'Registration.Event.EVT_desc'       => ['LIKE', $search_term],
3208
+				'Registration.Event.EVT_short_desc' => ['LIKE', $search_term],
3209
+				'ATT_fname'                         => ['LIKE', $search_term],
3210
+				'ATT_lname'                         => ['LIKE', $search_term],
3211
+				'ATT_short_bio'                     => ['LIKE', $search_term],
3212
+				'ATT_email'                         => ['LIKE', $search_term],
3213
+				'ATT_address'                       => ['LIKE', $search_term],
3214
+				'ATT_address2'                      => ['LIKE', $search_term],
3215
+				'ATT_city'                          => ['LIKE', $search_term],
3216
+				'Country.CNT_name'                  => ['LIKE', $search_term],
3217
+				'State.STA_name'                    => ['LIKE', $search_term],
3218
+				'ATT_phone'                         => ['LIKE', $search_term],
3219
+				'Registration.REG_final_price'      => ['LIKE', $search_term],
3220
+				'Registration.REG_code'             => ['LIKE', $search_term],
3221
+				'Registration.REG_group_size'       => ['LIKE', $search_term],
3222
+			];
3223
+		}
3224
+		$offset     = ($current_page - 1) * $per_page;
3225
+		$limit      = $count ? null : [$offset, $per_page];
3226
+		$query_args = [
3227
+			$_where,
3228
+			'extra_selects' => ['Registration_Count' => ['Registration.REG_ID', 'count', '%d']],
3229
+			'limit'         => $limit,
3230
+		];
3231
+		if (! $count) {
3232
+			$query_args['order_by'] = [$orderby => $sort];
3233
+		}
3234
+		$query_args[0]['status'] = $trash ? ['!=', 'publish'] : ['IN', ['publish']];
3235
+		return $count
3236
+			? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3237
+			: $this->getAttendeeModel()->get_all($query_args);
3238
+	}
3239
+
3240
+
3241
+	/**
3242
+	 * This is just taking care of resending the registration confirmation
3243
+	 *
3244
+	 * @return void
3245
+	 * @throws EE_Error
3246
+	 * @throws InvalidArgumentException
3247
+	 * @throws InvalidDataTypeException
3248
+	 * @throws InvalidInterfaceException
3249
+	 * @throws ReflectionException
3250
+	 */
3251
+	protected function _resend_registration()
3252
+	{
3253
+		$this->_process_resend_registration();
3254
+		$REG_ID      = $this->request->getRequestParam('_REG_ID', 0, 'int');
3255
+		$redirect_to = $this->request->getRequestParam('redirect_to');
3256
+		$query_args  = $redirect_to
3257
+			? ['action' => $redirect_to, '_REG_ID' => $REG_ID]
3258
+			: ['action' => 'default'];
3259
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3260
+	}
3261
+
3262
+
3263
+	/**
3264
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3265
+	 * to use when selecting registrations
3266
+	 *
3267
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3268
+	 *                                                     the query parameters from the request
3269
+	 * @return void ends the request with a redirect or download
3270
+	 */
3271
+	public function _registrations_report_base(string $method_name_for_getting_query_params)
3272
+	{
3273
+		$EVT_ID = $this->request->requestParamIsSet('EVT_ID')
3274
+			? $this->request->getRequestParam('EVT_ID', 0, DataType::INT)
3275
+			: null;
3276
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3277
+			$return_url    = $this->request->getRequestParam('return_url', '', DataType::URL);
3278
+			$filters       = $this->request->getRequestParam('filters', [], DataType::STRING, true);
3279
+			$report_params = $this->$method_name_for_getting_query_params($filters);
3280
+			$report_params = $this->convertDatetimeObjectsToStrings($report_params);
3281
+			$use_filters   = $this->request->getRequestParam('use_filters', false, DataType::BOOL);
3282
+			wp_redirect(
3283
+				EE_Admin_Page::add_query_args_and_nonce(
3284
+					[
3285
+						'page'        => EED_Batch::PAGE_SLUG,
3286
+						'batch'       => EED_Batch::batch_file_job,
3287
+						'EVT_ID'      => $EVT_ID,
3288
+						'filters'     => urlencode(serialize($report_params)),
3289
+						'use_filters' => urlencode($use_filters),
3290
+						'job_handler' => urlencode('EventEspresso\core\libraries\batch\JobHandlers\RegistrationsReport'),
3291
+						'return_url'  => urlencode($return_url),
3292
+					]
3293
+				)
3294
+			);
3295
+		} else {
3296
+			// Pull the current request params
3297
+			$request_args = $this->request->requestParams();
3298
+			$request_args = $this->convertDatetimeObjectsToStrings($request_args);
3299
+			// Set the required request_args to be passed to the export
3300
+			$required_request_args = [
3301
+				'export' => 'report',
3302
+				'action' => 'registrations_report_for_event',
3303
+				'EVT_ID' => $EVT_ID,
3304
+			];
3305
+			// Merge required request args, overriding any currently set
3306
+			$request_args = array_merge($request_args, $required_request_args);
3307
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3308
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3309
+				$EE_Export = EE_Export::instance($request_args);
3310
+				$EE_Export->export();
3311
+			}
3312
+		}
3313
+	}
3314
+
3315
+
3316
+	/**
3317
+	 * recursively convert Datetime objects in query params array to strings using MySQL format
3318
+	 *
3319
+	 * @param array $query_params
3320
+	 * @return array
3321
+	 * @since 5.0.19.p
3322
+	 */
3323
+	private function convertDatetimeObjectsToStrings(array $query_params): array
3324
+	{
3325
+		foreach ($query_params as $key => $value) {
3326
+			if (is_array($value)) {
3327
+				$query_params[$key] = $this->convertDatetimeObjectsToStrings($value);
3328
+			} elseif ($value instanceof DateTime) {
3329
+				$query_params[$key] = $value->format('Y-m-d H:i:s');
3330
+			}
3331
+		}
3332
+		return $query_params;
3333
+	}
3334
+
3335
+
3336
+	/**
3337
+	 * Creates a registration report using only query parameters in the request
3338
+	 *
3339
+	 * @return void
3340
+	 */
3341
+	public function _registrations_report()
3342
+	{
3343
+		$this->_registrations_report_base('_get_registration_query_parameters');
3344
+	}
3345
+
3346
+
3347
+	public function _contact_list_export()
3348
+	{
3349
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3350
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3351
+			$EE_Export = EE_Export::instance($this->request->requestParams());
3352
+			$EE_Export->export_attendees();
3353
+		}
3354
+	}
3355
+
3356
+
3357
+	public function _contact_list_report()
3358
+	{
3359
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3360
+			wp_redirect(
3361
+				EE_Admin_Page::add_query_args_and_nonce(
3362
+					[
3363
+						'page'        => EED_Batch::PAGE_SLUG,
3364
+						'batch'       => EED_Batch::batch_file_job,
3365
+						'job_handler' => urlencode('EventEspresso\core\libraries\batch\JobHandlers\AttendeesReport'),
3366
+						'return_url'  => urlencode($this->request->getRequestParam('return_url', '', DataType::URL)),
3367
+					]
3368
+				)
3369
+			);
3370
+		} else {
3371
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3372
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3373
+				$EE_Export = EE_Export::instance($this->request->requestParams());
3374
+				$EE_Export->report_attendees();
3375
+			}
3376
+		}
3377
+	}
3378
+
3379
+
3380
+
3381
+
3382
+
3383
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3384
+	/**
3385
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3386
+	 *
3387
+	 * @return void
3388
+	 * @throws EE_Error
3389
+	 * @throws InvalidArgumentException
3390
+	 * @throws InvalidDataTypeException
3391
+	 * @throws InvalidInterfaceException
3392
+	 * @throws ReflectionException
3393
+	 */
3394
+	protected function _duplicate_attendee()
3395
+	{
3396
+		$REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
3397
+		$action = $this->request->getRequestParam('return', 'default');
3398
+		// verify we have necessary info
3399
+		if (! $REG_ID) {
3400
+			EE_Error::add_error(
3401
+				esc_html__(
3402
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3403
+					'event_espresso'
3404
+				),
3405
+				__FILE__,
3406
+				__LINE__,
3407
+				__FUNCTION__
3408
+			);
3409
+			$query_args = ['action' => $action];
3410
+			$this->_redirect_after_action('', '', '', $query_args, true);
3411
+		}
3412
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3413
+		$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
3414
+		if (! $registration instanceof EE_Registration) {
3415
+			throw new RuntimeException(
3416
+				sprintf(
3417
+					esc_html__(
3418
+						'Unable to create the contact because a valid registration could not be retrieved for REG ID: %1$d',
3419
+						'event_espresso'
3420
+					),
3421
+					$REG_ID
3422
+				)
3423
+			);
3424
+		}
3425
+		$attendee = $registration->attendee();
3426
+		// remove relation of existing attendee on registration
3427
+		$registration->_remove_relation_to($attendee, 'Attendee');
3428
+		// new attendee
3429
+		$new_attendee = clone $attendee;
3430
+		$new_attendee->set('ATT_ID', 0);
3431
+		$new_attendee->save();
3432
+		// add new attendee to reg
3433
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3434
+		EE_Error::add_success(
3435
+			esc_html__(
3436
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3437
+				'event_espresso'
3438
+			)
3439
+		);
3440
+		// redirect to edit page for attendee
3441
+		$query_args = ['post' => $new_attendee->ID(), 'action' => 'edit_attendee'];
3442
+		$this->_redirect_after_action('', '', '', $query_args, true);
3443
+	}
3444
+
3445
+
3446
+	/**
3447
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3448
+	 *
3449
+	 * @param int     $post_id
3450
+	 * @param WP_Post $post
3451
+	 * @throws DomainException
3452
+	 * @throws EE_Error
3453
+	 * @throws InvalidArgumentException
3454
+	 * @throws InvalidDataTypeException
3455
+	 * @throws InvalidInterfaceException
3456
+	 * @throws LogicException
3457
+	 * @throws InvalidFormSubmissionException
3458
+	 * @throws ReflectionException
3459
+	 */
3460
+	protected function _insert_update_cpt_item($post_id, $post)
3461
+	{
3462
+		$success  = true;
3463
+		$attendee = $post instanceof WP_Post && $post->post_type === EspressoPostType::ATTENDEES
3464
+			? $this->getAttendeeModel()->get_one_by_ID($post_id)
3465
+			: null;
3466
+		// for attendee updates
3467
+		if ($attendee instanceof EE_Attendee) {
3468
+			// note we should only be UPDATING attendees at this point.
3469
+			$fname          = $this->request->getRequestParam('ATT_fname', '');
3470
+			$lname          = $this->request->getRequestParam('ATT_lname', '');
3471
+			$updated_fields = [
3472
+				'ATT_fname'     => $fname,
3473
+				'ATT_lname'     => $lname,
3474
+				'ATT_full_name' => "{$fname} {$lname}",
3475
+				'ATT_address'   => $this->request->getRequestParam('ATT_address', ''),
3476
+				'ATT_address2'  => $this->request->getRequestParam('ATT_address2', ''),
3477
+				'ATT_city'      => $this->request->getRequestParam('ATT_city', ''),
3478
+				'STA_ID'        => $this->request->getRequestParam('STA_ID', ''),
3479
+				'CNT_ISO'       => $this->request->getRequestParam('CNT_ISO', ''),
3480
+				'ATT_zip'       => $this->request->getRequestParam('ATT_zip', ''),
3481
+			];
3482
+			foreach ($updated_fields as $field => $value) {
3483
+				$attendee->set($field, $value);
3484
+			}
3485
+
3486
+			// process contact details metabox form handler (which will also save the attendee)
3487
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3488
+			$success              = $contact_details_form->process($this->request->requestParams());
3489
+
3490
+			$attendee_update_callbacks = apply_filters(
3491
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3492
+				[]
3493
+			);
3494
+			foreach ($attendee_update_callbacks as $a_callback) {
3495
+				if (false === call_user_func_array($a_callback, [$attendee, $this->request->requestParams()])) {
3496
+					throw new EE_Error(
3497
+						sprintf(
3498
+							esc_html__(
3499
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3500
+								'event_espresso'
3501
+							),
3502
+							$a_callback
3503
+						)
3504
+					);
3505
+				}
3506
+			}
3507
+		}
3508
+
3509
+		if ($success === false) {
3510
+			EE_Error::add_error(
3511
+				esc_html__(
3512
+					'Something went wrong with updating the meta table data for the registration.',
3513
+					'event_espresso'
3514
+				),
3515
+				__FILE__,
3516
+				__FUNCTION__,
3517
+				__LINE__
3518
+			);
3519
+		}
3520
+	}
3521
+
3522
+
3523
+	public function trash_cpt_item($post_id)
3524
+	{
3525
+	}
3526
+
3527
+
3528
+	public function delete_cpt_item($post_id)
3529
+	{
3530
+	}
3531
+
3532
+
3533
+	public function restore_cpt_item($post_id)
3534
+	{
3535
+	}
3536
+
3537
+
3538
+	protected function _restore_cpt_item($post_id, $revision_id)
3539
+	{
3540
+	}
3541
+
3542
+
3543
+	/**
3544
+	 * @throws EE_Error
3545
+	 * @throws ReflectionException
3546
+	 * @since 4.10.2.p
3547
+	 */
3548
+	public function attendee_editor_metaboxes()
3549
+	{
3550
+		$this->verify_cpt_object();
3551
+		remove_meta_box(
3552
+			'postexcerpt',
3553
+			$this->_cpt_routes[ $this->_req_action ],
3554
+			'normal'
3555
+		);
3556
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal');
3557
+		if (post_type_supports(EspressoPostType::ATTENDEES, 'excerpt')) {
3558
+			$this->addMetaBox(
3559
+				'postexcerpt',
3560
+				esc_html__('Short Biography', 'event_espresso'),
3561
+				'post_excerpt_meta_box',
3562
+				$this->_cpt_routes[ $this->_req_action ]
3563
+			);
3564
+		}
3565
+		if (post_type_supports(EspressoPostType::ATTENDEES, 'comments')) {
3566
+			$this->addMetaBox(
3567
+				'commentsdiv',
3568
+				esc_html__('Notes on the Contact', 'event_espresso'),
3569
+				'post_comment_meta_box',
3570
+				$this->_cpt_routes[ $this->_req_action ],
3571
+				'normal',
3572
+				'core'
3573
+			);
3574
+		}
3575
+		$this->addMetaBox(
3576
+			'attendee_contact_info',
3577
+			esc_html__('Contact Info', 'event_espresso'),
3578
+			[$this, 'attendee_contact_info'],
3579
+			$this->_cpt_routes[ $this->_req_action ],
3580
+			'side',
3581
+			'core'
3582
+		);
3583
+		$this->addMetaBox(
3584
+			'attendee_details_address',
3585
+			esc_html__('Address Details', 'event_espresso'),
3586
+			[$this, 'attendee_address_details'],
3587
+			$this->_cpt_routes[ $this->_req_action ],
3588
+			'normal',
3589
+			'core'
3590
+		);
3591
+		$this->addMetaBox(
3592
+			'attendee_registrations',
3593
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3594
+			[$this, 'attendee_registrations_meta_box'],
3595
+			$this->_cpt_routes[ $this->_req_action ]
3596
+		);
3597
+	}
3598
+
3599
+
3600
+	/**
3601
+	 * Metabox for attendee contact info
3602
+	 *
3603
+	 * @param WP_Post $post wp post object
3604
+	 * @return void attendee contact info ( and form )
3605
+	 * @throws EE_Error
3606
+	 * @throws InvalidArgumentException
3607
+	 * @throws InvalidDataTypeException
3608
+	 * @throws InvalidInterfaceException
3609
+	 * @throws LogicException
3610
+	 * @throws DomainException
3611
+	 */
3612
+	public function attendee_contact_info($post)
3613
+	{
3614
+		// get attendee object ( should already have it )
3615
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3616
+		$form->enqueueStylesAndScripts();
3617
+		echo wp_kses($form->display(), AllowedTags::getWithFormTags());
3618
+	}
3619
+
3620
+
3621
+	/**
3622
+	 * Return form handler for the contact details metabox
3623
+	 *
3624
+	 * @param EE_Attendee $attendee
3625
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3626
+	 * @throws DomainException
3627
+	 * @throws InvalidArgumentException
3628
+	 * @throws InvalidDataTypeException
3629
+	 * @throws InvalidInterfaceException
3630
+	 */
3631
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3632
+	{
3633
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3634
+	}
3635
+
3636
+
3637
+	/**
3638
+	 * Metabox for attendee details
3639
+	 *
3640
+	 * @param WP_Post $post wp post object
3641
+	 * @throws EE_Error
3642
+	 * @throws ReflectionException
3643
+	 */
3644
+	public function attendee_address_details($post)
3645
+	{
3646
+		// get attendee object (should already have it)
3647
+		$this->_template_args['attendee']     = $this->_cpt_model_obj;
3648
+		$this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3649
+			new EE_Question_Form_Input(
3650
+				EE_Question::new_instance(
3651
+					[
3652
+						'QST_ID'           => 0,
3653
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3654
+						'QST_system'       => 'admin-state',
3655
+					]
3656
+				),
3657
+				EE_Answer::new_instance(
3658
+					[
3659
+						'ANS_ID'    => 0,
3660
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3661
+					]
3662
+				),
3663
+				[
3664
+					'input_id'       => 'STA_ID',
3665
+					'input_name'     => 'STA_ID',
3666
+					'input_prefix'   => '',
3667
+					'append_qstn_id' => false,
3668
+				]
3669
+			)
3670
+		);
3671
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3672
+			new EE_Question_Form_Input(
3673
+				EE_Question::new_instance(
3674
+					[
3675
+						'QST_ID'           => 0,
3676
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3677
+						'QST_system'       => 'admin-country',
3678
+					]
3679
+				),
3680
+				EE_Answer::new_instance(
3681
+					[
3682
+						'ANS_ID'    => 0,
3683
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3684
+					]
3685
+				),
3686
+				[
3687
+					'input_id'       => 'CNT_ISO',
3688
+					'input_name'     => 'CNT_ISO',
3689
+					'input_prefix'   => '',
3690
+					'append_qstn_id' => false,
3691
+				]
3692
+			)
3693
+		);
3694
+		$template                             =
3695
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3696
+		EEH_Template::display_template($template, $this->_template_args);
3697
+	}
3698
+
3699
+
3700
+	/**
3701
+	 * _attendee_details
3702
+	 *
3703
+	 * @param $post
3704
+	 * @return void
3705
+	 * @throws DomainException
3706
+	 * @throws EE_Error
3707
+	 * @throws InvalidArgumentException
3708
+	 * @throws InvalidDataTypeException
3709
+	 * @throws InvalidInterfaceException
3710
+	 * @throws ReflectionException
3711
+	 */
3712
+	public function attendee_registrations_meta_box($post)
3713
+	{
3714
+		$this->_template_args['attendee']      = $this->_cpt_model_obj;
3715
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3716
+		$template                              =
3717
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3718
+		EEH_Template::display_template($template, $this->_template_args);
3719
+	}
3720
+
3721
+
3722
+	/**
3723
+	 * add in the form fields for the attendee edit
3724
+	 *
3725
+	 * @param WP_Post $post wp post object
3726
+	 * @return void echos html for new form.
3727
+	 * @throws DomainException
3728
+	 */
3729
+	public function after_title_form_fields($post)
3730
+	{
3731
+		if ($post->post_type === EspressoPostType::ATTENDEES) {
3732
+			$template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3733
+			$template_args['attendee'] = $this->_cpt_model_obj;
3734
+			EEH_Template::display_template($template, $template_args);
3735
+		}
3736
+	}
3737
+
3738
+
3739
+	/**
3740
+	 * _trash_or_restore_attendee
3741
+	 *
3742
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3743
+	 * @return void
3744
+	 * @throws EE_Error
3745
+	 * @throws InvalidArgumentException
3746
+	 * @throws InvalidDataTypeException
3747
+	 * @throws InvalidInterfaceException
3748
+	 * @throws ReflectionException
3749
+	 */
3750
+	protected function _trash_or_restore_attendees($trash = true)
3751
+	{
3752
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3753
+		$status = $trash ? 'trash' : 'publish';
3754
+		// Checkboxes
3755
+		if ($this->request->requestParamIsSet('ATT_IDs')) {
3756
+			$ATT_IDs = $this->request->getRequestParam('ATT_IDs', [], 'int', true);
3757
+			// if array has more than one element than success message should be plural
3758
+			$success = count($ATT_IDs) > 1 ? 2 : 1;
3759
+			// cycle thru checkboxes
3760
+			foreach ($ATT_IDs as $ATT_ID) {
3761
+				$updated = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID);
3762
+				if (! $updated) {
3763
+					$success = 0;
3764
+				}
3765
+			}
3766
+		} else {
3767
+			// grab single id and delete
3768
+			$ATT_ID = $this->request->getRequestParam('ATT_ID', 0, 'int');
3769
+			// update attendee
3770
+			$success = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID) ? 1 : 0;
3771
+		}
3772
+		$what        = $success > 1
3773
+			? esc_html__('Contacts', 'event_espresso')
3774
+			: esc_html__('Contact', 'event_espresso');
3775
+		$action_desc = $trash
3776
+			? esc_html__('moved to the trash', 'event_espresso')
3777
+			: esc_html__('restored', 'event_espresso');
3778
+		$this->_redirect_after_action($success, $what, $action_desc, ['action' => 'contact_list']);
3779
+	}
3780
+
3781
+
3782
+	/**
3783
+	 * @return void
3784
+	 * @throws EE_Error
3785
+	 * @throws ReflectionException
3786
+	 * @since  :VID:
3787
+	 */
3788
+	protected function deleteAttendees()
3789
+	{
3790
+		$success = 0;
3791
+		$att_ids = $this->getAttIdsFromRequest();
3792
+		foreach ($att_ids as $att_id) {
3793
+			$attendee = $this->getAttendeeModel()->get_one_by_ID($att_id);
3794
+			if ($attendee instanceof EE_Attendee) {
3795
+				$deleted = $attendee->delete_permanently();
3796
+				if($deleted) {
3797
+					$success++;
3798
+				}
3799
+			}
3800
+		}
3801
+		$what = $success > 1
3802
+			? esc_html__('Contacts', 'event_espresso')
3803
+			: esc_html__('Contact', 'event_espresso');
3804
+
3805
+		$this->_redirect_after_action(
3806
+			$success,
3807
+			$what,
3808
+			esc_html__('deleted', 'event_espresso'),
3809
+			[
3810
+				'action' => 'contact_list',
3811
+				'status' => 'trash',
3812
+			],
3813
+			$success == 0 ? true : false
3814
+		);
3815
+	}
3816
+
3817
+
3818
+	/**
3819
+	 * @return array
3820
+	 * @since  :VID:
3821
+	 */
3822
+	private function getAttIdsFromRequest(): array
3823
+	{
3824
+		if ($this->request->requestParamIsSet('ATT_IDs')) {
3825
+			return $this->request->getRequestParam('ATT_IDs', [], 'int', true);
3826
+		} else {
3827
+			return $this->request->getRequestParam('ATT_ID', [], 'int', true);
3828
+		}
3829
+	}
3830
+
3831
+
3832
+	/**
3833
+	 * @return EE_Session|null
3834
+	 * @since 5.0.20.p
3835
+	 */
3836
+	private function getSession(): ?EE_Session
3837
+	{
3838
+		return EE_Registry::instance()->SSN;
3839
+	}
3840
+
3841
+
3842
+	/**
3843
+	 * @param string $class
3844
+	 * @param string $function
3845
+	 * @return void
3846
+	 * @throws EE_Error
3847
+	 * @throws ReflectionException
3848
+	 * @since 5.0.20.p
3849
+	 */
3850
+	private function clearSession(string $class, string $function)
3851
+	{
3852
+		$session = $this->getSession();
3853
+		if ($session instanceof EE_Session) {
3854
+			$session->clear_session($class, $function);
3855
+		}
3856
+	}
3857
+
3858
+
3859
+	/**
3860
+	 * @return EE_Cart|null
3861
+	 * @since 5.0.20.p
3862
+	 */
3863
+	private function getCart(): ?EE_Cart
3864
+	{
3865
+		$session = $this->getSession();
3866
+		return $session instanceof EE_Session ? $session->cart() : null;
3867
+	}
3868 3868
 }
Please login to merge, or discard this patch.
admin_pages/messages/Messages_Admin_Page.core.php 2 patches
Indentation   +4105 added lines, -4105 removed lines patch added patch discarded remove patch
@@ -19,2521 +19,2521 @@  discard block
 block discarded – undo
19 19
  */
20 20
 class Messages_Admin_Page extends EE_Admin_Page
21 21
 {
22
-    private ?EEM_Message                   $MSG_MODEL                 = null;
22
+	private ?EEM_Message                   $MSG_MODEL                 = null;
23 23
 
24
-    private ?EEM_Message_Template          $MTP_MODEL                 = null;
24
+	private ?EEM_Message_Template          $MTP_MODEL                 = null;
25 25
 
26
-    private ?EEM_Message_Template_Group    $MTG_MODEL                 = null;
26
+	private ?EEM_Message_Template_Group    $MTG_MODEL                 = null;
27 27
 
28
-    protected ?EE_Message_Resource_Manager $_message_resource_manager = null;
28
+	protected ?EE_Message_Resource_Manager $_message_resource_manager = null;
29 29
 
30
-    protected ?EE_Message_Template_Group   $_message_template_group   = null;
30
+	protected ?EE_Message_Template_Group   $_message_template_group   = null;
31 31
 
32
-    protected ?EE_messenger                $_active_messenger         = null;
32
+	protected ?EE_messenger                $_active_messenger         = null;
33 33
 
34
-    protected ?MessageTemplateManager      $message_template_manager  = null;
34
+	protected ?MessageTemplateManager      $message_template_manager  = null;
35 35
 
36 36
 
37
-    /**
38
-     * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
39
-     * IF there is no group then it gets automatically set to the Default template pack.
40
-     *
41
-     * @since 4.5.0
42
-     */
43
-    protected ?EE_Messages_Template_Pack $_template_pack            = null;
37
+	/**
38
+	 * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
39
+	 * IF there is no group then it gets automatically set to the Default template pack.
40
+	 *
41
+	 * @since 4.5.0
42
+	 */
43
+	protected ?EE_Messages_Template_Pack $_template_pack            = null;
44 44
 
45
-    protected array                      $_active_messengers        = [];
46
-
47
-    protected array                      $_active_message_types     = [];
45
+	protected array                      $_active_messengers        = [];
46
+
47
+	protected array                      $_active_message_types     = [];
48 48
 
49
-    protected array                      $_shortcodes               = [];
50
-
51
-    protected array                      $_m_mt_settings            = [];
49
+	protected array                      $_shortcodes               = [];
50
+
51
+	protected array                      $_m_mt_settings            = [];
52 52
 
53
-    protected string                     $_active_message_type_name = '';
53
+	protected string                     $_active_message_type_name = '';
54 54
 
55
-    protected string                     $_active_messenger_name    = '';
56
-
57
-    protected string                     $_context_switcher         = '';
55
+	protected string                     $_active_messenger_name    = '';
56
+
57
+	protected string                     $_context_switcher         = '';
58 58
 
59 59
 
60
-    /**
61
-     * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
62
-     * group is.  If there is no group then it automatically gets set to default.
63
-     *
64
-     * @since 4.5.0
65
-     */
66
-    protected string $_variation = '';
67
-
68
-
69
-    /**
70
-     * @param bool $routing
71
-     * @throws EE_Error
72
-     * @throws ReflectionException
73
-     */
74
-    public function __construct($routing = true)
75
-    {
76
-        // make sure messages autoloader is running
77
-        EED_Messages::set_autoloaders();
78
-        parent::__construct($routing);
79
-    }
80
-
81
-
82
-    /**
83
-     * @return EEM_Message
84
-     * @throws EE_Error
85
-     * @throws ReflectionException
86
-     */
87
-    public function getMsgModel(): EEM_Message
88
-    {
89
-        if (! $this->MSG_MODEL instanceof EEM_Message) {
90
-            $this->MSG_MODEL = EEM_Message::instance();
91
-        }
92
-        return $this->MSG_MODEL;
93
-    }
94
-
95
-
96
-    /**
97
-     * @return EEM_Message_Template
98
-     * @throws EE_Error
99
-     * @throws ReflectionException
100
-     */
101
-    public function getMtpModel(): EEM_Message_Template
102
-    {
103
-        if (! $this->MTP_MODEL instanceof EEM_Message_Template) {
104
-            $this->MTP_MODEL = EEM_Message_Template::instance();
105
-        }
106
-        return $this->MTP_MODEL;
107
-    }
108
-
109
-
110
-    /**
111
-     * @return EEM_Message_Template_Group
112
-     * @throws EE_Error
113
-     * @throws ReflectionException
114
-     */
115
-    public function getMtgModel(): EEM_Message_Template_Group
116
-    {
117
-        if (! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
118
-            $this->MTG_MODEL = EEM_Message_Template_Group::instance();
119
-        }
120
-        return $this->MTG_MODEL;
121
-    }
122
-
123
-
124
-    public function getMessageTemplateManager(): MessageTemplateManager
125
-    {
126
-        if (! $this->message_template_manager instanceof MessageTemplateManager) {
127
-            $this->message_template_manager = $this->loader->getShared(MessageTemplateManager::class);
128
-        }
129
-        return $this->message_template_manager;
130
-    }
131
-
132
-
133
-    /**
134
-     * @throws EE_Error
135
-     * @throws ReflectionException
136
-     */
137
-    protected function _init_page_props()
138
-    {
139
-        $this->page_slug        = EE_MSG_PG_SLUG;
140
-        $this->page_label       = esc_html__('Messages Settings', 'event_espresso');
141
-        $this->_admin_base_url  = EE_MSG_ADMIN_URL;
142
-        $this->_admin_base_path = EE_MSG_ADMIN;
143
-
144
-        $messenger                       = $this->request->getRequestParam('messenger', '');
145
-        $message_type                    = $this->request->getRequestParam('message_type', '');
146
-        $this->_active_messenger_name    = $this->request->getRequestParam('MTP_messenger', $messenger);
147
-        $this->_active_message_type_name = $this->request->getRequestParam('MTP_message_type', $message_type);
148
-
149
-        $this->_load_message_resource_manager();
150
-    }
151
-
152
-
153
-    protected function _load_message_resource_manager()
154
-    {
155
-        if (! $this->_message_resource_manager instanceof EE_Message_Resource_Manager) {
156
-            $this->_message_resource_manager = $this->loader->getShared(EE_Message_Resource_Manager::class);
157
-        }
158
-    }
159
-
160
-
161
-    /**
162
-     * Generate select input with provided messenger options array.
163
-     *
164
-     * @param array $messenger_options Array of messengers indexed by slug and values are the messenger labels.
165
-     * @return string
166
-     * @throws EE_Error
167
-     */
168
-    public function get_messengers_select_input($messenger_options)
169
-    {
170
-        // if empty or just one value then just return an empty string
171
-        if (
172
-            empty($messenger_options)
173
-            || ! is_array($messenger_options)
174
-            || count($messenger_options) === 1
175
-        ) {
176
-            return '';
177
-        }
178
-        // merge in default
179
-        $messenger_options = array_merge(
180
-            ['none_selected' => esc_html__('Show All Messengers', 'event_espresso')],
181
-            $messenger_options
182
-        );
183
-        $input             = new EE_Select_Input(
184
-            $messenger_options,
185
-            [
186
-                'html_name'  => 'ee_messenger_filter_by',
187
-                'html_id'    => 'ee_messenger_filter_by',
188
-                'html_class' => 'wide',
189
-                'default'    => $this->request->getRequestParam('ee_messenger_filter_by', 'none_selected', 'title'),
190
-            ]
191
-        );
192
-
193
-        return $input->get_html_for_input();
194
-    }
195
-
196
-
197
-    /**
198
-     * Generate select input with provided message type options array.
199
-     *
200
-     * @param array $message_type_options Array of message types indexed by message type slug, and values are the
201
-     *                                    message type labels
202
-     * @return string
203
-     * @throws EE_Error
204
-     */
205
-    public function get_message_types_select_input($message_type_options)
206
-    {
207
-        // if empty or count of options is 1 then just return an empty string
208
-        if (
209
-            empty($message_type_options)
210
-            || ! is_array($message_type_options)
211
-            || count($message_type_options) === 1
212
-        ) {
213
-            return '';
214
-        }
215
-        // merge in default
216
-        $message_type_options = array_merge(
217
-            ['none_selected' => esc_html__('Show All Message Types', 'event_espresso')],
218
-            $message_type_options
219
-        );
220
-        $input                = new EE_Select_Input(
221
-            $message_type_options,
222
-            [
223
-                'html_name'  => 'ee_message_type_filter_by',
224
-                'html_id'    => 'ee_message_type_filter_by',
225
-                'html_class' => 'wide',
226
-                'default'    => $this->request->getRequestParam('ee_message_type_filter_by', 'none_selected', 'title'),
227
-            ]
228
-        );
229
-
230
-        return $input->get_html_for_input();
231
-    }
232
-
233
-
234
-    /**
235
-     * Generate select input with provide message type contexts array.
236
-     *
237
-     * @param array $context_options Array of message type contexts indexed by context slug, and values are the
238
-     *                               context label.
239
-     * @return string
240
-     * @throws EE_Error
241
-     */
242
-    public function get_contexts_for_message_types_select_input($context_options)
243
-    {
244
-        // if empty or count of options is one then just return empty string
245
-        if (
246
-            empty($context_options)
247
-            || ! is_array($context_options)
248
-            || count($context_options) === 1
249
-        ) {
250
-            return '';
251
-        }
252
-        // merge in default
253
-        $context_options = array_merge(
254
-            ['none_selected' => esc_html__('Show all Contexts', 'event_espresso')],
255
-            $context_options
256
-        );
257
-        $input           = new EE_Select_Input(
258
-            $context_options,
259
-            [
260
-                'html_name'  => 'ee_context_filter_by',
261
-                'html_id'    => 'ee_context_filter_by',
262
-                'html_class' => 'wide',
263
-                'default'    => $this->request->getRequestParam('ee_context_filter_by', 'none_selected', 'title'),
264
-            ]
265
-        );
266
-
267
-        return $input->get_html_for_input();
268
-    }
269
-
270
-
271
-    protected function _ajax_hooks()
272
-    {
273
-        if (! $this->capabilities->current_user_can('ee_edit_messages', 'edit-message-settings')) {
274
-            return;
275
-        }
276
-        add_action('wp_ajax_activate_messenger', [$this, 'activate_messenger_toggle']);
277
-        add_action('wp_ajax_activate_mt', [$this, 'activate_mt_toggle']);
278
-        add_action('wp_ajax_ee_msgs_save_settings', [$this, 'save_settings']);
279
-        add_action('wp_ajax_ee_msgs_update_mt_form', [$this, 'update_mt_form']);
280
-        add_action('wp_ajax_switch_template_pack', [$this, 'switch_template_pack']);
281
-        add_action('wp_ajax_toggle_context_template', [$this, 'toggle_context_template']);
282
-    }
283
-
284
-
285
-    protected function _define_page_props()
286
-    {
287
-        $this->_admin_page_title = $this->page_label;
288
-        $this->_labels           = [
289
-            'buttons'    => [
290
-                'add'    => esc_html__('Add New Message Template', 'event_espresso'),
291
-                'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
292
-                'delete' => esc_html__('Delete Message Template', 'event_espresso'),
293
-            ],
294
-            'publishbox' => esc_html__('Update Actions', 'event_espresso'),
295
-        ];
296
-    }
297
-
298
-
299
-    /**
300
-     *        an array for storing key => value pairs of request actions and their corresponding methods
301
-     *
302
-     * @access protected
303
-     * @return void
304
-     */
305
-    protected function _set_page_routes()
306
-    {
307
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
308
-        $GRP_ID = $this->request->getRequestParam('id', $GRP_ID, DataType::INTEGER);
309
-        $MSG_ID = $this->request->getRequestParam('MSG_ID', 0, DataType::INTEGER);
310
-
311
-        $this->_page_routes = [
312
-            'default'                          => [
313
-                'func'       => [$this, '_message_queue_list_table'],
314
-                'capability' => 'ee_read_global_messages',
315
-            ],
316
-            'global_mtps'                      => [
317
-                'func'       => [$this, '_ee_default_messages_overview_list_table'],
318
-                'capability' => 'ee_read_global_messages',
319
-            ],
320
-            'custom_mtps'                      => [
321
-                'func'       => [$this, '_custom_mtps_preview'],
322
-                'capability' => 'ee_read_messages',
323
-            ],
324
-            'add_new_message_template'         => [
325
-                'func'       => [$this, 'insertMessageTemplate'],
326
-                'capability' => 'ee_edit_messages',
327
-                'noheader'   => true,
328
-            ],
329
-            'edit_message_template'            => [
330
-                'func'       => [$this, '_edit_message_template'],
331
-                'capability' => 'ee_edit_message',
332
-                'obj_id'     => $GRP_ID,
333
-            ],
334
-            'preview_message'                  => [
335
-                'func'               => [$this, '_preview_message'],
336
-                'capability'         => 'ee_read_message',
337
-                'obj_id'             => $GRP_ID,
338
-                'noheader'           => true,
339
-                'headers_sent_route' => 'display_preview_message',
340
-            ],
341
-            'display_preview_message'          => [
342
-                'func'       => [$this, '_display_preview_message'],
343
-                'capability' => 'ee_read_message',
344
-                'obj_id'     => $GRP_ID,
345
-            ],
346
-            'insert_message_template'          => [
347
-                'func'       => [$this, 'insertMessageTemplate'],
348
-                'capability' => 'ee_edit_messages',
349
-                'noheader'   => true,
350
-            ],
351
-            'update_message_template'          => [
352
-                'func'       => [$this, 'updateMessageTemplate'],
353
-                'capability' => 'ee_edit_message',
354
-                'obj_id'     => $GRP_ID,
355
-                'noheader'   => true,
356
-            ],
357
-            'trash_message_template'           => [
358
-                'func'       => [$this, '_trash_or_restore_message_template'],
359
-                'capability' => 'ee_delete_message',
360
-                'obj_id'     => $GRP_ID,
361
-                'args'       => ['trash' => true, 'all' => true],
362
-                'noheader'   => true,
363
-            ],
364
-            'trash_message_template_context'   => [
365
-                'func'       => [$this, '_trash_or_restore_message_template'],
366
-                'capability' => 'ee_delete_message',
367
-                'obj_id'     => $GRP_ID,
368
-                'args'       => ['trash' => true],
369
-                'noheader'   => true,
370
-            ],
371
-            'restore_message_template'         => [
372
-                'func'       => [$this, '_trash_or_restore_message_template'],
373
-                'capability' => 'ee_delete_message',
374
-                'obj_id'     => $GRP_ID,
375
-                'args'       => ['trash' => false, 'all' => true],
376
-                'noheader'   => true,
377
-            ],
378
-            'restore_message_template_context' => [
379
-                'func'       => [$this, '_trash_or_restore_message_template'],
380
-                'capability' => 'ee_delete_message',
381
-                'obj_id'     => $GRP_ID,
382
-                'args'       => ['trash' => false],
383
-                'noheader'   => true,
384
-            ],
385
-            'delete_message_template'          => [
386
-                'func'       => [$this, '_delete_message_template'],
387
-                'capability' => 'ee_delete_message',
388
-                'obj_id'     => $GRP_ID,
389
-                'noheader'   => true,
390
-            ],
391
-            'reset_to_default'                 => [
392
-                'func'       => [$this, '_reset_to_default_template'],
393
-                'capability' => 'ee_edit_message',
394
-                'obj_id'     => $GRP_ID,
395
-                'noheader'   => true,
396
-            ],
397
-            'settings'                         => [
398
-                'func'       => [$this, '_settings'],
399
-                'capability' => 'manage_options',
400
-            ],
401
-            'update_global_settings'           => [
402
-                'func'       => [$this, '_update_global_settings'],
403
-                'capability' => 'manage_options',
404
-                'noheader'   => true,
405
-            ],
406
-            'generate_now'                     => [
407
-                'func'       => [$this, '_generate_now'],
408
-                'capability' => 'ee_send_message',
409
-                'noheader'   => true,
410
-            ],
411
-            'generate_and_send_now'            => [
412
-                'func'       => [$this, '_generate_and_send_now'],
413
-                'capability' => 'ee_send_message',
414
-                'noheader'   => true,
415
-            ],
416
-            'queue_for_resending'              => [
417
-                'func'       => [$this, '_queue_for_resending'],
418
-                'capability' => 'ee_send_message',
419
-                'noheader'   => true,
420
-            ],
421
-            'send_now'                         => [
422
-                'func'       => [$this, '_send_now'],
423
-                'capability' => 'ee_send_message',
424
-                'noheader'   => true,
425
-            ],
426
-            'delete_ee_message'                => [
427
-                'func'       => [$this, '_delete_ee_messages'],
428
-                'capability' => 'ee_delete_messages',
429
-                'noheader'   => true,
430
-            ],
431
-            'delete_ee_messages'               => [
432
-                'func'       => [$this, '_delete_ee_messages'],
433
-                'capability' => 'ee_delete_messages',
434
-                'noheader'   => true,
435
-                'obj_id'     => $MSG_ID,
436
-            ],
437
-        ];
438
-    }
439
-
440
-
441
-    protected function _set_page_config()
442
-    {
443
-        $this->_page_config = [
444
-            'default'                  => [
445
-                'nav'           => [
446
-                    'label' => esc_html__('Message Activity', 'event_espresso'),
447
-                    'icon'  => 'dashicons-email',
448
-                    'order' => 10,
449
-                ],
450
-                'list_table'    => 'EE_Message_List_Table',
451
-                // 'qtips' => array( 'EE_Message_List_Table_Tips' ),
452
-                'require_nonce' => false,
453
-            ],
454
-            'global_mtps'              => [
455
-                'nav'           => [
456
-                    'label' => esc_html__('Default Message Templates', 'event_espresso'),
457
-                    'icon'  => 'dashicons-layout',
458
-                    'order' => 20,
459
-                ],
460
-                'list_table'    => 'Messages_Template_List_Table',
461
-                'help_tabs'     => [
462
-                    'messages_overview_help_tab'                                => [
463
-                        'title'    => esc_html__('Messages Overview', 'event_espresso'),
464
-                        'filename' => 'messages_overview',
465
-                    ],
466
-                    'messages_overview_messages_table_column_headings_help_tab' => [
467
-                        'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
468
-                        'filename' => 'messages_overview_table_column_headings',
469
-                    ],
470
-                    'messages_overview_messages_filters_help_tab'               => [
471
-                        'title'    => esc_html__('Message Filters', 'event_espresso'),
472
-                        'filename' => 'messages_overview_filters',
473
-                    ],
474
-                    'messages_overview_messages_views_help_tab'                 => [
475
-                        'title'    => esc_html__('Message Views', 'event_espresso'),
476
-                        'filename' => 'messages_overview_views',
477
-                    ],
478
-                    'message_overview_message_types_help_tab'                   => [
479
-                        'title'    => esc_html__('Message Types', 'event_espresso'),
480
-                        'filename' => 'messages_overview_types',
481
-                    ],
482
-                    'messages_overview_messengers_help_tab'                     => [
483
-                        'title'    => esc_html__('Messengers', 'event_espresso'),
484
-                        'filename' => 'messages_overview_messengers',
485
-                    ],
486
-                ],
487
-                'require_nonce' => false,
488
-            ],
489
-            'custom_mtps'              => [
490
-                'nav'           => [
491
-                    'label' => esc_html__('Custom Message Templates', 'event_espresso'),
492
-                    'icon'  => 'dashicons-admin-customizer',
493
-                    'order' => 30,
494
-                ],
495
-                'help_tabs'     => [],
496
-                'require_nonce' => false,
497
-            ],
498
-            'add_new_message_template' => [
499
-                'nav'           => [
500
-                    'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
501
-                    'icon'       => 'dashicons-plus-alt',
502
-                    'order'      => 5,
503
-                    'persistent' => false,
504
-                ],
505
-                'require_nonce' => false,
506
-            ],
507
-            'edit_message_template'    => [
508
-                'labels'        => [
509
-                    'buttons'    => [
510
-                        'reset' => esc_html__('Reset Templates', 'event_espresso'),
511
-                    ],
512
-                    'publishbox' => esc_html__('Update Actions', 'event_espresso'),
513
-                ],
514
-                'nav'           => [
515
-                    'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
516
-                    'icon'       => 'dashicons-edit-large',
517
-                    'order'      => 5,
518
-                    'persistent' => false,
519
-                    'url'        => '',
520
-                ],
521
-                'metaboxes'     => ['_publish_post_box', '_register_edit_meta_boxes'],
522
-                'has_metaboxes' => true,
523
-                'help_tabs'     => [
524
-                    'edit_message_template'            => [
525
-                        'title'    => esc_html__('Message Template Editor', 'event_espresso'),
526
-                        'callback' => 'edit_message_template_help_tab',
527
-                    ],
528
-                    'message_templates_help_tab'       => [
529
-                        'title'    => esc_html__('Message Templates', 'event_espresso'),
530
-                        'filename' => 'messages_templates',
531
-                    ],
532
-                    'message_template_shortcodes'      => [
533
-                        'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
534
-                        'callback' => 'message_template_shortcodes_help_tab',
535
-                    ],
536
-                    'message_preview_help_tab'         => [
537
-                        'title'    => esc_html__('Message Preview', 'event_espresso'),
538
-                        'filename' => 'messages_preview',
539
-                    ],
540
-                    'messages_overview_other_help_tab' => [
541
-                        'title'    => esc_html__('Messages Other', 'event_espresso'),
542
-                        'filename' => 'messages_overview_other',
543
-                    ],
544
-                ],
545
-                'require_nonce' => false,
546
-            ],
547
-            'display_preview_message'  => [
548
-                'nav'           => [
549
-                    'label'      => esc_html__('Message Preview', 'event_espresso'),
550
-                    'icon'       => 'dashicons-visibility-bar',
551
-                    'order'      => 5,
552
-                    'url'        => '',
553
-                    'persistent' => false,
554
-                ],
555
-                'help_tabs'     => [
556
-                    'preview_message' => [
557
-                        'title'    => esc_html__('About Previews', 'event_espresso'),
558
-                        'callback' => 'preview_message_help_tab',
559
-                    ],
560
-                ],
561
-                'require_nonce' => false,
562
-            ],
563
-            'settings'                 => [
564
-                'nav'           => [
565
-                    'label' => esc_html__('Settings', 'event_espresso'),
566
-                    'icon'  => 'dashicons-admin-generic',
567
-                    'order' => 40,
568
-                ],
569
-                'metaboxes'     => ['_messages_settings_metaboxes'],
570
-                'help_tabs'     => [
571
-                    'messages_settings_help_tab'               => [
572
-                        'title'    => esc_html__('Messages Settings', 'event_espresso'),
573
-                        'filename' => 'messages_settings',
574
-                    ],
575
-                    'messages_settings_message_types_help_tab' => [
576
-                        'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
577
-                        'filename' => 'messages_settings_message_types',
578
-                    ],
579
-                    'messages_settings_messengers_help_tab'    => [
580
-                        'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
581
-                        'filename' => 'messages_settings_messengers',
582
-                    ],
583
-                ],
584
-                'require_nonce' => false,
585
-            ],
586
-        ];
587
-    }
588
-
589
-
590
-    protected function _add_screen_options()
591
-    {
592
-        // todo
593
-    }
594
-
595
-
596
-    protected function _add_screen_options_global_mtps()
597
-    {
598
-        /**
599
-         * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
600
-         * uses the $_admin_page_title property and we want different outputs in the different spots.
601
-         */
602
-        $page_title              = $this->_admin_page_title;
603
-        $this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
604
-        $this->_per_page_screen_option();
605
-        $this->_admin_page_title = $page_title;
606
-    }
607
-
608
-
609
-    protected function _add_screen_options_default()
610
-    {
611
-        $this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
612
-        $this->_per_page_screen_option();
613
-    }
614
-
615
-
616
-    // none of the below group are currently used for Messages
617
-    protected function _add_feature_pointers()
618
-    {
619
-    }
620
-
621
-
622
-    public function admin_init()
623
-    {
624
-    }
625
-
626
-
627
-    public function admin_notices()
628
-    {
629
-    }
630
-
631
-
632
-    public function admin_footer_scripts()
633
-    {
634
-    }
635
-
636
-
637
-    public function messages_help_tab()
638
-    {
639
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
640
-    }
641
-
642
-
643
-    public function messengers_help_tab()
644
-    {
645
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
646
-    }
647
-
648
-
649
-    public function message_types_help_tab()
650
-    {
651
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
652
-    }
653
-
654
-
655
-    public function messages_overview_help_tab()
656
-    {
657
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
658
-    }
659
-
660
-
661
-    public function message_templates_help_tab()
662
-    {
663
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
664
-    }
665
-
666
-
667
-    public function edit_message_template_help_tab()
668
-    {
669
-        $args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
670
-                        . esc_attr__('Editor Title', 'event_espresso')
671
-                        . '" />';
672
-        $args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
673
-                        . esc_attr__('Context Switcher and Preview', 'event_espresso')
674
-                        . '" />';
675
-        $args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
676
-                        . esc_attr__('Message Template Form Fields', 'event_espresso')
677
-                        . '" />';
678
-        $args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
679
-                        . esc_attr__('Shortcodes Metabox', 'event_espresso')
680
-                        . '" />';
681
-        $args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
682
-                        . esc_attr__('Publish Metabox', 'event_espresso')
683
-                        . '" />';
684
-        EEH_Template::display_template(
685
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
686
-            $args
687
-        );
688
-    }
689
-
690
-
691
-    /**
692
-     * @throws ReflectionException
693
-     * @throws EE_Error
694
-     */
695
-    public function message_template_shortcodes_help_tab()
696
-    {
697
-        $this->_set_shortcodes();
698
-        $args['shortcodes'] = $this->_shortcodes;
699
-        EEH_Template::display_template(
700
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
701
-            $args
702
-        );
703
-    }
704
-
705
-
706
-    public function preview_message_help_tab()
707
-    {
708
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
709
-    }
710
-
711
-
712
-    public function settings_help_tab()
713
-    {
714
-        $args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
715
-                        . '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
716
-        $args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
717
-                        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
718
-        $args['img3'] = '<div class="ee-switch">'
719
-                        . '<input class="ee-switch__input" id="ee-on-off-toggle-on" type="checkbox" checked>'
720
-                        . '<label class="ee-switch__toggle" for="ee-on-off-toggle-on"></label>'
721
-                        . '</div>';
722
-        $args['img4'] = '<div class="switch">'
723
-                        . '<input class="ee-switch__input" id="ee-on-off-toggle-off" type="checkbox">'
724
-                        . '<label class="ee-switch__toggle" for="ee-on-off-toggle-off"></label>'
725
-                        . '</div>';
726
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
727
-    }
728
-
729
-
730
-    public function load_scripts_styles()
731
-    {
732
-        wp_enqueue_style(
733
-            'espresso_ee_msg',
734
-            EE_MSG_ASSETS_URL . 'ee_message_admin.css',
735
-            [EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
736
-            EVENT_ESPRESSO_VERSION
737
-        );
738
-        wp_enqueue_style(
739
-            'ee_message_shortcodes',
740
-            EE_MSG_ASSETS_URL . 'ee_message_shortcodes.css',
741
-            [EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
742
-            EVENT_ESPRESSO_VERSION
743
-        );
744
-
745
-        wp_register_script(
746
-            'ee-messages-settings',
747
-            EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
748
-            ['jquery-ui-droppable', 'ee-serialize-full-array'],
749
-            EVENT_ESPRESSO_VERSION,
750
-            true
751
-        );
752
-        wp_register_script(
753
-            'ee-msg-list-table-js',
754
-            EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
755
-            ['ee-dialog'],
756
-            EVENT_ESPRESSO_VERSION
757
-        );
758
-    }
759
-
760
-
761
-    public function load_scripts_styles_default()
762
-    {
763
-        wp_enqueue_script('ee-msg-list-table-js');
764
-    }
765
-
766
-
767
-    public function wp_editor_css($mce_css)
768
-    {
769
-        // if we're on the edit_message_template route
770
-        if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
771
-            $message_type_name = $this->_active_message_type_name;
772
-
773
-            // we're going to REPLACE the existing mce css
774
-            // we need to get the css file location from the active messenger
775
-            $mce_css = $this->_active_messenger->get_variation(
776
-                $this->_template_pack,
777
-                $message_type_name,
778
-                true,
779
-                'wpeditor',
780
-                $this->_variation
781
-            );
782
-        }
783
-
784
-        return $mce_css;
785
-    }
786
-
787
-
788
-    /**
789
-     * @throws EE_Error
790
-     * @throws ReflectionException
791
-     */
792
-    public function load_scripts_styles_edit_message_template()
793
-    {
794
-        $this->_set_shortcodes();
795
-
796
-        EE_Registry::$i18n_js_strings['confirm_default_reset']        = sprintf(
797
-            esc_html__(
798
-                'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
799
-                'event_espresso'
800
-            ),
801
-            $this->_message_template_group->messenger_obj()->label['singular'],
802
-            $this->_message_template_group->message_type_obj()->label['singular']
803
-        );
804
-        EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
805
-            'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
806
-            'event_espresso'
807
-        );
808
-        EE_Registry::$i18n_js_strings['server_error']                 = esc_html__(
809
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
810
-            'event_espresso'
811
-        );
812
-
813
-        wp_register_script(
814
-            'ee_msgs_edit_js',
815
-            EE_MSG_ASSETS_URL . 'ee_message_editor.js',
816
-            ['jquery'],
817
-            EVENT_ESPRESSO_VERSION
818
-        );
819
-
820
-        wp_enqueue_script('ee_admin_js');
821
-        wp_enqueue_script('ee_msgs_edit_js');
822
-
823
-        // add in special css for tiny_mce
824
-        add_filter('mce_css', [$this, 'wp_editor_css']);
825
-    }
826
-
827
-
828
-    /**
829
-     * @throws EE_Error
830
-     * @throws ReflectionException
831
-     */
832
-    public function load_scripts_styles_display_preview_message()
833
-    {
834
-        $this->_set_message_template_group();
835
-        if ($this->_active_messenger_name) {
836
-            $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
837
-                $this->_active_messenger_name
838
-            );
839
-        }
840
-
841
-        wp_enqueue_style(
842
-            'espresso_preview_css',
843
-            $this->_active_messenger->get_variation(
844
-                $this->_template_pack,
845
-                $this->_active_message_type_name,
846
-                true,
847
-                'preview',
848
-                $this->_variation
849
-            )
850
-        );
851
-    }
852
-
853
-
854
-    public function load_scripts_styles_settings()
855
-    {
856
-        wp_register_style(
857
-            'ee-message-settings',
858
-            EE_MSG_ASSETS_URL . 'ee_message_settings.css',
859
-            [],
860
-            EVENT_ESPRESSO_VERSION
861
-        );
862
-        wp_enqueue_style('ee-text-links');
863
-        wp_enqueue_style('ee-message-settings');
864
-        wp_enqueue_script('ee-messages-settings');
865
-    }
866
-
867
-
868
-    /**
869
-     * set views array for List Table
870
-     */
871
-    public function _set_list_table_views_global_mtps()
872
-    {
873
-        $this->_views = [
874
-            'in_use' => [
875
-                'slug'  => 'in_use',
876
-                'label' => esc_html__('In Use', 'event_espresso'),
877
-                'count' => 0,
878
-            ],
879
-        ];
880
-    }
881
-
882
-
883
-    /**
884
-     * Set views array for the Custom Template List Table
885
-     */
886
-    public function _set_list_table_views_custom_mtps()
887
-    {
888
-        $this->_set_list_table_views_global_mtps();
889
-        $this->_views['in_use']['bulk_action'] = [
890
-            'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
891
-        ];
892
-    }
893
-
894
-
895
-    /**
896
-     * set views array for message queue list table
897
-     *
898
-     * @throws InvalidDataTypeException
899
-     * @throws InvalidInterfaceException
900
-     * @throws InvalidArgumentException
901
-     * @throws EE_Error
902
-     * @throws ReflectionException
903
-     */
904
-    public function _set_list_table_views_default()
905
-    {
906
-        EE_Registry::instance()->load_helper('Template');
907
-
908
-        $common_bulk_actions = $this->capabilities->current_user_can(
909
-            'ee_send_message',
910
-            'message_list_table_bulk_actions'
911
-        )
912
-            ? [
913
-                'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
914
-                'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
915
-                'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
916
-                'send_now'              => esc_html__('Send Now', 'event_espresso'),
917
-            ]
918
-            : [];
919
-
920
-        $delete_bulk_action = $this->capabilities->current_user_can(
921
-            'ee_delete_messages',
922
-            'message_list_table_bulk_actions'
923
-        )
924
-            ? ['delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso')]
925
-            : [];
926
-
927
-
928
-        $this->_views = [
929
-            'all' => [
930
-                'slug'        => 'all',
931
-                'label'       => esc_html__('All', 'event_espresso'),
932
-                'count'       => 0,
933
-                'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
934
-            ],
935
-        ];
936
-
937
-
938
-        foreach ($this->getMsgModel()->all_statuses() as $status) {
939
-            if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
940
-                continue;
941
-            }
942
-            $status_bulk_actions = $common_bulk_actions;
943
-            // unset bulk actions not applying to status
944
-            if (! empty($status_bulk_actions)) {
945
-                switch ($status) {
946
-                    case EEM_Message::status_idle:
947
-                    case EEM_Message::status_resend:
948
-                        $status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
949
-                        break;
950
-
951
-                    case EEM_Message::status_failed:
952
-                    case EEM_Message::status_debug_only:
953
-                    case EEM_Message::status_messenger_executing:
954
-                        $status_bulk_actions = [];
955
-                        break;
956
-
957
-                    case EEM_Message::status_incomplete:
958
-                        unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
959
-                        break;
960
-
961
-                    case EEM_Message::status_retry:
962
-                    case EEM_Message::status_sent:
963
-                        unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
964
-                        break;
965
-                }
966
-            }
967
-
968
-            // skip adding messenger executing status to views because it will be included with the Failed view.
969
-            if ($status === EEM_Message::status_messenger_executing) {
970
-                continue;
971
-            }
972
-
973
-            $this->_views[ strtolower($status) ] = [
974
-                'slug'        => strtolower($status),
975
-                'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
976
-                'count'       => 0,
977
-                'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
978
-            ];
979
-        }
980
-    }
981
-
982
-
983
-    /**
984
-     * @throws EE_Error
985
-     */
986
-    protected function _ee_default_messages_overview_list_table()
987
-    {
988
-        $this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
989
-        $this->display_admin_list_table_page_with_no_sidebar();
990
-    }
991
-
992
-
993
-    /**
994
-     * @throws EE_Error
995
-     * @throws ReflectionException
996
-     */
997
-    protected function _message_queue_list_table()
998
-    {
999
-        $this->_search_btn_label                   = esc_html__('Message Activity', 'event_espresso');
1000
-        $this->_template_args['per_column']        = 6;
1001
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_message_legend_items());
1002
-        $message_results                           = trim(EEM_Message::instance()->get_pretty_label_for_results());
1003
-        $this->_template_args['before_list_table'] = ! empty($message_results) ? "<h3>{$message_results}</h3>" : '';
1004
-        $this->display_admin_list_table_page_with_no_sidebar();
1005
-    }
1006
-
1007
-
1008
-    /**
1009
-     * @throws EE_Error
1010
-     */
1011
-    protected function _message_legend_items()
1012
-    {
1013
-        $action_css_classes = EEH_MSG_Template::get_message_action_icons();
1014
-        $action_items       = [];
1015
-
1016
-        foreach ($action_css_classes as $action_item => $action_details) {
1017
-            if ($action_item === 'see_notifications_for') {
1018
-                continue;
1019
-            }
1020
-            $action_items[ $action_item ] = [
1021
-                'class' => $action_details['css_class'],
1022
-                'desc'  => $action_details['label'],
1023
-            ];
1024
-        }
1025
-
1026
-        /** @var array $status_items status legend setup */
1027
-        $status_items = [
1028
-            'sent_status'                => [
1029
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_sent,
1030
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1031
-            ],
1032
-            'idle_status'                => [
1033
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_idle,
1034
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1035
-            ],
1036
-            'failed_status'              => [
1037
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_failed,
1038
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1039
-            ],
1040
-            'messenger_executing_status' => [
1041
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_messenger_executing,
1042
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1043
-            ],
1044
-            'resend_status'              => [
1045
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_resend,
1046
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1047
-            ],
1048
-            'incomplete_status'          => [
1049
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_incomplete,
1050
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1051
-            ],
1052
-            'retry_status'               => [
1053
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_retry,
1054
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1055
-            ],
1056
-        ];
1057
-        if (EEM_Message::debug()) {
1058
-            $status_items['debug_only_status'] = [
1059
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_debug_only,
1060
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1061
-            ];
1062
-        }
1063
-
1064
-        return array_merge($action_items, $status_items);
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * @throws EE_Error
1070
-     */
1071
-    protected function _custom_mtps_preview()
1072
-    {
1073
-        $this->_admin_page_title              = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1074
-        $this->_template_args['preview_img']  = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1075
-                                                . ' alt="' . esc_attr__(
1076
-                                                    'Preview Custom Message Templates screenshot',
1077
-                                                    'event_espresso'
1078
-                                                ) . '" />';
1079
-        $this->_template_args['preview_text'] = '<strong>'
1080
-                                                . esc_html__(
1081
-                                                    'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1082
-                                                    'event_espresso'
1083
-                                                )
1084
-                                                . '</strong>';
1085
-
1086
-        $this->display_admin_caf_preview_page('custom_message_types', false);
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * get_message_templates
1092
-     * This gets all the message templates for listing on the overview list.
1093
-     *
1094
-     * @param int    $per_page the amount of templates groups to show per page
1095
-     * @param string $type     the current _view we're getting templates for
1096
-     * @param bool   $count    return count?
1097
-     * @param bool   $all      disregard any paging info (get all data);
1098
-     * @param bool   $global   whether to return just global (true) or custom templates (false)
1099
-     * @return array|int
1100
-     * @throws EE_Error
1101
-     * @throws InvalidArgumentException
1102
-     * @throws InvalidDataTypeException
1103
-     * @throws InvalidInterfaceException
1104
-     * @throws ReflectionException
1105
-     */
1106
-    public function get_message_templates(
1107
-        int $per_page = 10,
1108
-        string $type = 'in_use',
1109
-        bool $count = false,
1110
-        bool $all = false,
1111
-        bool $global = true
1112
-    ) {
1113
-        $orderby = $this->request->getRequestParam('orderby', 'GRP_ID');
1114
-        // ensure that the orderby param is actually set within the request data
1115
-        $this->request->setRequestParam('orderby', $orderby);
1116
-        $order        = $this->request->getRequestParam('order', 'ASC');
1117
-        $current_page = $this->request->getRequestParam('paged', 1, DataType::INTEGER);
1118
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, DataType::INTEGER);
1119
-
1120
-        $offset = ($current_page - 1) * $per_page;
1121
-        $limit  = $all ? null : [$offset, $per_page];
1122
-
1123
-        // options will match what is in the _views array property
1124
-        return $type === 'in_use'
1125
-            ? $this->getMtgModel()->get_all_active_message_templates(
1126
-                $orderby,
1127
-                $order,
1128
-                $limit,
1129
-                $count,
1130
-                $global,
1131
-                true
1132
-            )
1133
-            : $this->getMtgModel()->get_all_trashed_grouped_message_templates(
1134
-                $orderby,
1135
-                $order,
1136
-                $limit,
1137
-                $count,
1138
-                $global
1139
-            );
1140
-    }
1141
-
1142
-
1143
-    /**
1144
-     * filters etc might need a list of installed message_types
1145
-     *
1146
-     * @return array an array of message type objects
1147
-     */
1148
-    public function get_installed_message_types(): array
1149
-    {
1150
-        $installed_message_types = $this->_message_resource_manager->installed_message_types();
1151
-        $installed               = [];
1152
-
1153
-        foreach ($installed_message_types as $message_type) {
1154
-            $installed[ $message_type->name ] = $message_type;
1155
-        }
1156
-
1157
-        return $installed;
1158
-    }
1159
-
1160
-
1161
-    /**
1162
-     * This is used when creating a custom template. All Custom Templates start based off another template.
1163
-     *
1164
-     * @param string     $message_type
1165
-     * @param string     $messenger
1166
-     * @param int|string $GRP_ID
1167
-     * @throws EE_error
1168
-     * @throws ReflectionException
1169
-     * @deprecated 5.0.8.p
1170
-     */
1171
-    public function add_message_template(string $message_type = '', string $messenger = '', $GRP_ID = '')
1172
-    {
1173
-        $this->insertMessageTemplate();
1174
-    }
1175
-
1176
-
1177
-    /**
1178
-     * @param string $message_type     message type slug
1179
-     * @param string $messenger        messenger slug
1180
-     * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1181
-     *                                 off of.
1182
-     * @throws EE_error
1183
-     * @throws ReflectionException
1184
-     * @deprecated 4.10.29.p
1185
-     */
1186
-    protected function _add_message_template($message_type, $messenger, $GRP_ID)
1187
-    {
1188
-        $this->insertMessageTemplate($message_type, $messenger, $GRP_ID);
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * _edit_message_template
1194
-     *
1195
-     * @access protected
1196
-     * @return void
1197
-     * @throws InvalidIdentifierException
1198
-     * @throws DomainException
1199
-     * @throws EE_Error
1200
-     * @throws InvalidArgumentException
1201
-     * @throws ReflectionException
1202
-     * @throws InvalidDataTypeException
1203
-     * @throws InvalidInterfaceException
1204
-     */
1205
-    protected function _edit_message_template()
1206
-    {
1207
-        $template_fields = '';
1208
-        $sidebar_fields  = '';
1209
-        // we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1210
-        // valid html in the templates.
1211
-        add_filter('tiny_mce_before_init', [$this, 'filter_tinymce_init'], 10, 2);
1212
-
1213
-        $GRP_ID = $this->request->getRequestParam('id', 0, DataType::INTEGER);
1214
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', $GRP_ID, DataType::INTEGER);
1215
-
1216
-        $EVT_ID = $this->request->getRequestParam('evt_id', 0, DataType::INTEGER);
1217
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', $EVT_ID, DataType::INTEGER);
1218
-
1219
-        $this->_set_shortcodes(); // this also sets the _message_template property.
1220
-        $message_template_group = $this->_message_template_group;
1221
-        $c_label                = $message_template_group->context_label();
1222
-        $c_config               = $message_template_group->contexts_config();
1223
-
1224
-        reset($c_config);
1225
-        $context = $this->request->getRequestParam('context', key($c_config));
1226
-        $context = strtolower($context);
1227
-
1228
-        $action = empty($GRP_ID) ? 'insert_message_template' : 'update_message_template';
1229
-
1230
-        $edit_message_template_form_url = add_query_arg(
1231
-            ['action' => $action, 'noheader' => true],
1232
-            EE_MSG_ADMIN_URL
1233
-        );
1234
-
1235
-        // set active messenger for this view
1236
-        $this->_active_messenger         = $this->_message_resource_manager->get_active_messenger(
1237
-            $message_template_group->messenger()
1238
-        );
1239
-        $this->_active_message_type_name = $message_template_group->message_type();
1240
-
1241
-
1242
-        // Do we have any validation errors?
1243
-        $validators = $this->_get_transient();
1244
-        $v_fields   = ! empty($validators) ? array_keys($validators) : [];
1245
-
1246
-
1247
-        // we need to assemble the title from Various details
1248
-        $context_label = sprintf(
1249
-            esc_html__('(%s %s)', 'event_espresso'),
1250
-            $c_config[ $context ]['label'],
1251
-            ucwords($c_label['label'])
1252
-        );
1253
-
1254
-        $title = sprintf(
1255
-            esc_html__(' %s %s Template %s', 'event_espresso'),
1256
-            ucwords($message_template_group->messenger_obj()->label['singular']),
1257
-            ucwords($message_template_group->message_type_obj()->label['singular']),
1258
-            $context_label
1259
-        );
1260
-
1261
-        $this->_template_args['GRP_ID']           = $GRP_ID;
1262
-        $this->_template_args['message_template'] = $message_template_group;
1263
-        $this->_template_args['is_extra_fields']  = false;
1264
-
1265
-
1266
-        // let's get EEH_MSG_Template so we can get template form fields
1267
-        $template_field_structure = EEH_MSG_Template::get_fields(
1268
-            $message_template_group->messenger(),
1269
-            $message_template_group->message_type()
1270
-        );
1271
-
1272
-        if (! $template_field_structure) {
1273
-            $template_field_structure = false;
1274
-            $template_fields          = esc_html__(
1275
-                'There was an error in assembling the fields for this display (you should see an error message)',
1276
-                'event_espresso'
1277
-            );
1278
-        }
1279
-
1280
-        $message_templates = $message_template_group->context_templates();
1281
-
1282
-        // if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1283
-        // will get handled in the "extra" array.
1284
-        if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1285
-            foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1286
-                unset($template_field_structure[ $context ][ $reference_field ]);
1287
-            }
1288
-        }
1289
-
1290
-        // let's loop through the template_field_structure and actually assemble the input fields!
1291
-        if (! empty($template_field_structure)) {
1292
-            foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1293
-                // if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1294
-                // the extra array and reset them.
1295
-                if ($template_field === 'extra') {
1296
-                    $this->_template_args['is_extra_fields'] = true;
1297
-                    foreach ($field_setup_array as $reference_field => $new_fields_array) {
1298
-                        $message_template = $message_templates[ $context ][ $reference_field ];
1299
-                        $content          = $message_template instanceof EE_Message_Template
1300
-                            ? $message_template->get('MTP_content')
1301
-                            : '';
1302
-                        foreach ($new_fields_array as $extra_field => $extra_array) {
1303
-                            // let's verify if we need this extra field via the shortcodes parameter.
1304
-                            $continue = false;
1305
-                            if (isset($extra_array['shortcodes_required'])) {
1306
-                                foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1307
-                                    if (! array_key_exists($shortcode, $this->_shortcodes)) {
1308
-                                        $continue = true;
1309
-                                    }
1310
-                                }
1311
-                                if ($continue) {
1312
-                                    continue;
1313
-                                }
1314
-                            }
1315
-
1316
-                            $field_id = $reference_field . '-' . $extra_field . '-content';
1317
-
1318
-                            $template_form_fields[ $field_id ]         = $extra_array;
1319
-                            $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1320
-                                                                         . $reference_field
1321
-                                                                         . '][content]['
1322
-                                                                         . $extra_field . ']';
1323
-                            $css_class                                 = $extra_array['css_class'] ?? '';
1324
-
1325
-                            $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1326
-                                                                              && in_array($extra_field, $v_fields, true)
1327
-                                                                              && (
1328
-                                                                                  is_array($validators[ $extra_field ])
1329
-                                                                                  && isset($validators[ $extra_field ]['msg'])
1330
-                                                                              )
1331
-                                ? 'validate-error ' . $css_class
1332
-                                : $css_class;
1333
-
1334
-                            $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1335
-                                                                          && isset($content[ $extra_field ])
1336
-                                ? $content[ $extra_field ]
1337
-                                : '';
1338
-
1339
-                            // do we have a validation error?  if we do then let's use that value instead
1340
-                            $template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1341
-                                ? $validators[ $extra_field ]['value']
1342
-                                : $template_form_fields[ $field_id ]['value'];
1343
-
1344
-
1345
-                            $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1346
-
1347
-                            // shortcode selector
1348
-                            $field_name_to_use                                   = $extra_field === 'main'
1349
-                                ? 'content'
1350
-                                : $extra_field;
1351
-                            $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1352
-                                $field_name_to_use,
1353
-                                $field_id
1354
-                            );
1355
-                        }
1356
-                        $template_field_MTP_id           = $reference_field . '-MTP_ID';
1357
-                        $template_field_template_name_id = $reference_field . '-name';
1358
-
1359
-                        $template_form_fields[ $template_field_MTP_id ] = [
1360
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1361
-                            'label'      => null,
1362
-                            'input'      => 'hidden',
1363
-                            'type'       => 'int',
1364
-                            'required'   => false,
1365
-                            'validation' => false,
1366
-                            'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1367
-                            'css_class'  => '',
1368
-                            'format'     => '%d',
1369
-                            'db-col'     => 'MTP_ID',
1370
-                        ];
1371
-
1372
-                        $template_form_fields[ $template_field_template_name_id ] = [
1373
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1374
-                            'label'      => null,
1375
-                            'input'      => 'hidden',
1376
-                            'type'       => 'string',
1377
-                            'required'   => false,
1378
-                            'validation' => true,
1379
-                            'value'      => $reference_field,
1380
-                            'css_class'  => '',
1381
-                            'format'     => '%s',
1382
-                            'db-col'     => 'MTP_template_field',
1383
-                        ];
1384
-                    }
1385
-                    continue; // skip the next stuff, we got the necessary fields here for this dataset.
1386
-                } else {
1387
-                    $field_id                                   = $template_field . '-content';
1388
-                    $template_form_fields[ $field_id ]          = $field_setup_array;
1389
-                    $template_form_fields[ $field_id ]['name']  =
1390
-                        'MTP_template_fields[' . $template_field . '][content]';
1391
-                    $message_template                           =
1392
-                        $message_templates[ $context ][ $template_field ] ?? null;
1393
-                    $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1394
-                                                                  && is_array($message_templates[ $context ])
1395
-                                                                  && $message_template instanceof EE_Message_Template
1396
-                        ? $message_template->get('MTP_content')
1397
-                        : '';
1398
-
1399
-                    // do we have a validator error for this field?  if we do then we'll use that value instead
1400
-                    $template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1401
-                        ? $validators[ $template_field ]['value']
1402
-                        : $template_form_fields[ $field_id ]['value'];
1403
-
1404
-
1405
-                    $template_form_fields[ $field_id ]['db-col']    = 'MTP_content';
1406
-                    $css_class                                      = $field_setup_array['css_class'] ?? '';
1407
-                    $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1408
-                                                                      && in_array($template_field, $v_fields, true)
1409
-                                                                      && isset($validators[ $template_field ]['msg'])
1410
-                        ? 'validate-error ' . $css_class
1411
-                        : $css_class;
1412
-
1413
-                    // shortcode selector
1414
-                    $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1415
-                        $template_field,
1416
-                        $field_id
1417
-                    );
1418
-                }
1419
-
1420
-                // k took care of content field(s) now let's take care of others.
1421
-
1422
-                $template_field_MTP_id                 = $template_field . '-MTP_ID';
1423
-                $template_field_field_template_name_id = $template_field . '-name';
1424
-
1425
-                // foreach template field there are actually two form fields created
1426
-                $template_form_fields[ $template_field_MTP_id ] = [
1427
-                    'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1428
-                    'label'      => null,
1429
-                    'input'      => 'hidden',
1430
-                    'type'       => 'int',
1431
-                    'required'   => false,
1432
-                    'validation' => true,
1433
-                    'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1434
-                    'css_class'  => '',
1435
-                    'format'     => '%d',
1436
-                    'db-col'     => 'MTP_ID',
1437
-                ];
1438
-
1439
-                $template_form_fields[ $template_field_field_template_name_id ] = [
1440
-                    'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1441
-                    'label'      => null,
1442
-                    'input'      => 'hidden',
1443
-                    'type'       => 'string',
1444
-                    'required'   => false,
1445
-                    'validation' => true,
1446
-                    'value'      => $template_field,
1447
-                    'css_class'  => '',
1448
-                    'format'     => '%s',
1449
-                    'db-col'     => 'MTP_template_field',
1450
-                ];
1451
-            }
1452
-
1453
-            // add other fields
1454
-            $template_form_fields['ee-msg-current-context'] = [
1455
-                'name'       => 'MTP_context',
1456
-                'label'      => null,
1457
-                'input'      => 'hidden',
1458
-                'type'       => 'string',
1459
-                'required'   => false,
1460
-                'validation' => true,
1461
-                'value'      => $context,
1462
-                'css_class'  => '',
1463
-                'format'     => '%s',
1464
-                'db-col'     => 'MTP_context',
1465
-            ];
1466
-
1467
-            $template_form_fields['ee-msg-grp-id'] = [
1468
-                'name'       => 'GRP_ID',
1469
-                'label'      => null,
1470
-                'input'      => 'hidden',
1471
-                'type'       => 'int',
1472
-                'required'   => false,
1473
-                'validation' => true,
1474
-                'value'      => $GRP_ID,
1475
-                'css_class'  => '',
1476
-                'format'     => '%d',
1477
-                'db-col'     => 'GRP_ID',
1478
-            ];
1479
-
1480
-            $template_form_fields['ee-msg-messenger'] = [
1481
-                'name'       => 'MTP_messenger',
1482
-                'label'      => null,
1483
-                'input'      => 'hidden',
1484
-                'type'       => 'string',
1485
-                'required'   => false,
1486
-                'validation' => true,
1487
-                'value'      => $message_template_group->messenger(),
1488
-                'css_class'  => '',
1489
-                'format'     => '%s',
1490
-                'db-col'     => 'MTP_messenger',
1491
-            ];
1492
-
1493
-            $template_form_fields['ee-msg-message-type'] = [
1494
-                'name'       => 'MTP_message_type',
1495
-                'label'      => null,
1496
-                'input'      => 'hidden',
1497
-                'type'       => 'string',
1498
-                'required'   => false,
1499
-                'validation' => true,
1500
-                'value'      => $message_template_group->message_type(),
1501
-                'css_class'  => '',
1502
-                'format'     => '%s',
1503
-                'db-col'     => 'MTP_message_type',
1504
-            ];
1505
-
1506
-            $sidebar_form_fields['ee-msg-is-global'] = [
1507
-                'name'       => 'MTP_is_global',
1508
-                'label'      => esc_html__('Global Template', 'event_espresso'),
1509
-                'input'      => 'hidden',
1510
-                'type'       => 'int',
1511
-                'required'   => false,
1512
-                'validation' => true,
1513
-                'value'      => $message_template_group->get('MTP_is_global'),
1514
-                'css_class'  => '',
1515
-                'format'     => '%d',
1516
-                'db-col'     => 'MTP_is_global',
1517
-            ];
1518
-
1519
-            $sidebar_form_fields['ee-msg-is-override'] = [
1520
-                'name'       => 'MTP_is_override',
1521
-                'label'      => esc_html__('Override all custom', 'event_espresso'),
1522
-                'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1523
-                'type'       => 'int',
1524
-                'required'   => false,
1525
-                'validation' => true,
1526
-                'value'      => $message_template_group->get('MTP_is_override'),
1527
-                'css_class'  => '',
1528
-                'format'     => '%d',
1529
-                'db-col'     => 'MTP_is_override',
1530
-            ];
1531
-
1532
-            $sidebar_form_fields['ee-msg-is-active'] = [
1533
-                'name'       => 'MTP_is_active',
1534
-                'label'      => esc_html__('Active Template', 'event_espresso'),
1535
-                'input'      => 'hidden',
1536
-                'type'       => 'int',
1537
-                'required'   => false,
1538
-                'validation' => true,
1539
-                'value'      => $message_template_group->is_active(),
1540
-                'css_class'  => '',
1541
-                'format'     => '%d',
1542
-                'db-col'     => 'MTP_is_active',
1543
-            ];
1544
-
1545
-            $sidebar_form_fields['ee-msg-deleted'] = [
1546
-                'name'       => 'MTP_deleted',
1547
-                'label'      => null,
1548
-                'input'      => 'hidden',
1549
-                'type'       => 'int',
1550
-                'required'   => false,
1551
-                'validation' => true,
1552
-                'value'      => $message_template_group->get('MTP_deleted'),
1553
-                'css_class'  => '',
1554
-                'format'     => '%d',
1555
-                'db-col'     => 'MTP_deleted',
1556
-            ];
1557
-            $sidebar_form_fields['ee-msg-author']  = [
1558
-                'name'       => 'MTP_user_id',
1559
-                'label'      => esc_html__('Author', 'event_espresso'),
1560
-                'input'      => 'hidden',
1561
-                'type'       => 'int',
1562
-                'required'   => false,
1563
-                'validation' => false,
1564
-                'value'      => $message_template_group->user(),
1565
-                'format'     => '%d',
1566
-                'db-col'     => 'MTP_user_id',
1567
-            ];
1568
-
1569
-            $sidebar_form_fields['ee-msg-route'] = [
1570
-                'name'  => 'action',
1571
-                'input' => 'hidden',
1572
-                'type'  => 'string',
1573
-                'value' => $action,
1574
-            ];
1575
-
1576
-            $sidebar_form_fields['ee-msg-id']        = [
1577
-                'name'  => 'id',
1578
-                'input' => 'hidden',
1579
-                'type'  => 'int',
1580
-                'value' => $GRP_ID,
1581
-            ];
1582
-            $sidebar_form_fields['ee-msg-evt-nonce'] = [
1583
-                'name'  => $action . '_nonce',
1584
-                'input' => 'hidden',
1585
-                'type'  => 'string',
1586
-                'value' => wp_create_nonce($action . '_nonce'),
1587
-            ];
1588
-
1589
-            $template_switch = $this->request->getRequestParam('template_switch');
1590
-            if ($template_switch) {
1591
-                $sidebar_form_fields['ee-msg-template-switch'] = [
1592
-                    'name'  => 'template_switch',
1593
-                    'input' => 'hidden',
1594
-                    'type'  => 'int',
1595
-                    'value' => 1,
1596
-                ];
1597
-            }
1598
-
1599
-
1600
-            $template_fields = $this->_generate_admin_form_fields($template_form_fields);
1601
-            $sidebar_fields  = $this->_generate_admin_form_fields($sidebar_form_fields);
1602
-        } //end if ( !empty($template_field_structure) )
1603
-
1604
-        // set extra content for publish box
1605
-        $this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1606
-        $this->_set_publish_post_box_vars(
1607
-            'id',
1608
-            $GRP_ID,
1609
-            '',
1610
-            add_query_arg(
1611
-                ['action' => $message_template_group->is_global() ? 'global_mtps' : 'custom_mtps'],
1612
-                $this->_admin_base_url
1613
-            ),
1614
-            true
1615
-        );
1616
-
1617
-        // add preview button
1618
-        $preview_url    = parent::add_query_args_and_nonce(
1619
-            [
1620
-                'message_type' => $message_template_group->message_type(),
1621
-                'messenger'    => $message_template_group->messenger(),
1622
-                'context'      => $context,
1623
-                'GRP_ID'       => $GRP_ID,
1624
-                'evt_id'       => $EVT_ID ?: false,
1625
-                'action'       => 'preview_message',
1626
-            ],
1627
-            $this->_admin_base_url
1628
-        );
1629
-        $preview_button = '<a href="' . $preview_url . '" class="button--secondary messages-preview-button">'
1630
-                          . esc_html__('Preview', 'event_espresso')
1631
-                          . '</a>';
1632
-
1633
-
1634
-        // setup context switcher
1635
-        $this->_set_context_switcher(
1636
-            $message_template_group,
1637
-            [
1638
-                'page'    => 'espresso_messages',
1639
-                'action'  => 'edit_message_template',
1640
-                'id'      => $GRP_ID,
1641
-                'evt_id'  => $EVT_ID,
1642
-                'context' => $context,
1643
-                'extra'   => $preview_button,
1644
-            ]
1645
-        );
1646
-
1647
-        // main box
1648
-        $this->_template_args['template_fields']                         = $template_fields;
1649
-        $this->_template_args['sidebar_box_id']                          = 'details';
1650
-        $this->_template_args['action']                                  = $action;
1651
-        $this->_template_args['context']                                 = $context;
1652
-        $this->_template_args['edit_message_template_form_url']          = $edit_message_template_form_url;
1653
-        $this->_template_args['learn_more_about_message_templates_link'] =
1654
-            $this->_learn_more_about_message_templates_link();
1655
-
1656
-        $this->_template_args['before_admin_page_content'] = '<div class="ee-msg-admin-header">';
1657
-        $this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1658
-            $message_template_group,
1659
-            $context,
1660
-            $context_label
1661
-        );
1662
-        $this->_template_args['before_admin_page_content'] .= $this->add_context_switcher();
1663
-        $this->_template_args['before_admin_page_content'] .= '</div>';
1664
-        $this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1665
-        $this->_template_args['after_admin_page_content']  = $this->_add_form_element_after();
1666
-
1667
-        $this->_template_path = $this->_template_args['GRP_ID']
1668
-            ? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1669
-            : EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1670
-
1671
-        // send along EE_Message_Template_Group object for further template use.
1672
-        $this->_template_args['MTP'] = $message_template_group;
1673
-
1674
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1675
-            $this->_template_path,
1676
-            $this->_template_args,
1677
-            true
1678
-        );
1679
-
1680
-        // finally, let's set the admin_page title
1681
-        $this->_admin_page_title = sprintf(esc_html__('Editing %s', 'event_espresso'), $title);
1682
-
1683
-        // we need to take care of setting the shortcodes property for use elsewhere.
1684
-        $this->_set_shortcodes();
1685
-
1686
-        // final template wrapper
1687
-        $this->display_admin_page_with_sidebar();
1688
-    }
1689
-
1690
-
1691
-    public function filter_tinymce_init($mceInit, $editor_id)
1692
-    {
1693
-        return $mceInit;
1694
-    }
1695
-
1696
-
1697
-    public function add_context_switcher()
1698
-    {
1699
-        return $this->_context_switcher;
1700
-    }
1701
-
1702
-
1703
-    /**
1704
-     * Adds the activation/deactivation toggle for the message template context.
1705
-     *
1706
-     * @param EE_Message_Template_Group $message_template_group
1707
-     * @param string                    $context
1708
-     * @param string                    $context_label
1709
-     * @return string
1710
-     * @throws DomainException
1711
-     * @throws EE_Error
1712
-     * @throws InvalidIdentifierException
1713
-     * @throws ReflectionException
1714
-     */
1715
-    protected function add_active_context_element(
1716
-        EE_Message_Template_Group $message_template_group,
1717
-        $context,
1718
-        $context_label
1719
-    ) {
1720
-        $template_args = [
1721
-            'context'                   => $context,
1722
-            'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1723
-            'is_active'                 => $message_template_group->is_context_active($context),
1724
-            'on_off_action'             => $message_template_group->is_context_active($context)
1725
-                ? 'context-off'
1726
-                : 'context-on',
1727
-            'context_label'             => str_replace(['(', ')'], '', $context_label),
1728
-            'message_template_group_id' => $message_template_group->ID(),
1729
-        ];
1730
-        return EEH_Template::display_template(
1731
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1732
-            $template_args,
1733
-            true
1734
-        );
1735
-    }
1736
-
1737
-
1738
-    /**
1739
-     * Ajax callback for `toggle_context_template` ajax action.
1740
-     * Handles toggling the message context on or off.
1741
-     *
1742
-     * @throws EE_Error
1743
-     * @throws InvalidArgumentException
1744
-     * @throws InvalidDataTypeException
1745
-     * @throws InvalidIdentifierException
1746
-     * @throws InvalidInterfaceException
1747
-     * @throws ReflectionException
1748
-     */
1749
-    public function toggle_context_template()
1750
-    {
1751
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1752
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1753
-        }
1754
-        $success = true;
1755
-        // check for required data
1756
-        if (
1757
-            ! (
1758
-                $this->request->requestParamIsSet('message_template_group_id')
1759
-                && $this->request->requestParamIsSet('context')
1760
-                && $this->request->requestParamIsSet('status')
1761
-            )
1762
-        ) {
1763
-            EE_Error::add_error(
1764
-                esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1765
-                __FILE__,
1766
-                __FUNCTION__,
1767
-                __LINE__
1768
-            );
1769
-            $success = false;
1770
-        }
1771
-
1772
-        $nonce   = $this->request->getRequestParam('toggle_context_nonce', '');
1773
-        $context = $this->request->getRequestParam('context', '');
1774
-        $status  = $this->request->getRequestParam('status', '');
1775
-
1776
-        $this->_verify_nonce($nonce, "activate_{$context}_toggle_nonce");
1777
-
1778
-        if ($status !== 'off' && $status !== 'on') {
1779
-            EE_Error::add_error(
1780
-                sprintf(
1781
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1782
-                    $status
1783
-                ),
1784
-                __FILE__,
1785
-                __FUNCTION__,
1786
-                __LINE__
1787
-            );
1788
-            $success = false;
1789
-        }
1790
-        $message_template_group_id = $this->request->getRequestParam('message_template_group_id', 0, DataType::INTEGER);
1791
-        $message_template_group    = $this->getMtgModel()->get_one_by_ID($message_template_group_id);
1792
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
1793
-            EE_Error::add_error(
1794
-                sprintf(
1795
-                    esc_html__(
1796
-                        'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1797
-                        'event_espresso'
1798
-                    ),
1799
-                    $message_template_group_id,
1800
-                    'EE_Message_Template_Group'
1801
-                ),
1802
-                __FILE__,
1803
-                __FUNCTION__,
1804
-                __LINE__
1805
-            );
1806
-            $success = false;
1807
-        }
1808
-        if ($success) {
1809
-            $success = $status === 'off'
1810
-                ? $message_template_group->deactivate_context($context)
1811
-                : $message_template_group->activate_context($context);
1812
-        }
1813
-        $this->_template_args['success'] = $success;
1814
-        $this->_return_json();
1815
-    }
1816
-
1817
-
1818
-    public function _add_form_element_before()
1819
-    {
1820
-        return '<form method="post" action="'
1821
-               . $this->_template_args['edit_message_template_form_url']
1822
-               . '" id="ee-msg-edit-frm">';
1823
-    }
1824
-
1825
-
1826
-    public function _add_form_element_after()
1827
-    {
1828
-        return '</form>';
1829
-    }
1830
-
1831
-
1832
-    /**
1833
-     * This executes switching the template pack for a message template.
1834
-     *
1835
-     * @throws EE_Error
1836
-     * @throws InvalidDataTypeException
1837
-     * @throws InvalidInterfaceException
1838
-     * @throws InvalidArgumentException
1839
-     * @throws ReflectionException
1840
-     * @since 4.5.0
1841
-     */
1842
-    public function switch_template_pack()
1843
-    {
1844
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1845
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1846
-        }
1847
-        $GRP_ID        = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
1848
-        $template_pack = $this->request->getRequestParam('template_pack', '');
1849
-
1850
-        // verify we have needed values.
1851
-        if (empty($GRP_ID) || empty($template_pack)) {
1852
-            $this->_template_args['error'] = true;
1853
-            EE_Error::add_error(
1854
-                esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1855
-                __FILE__,
1856
-                __FUNCTION__,
1857
-                __LINE__
1858
-            );
1859
-        } else {
1860
-            // get template, set the new template_pack and then reset to default
1861
-            /** @var EE_Message_Template_Group $message_template_group */
1862
-            $message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
1863
-
1864
-            $message_template_group->set_template_pack_name($template_pack);
1865
-            $this->request->setRequestParam('msgr', $message_template_group->messenger());
1866
-            $this->request->setRequestParam('mt', $message_template_group->message_type());
1867
-
1868
-            $query_args = $this->_reset_to_default_template();
1869
-
1870
-            if (empty($query_args['id'])) {
1871
-                EE_Error::add_error(
1872
-                    esc_html__(
1873
-                        'Something went wrong with switching the template pack. Please try again or contact EE support',
1874
-                        'event_espresso'
1875
-                    ),
1876
-                    __FILE__,
1877
-                    __FUNCTION__,
1878
-                    __LINE__
1879
-                );
1880
-                $this->_template_args['error'] = true;
1881
-            } else {
1882
-                $template_label       = $message_template_group->get_template_pack()->label;
1883
-                $template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
1884
-                EE_Error::add_success(
1885
-                    sprintf(
1886
-                        esc_html__(
1887
-                            'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
1888
-                            'event_espresso'
1889
-                        ),
1890
-                        $template_label,
1891
-                        $template_pack_labels->template_pack
1892
-                    )
1893
-                );
1894
-                // generate the redirect url for js.
1895
-                $url = self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1896
-
1897
-                $this->_template_args['data']['redirect_url'] = $url;
1898
-                $this->_template_args['success']              = true;
1899
-            }
1900
-
1901
-            $this->_return_json();
1902
-        }
1903
-    }
1904
-
1905
-
1906
-    /**
1907
-     * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
1908
-     * they want.
1909
-     *
1910
-     * @access protected
1911
-     * @return array|void
1912
-     * @throws EE_Error
1913
-     * @throws InvalidArgumentException
1914
-     * @throws InvalidDataTypeException
1915
-     * @throws InvalidInterfaceException
1916
-     * @throws ReflectionException
1917
-     */
1918
-    protected function _reset_to_default_template()
1919
-    {
1920
-        $templates    = [];
1921
-        $GRP_ID       = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
1922
-        $messenger    = $this->request->getRequestParam('msgr');
1923
-        $message_type = $this->request->getRequestParam('mt');
1924
-        // we need to make sure we've got the info we need.
1925
-        if (! ($GRP_ID && $messenger && $message_type)) {
1926
-            EE_Error::add_error(
1927
-                esc_html__(
1928
-                    'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
1929
-                    'event_espresso'
1930
-                ),
1931
-                __FILE__,
1932
-                __FUNCTION__,
1933
-                __LINE__
1934
-            );
1935
-        }
1936
-
1937
-        // all templates will be reset to whatever the defaults are
1938
-        // for the global template matching the messenger and message type.
1939
-        $success = ! empty($GRP_ID);
1940
-
1941
-        if ($success) {
1942
-            // let's first determine if the incoming template is a global template,
1943
-            // if it isn't then we need to get the global template matching messenger and message type.
1944
-            // $MTPG = $this->getMtgModel()->get_one_by_ID( $GRP_ID );
1945
-
1946
-
1947
-            // note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
1948
-            $success = $this->getMessageTemplateManager()->permanentlyDeleteMessageTemplates($GRP_ID);
1949
-
1950
-            if ($success) {
1951
-                // if successfully deleted, lets generate the new ones.
1952
-                // Note. We set GLOBAL to true, because resets on ANY template
1953
-                // will use the related global template defaults for regeneration.
1954
-                // This means that if a custom template is reset it resets to whatever the related global template is.
1955
-                // HOWEVER, we DO keep the template pack and template variation set
1956
-                // for the current custom template when resetting.
1957
-                $templates = $this->getMessageTemplateManager()->generateNewTemplates(
1958
-                    $messenger,
1959
-                    $message_type,
1960
-                    $GRP_ID,
1961
-                    true
1962
-                );
1963
-            }
1964
-        }
1965
-
1966
-        // any error messages?
1967
-        if (! $success) {
1968
-            EE_Error::add_error(
1969
-                esc_html__(
1970
-                    'Something went wrong with deleting existing templates. Unable to reset to default',
1971
-                    'event_espresso'
1972
-                ),
1973
-                __FILE__,
1974
-                __FUNCTION__,
1975
-                __LINE__
1976
-            );
1977
-        }
1978
-
1979
-        // all good, let's add a success message!
1980
-        if ($success && ! empty($templates)) {
1981
-            // the info for the template we generated is the first element in the returned array
1982
-            EE_Error::overwrite_success();
1983
-            EE_Error::add_success(esc_html__('Templates have been reset to defaults.', 'event_espresso'));
1984
-        }
1985
-
1986
-
1987
-        $query_args = [
1988
-            'id'      => $templates['GRP_ID'] ?? null,
1989
-            'context' => $templates['MTP_context'] ?? null,
1990
-            'action'  => isset($templates['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
1991
-        ];
1992
-
1993
-        // if called via ajax then we return query args otherwise redirect
1994
-        if ($this->request->isAjax()) {
1995
-            return $query_args;
1996
-        }
1997
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1998
-    }
1999
-
2000
-
2001
-    /**
2002
-     * Retrieve and set the message preview for display.
2003
-     *
2004
-     * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2005
-     * @return string
2006
-     * @throws ReflectionException
2007
-     * @throws EE_Error
2008
-     * @throws InvalidArgumentException
2009
-     * @throws InvalidDataTypeException
2010
-     * @throws InvalidInterfaceException
2011
-     */
2012
-    public function _preview_message($send = false)
2013
-    {
2014
-        // first make sure we've got the necessary parameters
2015
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
2016
-        if (! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2017
-            EE_Error::add_error(
2018
-                esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2019
-                __FILE__,
2020
-                __FUNCTION__,
2021
-                __LINE__
2022
-            );
2023
-        }
2024
-
2025
-        $context = $this->request->getRequestParam('context');
2026
-        // get the preview!
2027
-        $preview = EED_Messages::preview_message(
2028
-            $this->_active_message_type_name,
2029
-            $context,
2030
-            $this->_active_messenger_name,
2031
-            $send
2032
-        );
2033
-
2034
-        if ($send) {
2035
-            return $preview;
2036
-        }
2037
-
2038
-        // if we have an evt_id set on the request, use it.
2039
-        $EVT_ID = $this->request->getRequestParam('evt_id', 0, DataType::INTEGER);
2040
-
2041
-        // let's add a button to go back to the edit view
2042
-        $query_args             = [
2043
-            'id'      => $GRP_ID,
2044
-            'evt_id'  => $EVT_ID,
2045
-            'context' => $context,
2046
-            'action'  => 'edit_message_template',
2047
-        ];
2048
-        $go_back_url            = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2049
-        $preview_button         = '<a href="'
2050
-                                  . $go_back_url
2051
-                                  . '" class="button--secondary messages-preview-go-back-button">'
2052
-                                  . esc_html__('Go Back to Edit', 'event_espresso')
2053
-                                  . '</a>';
2054
-        $message_types          = $this->get_installed_message_types();
2055
-        $active_messenger       = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
2056
-        $active_messenger_label = $active_messenger instanceof EE_messenger
2057
-            ? ucwords($active_messenger->label['singular'])
2058
-            : esc_html__('Unknown Messenger', 'event_espresso');
2059
-        // let's provide a helpful title for context
2060
-        $preview_title = sprintf(
2061
-            esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2062
-            $active_messenger_label,
2063
-            ucwords($message_types[ $this->_active_message_type_name ]->label['singular'])
2064
-        );
2065
-        if (empty($preview)) {
2066
-            $this->noEventsErrorMessage();
2067
-        }
2068
-        // setup display of preview.
2069
-        $this->_admin_page_title                    = $preview_title;
2070
-        $this->_template_args['admin_page_title']   = $preview_title;
2071
-        $this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2072
-        $this->_template_args['data']['force_json'] = true;
2073
-
2074
-        return '';
2075
-    }
2076
-
2077
-
2078
-    /**
2079
-     * Used to set an error if there are no events available for generating a preview/test send.
2080
-     *
2081
-     * @param bool $test_send Whether the error should be generated for the context of a test send.
2082
-     */
2083
-    protected function noEventsErrorMessage($test_send = false)
2084
-    {
2085
-        $events_url = parent::add_query_args_and_nonce(
2086
-            [
2087
-                'action' => 'default',
2088
-                'page'   => 'espresso_events',
2089
-            ],
2090
-            admin_url('admin.php')
2091
-        );
2092
-        $message    = $test_send
2093
-            ? esc_html__(
2094
-                'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2095
-                'event_espresso'
2096
-            )
2097
-            : esc_html__(
2098
-                'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2099
-                'event_espresso'
2100
-            );
2101
-
2102
-        EE_Error::add_attention(
2103
-            sprintf(
2104
-                $message,
2105
-                "<a href='{$events_url}'>",
2106
-                '</a>'
2107
-            )
2108
-        );
2109
-    }
2110
-
2111
-
2112
-    /**
2113
-     * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2114
-     * gets called automatically.
2115
-     *
2116
-     * @return void
2117
-     * @throws EE_Error
2118
-     * @since 4.5.0
2119
-     */
2120
-    protected function _display_preview_message()
2121
-    {
2122
-        $this->display_admin_page_with_no_sidebar();
2123
-    }
2124
-
2125
-
2126
-    /**
2127
-     * registers metaboxes that should show up on the "edit_message_template" page
2128
-     *
2129
-     * @access protected
2130
-     * @return void
2131
-     */
2132
-    protected function _register_edit_meta_boxes()
2133
-    {
2134
-        $this->addMetaBox(
2135
-            'mtp_valid_shortcodes',
2136
-            esc_html__('Valid Shortcodes', 'event_espresso'),
2137
-            [$this, 'shortcode_meta_box'],
2138
-            $this->_current_screen->id,
2139
-            'side'
2140
-        );
2141
-        $this->addMetaBox(
2142
-            'mtp_extra_actions',
2143
-            esc_html__('Extra Actions', 'event_espresso'),
2144
-            [$this, 'extra_actions_meta_box'],
2145
-            $this->_current_screen->id,
2146
-            'side',
2147
-            'high'
2148
-        );
2149
-        $this->addMetaBox(
2150
-            'mtp_templates',
2151
-            esc_html__('Template Styles', 'event_espresso'),
2152
-            [$this, 'template_pack_meta_box'],
2153
-            $this->_current_screen->id,
2154
-            'side',
2155
-            'high'
2156
-        );
2157
-    }
2158
-
2159
-
2160
-    /**
2161
-     * metabox content for all template pack and variation selection.
2162
-     *
2163
-     * @return void
2164
-     * @throws DomainException
2165
-     * @throws EE_Error
2166
-     * @throws InvalidArgumentException
2167
-     * @throws ReflectionException
2168
-     * @throws InvalidDataTypeException
2169
-     * @throws InvalidInterfaceException
2170
-     * @since 4.5.0
2171
-     */
2172
-    public function template_pack_meta_box()
2173
-    {
2174
-        $this->_set_message_template_group();
2175
-
2176
-        $tp_collection = EEH_MSG_Template::get_template_pack_collection();
2177
-
2178
-        $tp_select_values = [];
2179
-
2180
-        foreach ($tp_collection as $tp) {
2181
-            // only include template packs that support this messenger and message type!
2182
-            $supports = $tp->get_supports();
2183
-            if (
2184
-                ! isset($supports[ $this->_message_template_group->messenger() ])
2185
-                || ! in_array(
2186
-                    $this->_message_template_group->message_type(),
2187
-                    $supports[ $this->_message_template_group->messenger() ],
2188
-                    true
2189
-                )
2190
-            ) {
2191
-                // not supported
2192
-                continue;
2193
-            }
2194
-
2195
-            $tp_select_values[] = [
2196
-                'text' => $tp->label,
2197
-                'id'   => $tp->dbref,
2198
-            ];
2199
-        }
2200
-
2201
-        // if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2202
-        // the default template pack.  This still allows for the odd template pack to override.
2203
-        if (empty($tp_select_values)) {
2204
-            $tp_select_values[] = [
2205
-                'text' => esc_html__('Default', 'event_espresso'),
2206
-                'id'   => 'default',
2207
-            ];
2208
-        }
2209
-
2210
-        // setup variation select values for the currently selected template.
2211
-        $variations               = $this->_message_template_group->get_template_pack()->get_variations(
2212
-            $this->_message_template_group->messenger(),
2213
-            $this->_message_template_group->message_type()
2214
-        );
2215
-        $variations_select_values = [];
2216
-        foreach ($variations as $variation => $label) {
2217
-            $variations_select_values[] = [
2218
-                'text' => $label,
2219
-                'id'   => $variation,
2220
-            ];
2221
-        }
2222
-
2223
-        $template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2224
-
2225
-        $template_args['template_packs_selector']        = EEH_Form_Fields::select_input(
2226
-            'MTP_template_pack',
2227
-            $tp_select_values,
2228
-            $this->_message_template_group->get_template_pack_name()
2229
-        );
2230
-        $template_args['variations_selector']            = EEH_Form_Fields::select_input(
2231
-            'MTP_template_variation',
2232
-            $variations_select_values,
2233
-            $this->_message_template_group->get_template_pack_variation()
2234
-        );
2235
-        $template_args['template_pack_label']            = $template_pack_labels->template_pack;
2236
-        $template_args['template_variation_label']       = $template_pack_labels->template_variation;
2237
-        $template_args['template_pack_description']      = $template_pack_labels->template_pack_description;
2238
-        $template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2239
-
2240
-        $template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2241
-
2242
-        EEH_Template::display_template($template, $template_args);
2243
-    }
2244
-
2245
-
2246
-    /**
2247
-     * This meta box holds any extra actions related to Message Templates
2248
-     * For now, this includes Resetting templates to defaults and sending a test email.
2249
-     *
2250
-     * @access  public
2251
-     * @return void
2252
-     * @throws EE_Error
2253
-     */
2254
-    public function extra_actions_meta_box()
2255
-    {
2256
-        $template_form_fields = [];
2257
-
2258
-        $extra_args = [
2259
-            'msgr'   => $this->_message_template_group->messenger(),
2260
-            'mt'     => $this->_message_template_group->message_type(),
2261
-            'GRP_ID' => $this->_message_template_group->GRP_ID(),
2262
-        ];
2263
-        // first we need to see if there are any fields
2264
-        $fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2265
-
2266
-        if (! empty($fields)) {
2267
-            // yup there be fields
2268
-            foreach ($fields as $field => $config) {
2269
-                $field_id = $this->_message_template_group->messenger() . '_' . $field;
2270
-                $existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2271
-                $default  = $config['default'] ?? '';
2272
-                $default  = $config['value'] ?? $default;
2273
-
2274
-                // if type is hidden and the value is empty
2275
-                // something may have gone wrong so let's correct with the defaults
2276
-                $fix                = $config['input'] === 'hidden'
2277
-                                      && isset($existing[ $field ])
2278
-                                      && empty($existing[ $field ])
2279
-                    ? $default
2280
-                    : '';
2281
-                $existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2282
-                    ? $existing[ $field ]
2283
-                    : $fix;
2284
-
2285
-                $template_form_fields[ $field_id ] = [
2286
-                    'name'       => 'test_settings_fld[' . $field . ']',
2287
-                    'label'      => $config['label'],
2288
-                    'input'      => $config['input'],
2289
-                    'type'       => $config['type'],
2290
-                    'required'   => $config['required'],
2291
-                    'validation' => $config['validation'],
2292
-                    'value'      => $existing[ $field ] ?? $default,
2293
-                    'css_class'  => $config['css_class'],
2294
-                    'options'    => $config['options'] ?? [],
2295
-                    'default'    => $default,
2296
-                    'format'     => $config['format'],
2297
-                ];
2298
-            }
2299
-        }
2300
-
2301
-        $test_settings_html = ! empty($template_form_fields)
2302
-            ? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2303
-            : '';
2304
-
2305
-        // print out $test_settings_fields
2306
-        if (! empty($test_settings_html)) {
2307
-            $test_settings_html .= '<input type="submit" class="button--primary mtp-test-button alignright" ';
2308
-            $test_settings_html .= 'name="test_button" value="';
2309
-            $test_settings_html .= esc_html__('Test Send', 'event_espresso');
2310
-            $test_settings_html .= '" /><div style="clear:both"></div>';
2311
-        }
2312
-
2313
-        // and button
2314
-        $test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2315
-        $test_settings_html .= '<p>';
2316
-        $test_settings_html .= esc_html__('Need to reset this message type and start over?', 'event_espresso');
2317
-        $test_settings_html .= '</p>';
2318
-        $test_settings_html .= $this->get_action_link_or_button(
2319
-            'reset_to_default',
2320
-            'reset',
2321
-            $extra_args,
2322
-            'button--primary reset-default-button'
2323
-        );
2324
-        $test_settings_html .= '</div><div style="clear:both"></div>';
2325
-        echo wp_kses($test_settings_html, AllowedTags::getWithFormTags());
2326
-    }
2327
-
2328
-
2329
-    /**
2330
-     * This returns the shortcode selector skeleton for a given context and field.
2331
-     *
2332
-     * @param string $field           The name of the field retrieving shortcodes for.
2333
-     * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2334
-     * @return string
2335
-     * @throws DomainException
2336
-     * @throws EE_Error
2337
-     * @throws InvalidArgumentException
2338
-     * @throws ReflectionException
2339
-     * @throws InvalidDataTypeException
2340
-     * @throws InvalidInterfaceException
2341
-     * @since 4.9.rc.000
2342
-     */
2343
-    protected function _get_shortcode_selector($field, $linked_input_id)
2344
-    {
2345
-        $template_args = [
2346
-            'shortcodes'      => $this->_get_shortcodes([$field]),
2347
-            'fieldname'       => $field,
2348
-            'linked_input_id' => $linked_input_id,
2349
-        ];
2350
-
2351
-        return EEH_Template::display_template(
2352
-            EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2353
-            $template_args,
2354
-            true
2355
-        );
2356
-    }
2357
-
2358
-
2359
-    /**
2360
-     * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2361
-     * page)
2362
-     *
2363
-     * @access public
2364
-     * @return void
2365
-     * @throws EE_Error
2366
-     * @throws InvalidArgumentException
2367
-     * @throws ReflectionException
2368
-     * @throws InvalidDataTypeException
2369
-     * @throws InvalidInterfaceException
2370
-     */
2371
-    public function shortcode_meta_box()
2372
-    {
2373
-        $shortcodes = $this->_get_shortcodes([], false);
2374
-        // just make sure the shortcodes property is set
2375
-        // $messenger = $this->_message_template_group->messenger_obj();
2376
-        // now let's set the content depending on the status of the shortcodes array
2377
-        if (empty($shortcodes)) {
2378
-            echo '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2379
-            return;
2380
-        }
2381
-        ?>
60
+	/**
61
+	 * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
62
+	 * group is.  If there is no group then it automatically gets set to default.
63
+	 *
64
+	 * @since 4.5.0
65
+	 */
66
+	protected string $_variation = '';
67
+
68
+
69
+	/**
70
+	 * @param bool $routing
71
+	 * @throws EE_Error
72
+	 * @throws ReflectionException
73
+	 */
74
+	public function __construct($routing = true)
75
+	{
76
+		// make sure messages autoloader is running
77
+		EED_Messages::set_autoloaders();
78
+		parent::__construct($routing);
79
+	}
80
+
81
+
82
+	/**
83
+	 * @return EEM_Message
84
+	 * @throws EE_Error
85
+	 * @throws ReflectionException
86
+	 */
87
+	public function getMsgModel(): EEM_Message
88
+	{
89
+		if (! $this->MSG_MODEL instanceof EEM_Message) {
90
+			$this->MSG_MODEL = EEM_Message::instance();
91
+		}
92
+		return $this->MSG_MODEL;
93
+	}
94
+
95
+
96
+	/**
97
+	 * @return EEM_Message_Template
98
+	 * @throws EE_Error
99
+	 * @throws ReflectionException
100
+	 */
101
+	public function getMtpModel(): EEM_Message_Template
102
+	{
103
+		if (! $this->MTP_MODEL instanceof EEM_Message_Template) {
104
+			$this->MTP_MODEL = EEM_Message_Template::instance();
105
+		}
106
+		return $this->MTP_MODEL;
107
+	}
108
+
109
+
110
+	/**
111
+	 * @return EEM_Message_Template_Group
112
+	 * @throws EE_Error
113
+	 * @throws ReflectionException
114
+	 */
115
+	public function getMtgModel(): EEM_Message_Template_Group
116
+	{
117
+		if (! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
118
+			$this->MTG_MODEL = EEM_Message_Template_Group::instance();
119
+		}
120
+		return $this->MTG_MODEL;
121
+	}
122
+
123
+
124
+	public function getMessageTemplateManager(): MessageTemplateManager
125
+	{
126
+		if (! $this->message_template_manager instanceof MessageTemplateManager) {
127
+			$this->message_template_manager = $this->loader->getShared(MessageTemplateManager::class);
128
+		}
129
+		return $this->message_template_manager;
130
+	}
131
+
132
+
133
+	/**
134
+	 * @throws EE_Error
135
+	 * @throws ReflectionException
136
+	 */
137
+	protected function _init_page_props()
138
+	{
139
+		$this->page_slug        = EE_MSG_PG_SLUG;
140
+		$this->page_label       = esc_html__('Messages Settings', 'event_espresso');
141
+		$this->_admin_base_url  = EE_MSG_ADMIN_URL;
142
+		$this->_admin_base_path = EE_MSG_ADMIN;
143
+
144
+		$messenger                       = $this->request->getRequestParam('messenger', '');
145
+		$message_type                    = $this->request->getRequestParam('message_type', '');
146
+		$this->_active_messenger_name    = $this->request->getRequestParam('MTP_messenger', $messenger);
147
+		$this->_active_message_type_name = $this->request->getRequestParam('MTP_message_type', $message_type);
148
+
149
+		$this->_load_message_resource_manager();
150
+	}
151
+
152
+
153
+	protected function _load_message_resource_manager()
154
+	{
155
+		if (! $this->_message_resource_manager instanceof EE_Message_Resource_Manager) {
156
+			$this->_message_resource_manager = $this->loader->getShared(EE_Message_Resource_Manager::class);
157
+		}
158
+	}
159
+
160
+
161
+	/**
162
+	 * Generate select input with provided messenger options array.
163
+	 *
164
+	 * @param array $messenger_options Array of messengers indexed by slug and values are the messenger labels.
165
+	 * @return string
166
+	 * @throws EE_Error
167
+	 */
168
+	public function get_messengers_select_input($messenger_options)
169
+	{
170
+		// if empty or just one value then just return an empty string
171
+		if (
172
+			empty($messenger_options)
173
+			|| ! is_array($messenger_options)
174
+			|| count($messenger_options) === 1
175
+		) {
176
+			return '';
177
+		}
178
+		// merge in default
179
+		$messenger_options = array_merge(
180
+			['none_selected' => esc_html__('Show All Messengers', 'event_espresso')],
181
+			$messenger_options
182
+		);
183
+		$input             = new EE_Select_Input(
184
+			$messenger_options,
185
+			[
186
+				'html_name'  => 'ee_messenger_filter_by',
187
+				'html_id'    => 'ee_messenger_filter_by',
188
+				'html_class' => 'wide',
189
+				'default'    => $this->request->getRequestParam('ee_messenger_filter_by', 'none_selected', 'title'),
190
+			]
191
+		);
192
+
193
+		return $input->get_html_for_input();
194
+	}
195
+
196
+
197
+	/**
198
+	 * Generate select input with provided message type options array.
199
+	 *
200
+	 * @param array $message_type_options Array of message types indexed by message type slug, and values are the
201
+	 *                                    message type labels
202
+	 * @return string
203
+	 * @throws EE_Error
204
+	 */
205
+	public function get_message_types_select_input($message_type_options)
206
+	{
207
+		// if empty or count of options is 1 then just return an empty string
208
+		if (
209
+			empty($message_type_options)
210
+			|| ! is_array($message_type_options)
211
+			|| count($message_type_options) === 1
212
+		) {
213
+			return '';
214
+		}
215
+		// merge in default
216
+		$message_type_options = array_merge(
217
+			['none_selected' => esc_html__('Show All Message Types', 'event_espresso')],
218
+			$message_type_options
219
+		);
220
+		$input                = new EE_Select_Input(
221
+			$message_type_options,
222
+			[
223
+				'html_name'  => 'ee_message_type_filter_by',
224
+				'html_id'    => 'ee_message_type_filter_by',
225
+				'html_class' => 'wide',
226
+				'default'    => $this->request->getRequestParam('ee_message_type_filter_by', 'none_selected', 'title'),
227
+			]
228
+		);
229
+
230
+		return $input->get_html_for_input();
231
+	}
232
+
233
+
234
+	/**
235
+	 * Generate select input with provide message type contexts array.
236
+	 *
237
+	 * @param array $context_options Array of message type contexts indexed by context slug, and values are the
238
+	 *                               context label.
239
+	 * @return string
240
+	 * @throws EE_Error
241
+	 */
242
+	public function get_contexts_for_message_types_select_input($context_options)
243
+	{
244
+		// if empty or count of options is one then just return empty string
245
+		if (
246
+			empty($context_options)
247
+			|| ! is_array($context_options)
248
+			|| count($context_options) === 1
249
+		) {
250
+			return '';
251
+		}
252
+		// merge in default
253
+		$context_options = array_merge(
254
+			['none_selected' => esc_html__('Show all Contexts', 'event_espresso')],
255
+			$context_options
256
+		);
257
+		$input           = new EE_Select_Input(
258
+			$context_options,
259
+			[
260
+				'html_name'  => 'ee_context_filter_by',
261
+				'html_id'    => 'ee_context_filter_by',
262
+				'html_class' => 'wide',
263
+				'default'    => $this->request->getRequestParam('ee_context_filter_by', 'none_selected', 'title'),
264
+			]
265
+		);
266
+
267
+		return $input->get_html_for_input();
268
+	}
269
+
270
+
271
+	protected function _ajax_hooks()
272
+	{
273
+		if (! $this->capabilities->current_user_can('ee_edit_messages', 'edit-message-settings')) {
274
+			return;
275
+		}
276
+		add_action('wp_ajax_activate_messenger', [$this, 'activate_messenger_toggle']);
277
+		add_action('wp_ajax_activate_mt', [$this, 'activate_mt_toggle']);
278
+		add_action('wp_ajax_ee_msgs_save_settings', [$this, 'save_settings']);
279
+		add_action('wp_ajax_ee_msgs_update_mt_form', [$this, 'update_mt_form']);
280
+		add_action('wp_ajax_switch_template_pack', [$this, 'switch_template_pack']);
281
+		add_action('wp_ajax_toggle_context_template', [$this, 'toggle_context_template']);
282
+	}
283
+
284
+
285
+	protected function _define_page_props()
286
+	{
287
+		$this->_admin_page_title = $this->page_label;
288
+		$this->_labels           = [
289
+			'buttons'    => [
290
+				'add'    => esc_html__('Add New Message Template', 'event_espresso'),
291
+				'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
292
+				'delete' => esc_html__('Delete Message Template', 'event_espresso'),
293
+			],
294
+			'publishbox' => esc_html__('Update Actions', 'event_espresso'),
295
+		];
296
+	}
297
+
298
+
299
+	/**
300
+	 *        an array for storing key => value pairs of request actions and their corresponding methods
301
+	 *
302
+	 * @access protected
303
+	 * @return void
304
+	 */
305
+	protected function _set_page_routes()
306
+	{
307
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
308
+		$GRP_ID = $this->request->getRequestParam('id', $GRP_ID, DataType::INTEGER);
309
+		$MSG_ID = $this->request->getRequestParam('MSG_ID', 0, DataType::INTEGER);
310
+
311
+		$this->_page_routes = [
312
+			'default'                          => [
313
+				'func'       => [$this, '_message_queue_list_table'],
314
+				'capability' => 'ee_read_global_messages',
315
+			],
316
+			'global_mtps'                      => [
317
+				'func'       => [$this, '_ee_default_messages_overview_list_table'],
318
+				'capability' => 'ee_read_global_messages',
319
+			],
320
+			'custom_mtps'                      => [
321
+				'func'       => [$this, '_custom_mtps_preview'],
322
+				'capability' => 'ee_read_messages',
323
+			],
324
+			'add_new_message_template'         => [
325
+				'func'       => [$this, 'insertMessageTemplate'],
326
+				'capability' => 'ee_edit_messages',
327
+				'noheader'   => true,
328
+			],
329
+			'edit_message_template'            => [
330
+				'func'       => [$this, '_edit_message_template'],
331
+				'capability' => 'ee_edit_message',
332
+				'obj_id'     => $GRP_ID,
333
+			],
334
+			'preview_message'                  => [
335
+				'func'               => [$this, '_preview_message'],
336
+				'capability'         => 'ee_read_message',
337
+				'obj_id'             => $GRP_ID,
338
+				'noheader'           => true,
339
+				'headers_sent_route' => 'display_preview_message',
340
+			],
341
+			'display_preview_message'          => [
342
+				'func'       => [$this, '_display_preview_message'],
343
+				'capability' => 'ee_read_message',
344
+				'obj_id'     => $GRP_ID,
345
+			],
346
+			'insert_message_template'          => [
347
+				'func'       => [$this, 'insertMessageTemplate'],
348
+				'capability' => 'ee_edit_messages',
349
+				'noheader'   => true,
350
+			],
351
+			'update_message_template'          => [
352
+				'func'       => [$this, 'updateMessageTemplate'],
353
+				'capability' => 'ee_edit_message',
354
+				'obj_id'     => $GRP_ID,
355
+				'noheader'   => true,
356
+			],
357
+			'trash_message_template'           => [
358
+				'func'       => [$this, '_trash_or_restore_message_template'],
359
+				'capability' => 'ee_delete_message',
360
+				'obj_id'     => $GRP_ID,
361
+				'args'       => ['trash' => true, 'all' => true],
362
+				'noheader'   => true,
363
+			],
364
+			'trash_message_template_context'   => [
365
+				'func'       => [$this, '_trash_or_restore_message_template'],
366
+				'capability' => 'ee_delete_message',
367
+				'obj_id'     => $GRP_ID,
368
+				'args'       => ['trash' => true],
369
+				'noheader'   => true,
370
+			],
371
+			'restore_message_template'         => [
372
+				'func'       => [$this, '_trash_or_restore_message_template'],
373
+				'capability' => 'ee_delete_message',
374
+				'obj_id'     => $GRP_ID,
375
+				'args'       => ['trash' => false, 'all' => true],
376
+				'noheader'   => true,
377
+			],
378
+			'restore_message_template_context' => [
379
+				'func'       => [$this, '_trash_or_restore_message_template'],
380
+				'capability' => 'ee_delete_message',
381
+				'obj_id'     => $GRP_ID,
382
+				'args'       => ['trash' => false],
383
+				'noheader'   => true,
384
+			],
385
+			'delete_message_template'          => [
386
+				'func'       => [$this, '_delete_message_template'],
387
+				'capability' => 'ee_delete_message',
388
+				'obj_id'     => $GRP_ID,
389
+				'noheader'   => true,
390
+			],
391
+			'reset_to_default'                 => [
392
+				'func'       => [$this, '_reset_to_default_template'],
393
+				'capability' => 'ee_edit_message',
394
+				'obj_id'     => $GRP_ID,
395
+				'noheader'   => true,
396
+			],
397
+			'settings'                         => [
398
+				'func'       => [$this, '_settings'],
399
+				'capability' => 'manage_options',
400
+			],
401
+			'update_global_settings'           => [
402
+				'func'       => [$this, '_update_global_settings'],
403
+				'capability' => 'manage_options',
404
+				'noheader'   => true,
405
+			],
406
+			'generate_now'                     => [
407
+				'func'       => [$this, '_generate_now'],
408
+				'capability' => 'ee_send_message',
409
+				'noheader'   => true,
410
+			],
411
+			'generate_and_send_now'            => [
412
+				'func'       => [$this, '_generate_and_send_now'],
413
+				'capability' => 'ee_send_message',
414
+				'noheader'   => true,
415
+			],
416
+			'queue_for_resending'              => [
417
+				'func'       => [$this, '_queue_for_resending'],
418
+				'capability' => 'ee_send_message',
419
+				'noheader'   => true,
420
+			],
421
+			'send_now'                         => [
422
+				'func'       => [$this, '_send_now'],
423
+				'capability' => 'ee_send_message',
424
+				'noheader'   => true,
425
+			],
426
+			'delete_ee_message'                => [
427
+				'func'       => [$this, '_delete_ee_messages'],
428
+				'capability' => 'ee_delete_messages',
429
+				'noheader'   => true,
430
+			],
431
+			'delete_ee_messages'               => [
432
+				'func'       => [$this, '_delete_ee_messages'],
433
+				'capability' => 'ee_delete_messages',
434
+				'noheader'   => true,
435
+				'obj_id'     => $MSG_ID,
436
+			],
437
+		];
438
+	}
439
+
440
+
441
+	protected function _set_page_config()
442
+	{
443
+		$this->_page_config = [
444
+			'default'                  => [
445
+				'nav'           => [
446
+					'label' => esc_html__('Message Activity', 'event_espresso'),
447
+					'icon'  => 'dashicons-email',
448
+					'order' => 10,
449
+				],
450
+				'list_table'    => 'EE_Message_List_Table',
451
+				// 'qtips' => array( 'EE_Message_List_Table_Tips' ),
452
+				'require_nonce' => false,
453
+			],
454
+			'global_mtps'              => [
455
+				'nav'           => [
456
+					'label' => esc_html__('Default Message Templates', 'event_espresso'),
457
+					'icon'  => 'dashicons-layout',
458
+					'order' => 20,
459
+				],
460
+				'list_table'    => 'Messages_Template_List_Table',
461
+				'help_tabs'     => [
462
+					'messages_overview_help_tab'                                => [
463
+						'title'    => esc_html__('Messages Overview', 'event_espresso'),
464
+						'filename' => 'messages_overview',
465
+					],
466
+					'messages_overview_messages_table_column_headings_help_tab' => [
467
+						'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
468
+						'filename' => 'messages_overview_table_column_headings',
469
+					],
470
+					'messages_overview_messages_filters_help_tab'               => [
471
+						'title'    => esc_html__('Message Filters', 'event_espresso'),
472
+						'filename' => 'messages_overview_filters',
473
+					],
474
+					'messages_overview_messages_views_help_tab'                 => [
475
+						'title'    => esc_html__('Message Views', 'event_espresso'),
476
+						'filename' => 'messages_overview_views',
477
+					],
478
+					'message_overview_message_types_help_tab'                   => [
479
+						'title'    => esc_html__('Message Types', 'event_espresso'),
480
+						'filename' => 'messages_overview_types',
481
+					],
482
+					'messages_overview_messengers_help_tab'                     => [
483
+						'title'    => esc_html__('Messengers', 'event_espresso'),
484
+						'filename' => 'messages_overview_messengers',
485
+					],
486
+				],
487
+				'require_nonce' => false,
488
+			],
489
+			'custom_mtps'              => [
490
+				'nav'           => [
491
+					'label' => esc_html__('Custom Message Templates', 'event_espresso'),
492
+					'icon'  => 'dashicons-admin-customizer',
493
+					'order' => 30,
494
+				],
495
+				'help_tabs'     => [],
496
+				'require_nonce' => false,
497
+			],
498
+			'add_new_message_template' => [
499
+				'nav'           => [
500
+					'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
501
+					'icon'       => 'dashicons-plus-alt',
502
+					'order'      => 5,
503
+					'persistent' => false,
504
+				],
505
+				'require_nonce' => false,
506
+			],
507
+			'edit_message_template'    => [
508
+				'labels'        => [
509
+					'buttons'    => [
510
+						'reset' => esc_html__('Reset Templates', 'event_espresso'),
511
+					],
512
+					'publishbox' => esc_html__('Update Actions', 'event_espresso'),
513
+				],
514
+				'nav'           => [
515
+					'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
516
+					'icon'       => 'dashicons-edit-large',
517
+					'order'      => 5,
518
+					'persistent' => false,
519
+					'url'        => '',
520
+				],
521
+				'metaboxes'     => ['_publish_post_box', '_register_edit_meta_boxes'],
522
+				'has_metaboxes' => true,
523
+				'help_tabs'     => [
524
+					'edit_message_template'            => [
525
+						'title'    => esc_html__('Message Template Editor', 'event_espresso'),
526
+						'callback' => 'edit_message_template_help_tab',
527
+					],
528
+					'message_templates_help_tab'       => [
529
+						'title'    => esc_html__('Message Templates', 'event_espresso'),
530
+						'filename' => 'messages_templates',
531
+					],
532
+					'message_template_shortcodes'      => [
533
+						'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
534
+						'callback' => 'message_template_shortcodes_help_tab',
535
+					],
536
+					'message_preview_help_tab'         => [
537
+						'title'    => esc_html__('Message Preview', 'event_espresso'),
538
+						'filename' => 'messages_preview',
539
+					],
540
+					'messages_overview_other_help_tab' => [
541
+						'title'    => esc_html__('Messages Other', 'event_espresso'),
542
+						'filename' => 'messages_overview_other',
543
+					],
544
+				],
545
+				'require_nonce' => false,
546
+			],
547
+			'display_preview_message'  => [
548
+				'nav'           => [
549
+					'label'      => esc_html__('Message Preview', 'event_espresso'),
550
+					'icon'       => 'dashicons-visibility-bar',
551
+					'order'      => 5,
552
+					'url'        => '',
553
+					'persistent' => false,
554
+				],
555
+				'help_tabs'     => [
556
+					'preview_message' => [
557
+						'title'    => esc_html__('About Previews', 'event_espresso'),
558
+						'callback' => 'preview_message_help_tab',
559
+					],
560
+				],
561
+				'require_nonce' => false,
562
+			],
563
+			'settings'                 => [
564
+				'nav'           => [
565
+					'label' => esc_html__('Settings', 'event_espresso'),
566
+					'icon'  => 'dashicons-admin-generic',
567
+					'order' => 40,
568
+				],
569
+				'metaboxes'     => ['_messages_settings_metaboxes'],
570
+				'help_tabs'     => [
571
+					'messages_settings_help_tab'               => [
572
+						'title'    => esc_html__('Messages Settings', 'event_espresso'),
573
+						'filename' => 'messages_settings',
574
+					],
575
+					'messages_settings_message_types_help_tab' => [
576
+						'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
577
+						'filename' => 'messages_settings_message_types',
578
+					],
579
+					'messages_settings_messengers_help_tab'    => [
580
+						'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
581
+						'filename' => 'messages_settings_messengers',
582
+					],
583
+				],
584
+				'require_nonce' => false,
585
+			],
586
+		];
587
+	}
588
+
589
+
590
+	protected function _add_screen_options()
591
+	{
592
+		// todo
593
+	}
594
+
595
+
596
+	protected function _add_screen_options_global_mtps()
597
+	{
598
+		/**
599
+		 * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
600
+		 * uses the $_admin_page_title property and we want different outputs in the different spots.
601
+		 */
602
+		$page_title              = $this->_admin_page_title;
603
+		$this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
604
+		$this->_per_page_screen_option();
605
+		$this->_admin_page_title = $page_title;
606
+	}
607
+
608
+
609
+	protected function _add_screen_options_default()
610
+	{
611
+		$this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
612
+		$this->_per_page_screen_option();
613
+	}
614
+
615
+
616
+	// none of the below group are currently used for Messages
617
+	protected function _add_feature_pointers()
618
+	{
619
+	}
620
+
621
+
622
+	public function admin_init()
623
+	{
624
+	}
625
+
626
+
627
+	public function admin_notices()
628
+	{
629
+	}
630
+
631
+
632
+	public function admin_footer_scripts()
633
+	{
634
+	}
635
+
636
+
637
+	public function messages_help_tab()
638
+	{
639
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
640
+	}
641
+
642
+
643
+	public function messengers_help_tab()
644
+	{
645
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
646
+	}
647
+
648
+
649
+	public function message_types_help_tab()
650
+	{
651
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
652
+	}
653
+
654
+
655
+	public function messages_overview_help_tab()
656
+	{
657
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
658
+	}
659
+
660
+
661
+	public function message_templates_help_tab()
662
+	{
663
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
664
+	}
665
+
666
+
667
+	public function edit_message_template_help_tab()
668
+	{
669
+		$args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
670
+						. esc_attr__('Editor Title', 'event_espresso')
671
+						. '" />';
672
+		$args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
673
+						. esc_attr__('Context Switcher and Preview', 'event_espresso')
674
+						. '" />';
675
+		$args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
676
+						. esc_attr__('Message Template Form Fields', 'event_espresso')
677
+						. '" />';
678
+		$args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
679
+						. esc_attr__('Shortcodes Metabox', 'event_espresso')
680
+						. '" />';
681
+		$args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
682
+						. esc_attr__('Publish Metabox', 'event_espresso')
683
+						. '" />';
684
+		EEH_Template::display_template(
685
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
686
+			$args
687
+		);
688
+	}
689
+
690
+
691
+	/**
692
+	 * @throws ReflectionException
693
+	 * @throws EE_Error
694
+	 */
695
+	public function message_template_shortcodes_help_tab()
696
+	{
697
+		$this->_set_shortcodes();
698
+		$args['shortcodes'] = $this->_shortcodes;
699
+		EEH_Template::display_template(
700
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
701
+			$args
702
+		);
703
+	}
704
+
705
+
706
+	public function preview_message_help_tab()
707
+	{
708
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
709
+	}
710
+
711
+
712
+	public function settings_help_tab()
713
+	{
714
+		$args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
715
+						. '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
716
+		$args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
717
+						. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
718
+		$args['img3'] = '<div class="ee-switch">'
719
+						. '<input class="ee-switch__input" id="ee-on-off-toggle-on" type="checkbox" checked>'
720
+						. '<label class="ee-switch__toggle" for="ee-on-off-toggle-on"></label>'
721
+						. '</div>';
722
+		$args['img4'] = '<div class="switch">'
723
+						. '<input class="ee-switch__input" id="ee-on-off-toggle-off" type="checkbox">'
724
+						. '<label class="ee-switch__toggle" for="ee-on-off-toggle-off"></label>'
725
+						. '</div>';
726
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
727
+	}
728
+
729
+
730
+	public function load_scripts_styles()
731
+	{
732
+		wp_enqueue_style(
733
+			'espresso_ee_msg',
734
+			EE_MSG_ASSETS_URL . 'ee_message_admin.css',
735
+			[EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
736
+			EVENT_ESPRESSO_VERSION
737
+		);
738
+		wp_enqueue_style(
739
+			'ee_message_shortcodes',
740
+			EE_MSG_ASSETS_URL . 'ee_message_shortcodes.css',
741
+			[EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
742
+			EVENT_ESPRESSO_VERSION
743
+		);
744
+
745
+		wp_register_script(
746
+			'ee-messages-settings',
747
+			EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
748
+			['jquery-ui-droppable', 'ee-serialize-full-array'],
749
+			EVENT_ESPRESSO_VERSION,
750
+			true
751
+		);
752
+		wp_register_script(
753
+			'ee-msg-list-table-js',
754
+			EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
755
+			['ee-dialog'],
756
+			EVENT_ESPRESSO_VERSION
757
+		);
758
+	}
759
+
760
+
761
+	public function load_scripts_styles_default()
762
+	{
763
+		wp_enqueue_script('ee-msg-list-table-js');
764
+	}
765
+
766
+
767
+	public function wp_editor_css($mce_css)
768
+	{
769
+		// if we're on the edit_message_template route
770
+		if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
771
+			$message_type_name = $this->_active_message_type_name;
772
+
773
+			// we're going to REPLACE the existing mce css
774
+			// we need to get the css file location from the active messenger
775
+			$mce_css = $this->_active_messenger->get_variation(
776
+				$this->_template_pack,
777
+				$message_type_name,
778
+				true,
779
+				'wpeditor',
780
+				$this->_variation
781
+			);
782
+		}
783
+
784
+		return $mce_css;
785
+	}
786
+
787
+
788
+	/**
789
+	 * @throws EE_Error
790
+	 * @throws ReflectionException
791
+	 */
792
+	public function load_scripts_styles_edit_message_template()
793
+	{
794
+		$this->_set_shortcodes();
795
+
796
+		EE_Registry::$i18n_js_strings['confirm_default_reset']        = sprintf(
797
+			esc_html__(
798
+				'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
799
+				'event_espresso'
800
+			),
801
+			$this->_message_template_group->messenger_obj()->label['singular'],
802
+			$this->_message_template_group->message_type_obj()->label['singular']
803
+		);
804
+		EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
805
+			'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
806
+			'event_espresso'
807
+		);
808
+		EE_Registry::$i18n_js_strings['server_error']                 = esc_html__(
809
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
810
+			'event_espresso'
811
+		);
812
+
813
+		wp_register_script(
814
+			'ee_msgs_edit_js',
815
+			EE_MSG_ASSETS_URL . 'ee_message_editor.js',
816
+			['jquery'],
817
+			EVENT_ESPRESSO_VERSION
818
+		);
819
+
820
+		wp_enqueue_script('ee_admin_js');
821
+		wp_enqueue_script('ee_msgs_edit_js');
822
+
823
+		// add in special css for tiny_mce
824
+		add_filter('mce_css', [$this, 'wp_editor_css']);
825
+	}
826
+
827
+
828
+	/**
829
+	 * @throws EE_Error
830
+	 * @throws ReflectionException
831
+	 */
832
+	public function load_scripts_styles_display_preview_message()
833
+	{
834
+		$this->_set_message_template_group();
835
+		if ($this->_active_messenger_name) {
836
+			$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
837
+				$this->_active_messenger_name
838
+			);
839
+		}
840
+
841
+		wp_enqueue_style(
842
+			'espresso_preview_css',
843
+			$this->_active_messenger->get_variation(
844
+				$this->_template_pack,
845
+				$this->_active_message_type_name,
846
+				true,
847
+				'preview',
848
+				$this->_variation
849
+			)
850
+		);
851
+	}
852
+
853
+
854
+	public function load_scripts_styles_settings()
855
+	{
856
+		wp_register_style(
857
+			'ee-message-settings',
858
+			EE_MSG_ASSETS_URL . 'ee_message_settings.css',
859
+			[],
860
+			EVENT_ESPRESSO_VERSION
861
+		);
862
+		wp_enqueue_style('ee-text-links');
863
+		wp_enqueue_style('ee-message-settings');
864
+		wp_enqueue_script('ee-messages-settings');
865
+	}
866
+
867
+
868
+	/**
869
+	 * set views array for List Table
870
+	 */
871
+	public function _set_list_table_views_global_mtps()
872
+	{
873
+		$this->_views = [
874
+			'in_use' => [
875
+				'slug'  => 'in_use',
876
+				'label' => esc_html__('In Use', 'event_espresso'),
877
+				'count' => 0,
878
+			],
879
+		];
880
+	}
881
+
882
+
883
+	/**
884
+	 * Set views array for the Custom Template List Table
885
+	 */
886
+	public function _set_list_table_views_custom_mtps()
887
+	{
888
+		$this->_set_list_table_views_global_mtps();
889
+		$this->_views['in_use']['bulk_action'] = [
890
+			'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
891
+		];
892
+	}
893
+
894
+
895
+	/**
896
+	 * set views array for message queue list table
897
+	 *
898
+	 * @throws InvalidDataTypeException
899
+	 * @throws InvalidInterfaceException
900
+	 * @throws InvalidArgumentException
901
+	 * @throws EE_Error
902
+	 * @throws ReflectionException
903
+	 */
904
+	public function _set_list_table_views_default()
905
+	{
906
+		EE_Registry::instance()->load_helper('Template');
907
+
908
+		$common_bulk_actions = $this->capabilities->current_user_can(
909
+			'ee_send_message',
910
+			'message_list_table_bulk_actions'
911
+		)
912
+			? [
913
+				'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
914
+				'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
915
+				'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
916
+				'send_now'              => esc_html__('Send Now', 'event_espresso'),
917
+			]
918
+			: [];
919
+
920
+		$delete_bulk_action = $this->capabilities->current_user_can(
921
+			'ee_delete_messages',
922
+			'message_list_table_bulk_actions'
923
+		)
924
+			? ['delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso')]
925
+			: [];
926
+
927
+
928
+		$this->_views = [
929
+			'all' => [
930
+				'slug'        => 'all',
931
+				'label'       => esc_html__('All', 'event_espresso'),
932
+				'count'       => 0,
933
+				'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
934
+			],
935
+		];
936
+
937
+
938
+		foreach ($this->getMsgModel()->all_statuses() as $status) {
939
+			if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
940
+				continue;
941
+			}
942
+			$status_bulk_actions = $common_bulk_actions;
943
+			// unset bulk actions not applying to status
944
+			if (! empty($status_bulk_actions)) {
945
+				switch ($status) {
946
+					case EEM_Message::status_idle:
947
+					case EEM_Message::status_resend:
948
+						$status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
949
+						break;
950
+
951
+					case EEM_Message::status_failed:
952
+					case EEM_Message::status_debug_only:
953
+					case EEM_Message::status_messenger_executing:
954
+						$status_bulk_actions = [];
955
+						break;
956
+
957
+					case EEM_Message::status_incomplete:
958
+						unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
959
+						break;
960
+
961
+					case EEM_Message::status_retry:
962
+					case EEM_Message::status_sent:
963
+						unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
964
+						break;
965
+				}
966
+			}
967
+
968
+			// skip adding messenger executing status to views because it will be included with the Failed view.
969
+			if ($status === EEM_Message::status_messenger_executing) {
970
+				continue;
971
+			}
972
+
973
+			$this->_views[ strtolower($status) ] = [
974
+				'slug'        => strtolower($status),
975
+				'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
976
+				'count'       => 0,
977
+				'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
978
+			];
979
+		}
980
+	}
981
+
982
+
983
+	/**
984
+	 * @throws EE_Error
985
+	 */
986
+	protected function _ee_default_messages_overview_list_table()
987
+	{
988
+		$this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
989
+		$this->display_admin_list_table_page_with_no_sidebar();
990
+	}
991
+
992
+
993
+	/**
994
+	 * @throws EE_Error
995
+	 * @throws ReflectionException
996
+	 */
997
+	protected function _message_queue_list_table()
998
+	{
999
+		$this->_search_btn_label                   = esc_html__('Message Activity', 'event_espresso');
1000
+		$this->_template_args['per_column']        = 6;
1001
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_message_legend_items());
1002
+		$message_results                           = trim(EEM_Message::instance()->get_pretty_label_for_results());
1003
+		$this->_template_args['before_list_table'] = ! empty($message_results) ? "<h3>{$message_results}</h3>" : '';
1004
+		$this->display_admin_list_table_page_with_no_sidebar();
1005
+	}
1006
+
1007
+
1008
+	/**
1009
+	 * @throws EE_Error
1010
+	 */
1011
+	protected function _message_legend_items()
1012
+	{
1013
+		$action_css_classes = EEH_MSG_Template::get_message_action_icons();
1014
+		$action_items       = [];
1015
+
1016
+		foreach ($action_css_classes as $action_item => $action_details) {
1017
+			if ($action_item === 'see_notifications_for') {
1018
+				continue;
1019
+			}
1020
+			$action_items[ $action_item ] = [
1021
+				'class' => $action_details['css_class'],
1022
+				'desc'  => $action_details['label'],
1023
+			];
1024
+		}
1025
+
1026
+		/** @var array $status_items status legend setup */
1027
+		$status_items = [
1028
+			'sent_status'                => [
1029
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_sent,
1030
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1031
+			],
1032
+			'idle_status'                => [
1033
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_idle,
1034
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1035
+			],
1036
+			'failed_status'              => [
1037
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_failed,
1038
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1039
+			],
1040
+			'messenger_executing_status' => [
1041
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_messenger_executing,
1042
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1043
+			],
1044
+			'resend_status'              => [
1045
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_resend,
1046
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1047
+			],
1048
+			'incomplete_status'          => [
1049
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_incomplete,
1050
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1051
+			],
1052
+			'retry_status'               => [
1053
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_retry,
1054
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1055
+			],
1056
+		];
1057
+		if (EEM_Message::debug()) {
1058
+			$status_items['debug_only_status'] = [
1059
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_debug_only,
1060
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1061
+			];
1062
+		}
1063
+
1064
+		return array_merge($action_items, $status_items);
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * @throws EE_Error
1070
+	 */
1071
+	protected function _custom_mtps_preview()
1072
+	{
1073
+		$this->_admin_page_title              = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1074
+		$this->_template_args['preview_img']  = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1075
+												. ' alt="' . esc_attr__(
1076
+													'Preview Custom Message Templates screenshot',
1077
+													'event_espresso'
1078
+												) . '" />';
1079
+		$this->_template_args['preview_text'] = '<strong>'
1080
+												. esc_html__(
1081
+													'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1082
+													'event_espresso'
1083
+												)
1084
+												. '</strong>';
1085
+
1086
+		$this->display_admin_caf_preview_page('custom_message_types', false);
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * get_message_templates
1092
+	 * This gets all the message templates for listing on the overview list.
1093
+	 *
1094
+	 * @param int    $per_page the amount of templates groups to show per page
1095
+	 * @param string $type     the current _view we're getting templates for
1096
+	 * @param bool   $count    return count?
1097
+	 * @param bool   $all      disregard any paging info (get all data);
1098
+	 * @param bool   $global   whether to return just global (true) or custom templates (false)
1099
+	 * @return array|int
1100
+	 * @throws EE_Error
1101
+	 * @throws InvalidArgumentException
1102
+	 * @throws InvalidDataTypeException
1103
+	 * @throws InvalidInterfaceException
1104
+	 * @throws ReflectionException
1105
+	 */
1106
+	public function get_message_templates(
1107
+		int $per_page = 10,
1108
+		string $type = 'in_use',
1109
+		bool $count = false,
1110
+		bool $all = false,
1111
+		bool $global = true
1112
+	) {
1113
+		$orderby = $this->request->getRequestParam('orderby', 'GRP_ID');
1114
+		// ensure that the orderby param is actually set within the request data
1115
+		$this->request->setRequestParam('orderby', $orderby);
1116
+		$order        = $this->request->getRequestParam('order', 'ASC');
1117
+		$current_page = $this->request->getRequestParam('paged', 1, DataType::INTEGER);
1118
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, DataType::INTEGER);
1119
+
1120
+		$offset = ($current_page - 1) * $per_page;
1121
+		$limit  = $all ? null : [$offset, $per_page];
1122
+
1123
+		// options will match what is in the _views array property
1124
+		return $type === 'in_use'
1125
+			? $this->getMtgModel()->get_all_active_message_templates(
1126
+				$orderby,
1127
+				$order,
1128
+				$limit,
1129
+				$count,
1130
+				$global,
1131
+				true
1132
+			)
1133
+			: $this->getMtgModel()->get_all_trashed_grouped_message_templates(
1134
+				$orderby,
1135
+				$order,
1136
+				$limit,
1137
+				$count,
1138
+				$global
1139
+			);
1140
+	}
1141
+
1142
+
1143
+	/**
1144
+	 * filters etc might need a list of installed message_types
1145
+	 *
1146
+	 * @return array an array of message type objects
1147
+	 */
1148
+	public function get_installed_message_types(): array
1149
+	{
1150
+		$installed_message_types = $this->_message_resource_manager->installed_message_types();
1151
+		$installed               = [];
1152
+
1153
+		foreach ($installed_message_types as $message_type) {
1154
+			$installed[ $message_type->name ] = $message_type;
1155
+		}
1156
+
1157
+		return $installed;
1158
+	}
1159
+
1160
+
1161
+	/**
1162
+	 * This is used when creating a custom template. All Custom Templates start based off another template.
1163
+	 *
1164
+	 * @param string     $message_type
1165
+	 * @param string     $messenger
1166
+	 * @param int|string $GRP_ID
1167
+	 * @throws EE_error
1168
+	 * @throws ReflectionException
1169
+	 * @deprecated 5.0.8.p
1170
+	 */
1171
+	public function add_message_template(string $message_type = '', string $messenger = '', $GRP_ID = '')
1172
+	{
1173
+		$this->insertMessageTemplate();
1174
+	}
1175
+
1176
+
1177
+	/**
1178
+	 * @param string $message_type     message type slug
1179
+	 * @param string $messenger        messenger slug
1180
+	 * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1181
+	 *                                 off of.
1182
+	 * @throws EE_error
1183
+	 * @throws ReflectionException
1184
+	 * @deprecated 4.10.29.p
1185
+	 */
1186
+	protected function _add_message_template($message_type, $messenger, $GRP_ID)
1187
+	{
1188
+		$this->insertMessageTemplate($message_type, $messenger, $GRP_ID);
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * _edit_message_template
1194
+	 *
1195
+	 * @access protected
1196
+	 * @return void
1197
+	 * @throws InvalidIdentifierException
1198
+	 * @throws DomainException
1199
+	 * @throws EE_Error
1200
+	 * @throws InvalidArgumentException
1201
+	 * @throws ReflectionException
1202
+	 * @throws InvalidDataTypeException
1203
+	 * @throws InvalidInterfaceException
1204
+	 */
1205
+	protected function _edit_message_template()
1206
+	{
1207
+		$template_fields = '';
1208
+		$sidebar_fields  = '';
1209
+		// we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1210
+		// valid html in the templates.
1211
+		add_filter('tiny_mce_before_init', [$this, 'filter_tinymce_init'], 10, 2);
1212
+
1213
+		$GRP_ID = $this->request->getRequestParam('id', 0, DataType::INTEGER);
1214
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', $GRP_ID, DataType::INTEGER);
1215
+
1216
+		$EVT_ID = $this->request->getRequestParam('evt_id', 0, DataType::INTEGER);
1217
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', $EVT_ID, DataType::INTEGER);
1218
+
1219
+		$this->_set_shortcodes(); // this also sets the _message_template property.
1220
+		$message_template_group = $this->_message_template_group;
1221
+		$c_label                = $message_template_group->context_label();
1222
+		$c_config               = $message_template_group->contexts_config();
1223
+
1224
+		reset($c_config);
1225
+		$context = $this->request->getRequestParam('context', key($c_config));
1226
+		$context = strtolower($context);
1227
+
1228
+		$action = empty($GRP_ID) ? 'insert_message_template' : 'update_message_template';
1229
+
1230
+		$edit_message_template_form_url = add_query_arg(
1231
+			['action' => $action, 'noheader' => true],
1232
+			EE_MSG_ADMIN_URL
1233
+		);
1234
+
1235
+		// set active messenger for this view
1236
+		$this->_active_messenger         = $this->_message_resource_manager->get_active_messenger(
1237
+			$message_template_group->messenger()
1238
+		);
1239
+		$this->_active_message_type_name = $message_template_group->message_type();
1240
+
1241
+
1242
+		// Do we have any validation errors?
1243
+		$validators = $this->_get_transient();
1244
+		$v_fields   = ! empty($validators) ? array_keys($validators) : [];
1245
+
1246
+
1247
+		// we need to assemble the title from Various details
1248
+		$context_label = sprintf(
1249
+			esc_html__('(%s %s)', 'event_espresso'),
1250
+			$c_config[ $context ]['label'],
1251
+			ucwords($c_label['label'])
1252
+		);
1253
+
1254
+		$title = sprintf(
1255
+			esc_html__(' %s %s Template %s', 'event_espresso'),
1256
+			ucwords($message_template_group->messenger_obj()->label['singular']),
1257
+			ucwords($message_template_group->message_type_obj()->label['singular']),
1258
+			$context_label
1259
+		);
1260
+
1261
+		$this->_template_args['GRP_ID']           = $GRP_ID;
1262
+		$this->_template_args['message_template'] = $message_template_group;
1263
+		$this->_template_args['is_extra_fields']  = false;
1264
+
1265
+
1266
+		// let's get EEH_MSG_Template so we can get template form fields
1267
+		$template_field_structure = EEH_MSG_Template::get_fields(
1268
+			$message_template_group->messenger(),
1269
+			$message_template_group->message_type()
1270
+		);
1271
+
1272
+		if (! $template_field_structure) {
1273
+			$template_field_structure = false;
1274
+			$template_fields          = esc_html__(
1275
+				'There was an error in assembling the fields for this display (you should see an error message)',
1276
+				'event_espresso'
1277
+			);
1278
+		}
1279
+
1280
+		$message_templates = $message_template_group->context_templates();
1281
+
1282
+		// if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1283
+		// will get handled in the "extra" array.
1284
+		if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1285
+			foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1286
+				unset($template_field_structure[ $context ][ $reference_field ]);
1287
+			}
1288
+		}
1289
+
1290
+		// let's loop through the template_field_structure and actually assemble the input fields!
1291
+		if (! empty($template_field_structure)) {
1292
+			foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1293
+				// if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1294
+				// the extra array and reset them.
1295
+				if ($template_field === 'extra') {
1296
+					$this->_template_args['is_extra_fields'] = true;
1297
+					foreach ($field_setup_array as $reference_field => $new_fields_array) {
1298
+						$message_template = $message_templates[ $context ][ $reference_field ];
1299
+						$content          = $message_template instanceof EE_Message_Template
1300
+							? $message_template->get('MTP_content')
1301
+							: '';
1302
+						foreach ($new_fields_array as $extra_field => $extra_array) {
1303
+							// let's verify if we need this extra field via the shortcodes parameter.
1304
+							$continue = false;
1305
+							if (isset($extra_array['shortcodes_required'])) {
1306
+								foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1307
+									if (! array_key_exists($shortcode, $this->_shortcodes)) {
1308
+										$continue = true;
1309
+									}
1310
+								}
1311
+								if ($continue) {
1312
+									continue;
1313
+								}
1314
+							}
1315
+
1316
+							$field_id = $reference_field . '-' . $extra_field . '-content';
1317
+
1318
+							$template_form_fields[ $field_id ]         = $extra_array;
1319
+							$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1320
+																		 . $reference_field
1321
+																		 . '][content]['
1322
+																		 . $extra_field . ']';
1323
+							$css_class                                 = $extra_array['css_class'] ?? '';
1324
+
1325
+							$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1326
+																			  && in_array($extra_field, $v_fields, true)
1327
+																			  && (
1328
+																				  is_array($validators[ $extra_field ])
1329
+																				  && isset($validators[ $extra_field ]['msg'])
1330
+																			  )
1331
+								? 'validate-error ' . $css_class
1332
+								: $css_class;
1333
+
1334
+							$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1335
+																		  && isset($content[ $extra_field ])
1336
+								? $content[ $extra_field ]
1337
+								: '';
1338
+
1339
+							// do we have a validation error?  if we do then let's use that value instead
1340
+							$template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1341
+								? $validators[ $extra_field ]['value']
1342
+								: $template_form_fields[ $field_id ]['value'];
1343
+
1344
+
1345
+							$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1346
+
1347
+							// shortcode selector
1348
+							$field_name_to_use                                   = $extra_field === 'main'
1349
+								? 'content'
1350
+								: $extra_field;
1351
+							$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1352
+								$field_name_to_use,
1353
+								$field_id
1354
+							);
1355
+						}
1356
+						$template_field_MTP_id           = $reference_field . '-MTP_ID';
1357
+						$template_field_template_name_id = $reference_field . '-name';
1358
+
1359
+						$template_form_fields[ $template_field_MTP_id ] = [
1360
+							'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1361
+							'label'      => null,
1362
+							'input'      => 'hidden',
1363
+							'type'       => 'int',
1364
+							'required'   => false,
1365
+							'validation' => false,
1366
+							'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1367
+							'css_class'  => '',
1368
+							'format'     => '%d',
1369
+							'db-col'     => 'MTP_ID',
1370
+						];
1371
+
1372
+						$template_form_fields[ $template_field_template_name_id ] = [
1373
+							'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1374
+							'label'      => null,
1375
+							'input'      => 'hidden',
1376
+							'type'       => 'string',
1377
+							'required'   => false,
1378
+							'validation' => true,
1379
+							'value'      => $reference_field,
1380
+							'css_class'  => '',
1381
+							'format'     => '%s',
1382
+							'db-col'     => 'MTP_template_field',
1383
+						];
1384
+					}
1385
+					continue; // skip the next stuff, we got the necessary fields here for this dataset.
1386
+				} else {
1387
+					$field_id                                   = $template_field . '-content';
1388
+					$template_form_fields[ $field_id ]          = $field_setup_array;
1389
+					$template_form_fields[ $field_id ]['name']  =
1390
+						'MTP_template_fields[' . $template_field . '][content]';
1391
+					$message_template                           =
1392
+						$message_templates[ $context ][ $template_field ] ?? null;
1393
+					$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1394
+																  && is_array($message_templates[ $context ])
1395
+																  && $message_template instanceof EE_Message_Template
1396
+						? $message_template->get('MTP_content')
1397
+						: '';
1398
+
1399
+					// do we have a validator error for this field?  if we do then we'll use that value instead
1400
+					$template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1401
+						? $validators[ $template_field ]['value']
1402
+						: $template_form_fields[ $field_id ]['value'];
1403
+
1404
+
1405
+					$template_form_fields[ $field_id ]['db-col']    = 'MTP_content';
1406
+					$css_class                                      = $field_setup_array['css_class'] ?? '';
1407
+					$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1408
+																	  && in_array($template_field, $v_fields, true)
1409
+																	  && isset($validators[ $template_field ]['msg'])
1410
+						? 'validate-error ' . $css_class
1411
+						: $css_class;
1412
+
1413
+					// shortcode selector
1414
+					$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1415
+						$template_field,
1416
+						$field_id
1417
+					);
1418
+				}
1419
+
1420
+				// k took care of content field(s) now let's take care of others.
1421
+
1422
+				$template_field_MTP_id                 = $template_field . '-MTP_ID';
1423
+				$template_field_field_template_name_id = $template_field . '-name';
1424
+
1425
+				// foreach template field there are actually two form fields created
1426
+				$template_form_fields[ $template_field_MTP_id ] = [
1427
+					'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1428
+					'label'      => null,
1429
+					'input'      => 'hidden',
1430
+					'type'       => 'int',
1431
+					'required'   => false,
1432
+					'validation' => true,
1433
+					'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1434
+					'css_class'  => '',
1435
+					'format'     => '%d',
1436
+					'db-col'     => 'MTP_ID',
1437
+				];
1438
+
1439
+				$template_form_fields[ $template_field_field_template_name_id ] = [
1440
+					'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1441
+					'label'      => null,
1442
+					'input'      => 'hidden',
1443
+					'type'       => 'string',
1444
+					'required'   => false,
1445
+					'validation' => true,
1446
+					'value'      => $template_field,
1447
+					'css_class'  => '',
1448
+					'format'     => '%s',
1449
+					'db-col'     => 'MTP_template_field',
1450
+				];
1451
+			}
1452
+
1453
+			// add other fields
1454
+			$template_form_fields['ee-msg-current-context'] = [
1455
+				'name'       => 'MTP_context',
1456
+				'label'      => null,
1457
+				'input'      => 'hidden',
1458
+				'type'       => 'string',
1459
+				'required'   => false,
1460
+				'validation' => true,
1461
+				'value'      => $context,
1462
+				'css_class'  => '',
1463
+				'format'     => '%s',
1464
+				'db-col'     => 'MTP_context',
1465
+			];
1466
+
1467
+			$template_form_fields['ee-msg-grp-id'] = [
1468
+				'name'       => 'GRP_ID',
1469
+				'label'      => null,
1470
+				'input'      => 'hidden',
1471
+				'type'       => 'int',
1472
+				'required'   => false,
1473
+				'validation' => true,
1474
+				'value'      => $GRP_ID,
1475
+				'css_class'  => '',
1476
+				'format'     => '%d',
1477
+				'db-col'     => 'GRP_ID',
1478
+			];
1479
+
1480
+			$template_form_fields['ee-msg-messenger'] = [
1481
+				'name'       => 'MTP_messenger',
1482
+				'label'      => null,
1483
+				'input'      => 'hidden',
1484
+				'type'       => 'string',
1485
+				'required'   => false,
1486
+				'validation' => true,
1487
+				'value'      => $message_template_group->messenger(),
1488
+				'css_class'  => '',
1489
+				'format'     => '%s',
1490
+				'db-col'     => 'MTP_messenger',
1491
+			];
1492
+
1493
+			$template_form_fields['ee-msg-message-type'] = [
1494
+				'name'       => 'MTP_message_type',
1495
+				'label'      => null,
1496
+				'input'      => 'hidden',
1497
+				'type'       => 'string',
1498
+				'required'   => false,
1499
+				'validation' => true,
1500
+				'value'      => $message_template_group->message_type(),
1501
+				'css_class'  => '',
1502
+				'format'     => '%s',
1503
+				'db-col'     => 'MTP_message_type',
1504
+			];
1505
+
1506
+			$sidebar_form_fields['ee-msg-is-global'] = [
1507
+				'name'       => 'MTP_is_global',
1508
+				'label'      => esc_html__('Global Template', 'event_espresso'),
1509
+				'input'      => 'hidden',
1510
+				'type'       => 'int',
1511
+				'required'   => false,
1512
+				'validation' => true,
1513
+				'value'      => $message_template_group->get('MTP_is_global'),
1514
+				'css_class'  => '',
1515
+				'format'     => '%d',
1516
+				'db-col'     => 'MTP_is_global',
1517
+			];
1518
+
1519
+			$sidebar_form_fields['ee-msg-is-override'] = [
1520
+				'name'       => 'MTP_is_override',
1521
+				'label'      => esc_html__('Override all custom', 'event_espresso'),
1522
+				'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1523
+				'type'       => 'int',
1524
+				'required'   => false,
1525
+				'validation' => true,
1526
+				'value'      => $message_template_group->get('MTP_is_override'),
1527
+				'css_class'  => '',
1528
+				'format'     => '%d',
1529
+				'db-col'     => 'MTP_is_override',
1530
+			];
1531
+
1532
+			$sidebar_form_fields['ee-msg-is-active'] = [
1533
+				'name'       => 'MTP_is_active',
1534
+				'label'      => esc_html__('Active Template', 'event_espresso'),
1535
+				'input'      => 'hidden',
1536
+				'type'       => 'int',
1537
+				'required'   => false,
1538
+				'validation' => true,
1539
+				'value'      => $message_template_group->is_active(),
1540
+				'css_class'  => '',
1541
+				'format'     => '%d',
1542
+				'db-col'     => 'MTP_is_active',
1543
+			];
1544
+
1545
+			$sidebar_form_fields['ee-msg-deleted'] = [
1546
+				'name'       => 'MTP_deleted',
1547
+				'label'      => null,
1548
+				'input'      => 'hidden',
1549
+				'type'       => 'int',
1550
+				'required'   => false,
1551
+				'validation' => true,
1552
+				'value'      => $message_template_group->get('MTP_deleted'),
1553
+				'css_class'  => '',
1554
+				'format'     => '%d',
1555
+				'db-col'     => 'MTP_deleted',
1556
+			];
1557
+			$sidebar_form_fields['ee-msg-author']  = [
1558
+				'name'       => 'MTP_user_id',
1559
+				'label'      => esc_html__('Author', 'event_espresso'),
1560
+				'input'      => 'hidden',
1561
+				'type'       => 'int',
1562
+				'required'   => false,
1563
+				'validation' => false,
1564
+				'value'      => $message_template_group->user(),
1565
+				'format'     => '%d',
1566
+				'db-col'     => 'MTP_user_id',
1567
+			];
1568
+
1569
+			$sidebar_form_fields['ee-msg-route'] = [
1570
+				'name'  => 'action',
1571
+				'input' => 'hidden',
1572
+				'type'  => 'string',
1573
+				'value' => $action,
1574
+			];
1575
+
1576
+			$sidebar_form_fields['ee-msg-id']        = [
1577
+				'name'  => 'id',
1578
+				'input' => 'hidden',
1579
+				'type'  => 'int',
1580
+				'value' => $GRP_ID,
1581
+			];
1582
+			$sidebar_form_fields['ee-msg-evt-nonce'] = [
1583
+				'name'  => $action . '_nonce',
1584
+				'input' => 'hidden',
1585
+				'type'  => 'string',
1586
+				'value' => wp_create_nonce($action . '_nonce'),
1587
+			];
1588
+
1589
+			$template_switch = $this->request->getRequestParam('template_switch');
1590
+			if ($template_switch) {
1591
+				$sidebar_form_fields['ee-msg-template-switch'] = [
1592
+					'name'  => 'template_switch',
1593
+					'input' => 'hidden',
1594
+					'type'  => 'int',
1595
+					'value' => 1,
1596
+				];
1597
+			}
1598
+
1599
+
1600
+			$template_fields = $this->_generate_admin_form_fields($template_form_fields);
1601
+			$sidebar_fields  = $this->_generate_admin_form_fields($sidebar_form_fields);
1602
+		} //end if ( !empty($template_field_structure) )
1603
+
1604
+		// set extra content for publish box
1605
+		$this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1606
+		$this->_set_publish_post_box_vars(
1607
+			'id',
1608
+			$GRP_ID,
1609
+			'',
1610
+			add_query_arg(
1611
+				['action' => $message_template_group->is_global() ? 'global_mtps' : 'custom_mtps'],
1612
+				$this->_admin_base_url
1613
+			),
1614
+			true
1615
+		);
1616
+
1617
+		// add preview button
1618
+		$preview_url    = parent::add_query_args_and_nonce(
1619
+			[
1620
+				'message_type' => $message_template_group->message_type(),
1621
+				'messenger'    => $message_template_group->messenger(),
1622
+				'context'      => $context,
1623
+				'GRP_ID'       => $GRP_ID,
1624
+				'evt_id'       => $EVT_ID ?: false,
1625
+				'action'       => 'preview_message',
1626
+			],
1627
+			$this->_admin_base_url
1628
+		);
1629
+		$preview_button = '<a href="' . $preview_url . '" class="button--secondary messages-preview-button">'
1630
+						  . esc_html__('Preview', 'event_espresso')
1631
+						  . '</a>';
1632
+
1633
+
1634
+		// setup context switcher
1635
+		$this->_set_context_switcher(
1636
+			$message_template_group,
1637
+			[
1638
+				'page'    => 'espresso_messages',
1639
+				'action'  => 'edit_message_template',
1640
+				'id'      => $GRP_ID,
1641
+				'evt_id'  => $EVT_ID,
1642
+				'context' => $context,
1643
+				'extra'   => $preview_button,
1644
+			]
1645
+		);
1646
+
1647
+		// main box
1648
+		$this->_template_args['template_fields']                         = $template_fields;
1649
+		$this->_template_args['sidebar_box_id']                          = 'details';
1650
+		$this->_template_args['action']                                  = $action;
1651
+		$this->_template_args['context']                                 = $context;
1652
+		$this->_template_args['edit_message_template_form_url']          = $edit_message_template_form_url;
1653
+		$this->_template_args['learn_more_about_message_templates_link'] =
1654
+			$this->_learn_more_about_message_templates_link();
1655
+
1656
+		$this->_template_args['before_admin_page_content'] = '<div class="ee-msg-admin-header">';
1657
+		$this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1658
+			$message_template_group,
1659
+			$context,
1660
+			$context_label
1661
+		);
1662
+		$this->_template_args['before_admin_page_content'] .= $this->add_context_switcher();
1663
+		$this->_template_args['before_admin_page_content'] .= '</div>';
1664
+		$this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1665
+		$this->_template_args['after_admin_page_content']  = $this->_add_form_element_after();
1666
+
1667
+		$this->_template_path = $this->_template_args['GRP_ID']
1668
+			? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1669
+			: EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1670
+
1671
+		// send along EE_Message_Template_Group object for further template use.
1672
+		$this->_template_args['MTP'] = $message_template_group;
1673
+
1674
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1675
+			$this->_template_path,
1676
+			$this->_template_args,
1677
+			true
1678
+		);
1679
+
1680
+		// finally, let's set the admin_page title
1681
+		$this->_admin_page_title = sprintf(esc_html__('Editing %s', 'event_espresso'), $title);
1682
+
1683
+		// we need to take care of setting the shortcodes property for use elsewhere.
1684
+		$this->_set_shortcodes();
1685
+
1686
+		// final template wrapper
1687
+		$this->display_admin_page_with_sidebar();
1688
+	}
1689
+
1690
+
1691
+	public function filter_tinymce_init($mceInit, $editor_id)
1692
+	{
1693
+		return $mceInit;
1694
+	}
1695
+
1696
+
1697
+	public function add_context_switcher()
1698
+	{
1699
+		return $this->_context_switcher;
1700
+	}
1701
+
1702
+
1703
+	/**
1704
+	 * Adds the activation/deactivation toggle for the message template context.
1705
+	 *
1706
+	 * @param EE_Message_Template_Group $message_template_group
1707
+	 * @param string                    $context
1708
+	 * @param string                    $context_label
1709
+	 * @return string
1710
+	 * @throws DomainException
1711
+	 * @throws EE_Error
1712
+	 * @throws InvalidIdentifierException
1713
+	 * @throws ReflectionException
1714
+	 */
1715
+	protected function add_active_context_element(
1716
+		EE_Message_Template_Group $message_template_group,
1717
+		$context,
1718
+		$context_label
1719
+	) {
1720
+		$template_args = [
1721
+			'context'                   => $context,
1722
+			'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1723
+			'is_active'                 => $message_template_group->is_context_active($context),
1724
+			'on_off_action'             => $message_template_group->is_context_active($context)
1725
+				? 'context-off'
1726
+				: 'context-on',
1727
+			'context_label'             => str_replace(['(', ')'], '', $context_label),
1728
+			'message_template_group_id' => $message_template_group->ID(),
1729
+		];
1730
+		return EEH_Template::display_template(
1731
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1732
+			$template_args,
1733
+			true
1734
+		);
1735
+	}
1736
+
1737
+
1738
+	/**
1739
+	 * Ajax callback for `toggle_context_template` ajax action.
1740
+	 * Handles toggling the message context on or off.
1741
+	 *
1742
+	 * @throws EE_Error
1743
+	 * @throws InvalidArgumentException
1744
+	 * @throws InvalidDataTypeException
1745
+	 * @throws InvalidIdentifierException
1746
+	 * @throws InvalidInterfaceException
1747
+	 * @throws ReflectionException
1748
+	 */
1749
+	public function toggle_context_template()
1750
+	{
1751
+		if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1752
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1753
+		}
1754
+		$success = true;
1755
+		// check for required data
1756
+		if (
1757
+			! (
1758
+				$this->request->requestParamIsSet('message_template_group_id')
1759
+				&& $this->request->requestParamIsSet('context')
1760
+				&& $this->request->requestParamIsSet('status')
1761
+			)
1762
+		) {
1763
+			EE_Error::add_error(
1764
+				esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1765
+				__FILE__,
1766
+				__FUNCTION__,
1767
+				__LINE__
1768
+			);
1769
+			$success = false;
1770
+		}
1771
+
1772
+		$nonce   = $this->request->getRequestParam('toggle_context_nonce', '');
1773
+		$context = $this->request->getRequestParam('context', '');
1774
+		$status  = $this->request->getRequestParam('status', '');
1775
+
1776
+		$this->_verify_nonce($nonce, "activate_{$context}_toggle_nonce");
1777
+
1778
+		if ($status !== 'off' && $status !== 'on') {
1779
+			EE_Error::add_error(
1780
+				sprintf(
1781
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1782
+					$status
1783
+				),
1784
+				__FILE__,
1785
+				__FUNCTION__,
1786
+				__LINE__
1787
+			);
1788
+			$success = false;
1789
+		}
1790
+		$message_template_group_id = $this->request->getRequestParam('message_template_group_id', 0, DataType::INTEGER);
1791
+		$message_template_group    = $this->getMtgModel()->get_one_by_ID($message_template_group_id);
1792
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
1793
+			EE_Error::add_error(
1794
+				sprintf(
1795
+					esc_html__(
1796
+						'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1797
+						'event_espresso'
1798
+					),
1799
+					$message_template_group_id,
1800
+					'EE_Message_Template_Group'
1801
+				),
1802
+				__FILE__,
1803
+				__FUNCTION__,
1804
+				__LINE__
1805
+			);
1806
+			$success = false;
1807
+		}
1808
+		if ($success) {
1809
+			$success = $status === 'off'
1810
+				? $message_template_group->deactivate_context($context)
1811
+				: $message_template_group->activate_context($context);
1812
+		}
1813
+		$this->_template_args['success'] = $success;
1814
+		$this->_return_json();
1815
+	}
1816
+
1817
+
1818
+	public function _add_form_element_before()
1819
+	{
1820
+		return '<form method="post" action="'
1821
+			   . $this->_template_args['edit_message_template_form_url']
1822
+			   . '" id="ee-msg-edit-frm">';
1823
+	}
1824
+
1825
+
1826
+	public function _add_form_element_after()
1827
+	{
1828
+		return '</form>';
1829
+	}
1830
+
1831
+
1832
+	/**
1833
+	 * This executes switching the template pack for a message template.
1834
+	 *
1835
+	 * @throws EE_Error
1836
+	 * @throws InvalidDataTypeException
1837
+	 * @throws InvalidInterfaceException
1838
+	 * @throws InvalidArgumentException
1839
+	 * @throws ReflectionException
1840
+	 * @since 4.5.0
1841
+	 */
1842
+	public function switch_template_pack()
1843
+	{
1844
+		if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1845
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1846
+		}
1847
+		$GRP_ID        = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
1848
+		$template_pack = $this->request->getRequestParam('template_pack', '');
1849
+
1850
+		// verify we have needed values.
1851
+		if (empty($GRP_ID) || empty($template_pack)) {
1852
+			$this->_template_args['error'] = true;
1853
+			EE_Error::add_error(
1854
+				esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1855
+				__FILE__,
1856
+				__FUNCTION__,
1857
+				__LINE__
1858
+			);
1859
+		} else {
1860
+			// get template, set the new template_pack and then reset to default
1861
+			/** @var EE_Message_Template_Group $message_template_group */
1862
+			$message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
1863
+
1864
+			$message_template_group->set_template_pack_name($template_pack);
1865
+			$this->request->setRequestParam('msgr', $message_template_group->messenger());
1866
+			$this->request->setRequestParam('mt', $message_template_group->message_type());
1867
+
1868
+			$query_args = $this->_reset_to_default_template();
1869
+
1870
+			if (empty($query_args['id'])) {
1871
+				EE_Error::add_error(
1872
+					esc_html__(
1873
+						'Something went wrong with switching the template pack. Please try again or contact EE support',
1874
+						'event_espresso'
1875
+					),
1876
+					__FILE__,
1877
+					__FUNCTION__,
1878
+					__LINE__
1879
+				);
1880
+				$this->_template_args['error'] = true;
1881
+			} else {
1882
+				$template_label       = $message_template_group->get_template_pack()->label;
1883
+				$template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
1884
+				EE_Error::add_success(
1885
+					sprintf(
1886
+						esc_html__(
1887
+							'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
1888
+							'event_espresso'
1889
+						),
1890
+						$template_label,
1891
+						$template_pack_labels->template_pack
1892
+					)
1893
+				);
1894
+				// generate the redirect url for js.
1895
+				$url = self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1896
+
1897
+				$this->_template_args['data']['redirect_url'] = $url;
1898
+				$this->_template_args['success']              = true;
1899
+			}
1900
+
1901
+			$this->_return_json();
1902
+		}
1903
+	}
1904
+
1905
+
1906
+	/**
1907
+	 * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
1908
+	 * they want.
1909
+	 *
1910
+	 * @access protected
1911
+	 * @return array|void
1912
+	 * @throws EE_Error
1913
+	 * @throws InvalidArgumentException
1914
+	 * @throws InvalidDataTypeException
1915
+	 * @throws InvalidInterfaceException
1916
+	 * @throws ReflectionException
1917
+	 */
1918
+	protected function _reset_to_default_template()
1919
+	{
1920
+		$templates    = [];
1921
+		$GRP_ID       = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
1922
+		$messenger    = $this->request->getRequestParam('msgr');
1923
+		$message_type = $this->request->getRequestParam('mt');
1924
+		// we need to make sure we've got the info we need.
1925
+		if (! ($GRP_ID && $messenger && $message_type)) {
1926
+			EE_Error::add_error(
1927
+				esc_html__(
1928
+					'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
1929
+					'event_espresso'
1930
+				),
1931
+				__FILE__,
1932
+				__FUNCTION__,
1933
+				__LINE__
1934
+			);
1935
+		}
1936
+
1937
+		// all templates will be reset to whatever the defaults are
1938
+		// for the global template matching the messenger and message type.
1939
+		$success = ! empty($GRP_ID);
1940
+
1941
+		if ($success) {
1942
+			// let's first determine if the incoming template is a global template,
1943
+			// if it isn't then we need to get the global template matching messenger and message type.
1944
+			// $MTPG = $this->getMtgModel()->get_one_by_ID( $GRP_ID );
1945
+
1946
+
1947
+			// note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
1948
+			$success = $this->getMessageTemplateManager()->permanentlyDeleteMessageTemplates($GRP_ID);
1949
+
1950
+			if ($success) {
1951
+				// if successfully deleted, lets generate the new ones.
1952
+				// Note. We set GLOBAL to true, because resets on ANY template
1953
+				// will use the related global template defaults for regeneration.
1954
+				// This means that if a custom template is reset it resets to whatever the related global template is.
1955
+				// HOWEVER, we DO keep the template pack and template variation set
1956
+				// for the current custom template when resetting.
1957
+				$templates = $this->getMessageTemplateManager()->generateNewTemplates(
1958
+					$messenger,
1959
+					$message_type,
1960
+					$GRP_ID,
1961
+					true
1962
+				);
1963
+			}
1964
+		}
1965
+
1966
+		// any error messages?
1967
+		if (! $success) {
1968
+			EE_Error::add_error(
1969
+				esc_html__(
1970
+					'Something went wrong with deleting existing templates. Unable to reset to default',
1971
+					'event_espresso'
1972
+				),
1973
+				__FILE__,
1974
+				__FUNCTION__,
1975
+				__LINE__
1976
+			);
1977
+		}
1978
+
1979
+		// all good, let's add a success message!
1980
+		if ($success && ! empty($templates)) {
1981
+			// the info for the template we generated is the first element in the returned array
1982
+			EE_Error::overwrite_success();
1983
+			EE_Error::add_success(esc_html__('Templates have been reset to defaults.', 'event_espresso'));
1984
+		}
1985
+
1986
+
1987
+		$query_args = [
1988
+			'id'      => $templates['GRP_ID'] ?? null,
1989
+			'context' => $templates['MTP_context'] ?? null,
1990
+			'action'  => isset($templates['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
1991
+		];
1992
+
1993
+		// if called via ajax then we return query args otherwise redirect
1994
+		if ($this->request->isAjax()) {
1995
+			return $query_args;
1996
+		}
1997
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1998
+	}
1999
+
2000
+
2001
+	/**
2002
+	 * Retrieve and set the message preview for display.
2003
+	 *
2004
+	 * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2005
+	 * @return string
2006
+	 * @throws ReflectionException
2007
+	 * @throws EE_Error
2008
+	 * @throws InvalidArgumentException
2009
+	 * @throws InvalidDataTypeException
2010
+	 * @throws InvalidInterfaceException
2011
+	 */
2012
+	public function _preview_message($send = false)
2013
+	{
2014
+		// first make sure we've got the necessary parameters
2015
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
2016
+		if (! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2017
+			EE_Error::add_error(
2018
+				esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2019
+				__FILE__,
2020
+				__FUNCTION__,
2021
+				__LINE__
2022
+			);
2023
+		}
2024
+
2025
+		$context = $this->request->getRequestParam('context');
2026
+		// get the preview!
2027
+		$preview = EED_Messages::preview_message(
2028
+			$this->_active_message_type_name,
2029
+			$context,
2030
+			$this->_active_messenger_name,
2031
+			$send
2032
+		);
2033
+
2034
+		if ($send) {
2035
+			return $preview;
2036
+		}
2037
+
2038
+		// if we have an evt_id set on the request, use it.
2039
+		$EVT_ID = $this->request->getRequestParam('evt_id', 0, DataType::INTEGER);
2040
+
2041
+		// let's add a button to go back to the edit view
2042
+		$query_args             = [
2043
+			'id'      => $GRP_ID,
2044
+			'evt_id'  => $EVT_ID,
2045
+			'context' => $context,
2046
+			'action'  => 'edit_message_template',
2047
+		];
2048
+		$go_back_url            = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2049
+		$preview_button         = '<a href="'
2050
+								  . $go_back_url
2051
+								  . '" class="button--secondary messages-preview-go-back-button">'
2052
+								  . esc_html__('Go Back to Edit', 'event_espresso')
2053
+								  . '</a>';
2054
+		$message_types          = $this->get_installed_message_types();
2055
+		$active_messenger       = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
2056
+		$active_messenger_label = $active_messenger instanceof EE_messenger
2057
+			? ucwords($active_messenger->label['singular'])
2058
+			: esc_html__('Unknown Messenger', 'event_espresso');
2059
+		// let's provide a helpful title for context
2060
+		$preview_title = sprintf(
2061
+			esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2062
+			$active_messenger_label,
2063
+			ucwords($message_types[ $this->_active_message_type_name ]->label['singular'])
2064
+		);
2065
+		if (empty($preview)) {
2066
+			$this->noEventsErrorMessage();
2067
+		}
2068
+		// setup display of preview.
2069
+		$this->_admin_page_title                    = $preview_title;
2070
+		$this->_template_args['admin_page_title']   = $preview_title;
2071
+		$this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2072
+		$this->_template_args['data']['force_json'] = true;
2073
+
2074
+		return '';
2075
+	}
2076
+
2077
+
2078
+	/**
2079
+	 * Used to set an error if there are no events available for generating a preview/test send.
2080
+	 *
2081
+	 * @param bool $test_send Whether the error should be generated for the context of a test send.
2082
+	 */
2083
+	protected function noEventsErrorMessage($test_send = false)
2084
+	{
2085
+		$events_url = parent::add_query_args_and_nonce(
2086
+			[
2087
+				'action' => 'default',
2088
+				'page'   => 'espresso_events',
2089
+			],
2090
+			admin_url('admin.php')
2091
+		);
2092
+		$message    = $test_send
2093
+			? esc_html__(
2094
+				'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2095
+				'event_espresso'
2096
+			)
2097
+			: esc_html__(
2098
+				'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2099
+				'event_espresso'
2100
+			);
2101
+
2102
+		EE_Error::add_attention(
2103
+			sprintf(
2104
+				$message,
2105
+				"<a href='{$events_url}'>",
2106
+				'</a>'
2107
+			)
2108
+		);
2109
+	}
2110
+
2111
+
2112
+	/**
2113
+	 * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2114
+	 * gets called automatically.
2115
+	 *
2116
+	 * @return void
2117
+	 * @throws EE_Error
2118
+	 * @since 4.5.0
2119
+	 */
2120
+	protected function _display_preview_message()
2121
+	{
2122
+		$this->display_admin_page_with_no_sidebar();
2123
+	}
2124
+
2125
+
2126
+	/**
2127
+	 * registers metaboxes that should show up on the "edit_message_template" page
2128
+	 *
2129
+	 * @access protected
2130
+	 * @return void
2131
+	 */
2132
+	protected function _register_edit_meta_boxes()
2133
+	{
2134
+		$this->addMetaBox(
2135
+			'mtp_valid_shortcodes',
2136
+			esc_html__('Valid Shortcodes', 'event_espresso'),
2137
+			[$this, 'shortcode_meta_box'],
2138
+			$this->_current_screen->id,
2139
+			'side'
2140
+		);
2141
+		$this->addMetaBox(
2142
+			'mtp_extra_actions',
2143
+			esc_html__('Extra Actions', 'event_espresso'),
2144
+			[$this, 'extra_actions_meta_box'],
2145
+			$this->_current_screen->id,
2146
+			'side',
2147
+			'high'
2148
+		);
2149
+		$this->addMetaBox(
2150
+			'mtp_templates',
2151
+			esc_html__('Template Styles', 'event_espresso'),
2152
+			[$this, 'template_pack_meta_box'],
2153
+			$this->_current_screen->id,
2154
+			'side',
2155
+			'high'
2156
+		);
2157
+	}
2158
+
2159
+
2160
+	/**
2161
+	 * metabox content for all template pack and variation selection.
2162
+	 *
2163
+	 * @return void
2164
+	 * @throws DomainException
2165
+	 * @throws EE_Error
2166
+	 * @throws InvalidArgumentException
2167
+	 * @throws ReflectionException
2168
+	 * @throws InvalidDataTypeException
2169
+	 * @throws InvalidInterfaceException
2170
+	 * @since 4.5.0
2171
+	 */
2172
+	public function template_pack_meta_box()
2173
+	{
2174
+		$this->_set_message_template_group();
2175
+
2176
+		$tp_collection = EEH_MSG_Template::get_template_pack_collection();
2177
+
2178
+		$tp_select_values = [];
2179
+
2180
+		foreach ($tp_collection as $tp) {
2181
+			// only include template packs that support this messenger and message type!
2182
+			$supports = $tp->get_supports();
2183
+			if (
2184
+				! isset($supports[ $this->_message_template_group->messenger() ])
2185
+				|| ! in_array(
2186
+					$this->_message_template_group->message_type(),
2187
+					$supports[ $this->_message_template_group->messenger() ],
2188
+					true
2189
+				)
2190
+			) {
2191
+				// not supported
2192
+				continue;
2193
+			}
2194
+
2195
+			$tp_select_values[] = [
2196
+				'text' => $tp->label,
2197
+				'id'   => $tp->dbref,
2198
+			];
2199
+		}
2200
+
2201
+		// if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2202
+		// the default template pack.  This still allows for the odd template pack to override.
2203
+		if (empty($tp_select_values)) {
2204
+			$tp_select_values[] = [
2205
+				'text' => esc_html__('Default', 'event_espresso'),
2206
+				'id'   => 'default',
2207
+			];
2208
+		}
2209
+
2210
+		// setup variation select values for the currently selected template.
2211
+		$variations               = $this->_message_template_group->get_template_pack()->get_variations(
2212
+			$this->_message_template_group->messenger(),
2213
+			$this->_message_template_group->message_type()
2214
+		);
2215
+		$variations_select_values = [];
2216
+		foreach ($variations as $variation => $label) {
2217
+			$variations_select_values[] = [
2218
+				'text' => $label,
2219
+				'id'   => $variation,
2220
+			];
2221
+		}
2222
+
2223
+		$template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2224
+
2225
+		$template_args['template_packs_selector']        = EEH_Form_Fields::select_input(
2226
+			'MTP_template_pack',
2227
+			$tp_select_values,
2228
+			$this->_message_template_group->get_template_pack_name()
2229
+		);
2230
+		$template_args['variations_selector']            = EEH_Form_Fields::select_input(
2231
+			'MTP_template_variation',
2232
+			$variations_select_values,
2233
+			$this->_message_template_group->get_template_pack_variation()
2234
+		);
2235
+		$template_args['template_pack_label']            = $template_pack_labels->template_pack;
2236
+		$template_args['template_variation_label']       = $template_pack_labels->template_variation;
2237
+		$template_args['template_pack_description']      = $template_pack_labels->template_pack_description;
2238
+		$template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2239
+
2240
+		$template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2241
+
2242
+		EEH_Template::display_template($template, $template_args);
2243
+	}
2244
+
2245
+
2246
+	/**
2247
+	 * This meta box holds any extra actions related to Message Templates
2248
+	 * For now, this includes Resetting templates to defaults and sending a test email.
2249
+	 *
2250
+	 * @access  public
2251
+	 * @return void
2252
+	 * @throws EE_Error
2253
+	 */
2254
+	public function extra_actions_meta_box()
2255
+	{
2256
+		$template_form_fields = [];
2257
+
2258
+		$extra_args = [
2259
+			'msgr'   => $this->_message_template_group->messenger(),
2260
+			'mt'     => $this->_message_template_group->message_type(),
2261
+			'GRP_ID' => $this->_message_template_group->GRP_ID(),
2262
+		];
2263
+		// first we need to see if there are any fields
2264
+		$fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2265
+
2266
+		if (! empty($fields)) {
2267
+			// yup there be fields
2268
+			foreach ($fields as $field => $config) {
2269
+				$field_id = $this->_message_template_group->messenger() . '_' . $field;
2270
+				$existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2271
+				$default  = $config['default'] ?? '';
2272
+				$default  = $config['value'] ?? $default;
2273
+
2274
+				// if type is hidden and the value is empty
2275
+				// something may have gone wrong so let's correct with the defaults
2276
+				$fix                = $config['input'] === 'hidden'
2277
+									  && isset($existing[ $field ])
2278
+									  && empty($existing[ $field ])
2279
+					? $default
2280
+					: '';
2281
+				$existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2282
+					? $existing[ $field ]
2283
+					: $fix;
2284
+
2285
+				$template_form_fields[ $field_id ] = [
2286
+					'name'       => 'test_settings_fld[' . $field . ']',
2287
+					'label'      => $config['label'],
2288
+					'input'      => $config['input'],
2289
+					'type'       => $config['type'],
2290
+					'required'   => $config['required'],
2291
+					'validation' => $config['validation'],
2292
+					'value'      => $existing[ $field ] ?? $default,
2293
+					'css_class'  => $config['css_class'],
2294
+					'options'    => $config['options'] ?? [],
2295
+					'default'    => $default,
2296
+					'format'     => $config['format'],
2297
+				];
2298
+			}
2299
+		}
2300
+
2301
+		$test_settings_html = ! empty($template_form_fields)
2302
+			? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2303
+			: '';
2304
+
2305
+		// print out $test_settings_fields
2306
+		if (! empty($test_settings_html)) {
2307
+			$test_settings_html .= '<input type="submit" class="button--primary mtp-test-button alignright" ';
2308
+			$test_settings_html .= 'name="test_button" value="';
2309
+			$test_settings_html .= esc_html__('Test Send', 'event_espresso');
2310
+			$test_settings_html .= '" /><div style="clear:both"></div>';
2311
+		}
2312
+
2313
+		// and button
2314
+		$test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2315
+		$test_settings_html .= '<p>';
2316
+		$test_settings_html .= esc_html__('Need to reset this message type and start over?', 'event_espresso');
2317
+		$test_settings_html .= '</p>';
2318
+		$test_settings_html .= $this->get_action_link_or_button(
2319
+			'reset_to_default',
2320
+			'reset',
2321
+			$extra_args,
2322
+			'button--primary reset-default-button'
2323
+		);
2324
+		$test_settings_html .= '</div><div style="clear:both"></div>';
2325
+		echo wp_kses($test_settings_html, AllowedTags::getWithFormTags());
2326
+	}
2327
+
2328
+
2329
+	/**
2330
+	 * This returns the shortcode selector skeleton for a given context and field.
2331
+	 *
2332
+	 * @param string $field           The name of the field retrieving shortcodes for.
2333
+	 * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2334
+	 * @return string
2335
+	 * @throws DomainException
2336
+	 * @throws EE_Error
2337
+	 * @throws InvalidArgumentException
2338
+	 * @throws ReflectionException
2339
+	 * @throws InvalidDataTypeException
2340
+	 * @throws InvalidInterfaceException
2341
+	 * @since 4.9.rc.000
2342
+	 */
2343
+	protected function _get_shortcode_selector($field, $linked_input_id)
2344
+	{
2345
+		$template_args = [
2346
+			'shortcodes'      => $this->_get_shortcodes([$field]),
2347
+			'fieldname'       => $field,
2348
+			'linked_input_id' => $linked_input_id,
2349
+		];
2350
+
2351
+		return EEH_Template::display_template(
2352
+			EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2353
+			$template_args,
2354
+			true
2355
+		);
2356
+	}
2357
+
2358
+
2359
+	/**
2360
+	 * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2361
+	 * page)
2362
+	 *
2363
+	 * @access public
2364
+	 * @return void
2365
+	 * @throws EE_Error
2366
+	 * @throws InvalidArgumentException
2367
+	 * @throws ReflectionException
2368
+	 * @throws InvalidDataTypeException
2369
+	 * @throws InvalidInterfaceException
2370
+	 */
2371
+	public function shortcode_meta_box()
2372
+	{
2373
+		$shortcodes = $this->_get_shortcodes([], false);
2374
+		// just make sure the shortcodes property is set
2375
+		// $messenger = $this->_message_template_group->messenger_obj();
2376
+		// now let's set the content depending on the status of the shortcodes array
2377
+		if (empty($shortcodes)) {
2378
+			echo '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2379
+			return;
2380
+		}
2381
+		?>
2382 2382
         <div style="float:right; margin-top:10px">
2383 2383
             <?php echo wp_kses($this->_get_help_tab_link('message_template_shortcodes'), AllowedTags::getAllowedTags());
2384
-            ?>
2384
+			?>
2385 2385
         </div>
2386 2386
         <p class="small-text">
2387 2387
             <?php printf(
2388
-                esc_html__(
2389
-                    'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2390
-                    'event_espresso'
2391
-                ),
2392
-                '<span class="dashicons dashicons-shortcode"></span>'
2393
-            ); ?>
2388
+				esc_html__(
2389
+					'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2390
+					'event_espresso'
2391
+				),
2392
+				'<span class="dashicons dashicons-shortcode"></span>'
2393
+			); ?>
2394 2394
         </p>
2395 2395
         <?php
2396
-    }
2397
-
2398
-
2399
-    /**
2400
-     * used to set the $_shortcodes property for when its needed elsewhere.
2401
-     *
2402
-     * @access protected
2403
-     * @return void
2404
-     * @throws EE_Error
2405
-     * @throws InvalidArgumentException
2406
-     * @throws ReflectionException
2407
-     * @throws InvalidDataTypeException
2408
-     * @throws InvalidInterfaceException
2409
-     */
2410
-    protected function _set_shortcodes()
2411
-    {
2412
-        // no need to run this if the property is already set
2413
-        if (! empty($this->_shortcodes)) {
2414
-            return;
2415
-        }
2416
-
2417
-        $this->_shortcodes = $this->_get_shortcodes();
2418
-    }
2419
-
2420
-
2421
-    /**
2422
-     * gets all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2423
-     * property)
2424
-     *
2425
-     * @access  protected
2426
-     * @param array   $fields  include an array of specific field names that you want to be used to get the shortcodes
2427
-     *                         for. Defaults to all (for the given context)
2428
-     * @param boolean $merged  Whether to merge all the shortcodes into one list of unique shortcodes
2429
-     * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2430
-     *                         true just an array of shortcode/label pairs.
2431
-     * @throws EE_Error
2432
-     * @throws InvalidArgumentException
2433
-     * @throws ReflectionException
2434
-     * @throws InvalidDataTypeException
2435
-     * @throws InvalidInterfaceException
2436
-     */
2437
-    protected function _get_shortcodes(array $fields = [], bool $merged = true): array
2438
-    {
2439
-        $this->_set_message_template_group();
2440
-
2441
-        // we need the messenger and message template to retrieve the valid shortcodes array.
2442
-        $GRP_ID = $this->request->getRequestParam('id', 0, DataType::INTEGER);
2443
-        if (empty($GRP_ID)) {
2444
-            return [];
2445
-        }
2446
-        $context = $this->request->getRequestParam(
2447
-            'messenger',
2448
-            key($this->_message_template_group->contexts_config())
2449
-        );
2450
-        return $this->_message_template_group->get_shortcodes($context, $fields, $merged);
2451
-    }
2452
-
2453
-
2454
-    /**
2455
-     * This sets the _message_template property (containing the called message_template object)
2456
-     *
2457
-     * @access protected
2458
-     * @return void
2459
-     * @throws EE_Error
2460
-     * @throws InvalidArgumentException
2461
-     * @throws ReflectionException
2462
-     * @throws InvalidDataTypeException
2463
-     * @throws InvalidInterfaceException
2464
-     */
2465
-    protected function _set_message_template_group()
2466
-    {
2467
-        // get out if this is already set.
2468
-        if (! empty($this->_message_template_group)) {
2469
-            return;
2470
-        }
2471
-
2472
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
2473
-        $GRP_ID = $this->request->getRequestParam('id', $GRP_ID, DataType::INTEGER);
2474
-
2475
-        // let's get the message templates
2476
-        $this->_message_template_group = ! empty($GRP_ID)
2477
-            ? $this->getMtgModel()->get_one_by_ID($GRP_ID)
2478
-            : $this->getMtgModel()->create_default_object();
2479
-
2480
-        $this->_template_pack = $this->_message_template_group->get_template_pack();
2481
-        $this->_variation     = $this->_message_template_group->get_template_pack_variation();
2482
-    }
2483
-
2484
-
2485
-    /**
2486
-     * sets up a context switcher for edit forms
2487
-     *
2488
-     * @access  protected
2489
-     * @param EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2490
-     * @param array                     $args                  various things the context switcher needs.
2491
-     * @throws EE_Error
2492
-     */
2493
-    protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, array $args)
2494
-    {
2495
-        $context_details = $template_group_object->contexts_config();
2496
-        $context_label   = $template_group_object->context_label();
2497
-        ob_start();
2498
-        ?>
2396
+	}
2397
+
2398
+
2399
+	/**
2400
+	 * used to set the $_shortcodes property for when its needed elsewhere.
2401
+	 *
2402
+	 * @access protected
2403
+	 * @return void
2404
+	 * @throws EE_Error
2405
+	 * @throws InvalidArgumentException
2406
+	 * @throws ReflectionException
2407
+	 * @throws InvalidDataTypeException
2408
+	 * @throws InvalidInterfaceException
2409
+	 */
2410
+	protected function _set_shortcodes()
2411
+	{
2412
+		// no need to run this if the property is already set
2413
+		if (! empty($this->_shortcodes)) {
2414
+			return;
2415
+		}
2416
+
2417
+		$this->_shortcodes = $this->_get_shortcodes();
2418
+	}
2419
+
2420
+
2421
+	/**
2422
+	 * gets all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2423
+	 * property)
2424
+	 *
2425
+	 * @access  protected
2426
+	 * @param array   $fields  include an array of specific field names that you want to be used to get the shortcodes
2427
+	 *                         for. Defaults to all (for the given context)
2428
+	 * @param boolean $merged  Whether to merge all the shortcodes into one list of unique shortcodes
2429
+	 * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2430
+	 *                         true just an array of shortcode/label pairs.
2431
+	 * @throws EE_Error
2432
+	 * @throws InvalidArgumentException
2433
+	 * @throws ReflectionException
2434
+	 * @throws InvalidDataTypeException
2435
+	 * @throws InvalidInterfaceException
2436
+	 */
2437
+	protected function _get_shortcodes(array $fields = [], bool $merged = true): array
2438
+	{
2439
+		$this->_set_message_template_group();
2440
+
2441
+		// we need the messenger and message template to retrieve the valid shortcodes array.
2442
+		$GRP_ID = $this->request->getRequestParam('id', 0, DataType::INTEGER);
2443
+		if (empty($GRP_ID)) {
2444
+			return [];
2445
+		}
2446
+		$context = $this->request->getRequestParam(
2447
+			'messenger',
2448
+			key($this->_message_template_group->contexts_config())
2449
+		);
2450
+		return $this->_message_template_group->get_shortcodes($context, $fields, $merged);
2451
+	}
2452
+
2453
+
2454
+	/**
2455
+	 * This sets the _message_template property (containing the called message_template object)
2456
+	 *
2457
+	 * @access protected
2458
+	 * @return void
2459
+	 * @throws EE_Error
2460
+	 * @throws InvalidArgumentException
2461
+	 * @throws ReflectionException
2462
+	 * @throws InvalidDataTypeException
2463
+	 * @throws InvalidInterfaceException
2464
+	 */
2465
+	protected function _set_message_template_group()
2466
+	{
2467
+		// get out if this is already set.
2468
+		if (! empty($this->_message_template_group)) {
2469
+			return;
2470
+		}
2471
+
2472
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
2473
+		$GRP_ID = $this->request->getRequestParam('id', $GRP_ID, DataType::INTEGER);
2474
+
2475
+		// let's get the message templates
2476
+		$this->_message_template_group = ! empty($GRP_ID)
2477
+			? $this->getMtgModel()->get_one_by_ID($GRP_ID)
2478
+			: $this->getMtgModel()->create_default_object();
2479
+
2480
+		$this->_template_pack = $this->_message_template_group->get_template_pack();
2481
+		$this->_variation     = $this->_message_template_group->get_template_pack_variation();
2482
+	}
2483
+
2484
+
2485
+	/**
2486
+	 * sets up a context switcher for edit forms
2487
+	 *
2488
+	 * @access  protected
2489
+	 * @param EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2490
+	 * @param array                     $args                  various things the context switcher needs.
2491
+	 * @throws EE_Error
2492
+	 */
2493
+	protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, array $args)
2494
+	{
2495
+		$context_details = $template_group_object->contexts_config();
2496
+		$context_label   = $template_group_object->context_label();
2497
+		ob_start();
2498
+		?>
2499 2499
         <div class="ee-msg-switcher-container">
2500 2500
             <form method="get" action="<?php echo esc_url_raw(EE_MSG_ADMIN_URL); ?>" id="ee-msg-context-switcher-frm">
2501 2501
                 <?php
2502
-                foreach ($args as $name => $value) {
2503
-                    if ($name === 'context' || empty($value) || $name === 'extra') {
2504
-                        continue;
2505
-                    }
2506
-                    ?>
2502
+				foreach ($args as $name => $value) {
2503
+					if ($name === 'context' || empty($value) || $name === 'extra') {
2504
+						continue;
2505
+					}
2506
+					?>
2507 2507
                     <input type="hidden"
2508 2508
                            name="<?php echo esc_attr($name); ?>"
2509 2509
                            value="<?php echo esc_attr($value); ?>"
2510 2510
                     />
2511 2511
                     <?php
2512
-                }
2513
-                // setup nonce_url
2514
-                wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2515
-                $id = 'ee-' . sanitize_key($context_label['label']) . '-select';
2516
-                ?>
2512
+				}
2513
+				// setup nonce_url
2514
+				wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2515
+				$id = 'ee-' . sanitize_key($context_label['label']) . '-select';
2516
+				?>
2517 2517
                 <label for='<?php echo esc_attr($id); ?>' class='screen-reader-text'>
2518 2518
                     <?php esc_html_e('message context options', 'event_espresso'); ?>
2519 2519
                 </label>
2520 2520
                 <select id="<?php echo esc_attr($id); ?>" name="context">
2521 2521
                     <?php
2522
-                    $context_templates = $template_group_object->context_templates();
2523
-                    if (is_array($context_templates)) :
2524
-                        foreach ($context_templates as $context => $template_fields) :
2525
-                            $checked = ($context === $args['context']) ? 'selected' : '';
2526
-                            ?>
2522
+					$context_templates = $template_group_object->context_templates();
2523
+					if (is_array($context_templates)) :
2524
+						foreach ($context_templates as $context => $template_fields) :
2525
+							$checked = ($context === $args['context']) ? 'selected' : '';
2526
+							?>
2527 2527
                             <option value="<?php echo esc_attr($context); ?>" <?php echo esc_attr($checked); ?>>
2528 2528
                                 <?php echo esc_html($context_details[ $context ]['label']); ?>
2529 2529
                             </option>
2530 2530
                         <?php endforeach;
2531
-                    endif; ?>
2531
+					endif; ?>
2532 2532
                 </select>
2533 2533
                 <?php $button_text = sprintf(
2534
-                    esc_html__('Switch %s', 'event_espresso'),
2535
-                    ucwords($context_label['label'])
2536
-                ); ?>
2534
+					esc_html__('Switch %s', 'event_espresso'),
2535
+					ucwords($context_label['label'])
2536
+				); ?>
2537 2537
                 <input class='button--secondary'
2538 2538
                        id="submit-msg-context-switcher-sbmt"
2539 2539
                        type="submit"
@@ -2543,1634 +2543,1634 @@  discard block
 block discarded – undo
2543 2543
             <?php echo wp_kses($args['extra'], AllowedTags::getWithFormTags()); ?>
2544 2544
         </div> <!-- end .ee-msg-switcher-container -->
2545 2545
         <?php $this->_context_switcher = ob_get_clean();
2546
-    }
2547
-
2548
-
2549
-    /**
2550
-     * @throws EE_Error
2551
-     * @throws ReflectionException
2552
-     * @deprecated 5.0.8.p
2553
-     */
2554
-    protected function _insert_or_update_message_template($new = false)
2555
-    {
2556
-        if ($new) {
2557
-            $this->insertMessageTemplate();
2558
-        } else {
2559
-            $this->updateMessageTemplate();
2560
-        }
2561
-    }
2562
-
2563
-
2564
-    /**
2565
-     * @throws EE_Error
2566
-     * @throws ReflectionException
2567
-     */
2568
-    protected function insertMessageTemplate(): void
2569
-    {
2570
-        $success   = true;
2571
-        $templates = [];
2572
-        try {
2573
-            $templates = $this->getMessageTemplateManager()->generateNewTemplates();
2574
-        } catch (Exception $exception) {
2575
-            $success = false;
2576
-            EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2577
-        }
2578
-
2579
-        /** @var MessageTemplateRequestData $form_data */
2580
-        $form_data = $this->loader->getShared(MessageTemplateRequestData::class);
2581
-        $this->_redirect_after_action(
2582
-            $success && isset($templates['GRP_ID'], $templates['MTP_context']),
2583
-            $this->generateUpdateDescription($form_data->messenger(), $form_data->messageType(), $form_data->context()),
2584
-            'created',
2585
-            [
2586
-                'id'      => $templates['GRP_ID'] ?? 0,
2587
-                'context' => $templates['MTP_context'] ?? '',
2588
-                'action'  => 'edit_message_template',
2589
-            ],
2590
-            $this->performTestSendAfterUpdate($form_data->messenger(), $form_data->messageType(), $form_data->context())
2591
-        );
2592
-    }
2593
-
2594
-
2595
-    /**
2596
-     * @throws EE_Error
2597
-     * @throws ReflectionException
2598
-     */
2599
-    protected function updateMessageTemplate(): void
2600
-    {
2601
-        $success = true;
2602
-        try {
2603
-            $this->getMessageTemplateManager()->updateExistingTemplates();
2604
-        } catch (Exception $exception) {
2605
-            $success = false;
2606
-            EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2607
-        }
2608
-
2609
-        /** @var MessageTemplateRequestData $form_data */
2610
-        $form_data = $this->loader->getShared(MessageTemplateRequestData::class);
2611
-
2612
-        $this->_redirect_after_action(
2613
-            $success,
2614
-            $this->generateUpdateDescription($form_data->messenger(), $form_data->messageType(), $form_data->context()),
2615
-            'updated',
2616
-            [
2617
-                'id'      => $form_data->groupID(),
2618
-                'context' => $form_data->context(),
2619
-                'action'  => 'edit_message_template',
2620
-            ],
2621
-            $this->performTestSendAfterUpdate($form_data->messenger(), $form_data->messageType(), $form_data->context())
2622
-        );
2623
-    }
2624
-
2625
-
2626
-    /**
2627
-     * @param string $messenger
2628
-     * @param string $message_type
2629
-     * @param string $context
2630
-     * @return string
2631
-     * @since 4.10.29.p
2632
-     */
2633
-    private function generateUpdateDescription(string $messenger, string $message_type, string $context): string
2634
-    {
2635
-        // need the message type and messenger objects to be able to use the labels for the notices
2636
-        $messenger_object = $this->_message_resource_manager->get_messenger($messenger);
2637
-        $messenger_label  = $messenger_object instanceof EE_messenger
2638
-            ? ucwords($messenger_object->label['singular'])
2639
-            : '';
2640
-
2641
-        $message_type_object = $this->_message_resource_manager->get_message_type($message_type);
2642
-        $message_type_label  = $message_type_object instanceof EE_message_type
2643
-            ? ucwords($message_type_object->label['singular'])
2644
-            : '';
2645
-
2646
-        $context   = ucwords(str_replace('_', ' ', $context));
2647
-        $item_desc = $messenger_label && $message_type_label
2648
-            ? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2649
-            : '';
2650
-        $item_desc .= 'Message Template';
2651
-        return $item_desc;
2652
-    }
2653
-
2654
-
2655
-    /**
2656
-     * @param string $messenger
2657
-     * @param string $message_type
2658
-     * @param string $context
2659
-     * @return bool
2660
-     * @throws EE_Error
2661
-     * @throws ReflectionException
2662
-     * @since 4.10.29.p
2663
-     */
2664
-    private function performTestSendAfterUpdate(string $messenger, string $message_type, string $context): bool
2665
-    {
2666
-        // was a test send triggered?
2667
-        if ($this->request->requestParamIsSet('test_button')) {
2668
-            EE_Error::overwrite_success();
2669
-            $this->_do_test_send($context, $messenger, $message_type);
2670
-            return true;
2671
-        }
2672
-        return false;
2673
-    }
2674
-
2675
-
2676
-    /**
2677
-     * processes a test send request to do an actual messenger delivery test for the given message template being tested
2678
-     *
2679
-     * @param string $context      what context being tested
2680
-     * @param string $messenger    messenger being tested
2681
-     * @param string $message_type message type being tested
2682
-     * @throws EE_Error
2683
-     * @throws InvalidArgumentException
2684
-     * @throws InvalidDataTypeException
2685
-     * @throws InvalidInterfaceException
2686
-     * @throws ReflectionException
2687
-     */
2688
-    protected function _do_test_send(string $context, string $messenger, string $message_type)
2689
-    {
2690
-        // set things up for preview
2691
-        $this->request->setRequestParam('messenger', $messenger);
2692
-        $this->request->setRequestParam('message_type', $message_type);
2693
-        $this->request->setRequestParam('context', $context);
2694
-        $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
2695
-
2696
-        $active_messenger  = $this->_message_resource_manager->get_active_messenger($messenger);
2697
-        $test_settings_fld = $this->request->getRequestParam('test_settings_fld', [], 'string', true);
2698
-
2699
-        // let's save any existing fields that might be required by the messenger
2700
-        if (
2701
-            ! empty($test_settings_fld)
2702
-            && $active_messenger instanceof EE_messenger
2703
-            && apply_filters(
2704
-                'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
2705
-                true,
2706
-                $test_settings_fld,
2707
-                $active_messenger
2708
-            )
2709
-        ) {
2710
-            $active_messenger->set_existing_test_settings($test_settings_fld);
2711
-        }
2712
-
2713
-        /**
2714
-         * Use filter to add additional controls on whether message can send or not
2715
-         */
2716
-        if (
2717
-            apply_filters(
2718
-                'FHEE__Messages_Admin_Page__do_test_send__can_send',
2719
-                true,
2720
-                $context,
2721
-                $this->request->requestParams(),
2722
-                $messenger,
2723
-                $message_type
2724
-            )
2725
-        ) {
2726
-            if (EEM_Event::instance()->count() > 0) {
2727
-                $success = $this->_preview_message(true);
2728
-                if ($success) {
2729
-                    EE_Error::add_success(esc_html__('Test message sent', 'event_espresso'));
2730
-                } else {
2731
-                    EE_Error::add_error(
2732
-                        esc_html__('The test message was not sent', 'event_espresso'),
2733
-                        __FILE__,
2734
-                        __FUNCTION__,
2735
-                        __LINE__
2736
-                    );
2737
-                }
2738
-            } else {
2739
-                $this->noEventsErrorMessage(true);
2740
-            }
2741
-        }
2742
-    }
2743
-
2744
-
2745
-    /**
2746
-     * [_trash_or_restore_message_template]
2747
-     *
2748
-     * @param boolean $trash  whether to move an item to trash/restore (TRUE) or restore it (FALSE)
2749
-     * @param boolean $all    whether this is going to trash/restore all contexts within a template group (TRUE) OR just
2750
-     *                        an individual context (FALSE).
2751
-     * @return void
2752
-     * @throws EE_Error
2753
-     * @throws InvalidArgumentException
2754
-     * @throws InvalidDataTypeException
2755
-     * @throws InvalidInterfaceException
2756
-     * @throws ReflectionException
2757
-     */
2758
-    protected function _trash_or_restore_message_template($trash = true, $all = false)
2759
-    {
2760
-        $success = 1;
2761
-
2762
-        // incoming GRP_IDs
2763
-        if ($all) {
2764
-            // Checkboxes
2765
-            $checkboxes = $this->request->getRequestParam('checkbox', [], DataType::INTEGER, true);
2766
-            if (! empty($checkboxes)) {
2767
-                // if array has more than one element then success message should be plural.
2768
-                // todo: what about nonce?
2769
-                $success = count($checkboxes) > 1 ? 2 : 1;
2770
-
2771
-                // cycle through checkboxes
2772
-                foreach (array_keys($checkboxes) as $GRP_ID) {
2773
-                    $trashed_or_restored = $trash
2774
-                        ? $this->getMessageTemplateManager()->trashMessageTemplate($GRP_ID)
2775
-                        : $this->getMessageTemplateManager()->restoreMessageTemplate($GRP_ID);
2776
-                    if (! $trashed_or_restored) {
2777
-                        $success = 0;
2778
-                    }
2779
-                }
2780
-            } else {
2781
-                // grab single GRP_ID and handle
2782
-                $GRP_ID = $this->request->getRequestParam('id', 0, DataType::INTEGER);
2783
-                if (! empty($GRP_ID)) {
2784
-                    $trashed_or_restored = $trash
2785
-                        ? $this->getMessageTemplateManager()->trashMessageTemplate($GRP_ID)
2786
-                        : $this->getMessageTemplateManager()->restoreMessageTemplate($GRP_ID);
2787
-                    if (! $trashed_or_restored) {
2788
-                        $success = 0;
2789
-                    }
2790
-                } else {
2791
-                    $success = 0;
2792
-                }
2793
-            }
2794
-        }
2795
-
2796
-        $action_desc = $trash
2797
-            ? esc_html__('moved to the trash', 'event_espresso')
2798
-            : esc_html__('restored', 'event_espresso');
2799
-
2800
-        $template_switch = $this->request->getRequestParam('template_switch', false, DataType::BOOLEAN);
2801
-        $action_desc     = $template_switch ? esc_html__('switched', 'event_espresso') : $action_desc;
2802
-
2803
-        $item_desc = $all ? _n(
2804
-            'Message Template Group',
2805
-            'Message Template Groups',
2806
-            $success,
2807
-            'event_espresso'
2808
-        ) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
2809
-
2810
-        $item_desc = $template_switch
2811
-            ? _n('template', 'templates', $success, 'event_espresso')
2812
-            : $item_desc;
2813
-
2814
-        $this->_redirect_after_action(
2815
-            $success,
2816
-            $item_desc,
2817
-            $action_desc,
2818
-            [
2819
-                'action' => $this->request->getRequestParam('return'),
2820
-            ]
2821
-        );
2822
-    }
2823
-
2824
-
2825
-    /**
2826
-     * [_delete_message_template]
2827
-     * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
2828
-     *
2829
-     * @return void
2830
-     * @throws EE_Error
2831
-     * @throws InvalidArgumentException
2832
-     * @throws InvalidDataTypeException
2833
-     * @throws InvalidInterfaceException
2834
-     * @throws ReflectionException
2835
-     */
2836
-    protected function _delete_message_template()
2837
-    {
2838
-        // checkboxes
2839
-        $checkboxes = $this->request->getRequestParam('checkbox', [], DataType::INTEGER, true);
2840
-        if (! empty($checkboxes)) {
2841
-            // if array has more than one element then success message should be plural
2842
-            $success = count($checkboxes) > 1 ? 2 : 1;
2843
-
2844
-            // cycle through bulk action checkboxes
2845
-            foreach (array_keys($checkboxes) as $GRP_ID) {
2846
-                $success = $this->getMessageTemplateManager()->permanentlyDeleteMessageTemplateGroup($GRP_ID) ? $success
2847
-                    : false;
2848
-            }
2849
-        } else {
2850
-            // grab single grp_id and delete
2851
-            $GRP_ID  = $this->request->getRequestParam('id', 0, DataType::INTEGER);
2852
-            $success = $this->getMessageTemplateManager()->permanentlyDeleteMessageTemplateGroup($GRP_ID);
2853
-        }
2854
-
2855
-        $this->_redirect_after_action(
2856
-            $success,
2857
-            'Message Templates',
2858
-            'deleted',
2859
-            [
2860
-                'action' => $this->request->getRequestParam('return'),
2861
-            ]
2862
-        );
2863
-    }
2864
-
2865
-
2866
-    /**
2867
-     *    _learn_more_about_message_templates_link
2868
-     *
2869
-     * @access protected
2870
-     * @return string
2871
-     */
2872
-    protected function _learn_more_about_message_templates_link()
2873
-    {
2874
-        return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
2875
-               . esc_html__('learn more about how message templates works', 'event_espresso')
2876
-               . '</a>';
2877
-    }
2878
-
2879
-
2880
-    /**
2881
-     * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
2882
-     * ajax and other routes.
2883
-     *
2884
-     * @return void
2885
-     * @throws DomainException
2886
-     * @throws EE_Error
2887
-     */
2888
-    protected function _settings()
2889
-    {
2890
-        $this->_set_m_mt_settings();
2891
-        // let's setup the messenger tabs
2892
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
2893
-            $this->_m_mt_settings['messenger_tabs'],
2894
-            'messenger_links',
2895
-            '|',
2896
-            $this->request->getRequestParam('selected_messenger', 'email')
2897
-        );
2898
-
2899
-        $this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
2900
-        $this->_template_args['after_admin_page_content']  = '</div><!-- end .ui-widget -->';
2901
-
2902
-        $this->display_admin_page_with_sidebar();
2903
-    }
2904
-
2905
-
2906
-    /**
2907
-     * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
2908
-     *
2909
-     * @access protected
2910
-     * @return void
2911
-     * @throws DomainException
2912
-     */
2913
-    protected function _set_m_mt_settings()
2914
-    {
2915
-        // first if this is already set then lets get out no need to regenerate data.
2916
-        if (! empty($this->_m_mt_settings)) {
2917
-            return;
2918
-        }
2919
-
2920
-        // get all installed messengers and message_types
2921
-        $messengers    = $this->_message_resource_manager->installed_messengers();
2922
-        $message_types = $this->_message_resource_manager->installed_message_types();
2923
-
2924
-
2925
-        // assemble the array for the _tab_text_links helper
2926
-
2927
-        foreach ($messengers as $messenger) {
2928
-            $active                                                     =
2929
-                $this->_message_resource_manager->is_messenger_active($messenger->name);
2930
-            $class                                                      =
2931
-                'ee-messenger-' . sanitize_key($messenger->label['singular']);
2932
-            $this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = [
2933
-                'label' => ucwords($messenger->label['singular']),
2934
-                'class' => $active ? "{$class} messenger-active" : $class,
2935
-                'href'  => $messenger->name,
2936
-                'title' => esc_html__('Modify this Messenger', 'event_espresso'),
2937
-                'slug'  => $messenger->name,
2938
-                'obj'   => $messenger,
2939
-                'icon'  => $active
2940
-                    ? '<span class="dashicons dashicons-yes-alt"></span>'
2941
-                    : '<span class="dashicons dashicons-remove"></span>',
2942
-            ];
2943
-
2944
-
2945
-            $message_types_for_messenger = $messenger->get_valid_message_types();
2946
-
2947
-            foreach ($message_types as $message_type) {
2948
-                // first we need to verify that this message type is valid with this messenger. Cause if it isn't then
2949
-                // it shouldn't show in either the inactive OR active metabox.
2950
-                if (! in_array($message_type->name, $message_types_for_messenger, true)) {
2951
-                    continue;
2952
-                }
2953
-
2954
-                $a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
2955
-                    $messenger->name,
2956
-                    $message_type->name
2957
-                )
2958
-                    ? 'active'
2959
-                    : 'inactive';
2960
-
2961
-                $this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = [
2962
-                    'label'    => ucwords($message_type->label['singular']),
2963
-                    'class'    => 'message-type-' . $a_or_i,
2964
-                    'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
2965
-                    'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
2966
-                    'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
2967
-                    'title'    => $a_or_i === 'active'
2968
-                        ? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
2969
-                        : esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
2970
-                    'content'  => $a_or_i === 'active'
2971
-                        ? $this->_message_type_settings_content($message_type, $messenger, true)
2972
-                        : $this->_message_type_settings_content($message_type, $messenger),
2973
-                    'slug'     => $message_type->name,
2974
-                    'active'   => $a_or_i === 'active',
2975
-                    'obj'      => $message_type,
2976
-                ];
2977
-            }
2978
-        }
2979
-    }
2980
-
2981
-
2982
-    /**
2983
-     * This just prepares the content for the message type settings
2984
-     *
2985
-     * @param EE_message_type $message_type The message type object
2986
-     * @param EE_messenger    $messenger    The messenger object
2987
-     * @param boolean         $active       Whether the message type is active or not
2988
-     * @return string html output for the content
2989
-     * @throws DomainException
2990
-     */
2991
-    protected function _message_type_settings_content($message_type, $messenger, $active = false)
2992
-    {
2993
-        // get message type fields
2994
-        $fields                                         = $message_type->get_admin_settings_fields();
2995
-        $settings_template_args['template_form_fields'] = '';
2996
-
2997
-        if (! empty($fields) && $active) {
2998
-            $existing_settings = $message_type->get_existing_admin_settings($messenger->name);
2999
-            foreach ($fields as $fldname => $fldprops) {
3000
-                $field_id                         = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3001
-                $template_form_field[ $field_id ] = [
3002
-                    'name'       => 'message_type_settings[' . $fldname . ']',
3003
-                    'label'      => $fldprops['label'],
3004
-                    'input'      => $fldprops['field_type'],
3005
-                    'type'       => $fldprops['value_type'],
3006
-                    'required'   => $fldprops['required'],
3007
-                    'validation' => $fldprops['validation'],
3008
-                    'value'      => $existing_settings[ $fldname ] ?? $fldprops['default'],
3009
-                    'options'    => $fldprops['options'] ?? [],
3010
-                    'default'    => $existing_settings[ $fldname ] ?? $fldprops['default'],
3011
-                    'css_class'  => 'no-drag',
3012
-                    'format'     => $fldprops['format'],
3013
-                ];
3014
-            }
3015
-
3016
-
3017
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3018
-                ? $this->_generate_admin_form_fields(
3019
-                    $template_form_field,
3020
-                    'string',
3021
-                    'ee_mt_activate_form'
3022
-                )
3023
-                : '';
3024
-        }
3025
-
3026
-        $settings_template_args['description'] = $message_type->description;
3027
-        // we also need some hidden fields
3028
-        $hidden_fields = [
3029
-            'message_type_settings[messenger]' . $message_type->name    => [
3030
-                'type'  => 'hidden',
3031
-                'value' => $messenger->name,
3032
-            ],
3033
-            'message_type_settings[message_type]' . $message_type->name => [
3034
-                'type'  => 'hidden',
3035
-                'value' => $message_type->name,
3036
-            ],
3037
-            'type' . $message_type->name                                => [
3038
-                'type'  => 'hidden',
3039
-                'value' => 'message_type',
3040
-            ],
3041
-        ];
3042
-
3043
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3044
-            $hidden_fields,
3045
-            'array'
3046
-        );
3047
-        $settings_template_args['show_form']     = empty($settings_template_args['template_form_fields'])
3048
-            ? ' hidden'
3049
-            : '';
3050
-
3051
-
3052
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3053
-        return EEH_Template::display_template($template, $settings_template_args, true);
3054
-    }
3055
-
3056
-
3057
-    /**
3058
-     * Generate all the metaboxes for the message types and register them for the messages settings page.
3059
-     *
3060
-     * @access protected
3061
-     * @return void
3062
-     * @throws DomainException
3063
-     */
3064
-    protected function _messages_settings_metaboxes()
3065
-    {
3066
-        $this->_set_m_mt_settings();
3067
-        $m_boxes         = $mt_boxes = [];
3068
-        $m_template_args = $mt_template_args = [];
3069
-
3070
-        $selected_messenger = $this->request->getRequestParam('selected_messenger', 'email');
3071
-
3072
-        if (isset($this->_m_mt_settings['messenger_tabs'])) {
3073
-            foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3074
-                $is_messenger_active = $this->_message_resource_manager->is_messenger_active($messenger);
3075
-                $hide_on_message     = $is_messenger_active ? '' : 'hidden';
3076
-                $hide_off_message    = $is_messenger_active ? 'hidden' : '';
3077
-
3078
-                // messenger meta boxes
3079
-                $active         = $selected_messenger === $messenger;
3080
-                $active_mt_tabs = $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active'] ?? '';
3081
-
3082
-                $m_boxes[ $messenger . '_a_box' ] = sprintf(
3083
-                    esc_html__('%s Settings', 'event_espresso'),
3084
-                    $tab_array['label']
3085
-                );
3086
-
3087
-                $m_template_args[ $messenger . '_a_box' ] = [
3088
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3089
-                    'inactive_message_types' => isset(
3090
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3091
-                    )
3092
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3093
-                        : '',
3094
-                    'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3095
-                    'hidden'                 => $active ? '' : ' hidden',
3096
-                    'hide_on_message'        => $hide_on_message,
3097
-                    'messenger'              => $messenger,
3098
-                    'active'                 => $active,
3099
-                ];
3100
-
3101
-                // message type meta boxes
3102
-                // (which is really just the inactive container for each messenger
3103
-                // showing inactive message types for that messenger)
3104
-                $mt_boxes[ $messenger . '_i_box' ]         = esc_html__('Inactive Message Types', 'event_espresso');
3105
-                $mt_template_args[ $messenger . '_i_box' ] = [
3106
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3107
-                    'inactive_message_types' => isset(
3108
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3109
-                    )
3110
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3111
-                        : '',
3112
-                    'hidden'                 => $active ? '' : ' hidden',
3113
-                    'hide_on_message'        => $hide_on_message,
3114
-                    'hide_off_message'       => $hide_off_message,
3115
-                    'messenger'              => $messenger,
3116
-                    'active'                 => $active,
3117
-                ];
3118
-            }
3119
-        }
3120
-
3121
-
3122
-        // register messenger metaboxes
3123
-        $m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3124
-        foreach ($m_boxes as $box => $label) {
3125
-            $callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]];
3126
-            $msgr          = str_replace('_a_box', '', $box);
3127
-            $this->addMetaBox(
3128
-                'espresso_' . $msgr . '_settings',
3129
-                $label,
3130
-                function ($post, $metabox) {
3131
-                    EEH_Template::display_template(
3132
-                        $metabox['args']['template_path'],
3133
-                        $metabox['args']['template_args']
3134
-                    );
3135
-                },
3136
-                $this->_current_screen->id,
3137
-                'normal',
3138
-                'high',
3139
-                $callback_args
3140
-            );
3141
-        }
3142
-
3143
-        // register message type metaboxes
3144
-        $mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3145
-        foreach ($mt_boxes as $box => $label) {
3146
-            $callback_args = [
3147
-                'template_path' => $mt_template_path,
3148
-                'template_args' => $mt_template_args[ $box ],
3149
-            ];
3150
-            $mt            = str_replace('_i_box', '', $box);
3151
-            $this->addMetaBox(
3152
-                'espresso_' . $mt . '_inactive_mts',
3153
-                $label,
3154
-                function ($post, $metabox) {
3155
-                    EEH_Template::display_template(
3156
-                        $metabox['args']['template_path'],
3157
-                        $metabox['args']['template_args']
3158
-                    );
3159
-                },
3160
-                $this->_current_screen->id,
3161
-                'side',
3162
-                'high',
3163
-                $callback_args
3164
-            );
3165
-        }
3166
-
3167
-        // register metabox for global messages settings but only when on the main site.  On single site installs this
3168
-        // will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3169
-        if (is_main_site()) {
3170
-            $this->addMetaBox(
3171
-                'espresso_global_message_settings',
3172
-                esc_html__('Global Message Settings', 'event_espresso'),
3173
-                [$this, 'global_messages_settings_metabox_content'],
3174
-                $this->_current_screen->id,
3175
-                'normal',
3176
-                'low',
3177
-                []
3178
-            );
3179
-        }
3180
-    }
3181
-
3182
-
3183
-    /**
3184
-     *  This generates the content for the global messages settings metabox.
3185
-     *
3186
-     * @return void
3187
-     * @throws EE_Error
3188
-     * @throws InvalidArgumentException
3189
-     * @throws ReflectionException
3190
-     * @throws InvalidDataTypeException
3191
-     * @throws InvalidInterfaceException
3192
-     */
3193
-    public function global_messages_settings_metabox_content()
3194
-    {
3195
-        $form = $this->_generate_global_settings_form();
3196
-        echo wp_kses(
3197
-            $form->form_open(
3198
-                $this->add_query_args_and_nonce(['action' => 'update_global_settings'], EE_MSG_ADMIN_URL),
3199
-                'POST'
3200
-            ),
3201
-            AllowedTags::getWithFormTags()
3202
-        );
3203
-        echo wp_kses($form->get_html(), AllowedTags::getWithFormTags());
3204
-        echo wp_kses($form->form_close(), AllowedTags::getWithFormTags());
3205
-    }
3206
-
3207
-
3208
-    /**
3209
-     * This generates and returns the form object for the global messages settings.
3210
-     *
3211
-     * @return EE_Form_Section_Proper
3212
-     * @throws EE_Error
3213
-     * @throws InvalidArgumentException
3214
-     * @throws ReflectionException
3215
-     * @throws InvalidDataTypeException
3216
-     * @throws InvalidInterfaceException
3217
-     */
3218
-    protected function _generate_global_settings_form()
3219
-    {
3220
-        /** @var EE_Network_Core_Config $network_config */
3221
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3222
-
3223
-        return new EE_Form_Section_Proper(
3224
-            [
3225
-                'name'            => 'global_messages_settings',
3226
-                'html_id'         => 'global_messages_settings',
3227
-                'html_class'      => 'form-table',
3228
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3229
-                'subsections'     => apply_filters(
3230
-                    'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3231
-                    [
3232
-                        'do_messages_on_same_request' => new EE_Select_Input(
3233
-                            [
3234
-                                true  => esc_html__('On the same request', 'event_espresso'),
3235
-                                false => esc_html__('On a separate request', 'event_espresso'),
3236
-                            ],
3237
-                            [
3238
-                                'default'         => $network_config->do_messages_on_same_request,
3239
-                                'html_label_text' => esc_html__(
3240
-                                    'Generate and send all messages:',
3241
-                                    'event_espresso'
3242
-                                ),
3243
-                                'html_help_text'  => esc_html__(
3244
-                                    'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3245
-                                    'event_espresso'
3246
-                                ),
3247
-                            ]
3248
-                        ),
3249
-                        'delete_threshold'            => new EE_Select_Input(
3250
-                            [
3251
-                                0  => esc_html__('Forever', 'event_espresso'),
3252
-                                3  => esc_html__('3 Months', 'event_espresso'),
3253
-                                6  => esc_html__('6 Months', 'event_espresso'),
3254
-                                9  => esc_html__('9 Months', 'event_espresso'),
3255
-                                12 => esc_html__('12 Months', 'event_espresso'),
3256
-                                24 => esc_html__('24 Months', 'event_espresso'),
3257
-                                36 => esc_html__('36 Months', 'event_espresso'),
3258
-                            ],
3259
-                            [
3260
-                                'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3261
-                                'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3262
-                                'html_help_text'  => esc_html__(
3263
-                                    'You can control how long a record of processed messages is kept via this option.',
3264
-                                    'event_espresso'
3265
-                                ),
3266
-                            ]
3267
-                        ),
3268
-                        'update_settings'             => new EE_Submit_Input(
3269
-                            [
3270
-                                'default'         => esc_html__('Update', 'event_espresso'),
3271
-                                'html_label_text' => '',
3272
-                            ]
3273
-                        ),
3274
-                    ]
3275
-                ),
3276
-            ]
3277
-        );
3278
-    }
3279
-
3280
-
3281
-    /**
3282
-     * This handles updating the global settings set on the admin page.
3283
-     *
3284
-     * @throws EE_Error
3285
-     * @throws InvalidDataTypeException
3286
-     * @throws InvalidInterfaceException
3287
-     * @throws InvalidArgumentException
3288
-     * @throws ReflectionException
3289
-     */
3290
-    protected function _update_global_settings()
3291
-    {
3292
-        /** @var EE_Network_Core_Config $network_config */
3293
-        $network_config  = EE_Registry::instance()->NET_CFG->core;
3294
-        $messages_config = EE_Registry::instance()->CFG->messages;
3295
-        $form            = $this->_generate_global_settings_form();
3296
-        if ($form->was_submitted()) {
3297
-            $form->receive_form_submission();
3298
-            if ($form->is_valid()) {
3299
-                $valid_data = $form->valid_data();
3300
-                // \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 3);
3301
-                foreach ($valid_data as $property => $value) {
3302
-                    $setter = 'set_' . $property;
3303
-                    if (method_exists($network_config, $setter)) {
3304
-                        $network_config->{$setter}($value);
3305
-                    } elseif (
3306
-                        property_exists($network_config, $property)
3307
-                        && $network_config->{$property} !== $value
3308
-                    ) {
3309
-                        $network_config->{$property} = $value;
3310
-                    } elseif (
3311
-                        property_exists($messages_config, $property)
3312
-                        && $messages_config->{$property} !== $value
3313
-                    ) {
3314
-                        $messages_config->{$property} = $value;
3315
-                    }
3316
-                }
3317
-                // only update if the form submission was valid!
3318
-                EE_Registry::instance()->NET_CFG->update_config(true, false);
3319
-                EE_Registry::instance()->CFG->update_espresso_config();
3320
-                EE_Error::overwrite_success();
3321
-                EE_Error::add_success(esc_html__('Global message settings were updated', 'event_espresso'));
3322
-            }
3323
-        }
3324
-        $this->_redirect_after_action(0, '', '', ['action' => 'settings'], true);
3325
-    }
3326
-
3327
-
3328
-    /**
3329
-     * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3330
-     *
3331
-     * @param array $tab_array This is an array of message type tab details used to generate the tabs
3332
-     * @return string html formatted tabs
3333
-     * @throws DomainException
3334
-     */
3335
-    protected function _get_mt_tabs($tab_array)
3336
-    {
3337
-        $tab_array = (array) $tab_array;
3338
-        $template  = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3339
-        $tabs      = '';
3340
-
3341
-        foreach ($tab_array as $tab) {
3342
-            $tabs .= EEH_Template::display_template($template, $tab, true);
3343
-        }
3344
-
3345
-        return $tabs;
3346
-    }
3347
-
3348
-
3349
-    /**
3350
-     * This prepares the content of the messenger meta box admin settings
3351
-     *
3352
-     * @param EE_messenger $messenger The messenger we're setting up content for
3353
-     * @return string html formatted content
3354
-     * @throws DomainException
3355
-     */
3356
-    protected function _get_messenger_box_content(EE_messenger $messenger)
3357
-    {
3358
-        $fields = $messenger->get_admin_settings_fields();
3359
-
3360
-        $settings_template_args['template_form_fields'] = '';
3361
-        // is $messenger active?
3362
-        $settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3363
-
3364
-
3365
-        if (! empty($fields)) {
3366
-            $existing_settings = $messenger->get_existing_admin_settings();
3367
-
3368
-            foreach ($fields as $field_name => $field_props) {
3369
-                $field_id                         = $messenger->name . '-' . $field_name;
3370
-                $template_form_field[ $field_id ] = [
3371
-                    'name'       => 'messenger_settings[' . $field_id . ']',
3372
-                    'label'      => $field_props['label'],
3373
-                    'input'      => $field_props['field_type'],
3374
-                    'type'       => $field_props['value_type'],
3375
-                    'required'   => $field_props['required'],
3376
-                    'validation' => $field_props['validation'],
3377
-                    'value'      => $existing_settings[ $field_id ] ?? $field_props['default'],
3378
-                    'css_class'  => '',
3379
-                    'format'     => $field_props['format'],
3380
-                ];
3381
-            }
3382
-
3383
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3384
-                ? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3385
-                : '';
3386
-        }
3387
-
3388
-        // we also need some hidden fields
3389
-        $settings_template_args['hidden_fields'] = [
3390
-            'messenger_settings[messenger]' . $messenger->name => [
3391
-                'type'  => 'hidden',
3392
-                'value' => $messenger->name,
3393
-            ],
3394
-            'type' . $messenger->name                          => [
3395
-                'type'  => 'hidden',
3396
-                'value' => 'messenger',
3397
-            ],
3398
-        ];
3399
-
3400
-        // make sure any active message types that are existing are included in the hidden fields
3401
-        if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3402
-            foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3403
-                $settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = [
3404
-                    'type'  => 'hidden',
3405
-                    'value' => $mt,
3406
-                ];
3407
-            }
3408
-        }
3409
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3410
-            $settings_template_args['hidden_fields'],
3411
-            'array'
3412
-        );
3413
-        $active                                  =
3414
-            $this->_message_resource_manager->is_messenger_active($messenger->name);
3415
-
3416
-        $settings_template_args['messenger']           = $messenger->name;
3417
-        $settings_template_args['description']         = $messenger->description;
3418
-        $settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3419
-
3420
-
3421
-        $settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3422
-            $messenger->name
3423
-        )
3424
-            ? $settings_template_args['show_hide_edit_form']
3425
-            : ' hidden';
3426
-
3427
-        $settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3428
-            ? ' hidden'
3429
-            : $settings_template_args['show_hide_edit_form'];
3430
-
3431
-
3432
-        $settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3433
-        $settings_template_args['nonce']         = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3434
-        $settings_template_args['on_off_status'] = $active;
3435
-        $template                                = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3436
-        return EEH_Template::display_template(
3437
-            $template,
3438
-            $settings_template_args,
3439
-            true
3440
-        );
3441
-    }
3442
-
3443
-
3444
-    /**
3445
-     * used by ajax on the messages settings page to activate|deactivate the messenger
3446
-     *
3447
-     * @throws DomainException
3448
-     * @throws EE_Error
3449
-     * @throws InvalidDataTypeException
3450
-     * @throws InvalidInterfaceException
3451
-     * @throws InvalidArgumentException
3452
-     * @throws ReflectionException
3453
-     */
3454
-    public function activate_messenger_toggle()
3455
-    {
3456
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3457
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3458
-        }
3459
-        $success = true;
3460
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3461
-        // let's check that we have required data
3462
-
3463
-        if (! $this->_active_messenger_name) {
3464
-            EE_Error::add_error(
3465
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3466
-                __FILE__,
3467
-                __FUNCTION__,
3468
-                __LINE__
3469
-            );
3470
-            $success = false;
3471
-        }
3472
-
3473
-        // do a nonce check here since we're not arriving via a normal route
3474
-        $nonce     = $this->request->getRequestParam('activate_nonce', '');
3475
-        $nonce_ref = "activate_{$this->_active_messenger_name}_toggle_nonce";
3476
-
3477
-        $this->_verify_nonce($nonce, $nonce_ref);
3478
-
3479
-
3480
-        $status = $this->request->getRequestParam('status');
3481
-        if (! $status) {
3482
-            EE_Error::add_error(
3483
-                esc_html__(
3484
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3485
-                    'event_espresso'
3486
-                ),
3487
-                __FILE__,
3488
-                __FUNCTION__,
3489
-                __LINE__
3490
-            );
3491
-            $success = false;
3492
-        }
3493
-
3494
-        // do check to verify we have a valid status.
3495
-        if ($status !== 'off' && $status !== 'on') {
3496
-            EE_Error::add_error(
3497
-                sprintf(
3498
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3499
-                    $status
3500
-                ),
3501
-                __FILE__,
3502
-                __FUNCTION__,
3503
-                __LINE__
3504
-            );
3505
-            $success = false;
3506
-        }
3507
-
3508
-        if ($success) {
3509
-            // made it here?  Stop dawdling then!!
3510
-            $success = $status === 'off'
3511
-                ? $this->_deactivate_messenger($this->_active_messenger_name)
3512
-                : $this->_activate_messenger($this->_active_messenger_name);
3513
-        }
3514
-
3515
-        $this->_template_args['success'] = $success;
3516
-
3517
-        // no special instructions so let's just do the json return (which should automatically do all the special stuff).
3518
-        $this->_return_json();
3519
-    }
3520
-
3521
-
3522
-    /**
3523
-     * used by ajax from the messages settings page to activate|deactivate a message type
3524
-     *
3525
-     * @throws DomainException
3526
-     * @throws EE_Error
3527
-     * @throws ReflectionException
3528
-     * @throws InvalidDataTypeException
3529
-     * @throws InvalidInterfaceException
3530
-     * @throws InvalidArgumentException
3531
-     */
3532
-    public function activate_mt_toggle()
3533
-    {
3534
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3535
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3536
-        }
3537
-        $success = true;
3538
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3539
-
3540
-        // let's make sure we have the necessary data
3541
-        if (! $this->_active_message_type_name) {
3542
-            EE_Error::add_error(
3543
-                esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3544
-                __FILE__,
3545
-                __FUNCTION__,
3546
-                __LINE__
3547
-            );
3548
-            $success = false;
3549
-        }
3550
-
3551
-        if (! $this->_active_messenger_name) {
3552
-            EE_Error::add_error(
3553
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3554
-                __FILE__,
3555
-                __FUNCTION__,
3556
-                __LINE__
3557
-            );
3558
-            $success = false;
3559
-        }
3560
-
3561
-        $status = $this->request->getRequestParam('status');
3562
-        if (! $status) {
3563
-            EE_Error::add_error(
3564
-                esc_html__(
3565
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3566
-                    'event_espresso'
3567
-                ),
3568
-                __FILE__,
3569
-                __FUNCTION__,
3570
-                __LINE__
3571
-            );
3572
-            $success = false;
3573
-        }
3574
-
3575
-
3576
-        // do check to verify we have a valid status.
3577
-        if ($status !== 'activate' && $status !== 'deactivate') {
3578
-            EE_Error::add_error(
3579
-                sprintf(
3580
-                    esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3581
-                    $status
3582
-                ),
3583
-                __FILE__,
3584
-                __FUNCTION__,
3585
-                __LINE__
3586
-            );
3587
-            $success = false;
3588
-        }
3589
-
3590
-
3591
-        // do a nonce check here since we're not arriving via a normal route
3592
-        $nonce = $this->request->getRequestParam('mt_nonce', '');
3593
-        $this->_verify_nonce($nonce, "{$this->_active_message_type_name}_nonce");
3594
-
3595
-        if ($success) {
3596
-            // made it here? um, what are you waiting for then?
3597
-            $success = $status === 'deactivate'
3598
-                ? $this->_deactivate_message_type_for_messenger(
3599
-                    $this->_active_messenger_name,
3600
-                    $this->_active_message_type_name
3601
-                )
3602
-                : $this->_activate_message_type_for_messenger(
3603
-                    $this->_active_messenger_name,
3604
-                    $this->_active_message_type_name
3605
-                );
3606
-        }
3607
-
3608
-        $this->_template_args['success'] = $success;
3609
-        $this->_return_json();
3610
-    }
3611
-
3612
-
3613
-    /**
3614
-     * Takes care of processing activating a messenger and preparing the appropriate response.
3615
-     *
3616
-     * @param string $messenger_name The name of the messenger being activated
3617
-     * @return bool
3618
-     * @throws DomainException
3619
-     * @throws EE_Error
3620
-     * @throws InvalidArgumentException
3621
-     * @throws ReflectionException
3622
-     * @throws InvalidDataTypeException
3623
-     * @throws InvalidInterfaceException
3624
-     */
3625
-    protected function _activate_messenger($messenger_name)
3626
-    {
3627
-        $active_messenger          = $this->_message_resource_manager->get_messenger($messenger_name);
3628
-        $message_types_to_activate = $active_messenger instanceof EE_Messenger
3629
-            ? $active_messenger->get_default_message_types()
3630
-            : [];
3631
-
3632
-        // ensure is active
3633
-        $this->_message_resource_manager->activate_messenger($active_messenger, $message_types_to_activate);
3634
-
3635
-        // set response_data for reload
3636
-        foreach ($message_types_to_activate as $message_type_name) {
3637
-            $message_type = $this->_message_resource_manager->get_message_type($message_type_name);
3638
-            if (
3639
-                $this->_message_resource_manager->is_message_type_active_for_messenger(
3640
-                    $messenger_name,
3641
-                    $message_type_name
3642
-                )
3643
-                && $message_type instanceof EE_message_type
3644
-            ) {
3645
-                $this->_template_args['data']['active_mts'][] = $message_type_name;
3646
-                if ($message_type->get_admin_settings_fields()) {
3647
-                    $this->_template_args['data']['mt_reload'][] = $message_type_name;
3648
-                }
3649
-            }
3650
-        }
3651
-
3652
-        // add success message for activating messenger
3653
-        return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
3654
-    }
3655
-
3656
-
3657
-    /**
3658
-     * Takes care of processing deactivating a messenger and preparing the appropriate response.
3659
-     *
3660
-     * @param string $messenger_name The name of the messenger being activated
3661
-     * @return bool
3662
-     * @throws DomainException
3663
-     * @throws EE_Error
3664
-     * @throws InvalidArgumentException
3665
-     * @throws ReflectionException
3666
-     * @throws InvalidDataTypeException
3667
-     * @throws InvalidInterfaceException
3668
-     */
3669
-    protected function _deactivate_messenger($messenger_name)
3670
-    {
3671
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
3672
-        $this->_message_resource_manager->deactivate_messenger($messenger_name);
3673
-
3674
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
3675
-    }
3676
-
3677
-
3678
-    /**
3679
-     * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
3680
-     *
3681
-     * @param string $messenger_name    The name of the messenger the message type is being activated for.
3682
-     * @param string $message_type_name The name of the message type being activated for the messenger
3683
-     * @return bool
3684
-     * @throws DomainException
3685
-     * @throws EE_Error
3686
-     * @throws InvalidArgumentException
3687
-     * @throws ReflectionException
3688
-     * @throws InvalidDataTypeException
3689
-     * @throws InvalidInterfaceException
3690
-     */
3691
-    protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
3692
-    {
3693
-        $active_messenger         = $this->_message_resource_manager->get_messenger($messenger_name);
3694
-        $message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
3695
-
3696
-        // ensure is active
3697
-        $this->_message_resource_manager->activate_messenger($active_messenger, $message_type_name);
3698
-
3699
-        // set response for load
3700
-        if (
3701
-            $this->_message_resource_manager->is_message_type_active_for_messenger(
3702
-                $messenger_name,
3703
-                $message_type_name
3704
-            )
3705
-        ) {
3706
-            $this->_template_args['data']['active_mts'][] = $message_type_name;
3707
-            if ($message_type_to_activate->get_admin_settings_fields()) {
3708
-                $this->_template_args['data']['mt_reload'][] = $message_type_name;
3709
-            }
3710
-        }
3711
-
3712
-        return $this->_setup_response_message_for_activating_messenger_with_message_types(
3713
-            $active_messenger,
3714
-            $message_type_to_activate
3715
-        );
3716
-    }
3717
-
3718
-
3719
-    /**
3720
-     * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
3721
-     *
3722
-     * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
3723
-     * @param string $message_type_name The name of the message type being deactivated for the messenger
3724
-     * @return bool
3725
-     * @throws DomainException
3726
-     * @throws EE_Error
3727
-     * @throws InvalidArgumentException
3728
-     * @throws ReflectionException
3729
-     * @throws InvalidDataTypeException
3730
-     * @throws InvalidInterfaceException
3731
-     */
3732
-    protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
3733
-    {
3734
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
3735
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
3736
-        $message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
3737
-        $this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
3738
-
3739
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
3740
-            $active_messenger,
3741
-            $message_type_to_deactivate
3742
-        );
3743
-    }
3744
-
3745
-
3746
-    /**
3747
-     * This just initializes the defaults for activating messenger and message type responses.
3748
-     */
3749
-    protected function _prep_default_response_for_messenger_or_message_type_toggle()
3750
-    {
3751
-        $this->_template_args['data']['active_mts'] = [];
3752
-        $this->_template_args['data']['mt_reload']  = [];
3753
-    }
3754
-
3755
-
3756
-    /**
3757
-     * Setup appropriate response for activating a messenger and/or message types
3758
-     *
3759
-     * @param EE_messenger         $messenger
3760
-     * @param EE_message_type|null $message_type
3761
-     * @return bool
3762
-     * @throws DomainException
3763
-     * @throws EE_Error
3764
-     * @throws InvalidArgumentException
3765
-     * @throws ReflectionException
3766
-     * @throws InvalidDataTypeException
3767
-     * @throws InvalidInterfaceException
3768
-     */
3769
-    protected function _setup_response_message_for_activating_messenger_with_message_types(
3770
-        $messenger,
3771
-        EE_Message_Type $message_type = null
3772
-    ) {
3773
-        // if $messenger isn't a valid messenger object then get out.
3774
-        if (! $messenger instanceof EE_Messenger) {
3775
-            EE_Error::add_error(
3776
-                esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
3777
-                __FILE__,
3778
-                __FUNCTION__,
3779
-                __LINE__
3780
-            );
3781
-            return false;
3782
-        }
3783
-        // activated
3784
-        if ($this->_template_args['data']['active_mts']) {
3785
-            EE_Error::overwrite_success();
3786
-            // activated a message type with the messenger
3787
-            if ($message_type instanceof EE_message_type) {
3788
-                EE_Error::add_success(
3789
-                    sprintf(
3790
-                        esc_html__(
3791
-                            '%s message type has been successfully activated with the %s messenger',
3792
-                            'event_espresso'
3793
-                        ),
3794
-                        ucwords($message_type->label['singular']),
3795
-                        ucwords($messenger->label['singular'])
3796
-                    )
3797
-                );
3798
-
3799
-                // if message type was invoice then let's make sure we activate the invoice payment method.
3800
-                if ($message_type->name === 'invoice') {
3801
-                    EE_Registry::instance()->load_lib('Payment_Method_Manager');
3802
-                    $pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
3803
-                    if ($pm instanceof EE_Payment_Method) {
3804
-                        EE_Error::add_attention(
3805
-                            esc_html__(
3806
-                                'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
3807
-                                'event_espresso'
3808
-                            )
3809
-                        );
3810
-                    }
3811
-                }
3812
-                // just toggles the entire messenger
3813
-            } else {
3814
-                EE_Error::add_success(
3815
-                    sprintf(
3816
-                        esc_html__('%s messenger has been successfully activated', 'event_espresso'),
3817
-                        ucwords($messenger->label['singular'])
3818
-                    )
3819
-                );
3820
-            }
3821
-
3822
-            return true;
3823
-
3824
-            // possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
3825
-            // message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
3826
-            // in which case we just give a success message for the messenger being successfully activated.
3827
-        } else {
3828
-            if (! $messenger->get_default_message_types()) {
3829
-                // messenger doesn't have any default message types so still a success.
3830
-                EE_Error::add_success(
3831
-                    sprintf(
3832
-                        esc_html__('%s messenger was successfully activated.', 'event_espresso'),
3833
-                        ucwords($messenger->label['singular'])
3834
-                    )
3835
-                );
3836
-
3837
-                return true;
3838
-            } else {
3839
-                EE_Error::add_error(
3840
-                    $message_type instanceof EE_message_type
3841
-                        ? sprintf(
3842
-                        esc_html__(
3843
-                            '%s message type was not successfully activated with the %s messenger',
3844
-                            'event_espresso'
3845
-                        ),
3846
-                        ucwords($message_type->label['singular']),
3847
-                        ucwords($messenger->label['singular'])
3848
-                    )
3849
-                        : sprintf(
3850
-                        esc_html__('%s messenger was not successfully activated', 'event_espresso'),
3851
-                        ucwords($messenger->label['singular'])
3852
-                    ),
3853
-                    __FILE__,
3854
-                    __FUNCTION__,
3855
-                    __LINE__
3856
-                );
3857
-
3858
-                return false;
3859
-            }
3860
-        }
3861
-    }
3862
-
3863
-
3864
-    /**
3865
-     * This sets up the appropriate response for deactivating a messenger and/or message type.
3866
-     *
3867
-     * @param EE_messenger         $messenger
3868
-     * @param EE_message_type|null $message_type
3869
-     * @return bool
3870
-     * @throws DomainException
3871
-     * @throws EE_Error
3872
-     * @throws InvalidArgumentException
3873
-     * @throws ReflectionException
3874
-     * @throws InvalidDataTypeException
3875
-     * @throws InvalidInterfaceException
3876
-     */
3877
-    protected function _setup_response_message_for_deactivating_messenger_with_message_types(
3878
-        $messenger,
3879
-        EE_message_type $message_type = null
3880
-    ) {
3881
-        EE_Error::overwrite_success();
3882
-
3883
-        // if $messenger isn't a valid messenger object then get out.
3884
-        if (! $messenger instanceof EE_Messenger) {
3885
-            EE_Error::add_error(
3886
-                esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
3887
-                __FILE__,
3888
-                __FUNCTION__,
3889
-                __LINE__
3890
-            );
3891
-
3892
-            return false;
3893
-        }
3894
-
3895
-        if ($message_type instanceof EE_message_type) {
3896
-            $message_type_name = $message_type->name;
3897
-            EE_Error::add_success(
3898
-                sprintf(
3899
-                    esc_html__(
3900
-                        '%s message type has been successfully deactivated for the %s messenger.',
3901
-                        'event_espresso'
3902
-                    ),
3903
-                    ucwords($message_type->label['singular']),
3904
-                    ucwords($messenger->label['singular'])
3905
-                )
3906
-            );
3907
-        } else {
3908
-            $message_type_name = '';
3909
-            EE_Error::add_success(
3910
-                sprintf(
3911
-                    esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
3912
-                    ucwords($messenger->label['singular'])
3913
-                )
3914
-            );
3915
-        }
3916
-
3917
-        // if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
3918
-        if (
3919
-            $messenger->name === 'html'
3920
-            && (
3921
-                is_null($message_type)
3922
-                || $message_type_name === 'invoice'
3923
-            )
3924
-        ) {
3925
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
3926
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
3927
-            if ($count_updated > 0) {
3928
-                $msg = $message_type_name === 'invoice'
3929
-                    ? esc_html__(
3930
-                        'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
3931
-                        'event_espresso'
3932
-                    )
3933
-                    : esc_html__(
3934
-                        'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
3935
-                        'event_espresso'
3936
-                    );
3937
-                EE_Error::add_attention($msg);
3938
-            }
3939
-        }
3940
-
3941
-        return true;
3942
-    }
3943
-
3944
-
3945
-    /**
3946
-     * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
3947
-     *
3948
-     * @throws DomainException
3949
-     * @throws EE_Error
3950
-     * @throws EE_Error
3951
-     */
3952
-    public function update_mt_form()
3953
-    {
3954
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3955
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3956
-        }
3957
-        if (! $this->_active_messenger_name || ! $this->_active_message_type_name) {
3958
-            EE_Error::add_error(
3959
-                esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
3960
-                __FILE__,
3961
-                __FUNCTION__,
3962
-                __LINE__
3963
-            );
3964
-            $this->_return_json();
3965
-        }
3966
-
3967
-        $message_types = $this->get_installed_message_types();
3968
-        $message_type  = $message_types[ $this->_active_message_type_name ];
3969
-        $messenger     = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
3970
-        $content       = $this->_message_type_settings_content($message_type, $messenger, true);
3971
-
3972
-        $this->_template_args['success'] = true;
3973
-        $this->_template_args['content'] = $content;
3974
-        $this->_return_json();
3975
-    }
3976
-
3977
-
3978
-    /**
3979
-     * this handles saving the settings for a messenger or message type
3980
-     *
3981
-     * @throws EE_Error
3982
-     * @throws EE_Error
3983
-     */
3984
-    public function save_settings()
3985
-    {
3986
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3987
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3988
-        }
3989
-        $type = $this->request->getRequestParam('type');
3990
-        if (! $type) {
3991
-            EE_Error::add_error(
3992
-                esc_html__(
3993
-                    'Cannot save settings because type is unknown (messenger settings or message type settings?)',
3994
-                    'event_espresso'
3995
-                ),
3996
-                __FILE__,
3997
-                __FUNCTION__,
3998
-                __LINE__
3999
-            );
4000
-            $this->_template_args['error'] = true;
4001
-            $this->_return_json();
4002
-        }
4003
-
4004
-
4005
-        if ($type === 'messenger') {
4006
-            // this should be an array.
4007
-            $settings  = $this->request->getRequestParam('messenger_settings', [], 'string', true);
4008
-            $messenger = $settings['messenger'];
4009
-            // remove messenger and message_types from settings array
4010
-            unset($settings['messenger'], $settings['message_types']);
4011
-            $this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4012
-        } elseif ($type === 'message_type') {
4013
-            $settings     = $this->request->getRequestParam('message_type_settings', [], 'string', true);
4014
-            $messenger    = $settings['messenger'];
4015
-            $message_type = $settings['message_type'];
4016
-            // remove messenger and message_types from settings array
4017
-            unset($settings['messenger'], $settings['message_types']);
4018
-            $this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4019
-        }
4020
-
4021
-        // okay we should have the data all setup.  Now we just update!
4022
-        $success = $this->_message_resource_manager->update_active_messengers_option();
4023
-
4024
-        if ($success) {
4025
-            EE_Error::add_success(esc_html__('Settings updated', 'event_espresso'));
4026
-        } else {
4027
-            EE_Error::add_error(
4028
-                esc_html__('Settings did not get updated', 'event_espresso'),
4029
-                __FILE__,
4030
-                __FUNCTION__,
4031
-                __LINE__
4032
-            );
4033
-        }
4034
-
4035
-        $this->_template_args['success'] = $success;
4036
-        $this->_return_json();
4037
-    }
4038
-
4039
-
4040
-
4041
-
4042
-    /**  EE MESSAGE PROCESSING ACTIONS **/
4043
-
4044
-
4045
-    /**
4046
-     * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4047
-     * However, this does not send immediately, it just queues for sending.
4048
-     *
4049
-     * @throws EE_Error
4050
-     * @throws InvalidDataTypeException
4051
-     * @throws InvalidInterfaceException
4052
-     * @throws InvalidArgumentException
4053
-     * @throws ReflectionException
4054
-     * @since 4.9.0
4055
-     */
4056
-    protected function _generate_now()
4057
-    {
4058
-        EED_Messages::generate_now($this->_get_msg_ids_from_request());
4059
-        $this->_redirect_after_action(false, '', '', [], true);
4060
-    }
4061
-
4062
-
4063
-    /**
4064
-     * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4065
-     * are EEM_Message::status_resend or EEM_Message::status_idle
4066
-     *
4067
-     * @throws EE_Error
4068
-     * @throws InvalidDataTypeException
4069
-     * @throws InvalidInterfaceException
4070
-     * @throws InvalidArgumentException
4071
-     * @throws ReflectionException
4072
-     * @since 4.9.0
4073
-     */
4074
-    protected function _generate_and_send_now()
4075
-    {
4076
-        EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4077
-        $this->_redirect_after_action(false, '', '', [], true);
4078
-    }
4079
-
4080
-
4081
-    /**
4082
-     * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4083
-     *
4084
-     * @throws EE_Error
4085
-     * @throws InvalidDataTypeException
4086
-     * @throws InvalidInterfaceException
4087
-     * @throws InvalidArgumentException
4088
-     * @throws ReflectionException
4089
-     * @since 4.9.0
4090
-     */
4091
-    protected function _queue_for_resending()
4092
-    {
4093
-        EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4094
-        $this->_redirect_after_action(false, '', '', [], true);
4095
-    }
4096
-
4097
-
4098
-    /**
4099
-     *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4100
-     *
4101
-     * @throws EE_Error
4102
-     * @throws InvalidDataTypeException
4103
-     * @throws InvalidInterfaceException
4104
-     * @throws InvalidArgumentException
4105
-     * @throws ReflectionException
4106
-     * @since 4.9.0
4107
-     */
4108
-    protected function _send_now()
4109
-    {
4110
-        EED_Messages::send_now($this->_get_msg_ids_from_request());
4111
-        $this->_redirect_after_action(false, '', '', [], true);
4112
-    }
4113
-
4114
-
4115
-    /**
4116
-     * Deletes EE_messages for IDs in the request.
4117
-     *
4118
-     * @throws EE_Error
4119
-     * @throws InvalidDataTypeException
4120
-     * @throws InvalidInterfaceException
4121
-     * @throws InvalidArgumentException
4122
-     * @throws ReflectionException
4123
-     * @since 4.9.0
4124
-     */
4125
-    protected function _delete_ee_messages()
4126
-    {
4127
-        $MSG_IDs       = $this->_get_msg_ids_from_request();
4128
-        $deleted_count = 0;
4129
-        foreach ($MSG_IDs as $MSG_ID) {
4130
-            if ($this->getMsgModel()->delete_by_ID($MSG_ID)) {
4131
-                $deleted_count++;
4132
-            }
4133
-        }
4134
-        if ($deleted_count) {
4135
-            EE_Error::add_success(
4136
-                esc_html(
4137
-                    _n(
4138
-                        'Message successfully deleted',
4139
-                        'Messages successfully deleted',
4140
-                        $deleted_count,
4141
-                        'event_espresso'
4142
-                    )
4143
-                )
4144
-            );
4145
-        } else {
4146
-            EE_Error::add_error(
4147
-                _n('The message was not deleted.', 'The messages were not deleted', count($MSG_IDs), 'event_espresso'),
4148
-                __FILE__,
4149
-                __FUNCTION__,
4150
-                __LINE__
4151
-            );
4152
-        }
4153
-        $this->_redirect_after_action(false, '', '', [], true);
4154
-    }
4155
-
4156
-
4157
-    /**
4158
-     *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4159
-     *
4160
-     * @return array
4161
-     * @since 4.9.0
4162
-     */
4163
-    protected function _get_msg_ids_from_request()
4164
-    {
4165
-        $MSG_IDs = $this->request->getRequestParam('MSG_ID', [], 'string', true);
4166
-        if (empty($MSG_IDs)) {
4167
-            return [];
4168
-        }
4169
-        // if 'MSG_ID' was just a single ID (not an array)
4170
-        // then $MSG_IDs will be something like [123] so $MSG_IDs[0] should be 123
4171
-        // otherwise, $MSG_IDs was already an array where message IDs were used as the keys
4172
-        return count($MSG_IDs) === 1 && isset($MSG_IDs[0])
4173
-            ? $MSG_IDs
4174
-            : array_keys($MSG_IDs);
4175
-    }
2546
+	}
2547
+
2548
+
2549
+	/**
2550
+	 * @throws EE_Error
2551
+	 * @throws ReflectionException
2552
+	 * @deprecated 5.0.8.p
2553
+	 */
2554
+	protected function _insert_or_update_message_template($new = false)
2555
+	{
2556
+		if ($new) {
2557
+			$this->insertMessageTemplate();
2558
+		} else {
2559
+			$this->updateMessageTemplate();
2560
+		}
2561
+	}
2562
+
2563
+
2564
+	/**
2565
+	 * @throws EE_Error
2566
+	 * @throws ReflectionException
2567
+	 */
2568
+	protected function insertMessageTemplate(): void
2569
+	{
2570
+		$success   = true;
2571
+		$templates = [];
2572
+		try {
2573
+			$templates = $this->getMessageTemplateManager()->generateNewTemplates();
2574
+		} catch (Exception $exception) {
2575
+			$success = false;
2576
+			EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2577
+		}
2578
+
2579
+		/** @var MessageTemplateRequestData $form_data */
2580
+		$form_data = $this->loader->getShared(MessageTemplateRequestData::class);
2581
+		$this->_redirect_after_action(
2582
+			$success && isset($templates['GRP_ID'], $templates['MTP_context']),
2583
+			$this->generateUpdateDescription($form_data->messenger(), $form_data->messageType(), $form_data->context()),
2584
+			'created',
2585
+			[
2586
+				'id'      => $templates['GRP_ID'] ?? 0,
2587
+				'context' => $templates['MTP_context'] ?? '',
2588
+				'action'  => 'edit_message_template',
2589
+			],
2590
+			$this->performTestSendAfterUpdate($form_data->messenger(), $form_data->messageType(), $form_data->context())
2591
+		);
2592
+	}
2593
+
2594
+
2595
+	/**
2596
+	 * @throws EE_Error
2597
+	 * @throws ReflectionException
2598
+	 */
2599
+	protected function updateMessageTemplate(): void
2600
+	{
2601
+		$success = true;
2602
+		try {
2603
+			$this->getMessageTemplateManager()->updateExistingTemplates();
2604
+		} catch (Exception $exception) {
2605
+			$success = false;
2606
+			EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2607
+		}
2608
+
2609
+		/** @var MessageTemplateRequestData $form_data */
2610
+		$form_data = $this->loader->getShared(MessageTemplateRequestData::class);
2611
+
2612
+		$this->_redirect_after_action(
2613
+			$success,
2614
+			$this->generateUpdateDescription($form_data->messenger(), $form_data->messageType(), $form_data->context()),
2615
+			'updated',
2616
+			[
2617
+				'id'      => $form_data->groupID(),
2618
+				'context' => $form_data->context(),
2619
+				'action'  => 'edit_message_template',
2620
+			],
2621
+			$this->performTestSendAfterUpdate($form_data->messenger(), $form_data->messageType(), $form_data->context())
2622
+		);
2623
+	}
2624
+
2625
+
2626
+	/**
2627
+	 * @param string $messenger
2628
+	 * @param string $message_type
2629
+	 * @param string $context
2630
+	 * @return string
2631
+	 * @since 4.10.29.p
2632
+	 */
2633
+	private function generateUpdateDescription(string $messenger, string $message_type, string $context): string
2634
+	{
2635
+		// need the message type and messenger objects to be able to use the labels for the notices
2636
+		$messenger_object = $this->_message_resource_manager->get_messenger($messenger);
2637
+		$messenger_label  = $messenger_object instanceof EE_messenger
2638
+			? ucwords($messenger_object->label['singular'])
2639
+			: '';
2640
+
2641
+		$message_type_object = $this->_message_resource_manager->get_message_type($message_type);
2642
+		$message_type_label  = $message_type_object instanceof EE_message_type
2643
+			? ucwords($message_type_object->label['singular'])
2644
+			: '';
2645
+
2646
+		$context   = ucwords(str_replace('_', ' ', $context));
2647
+		$item_desc = $messenger_label && $message_type_label
2648
+			? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2649
+			: '';
2650
+		$item_desc .= 'Message Template';
2651
+		return $item_desc;
2652
+	}
2653
+
2654
+
2655
+	/**
2656
+	 * @param string $messenger
2657
+	 * @param string $message_type
2658
+	 * @param string $context
2659
+	 * @return bool
2660
+	 * @throws EE_Error
2661
+	 * @throws ReflectionException
2662
+	 * @since 4.10.29.p
2663
+	 */
2664
+	private function performTestSendAfterUpdate(string $messenger, string $message_type, string $context): bool
2665
+	{
2666
+		// was a test send triggered?
2667
+		if ($this->request->requestParamIsSet('test_button')) {
2668
+			EE_Error::overwrite_success();
2669
+			$this->_do_test_send($context, $messenger, $message_type);
2670
+			return true;
2671
+		}
2672
+		return false;
2673
+	}
2674
+
2675
+
2676
+	/**
2677
+	 * processes a test send request to do an actual messenger delivery test for the given message template being tested
2678
+	 *
2679
+	 * @param string $context      what context being tested
2680
+	 * @param string $messenger    messenger being tested
2681
+	 * @param string $message_type message type being tested
2682
+	 * @throws EE_Error
2683
+	 * @throws InvalidArgumentException
2684
+	 * @throws InvalidDataTypeException
2685
+	 * @throws InvalidInterfaceException
2686
+	 * @throws ReflectionException
2687
+	 */
2688
+	protected function _do_test_send(string $context, string $messenger, string $message_type)
2689
+	{
2690
+		// set things up for preview
2691
+		$this->request->setRequestParam('messenger', $messenger);
2692
+		$this->request->setRequestParam('message_type', $message_type);
2693
+		$this->request->setRequestParam('context', $context);
2694
+		$this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
2695
+
2696
+		$active_messenger  = $this->_message_resource_manager->get_active_messenger($messenger);
2697
+		$test_settings_fld = $this->request->getRequestParam('test_settings_fld', [], 'string', true);
2698
+
2699
+		// let's save any existing fields that might be required by the messenger
2700
+		if (
2701
+			! empty($test_settings_fld)
2702
+			&& $active_messenger instanceof EE_messenger
2703
+			&& apply_filters(
2704
+				'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
2705
+				true,
2706
+				$test_settings_fld,
2707
+				$active_messenger
2708
+			)
2709
+		) {
2710
+			$active_messenger->set_existing_test_settings($test_settings_fld);
2711
+		}
2712
+
2713
+		/**
2714
+		 * Use filter to add additional controls on whether message can send or not
2715
+		 */
2716
+		if (
2717
+			apply_filters(
2718
+				'FHEE__Messages_Admin_Page__do_test_send__can_send',
2719
+				true,
2720
+				$context,
2721
+				$this->request->requestParams(),
2722
+				$messenger,
2723
+				$message_type
2724
+			)
2725
+		) {
2726
+			if (EEM_Event::instance()->count() > 0) {
2727
+				$success = $this->_preview_message(true);
2728
+				if ($success) {
2729
+					EE_Error::add_success(esc_html__('Test message sent', 'event_espresso'));
2730
+				} else {
2731
+					EE_Error::add_error(
2732
+						esc_html__('The test message was not sent', 'event_espresso'),
2733
+						__FILE__,
2734
+						__FUNCTION__,
2735
+						__LINE__
2736
+					);
2737
+				}
2738
+			} else {
2739
+				$this->noEventsErrorMessage(true);
2740
+			}
2741
+		}
2742
+	}
2743
+
2744
+
2745
+	/**
2746
+	 * [_trash_or_restore_message_template]
2747
+	 *
2748
+	 * @param boolean $trash  whether to move an item to trash/restore (TRUE) or restore it (FALSE)
2749
+	 * @param boolean $all    whether this is going to trash/restore all contexts within a template group (TRUE) OR just
2750
+	 *                        an individual context (FALSE).
2751
+	 * @return void
2752
+	 * @throws EE_Error
2753
+	 * @throws InvalidArgumentException
2754
+	 * @throws InvalidDataTypeException
2755
+	 * @throws InvalidInterfaceException
2756
+	 * @throws ReflectionException
2757
+	 */
2758
+	protected function _trash_or_restore_message_template($trash = true, $all = false)
2759
+	{
2760
+		$success = 1;
2761
+
2762
+		// incoming GRP_IDs
2763
+		if ($all) {
2764
+			// Checkboxes
2765
+			$checkboxes = $this->request->getRequestParam('checkbox', [], DataType::INTEGER, true);
2766
+			if (! empty($checkboxes)) {
2767
+				// if array has more than one element then success message should be plural.
2768
+				// todo: what about nonce?
2769
+				$success = count($checkboxes) > 1 ? 2 : 1;
2770
+
2771
+				// cycle through checkboxes
2772
+				foreach (array_keys($checkboxes) as $GRP_ID) {
2773
+					$trashed_or_restored = $trash
2774
+						? $this->getMessageTemplateManager()->trashMessageTemplate($GRP_ID)
2775
+						: $this->getMessageTemplateManager()->restoreMessageTemplate($GRP_ID);
2776
+					if (! $trashed_or_restored) {
2777
+						$success = 0;
2778
+					}
2779
+				}
2780
+			} else {
2781
+				// grab single GRP_ID and handle
2782
+				$GRP_ID = $this->request->getRequestParam('id', 0, DataType::INTEGER);
2783
+				if (! empty($GRP_ID)) {
2784
+					$trashed_or_restored = $trash
2785
+						? $this->getMessageTemplateManager()->trashMessageTemplate($GRP_ID)
2786
+						: $this->getMessageTemplateManager()->restoreMessageTemplate($GRP_ID);
2787
+					if (! $trashed_or_restored) {
2788
+						$success = 0;
2789
+					}
2790
+				} else {
2791
+					$success = 0;
2792
+				}
2793
+			}
2794
+		}
2795
+
2796
+		$action_desc = $trash
2797
+			? esc_html__('moved to the trash', 'event_espresso')
2798
+			: esc_html__('restored', 'event_espresso');
2799
+
2800
+		$template_switch = $this->request->getRequestParam('template_switch', false, DataType::BOOLEAN);
2801
+		$action_desc     = $template_switch ? esc_html__('switched', 'event_espresso') : $action_desc;
2802
+
2803
+		$item_desc = $all ? _n(
2804
+			'Message Template Group',
2805
+			'Message Template Groups',
2806
+			$success,
2807
+			'event_espresso'
2808
+		) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
2809
+
2810
+		$item_desc = $template_switch
2811
+			? _n('template', 'templates', $success, 'event_espresso')
2812
+			: $item_desc;
2813
+
2814
+		$this->_redirect_after_action(
2815
+			$success,
2816
+			$item_desc,
2817
+			$action_desc,
2818
+			[
2819
+				'action' => $this->request->getRequestParam('return'),
2820
+			]
2821
+		);
2822
+	}
2823
+
2824
+
2825
+	/**
2826
+	 * [_delete_message_template]
2827
+	 * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
2828
+	 *
2829
+	 * @return void
2830
+	 * @throws EE_Error
2831
+	 * @throws InvalidArgumentException
2832
+	 * @throws InvalidDataTypeException
2833
+	 * @throws InvalidInterfaceException
2834
+	 * @throws ReflectionException
2835
+	 */
2836
+	protected function _delete_message_template()
2837
+	{
2838
+		// checkboxes
2839
+		$checkboxes = $this->request->getRequestParam('checkbox', [], DataType::INTEGER, true);
2840
+		if (! empty($checkboxes)) {
2841
+			// if array has more than one element then success message should be plural
2842
+			$success = count($checkboxes) > 1 ? 2 : 1;
2843
+
2844
+			// cycle through bulk action checkboxes
2845
+			foreach (array_keys($checkboxes) as $GRP_ID) {
2846
+				$success = $this->getMessageTemplateManager()->permanentlyDeleteMessageTemplateGroup($GRP_ID) ? $success
2847
+					: false;
2848
+			}
2849
+		} else {
2850
+			// grab single grp_id and delete
2851
+			$GRP_ID  = $this->request->getRequestParam('id', 0, DataType::INTEGER);
2852
+			$success = $this->getMessageTemplateManager()->permanentlyDeleteMessageTemplateGroup($GRP_ID);
2853
+		}
2854
+
2855
+		$this->_redirect_after_action(
2856
+			$success,
2857
+			'Message Templates',
2858
+			'deleted',
2859
+			[
2860
+				'action' => $this->request->getRequestParam('return'),
2861
+			]
2862
+		);
2863
+	}
2864
+
2865
+
2866
+	/**
2867
+	 *    _learn_more_about_message_templates_link
2868
+	 *
2869
+	 * @access protected
2870
+	 * @return string
2871
+	 */
2872
+	protected function _learn_more_about_message_templates_link()
2873
+	{
2874
+		return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
2875
+			   . esc_html__('learn more about how message templates works', 'event_espresso')
2876
+			   . '</a>';
2877
+	}
2878
+
2879
+
2880
+	/**
2881
+	 * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
2882
+	 * ajax and other routes.
2883
+	 *
2884
+	 * @return void
2885
+	 * @throws DomainException
2886
+	 * @throws EE_Error
2887
+	 */
2888
+	protected function _settings()
2889
+	{
2890
+		$this->_set_m_mt_settings();
2891
+		// let's setup the messenger tabs
2892
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
2893
+			$this->_m_mt_settings['messenger_tabs'],
2894
+			'messenger_links',
2895
+			'|',
2896
+			$this->request->getRequestParam('selected_messenger', 'email')
2897
+		);
2898
+
2899
+		$this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
2900
+		$this->_template_args['after_admin_page_content']  = '</div><!-- end .ui-widget -->';
2901
+
2902
+		$this->display_admin_page_with_sidebar();
2903
+	}
2904
+
2905
+
2906
+	/**
2907
+	 * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
2908
+	 *
2909
+	 * @access protected
2910
+	 * @return void
2911
+	 * @throws DomainException
2912
+	 */
2913
+	protected function _set_m_mt_settings()
2914
+	{
2915
+		// first if this is already set then lets get out no need to regenerate data.
2916
+		if (! empty($this->_m_mt_settings)) {
2917
+			return;
2918
+		}
2919
+
2920
+		// get all installed messengers and message_types
2921
+		$messengers    = $this->_message_resource_manager->installed_messengers();
2922
+		$message_types = $this->_message_resource_manager->installed_message_types();
2923
+
2924
+
2925
+		// assemble the array for the _tab_text_links helper
2926
+
2927
+		foreach ($messengers as $messenger) {
2928
+			$active                                                     =
2929
+				$this->_message_resource_manager->is_messenger_active($messenger->name);
2930
+			$class                                                      =
2931
+				'ee-messenger-' . sanitize_key($messenger->label['singular']);
2932
+			$this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = [
2933
+				'label' => ucwords($messenger->label['singular']),
2934
+				'class' => $active ? "{$class} messenger-active" : $class,
2935
+				'href'  => $messenger->name,
2936
+				'title' => esc_html__('Modify this Messenger', 'event_espresso'),
2937
+				'slug'  => $messenger->name,
2938
+				'obj'   => $messenger,
2939
+				'icon'  => $active
2940
+					? '<span class="dashicons dashicons-yes-alt"></span>'
2941
+					: '<span class="dashicons dashicons-remove"></span>',
2942
+			];
2943
+
2944
+
2945
+			$message_types_for_messenger = $messenger->get_valid_message_types();
2946
+
2947
+			foreach ($message_types as $message_type) {
2948
+				// first we need to verify that this message type is valid with this messenger. Cause if it isn't then
2949
+				// it shouldn't show in either the inactive OR active metabox.
2950
+				if (! in_array($message_type->name, $message_types_for_messenger, true)) {
2951
+					continue;
2952
+				}
2953
+
2954
+				$a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
2955
+					$messenger->name,
2956
+					$message_type->name
2957
+				)
2958
+					? 'active'
2959
+					: 'inactive';
2960
+
2961
+				$this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = [
2962
+					'label'    => ucwords($message_type->label['singular']),
2963
+					'class'    => 'message-type-' . $a_or_i,
2964
+					'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
2965
+					'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
2966
+					'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
2967
+					'title'    => $a_or_i === 'active'
2968
+						? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
2969
+						: esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
2970
+					'content'  => $a_or_i === 'active'
2971
+						? $this->_message_type_settings_content($message_type, $messenger, true)
2972
+						: $this->_message_type_settings_content($message_type, $messenger),
2973
+					'slug'     => $message_type->name,
2974
+					'active'   => $a_or_i === 'active',
2975
+					'obj'      => $message_type,
2976
+				];
2977
+			}
2978
+		}
2979
+	}
2980
+
2981
+
2982
+	/**
2983
+	 * This just prepares the content for the message type settings
2984
+	 *
2985
+	 * @param EE_message_type $message_type The message type object
2986
+	 * @param EE_messenger    $messenger    The messenger object
2987
+	 * @param boolean         $active       Whether the message type is active or not
2988
+	 * @return string html output for the content
2989
+	 * @throws DomainException
2990
+	 */
2991
+	protected function _message_type_settings_content($message_type, $messenger, $active = false)
2992
+	{
2993
+		// get message type fields
2994
+		$fields                                         = $message_type->get_admin_settings_fields();
2995
+		$settings_template_args['template_form_fields'] = '';
2996
+
2997
+		if (! empty($fields) && $active) {
2998
+			$existing_settings = $message_type->get_existing_admin_settings($messenger->name);
2999
+			foreach ($fields as $fldname => $fldprops) {
3000
+				$field_id                         = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3001
+				$template_form_field[ $field_id ] = [
3002
+					'name'       => 'message_type_settings[' . $fldname . ']',
3003
+					'label'      => $fldprops['label'],
3004
+					'input'      => $fldprops['field_type'],
3005
+					'type'       => $fldprops['value_type'],
3006
+					'required'   => $fldprops['required'],
3007
+					'validation' => $fldprops['validation'],
3008
+					'value'      => $existing_settings[ $fldname ] ?? $fldprops['default'],
3009
+					'options'    => $fldprops['options'] ?? [],
3010
+					'default'    => $existing_settings[ $fldname ] ?? $fldprops['default'],
3011
+					'css_class'  => 'no-drag',
3012
+					'format'     => $fldprops['format'],
3013
+				];
3014
+			}
3015
+
3016
+
3017
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3018
+				? $this->_generate_admin_form_fields(
3019
+					$template_form_field,
3020
+					'string',
3021
+					'ee_mt_activate_form'
3022
+				)
3023
+				: '';
3024
+		}
3025
+
3026
+		$settings_template_args['description'] = $message_type->description;
3027
+		// we also need some hidden fields
3028
+		$hidden_fields = [
3029
+			'message_type_settings[messenger]' . $message_type->name    => [
3030
+				'type'  => 'hidden',
3031
+				'value' => $messenger->name,
3032
+			],
3033
+			'message_type_settings[message_type]' . $message_type->name => [
3034
+				'type'  => 'hidden',
3035
+				'value' => $message_type->name,
3036
+			],
3037
+			'type' . $message_type->name                                => [
3038
+				'type'  => 'hidden',
3039
+				'value' => 'message_type',
3040
+			],
3041
+		];
3042
+
3043
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3044
+			$hidden_fields,
3045
+			'array'
3046
+		);
3047
+		$settings_template_args['show_form']     = empty($settings_template_args['template_form_fields'])
3048
+			? ' hidden'
3049
+			: '';
3050
+
3051
+
3052
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3053
+		return EEH_Template::display_template($template, $settings_template_args, true);
3054
+	}
3055
+
3056
+
3057
+	/**
3058
+	 * Generate all the metaboxes for the message types and register them for the messages settings page.
3059
+	 *
3060
+	 * @access protected
3061
+	 * @return void
3062
+	 * @throws DomainException
3063
+	 */
3064
+	protected function _messages_settings_metaboxes()
3065
+	{
3066
+		$this->_set_m_mt_settings();
3067
+		$m_boxes         = $mt_boxes = [];
3068
+		$m_template_args = $mt_template_args = [];
3069
+
3070
+		$selected_messenger = $this->request->getRequestParam('selected_messenger', 'email');
3071
+
3072
+		if (isset($this->_m_mt_settings['messenger_tabs'])) {
3073
+			foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3074
+				$is_messenger_active = $this->_message_resource_manager->is_messenger_active($messenger);
3075
+				$hide_on_message     = $is_messenger_active ? '' : 'hidden';
3076
+				$hide_off_message    = $is_messenger_active ? 'hidden' : '';
3077
+
3078
+				// messenger meta boxes
3079
+				$active         = $selected_messenger === $messenger;
3080
+				$active_mt_tabs = $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active'] ?? '';
3081
+
3082
+				$m_boxes[ $messenger . '_a_box' ] = sprintf(
3083
+					esc_html__('%s Settings', 'event_espresso'),
3084
+					$tab_array['label']
3085
+				);
3086
+
3087
+				$m_template_args[ $messenger . '_a_box' ] = [
3088
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3089
+					'inactive_message_types' => isset(
3090
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3091
+					)
3092
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3093
+						: '',
3094
+					'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3095
+					'hidden'                 => $active ? '' : ' hidden',
3096
+					'hide_on_message'        => $hide_on_message,
3097
+					'messenger'              => $messenger,
3098
+					'active'                 => $active,
3099
+				];
3100
+
3101
+				// message type meta boxes
3102
+				// (which is really just the inactive container for each messenger
3103
+				// showing inactive message types for that messenger)
3104
+				$mt_boxes[ $messenger . '_i_box' ]         = esc_html__('Inactive Message Types', 'event_espresso');
3105
+				$mt_template_args[ $messenger . '_i_box' ] = [
3106
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3107
+					'inactive_message_types' => isset(
3108
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3109
+					)
3110
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3111
+						: '',
3112
+					'hidden'                 => $active ? '' : ' hidden',
3113
+					'hide_on_message'        => $hide_on_message,
3114
+					'hide_off_message'       => $hide_off_message,
3115
+					'messenger'              => $messenger,
3116
+					'active'                 => $active,
3117
+				];
3118
+			}
3119
+		}
3120
+
3121
+
3122
+		// register messenger metaboxes
3123
+		$m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3124
+		foreach ($m_boxes as $box => $label) {
3125
+			$callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]];
3126
+			$msgr          = str_replace('_a_box', '', $box);
3127
+			$this->addMetaBox(
3128
+				'espresso_' . $msgr . '_settings',
3129
+				$label,
3130
+				function ($post, $metabox) {
3131
+					EEH_Template::display_template(
3132
+						$metabox['args']['template_path'],
3133
+						$metabox['args']['template_args']
3134
+					);
3135
+				},
3136
+				$this->_current_screen->id,
3137
+				'normal',
3138
+				'high',
3139
+				$callback_args
3140
+			);
3141
+		}
3142
+
3143
+		// register message type metaboxes
3144
+		$mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3145
+		foreach ($mt_boxes as $box => $label) {
3146
+			$callback_args = [
3147
+				'template_path' => $mt_template_path,
3148
+				'template_args' => $mt_template_args[ $box ],
3149
+			];
3150
+			$mt            = str_replace('_i_box', '', $box);
3151
+			$this->addMetaBox(
3152
+				'espresso_' . $mt . '_inactive_mts',
3153
+				$label,
3154
+				function ($post, $metabox) {
3155
+					EEH_Template::display_template(
3156
+						$metabox['args']['template_path'],
3157
+						$metabox['args']['template_args']
3158
+					);
3159
+				},
3160
+				$this->_current_screen->id,
3161
+				'side',
3162
+				'high',
3163
+				$callback_args
3164
+			);
3165
+		}
3166
+
3167
+		// register metabox for global messages settings but only when on the main site.  On single site installs this
3168
+		// will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3169
+		if (is_main_site()) {
3170
+			$this->addMetaBox(
3171
+				'espresso_global_message_settings',
3172
+				esc_html__('Global Message Settings', 'event_espresso'),
3173
+				[$this, 'global_messages_settings_metabox_content'],
3174
+				$this->_current_screen->id,
3175
+				'normal',
3176
+				'low',
3177
+				[]
3178
+			);
3179
+		}
3180
+	}
3181
+
3182
+
3183
+	/**
3184
+	 *  This generates the content for the global messages settings metabox.
3185
+	 *
3186
+	 * @return void
3187
+	 * @throws EE_Error
3188
+	 * @throws InvalidArgumentException
3189
+	 * @throws ReflectionException
3190
+	 * @throws InvalidDataTypeException
3191
+	 * @throws InvalidInterfaceException
3192
+	 */
3193
+	public function global_messages_settings_metabox_content()
3194
+	{
3195
+		$form = $this->_generate_global_settings_form();
3196
+		echo wp_kses(
3197
+			$form->form_open(
3198
+				$this->add_query_args_and_nonce(['action' => 'update_global_settings'], EE_MSG_ADMIN_URL),
3199
+				'POST'
3200
+			),
3201
+			AllowedTags::getWithFormTags()
3202
+		);
3203
+		echo wp_kses($form->get_html(), AllowedTags::getWithFormTags());
3204
+		echo wp_kses($form->form_close(), AllowedTags::getWithFormTags());
3205
+	}
3206
+
3207
+
3208
+	/**
3209
+	 * This generates and returns the form object for the global messages settings.
3210
+	 *
3211
+	 * @return EE_Form_Section_Proper
3212
+	 * @throws EE_Error
3213
+	 * @throws InvalidArgumentException
3214
+	 * @throws ReflectionException
3215
+	 * @throws InvalidDataTypeException
3216
+	 * @throws InvalidInterfaceException
3217
+	 */
3218
+	protected function _generate_global_settings_form()
3219
+	{
3220
+		/** @var EE_Network_Core_Config $network_config */
3221
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3222
+
3223
+		return new EE_Form_Section_Proper(
3224
+			[
3225
+				'name'            => 'global_messages_settings',
3226
+				'html_id'         => 'global_messages_settings',
3227
+				'html_class'      => 'form-table',
3228
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3229
+				'subsections'     => apply_filters(
3230
+					'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3231
+					[
3232
+						'do_messages_on_same_request' => new EE_Select_Input(
3233
+							[
3234
+								true  => esc_html__('On the same request', 'event_espresso'),
3235
+								false => esc_html__('On a separate request', 'event_espresso'),
3236
+							],
3237
+							[
3238
+								'default'         => $network_config->do_messages_on_same_request,
3239
+								'html_label_text' => esc_html__(
3240
+									'Generate and send all messages:',
3241
+									'event_espresso'
3242
+								),
3243
+								'html_help_text'  => esc_html__(
3244
+									'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3245
+									'event_espresso'
3246
+								),
3247
+							]
3248
+						),
3249
+						'delete_threshold'            => new EE_Select_Input(
3250
+							[
3251
+								0  => esc_html__('Forever', 'event_espresso'),
3252
+								3  => esc_html__('3 Months', 'event_espresso'),
3253
+								6  => esc_html__('6 Months', 'event_espresso'),
3254
+								9  => esc_html__('9 Months', 'event_espresso'),
3255
+								12 => esc_html__('12 Months', 'event_espresso'),
3256
+								24 => esc_html__('24 Months', 'event_espresso'),
3257
+								36 => esc_html__('36 Months', 'event_espresso'),
3258
+							],
3259
+							[
3260
+								'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3261
+								'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3262
+								'html_help_text'  => esc_html__(
3263
+									'You can control how long a record of processed messages is kept via this option.',
3264
+									'event_espresso'
3265
+								),
3266
+							]
3267
+						),
3268
+						'update_settings'             => new EE_Submit_Input(
3269
+							[
3270
+								'default'         => esc_html__('Update', 'event_espresso'),
3271
+								'html_label_text' => '',
3272
+							]
3273
+						),
3274
+					]
3275
+				),
3276
+			]
3277
+		);
3278
+	}
3279
+
3280
+
3281
+	/**
3282
+	 * This handles updating the global settings set on the admin page.
3283
+	 *
3284
+	 * @throws EE_Error
3285
+	 * @throws InvalidDataTypeException
3286
+	 * @throws InvalidInterfaceException
3287
+	 * @throws InvalidArgumentException
3288
+	 * @throws ReflectionException
3289
+	 */
3290
+	protected function _update_global_settings()
3291
+	{
3292
+		/** @var EE_Network_Core_Config $network_config */
3293
+		$network_config  = EE_Registry::instance()->NET_CFG->core;
3294
+		$messages_config = EE_Registry::instance()->CFG->messages;
3295
+		$form            = $this->_generate_global_settings_form();
3296
+		if ($form->was_submitted()) {
3297
+			$form->receive_form_submission();
3298
+			if ($form->is_valid()) {
3299
+				$valid_data = $form->valid_data();
3300
+				// \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 3);
3301
+				foreach ($valid_data as $property => $value) {
3302
+					$setter = 'set_' . $property;
3303
+					if (method_exists($network_config, $setter)) {
3304
+						$network_config->{$setter}($value);
3305
+					} elseif (
3306
+						property_exists($network_config, $property)
3307
+						&& $network_config->{$property} !== $value
3308
+					) {
3309
+						$network_config->{$property} = $value;
3310
+					} elseif (
3311
+						property_exists($messages_config, $property)
3312
+						&& $messages_config->{$property} !== $value
3313
+					) {
3314
+						$messages_config->{$property} = $value;
3315
+					}
3316
+				}
3317
+				// only update if the form submission was valid!
3318
+				EE_Registry::instance()->NET_CFG->update_config(true, false);
3319
+				EE_Registry::instance()->CFG->update_espresso_config();
3320
+				EE_Error::overwrite_success();
3321
+				EE_Error::add_success(esc_html__('Global message settings were updated', 'event_espresso'));
3322
+			}
3323
+		}
3324
+		$this->_redirect_after_action(0, '', '', ['action' => 'settings'], true);
3325
+	}
3326
+
3327
+
3328
+	/**
3329
+	 * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3330
+	 *
3331
+	 * @param array $tab_array This is an array of message type tab details used to generate the tabs
3332
+	 * @return string html formatted tabs
3333
+	 * @throws DomainException
3334
+	 */
3335
+	protected function _get_mt_tabs($tab_array)
3336
+	{
3337
+		$tab_array = (array) $tab_array;
3338
+		$template  = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3339
+		$tabs      = '';
3340
+
3341
+		foreach ($tab_array as $tab) {
3342
+			$tabs .= EEH_Template::display_template($template, $tab, true);
3343
+		}
3344
+
3345
+		return $tabs;
3346
+	}
3347
+
3348
+
3349
+	/**
3350
+	 * This prepares the content of the messenger meta box admin settings
3351
+	 *
3352
+	 * @param EE_messenger $messenger The messenger we're setting up content for
3353
+	 * @return string html formatted content
3354
+	 * @throws DomainException
3355
+	 */
3356
+	protected function _get_messenger_box_content(EE_messenger $messenger)
3357
+	{
3358
+		$fields = $messenger->get_admin_settings_fields();
3359
+
3360
+		$settings_template_args['template_form_fields'] = '';
3361
+		// is $messenger active?
3362
+		$settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3363
+
3364
+
3365
+		if (! empty($fields)) {
3366
+			$existing_settings = $messenger->get_existing_admin_settings();
3367
+
3368
+			foreach ($fields as $field_name => $field_props) {
3369
+				$field_id                         = $messenger->name . '-' . $field_name;
3370
+				$template_form_field[ $field_id ] = [
3371
+					'name'       => 'messenger_settings[' . $field_id . ']',
3372
+					'label'      => $field_props['label'],
3373
+					'input'      => $field_props['field_type'],
3374
+					'type'       => $field_props['value_type'],
3375
+					'required'   => $field_props['required'],
3376
+					'validation' => $field_props['validation'],
3377
+					'value'      => $existing_settings[ $field_id ] ?? $field_props['default'],
3378
+					'css_class'  => '',
3379
+					'format'     => $field_props['format'],
3380
+				];
3381
+			}
3382
+
3383
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3384
+				? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3385
+				: '';
3386
+		}
3387
+
3388
+		// we also need some hidden fields
3389
+		$settings_template_args['hidden_fields'] = [
3390
+			'messenger_settings[messenger]' . $messenger->name => [
3391
+				'type'  => 'hidden',
3392
+				'value' => $messenger->name,
3393
+			],
3394
+			'type' . $messenger->name                          => [
3395
+				'type'  => 'hidden',
3396
+				'value' => 'messenger',
3397
+			],
3398
+		];
3399
+
3400
+		// make sure any active message types that are existing are included in the hidden fields
3401
+		if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3402
+			foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3403
+				$settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = [
3404
+					'type'  => 'hidden',
3405
+					'value' => $mt,
3406
+				];
3407
+			}
3408
+		}
3409
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3410
+			$settings_template_args['hidden_fields'],
3411
+			'array'
3412
+		);
3413
+		$active                                  =
3414
+			$this->_message_resource_manager->is_messenger_active($messenger->name);
3415
+
3416
+		$settings_template_args['messenger']           = $messenger->name;
3417
+		$settings_template_args['description']         = $messenger->description;
3418
+		$settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3419
+
3420
+
3421
+		$settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3422
+			$messenger->name
3423
+		)
3424
+			? $settings_template_args['show_hide_edit_form']
3425
+			: ' hidden';
3426
+
3427
+		$settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3428
+			? ' hidden'
3429
+			: $settings_template_args['show_hide_edit_form'];
3430
+
3431
+
3432
+		$settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3433
+		$settings_template_args['nonce']         = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3434
+		$settings_template_args['on_off_status'] = $active;
3435
+		$template                                = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3436
+		return EEH_Template::display_template(
3437
+			$template,
3438
+			$settings_template_args,
3439
+			true
3440
+		);
3441
+	}
3442
+
3443
+
3444
+	/**
3445
+	 * used by ajax on the messages settings page to activate|deactivate the messenger
3446
+	 *
3447
+	 * @throws DomainException
3448
+	 * @throws EE_Error
3449
+	 * @throws InvalidDataTypeException
3450
+	 * @throws InvalidInterfaceException
3451
+	 * @throws InvalidArgumentException
3452
+	 * @throws ReflectionException
3453
+	 */
3454
+	public function activate_messenger_toggle()
3455
+	{
3456
+		if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3457
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3458
+		}
3459
+		$success = true;
3460
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3461
+		// let's check that we have required data
3462
+
3463
+		if (! $this->_active_messenger_name) {
3464
+			EE_Error::add_error(
3465
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3466
+				__FILE__,
3467
+				__FUNCTION__,
3468
+				__LINE__
3469
+			);
3470
+			$success = false;
3471
+		}
3472
+
3473
+		// do a nonce check here since we're not arriving via a normal route
3474
+		$nonce     = $this->request->getRequestParam('activate_nonce', '');
3475
+		$nonce_ref = "activate_{$this->_active_messenger_name}_toggle_nonce";
3476
+
3477
+		$this->_verify_nonce($nonce, $nonce_ref);
3478
+
3479
+
3480
+		$status = $this->request->getRequestParam('status');
3481
+		if (! $status) {
3482
+			EE_Error::add_error(
3483
+				esc_html__(
3484
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3485
+					'event_espresso'
3486
+				),
3487
+				__FILE__,
3488
+				__FUNCTION__,
3489
+				__LINE__
3490
+			);
3491
+			$success = false;
3492
+		}
3493
+
3494
+		// do check to verify we have a valid status.
3495
+		if ($status !== 'off' && $status !== 'on') {
3496
+			EE_Error::add_error(
3497
+				sprintf(
3498
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3499
+					$status
3500
+				),
3501
+				__FILE__,
3502
+				__FUNCTION__,
3503
+				__LINE__
3504
+			);
3505
+			$success = false;
3506
+		}
3507
+
3508
+		if ($success) {
3509
+			// made it here?  Stop dawdling then!!
3510
+			$success = $status === 'off'
3511
+				? $this->_deactivate_messenger($this->_active_messenger_name)
3512
+				: $this->_activate_messenger($this->_active_messenger_name);
3513
+		}
3514
+
3515
+		$this->_template_args['success'] = $success;
3516
+
3517
+		// no special instructions so let's just do the json return (which should automatically do all the special stuff).
3518
+		$this->_return_json();
3519
+	}
3520
+
3521
+
3522
+	/**
3523
+	 * used by ajax from the messages settings page to activate|deactivate a message type
3524
+	 *
3525
+	 * @throws DomainException
3526
+	 * @throws EE_Error
3527
+	 * @throws ReflectionException
3528
+	 * @throws InvalidDataTypeException
3529
+	 * @throws InvalidInterfaceException
3530
+	 * @throws InvalidArgumentException
3531
+	 */
3532
+	public function activate_mt_toggle()
3533
+	{
3534
+		if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3535
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3536
+		}
3537
+		$success = true;
3538
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3539
+
3540
+		// let's make sure we have the necessary data
3541
+		if (! $this->_active_message_type_name) {
3542
+			EE_Error::add_error(
3543
+				esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3544
+				__FILE__,
3545
+				__FUNCTION__,
3546
+				__LINE__
3547
+			);
3548
+			$success = false;
3549
+		}
3550
+
3551
+		if (! $this->_active_messenger_name) {
3552
+			EE_Error::add_error(
3553
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3554
+				__FILE__,
3555
+				__FUNCTION__,
3556
+				__LINE__
3557
+			);
3558
+			$success = false;
3559
+		}
3560
+
3561
+		$status = $this->request->getRequestParam('status');
3562
+		if (! $status) {
3563
+			EE_Error::add_error(
3564
+				esc_html__(
3565
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3566
+					'event_espresso'
3567
+				),
3568
+				__FILE__,
3569
+				__FUNCTION__,
3570
+				__LINE__
3571
+			);
3572
+			$success = false;
3573
+		}
3574
+
3575
+
3576
+		// do check to verify we have a valid status.
3577
+		if ($status !== 'activate' && $status !== 'deactivate') {
3578
+			EE_Error::add_error(
3579
+				sprintf(
3580
+					esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3581
+					$status
3582
+				),
3583
+				__FILE__,
3584
+				__FUNCTION__,
3585
+				__LINE__
3586
+			);
3587
+			$success = false;
3588
+		}
3589
+
3590
+
3591
+		// do a nonce check here since we're not arriving via a normal route
3592
+		$nonce = $this->request->getRequestParam('mt_nonce', '');
3593
+		$this->_verify_nonce($nonce, "{$this->_active_message_type_name}_nonce");
3594
+
3595
+		if ($success) {
3596
+			// made it here? um, what are you waiting for then?
3597
+			$success = $status === 'deactivate'
3598
+				? $this->_deactivate_message_type_for_messenger(
3599
+					$this->_active_messenger_name,
3600
+					$this->_active_message_type_name
3601
+				)
3602
+				: $this->_activate_message_type_for_messenger(
3603
+					$this->_active_messenger_name,
3604
+					$this->_active_message_type_name
3605
+				);
3606
+		}
3607
+
3608
+		$this->_template_args['success'] = $success;
3609
+		$this->_return_json();
3610
+	}
3611
+
3612
+
3613
+	/**
3614
+	 * Takes care of processing activating a messenger and preparing the appropriate response.
3615
+	 *
3616
+	 * @param string $messenger_name The name of the messenger being activated
3617
+	 * @return bool
3618
+	 * @throws DomainException
3619
+	 * @throws EE_Error
3620
+	 * @throws InvalidArgumentException
3621
+	 * @throws ReflectionException
3622
+	 * @throws InvalidDataTypeException
3623
+	 * @throws InvalidInterfaceException
3624
+	 */
3625
+	protected function _activate_messenger($messenger_name)
3626
+	{
3627
+		$active_messenger          = $this->_message_resource_manager->get_messenger($messenger_name);
3628
+		$message_types_to_activate = $active_messenger instanceof EE_Messenger
3629
+			? $active_messenger->get_default_message_types()
3630
+			: [];
3631
+
3632
+		// ensure is active
3633
+		$this->_message_resource_manager->activate_messenger($active_messenger, $message_types_to_activate);
3634
+
3635
+		// set response_data for reload
3636
+		foreach ($message_types_to_activate as $message_type_name) {
3637
+			$message_type = $this->_message_resource_manager->get_message_type($message_type_name);
3638
+			if (
3639
+				$this->_message_resource_manager->is_message_type_active_for_messenger(
3640
+					$messenger_name,
3641
+					$message_type_name
3642
+				)
3643
+				&& $message_type instanceof EE_message_type
3644
+			) {
3645
+				$this->_template_args['data']['active_mts'][] = $message_type_name;
3646
+				if ($message_type->get_admin_settings_fields()) {
3647
+					$this->_template_args['data']['mt_reload'][] = $message_type_name;
3648
+				}
3649
+			}
3650
+		}
3651
+
3652
+		// add success message for activating messenger
3653
+		return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
3654
+	}
3655
+
3656
+
3657
+	/**
3658
+	 * Takes care of processing deactivating a messenger and preparing the appropriate response.
3659
+	 *
3660
+	 * @param string $messenger_name The name of the messenger being activated
3661
+	 * @return bool
3662
+	 * @throws DomainException
3663
+	 * @throws EE_Error
3664
+	 * @throws InvalidArgumentException
3665
+	 * @throws ReflectionException
3666
+	 * @throws InvalidDataTypeException
3667
+	 * @throws InvalidInterfaceException
3668
+	 */
3669
+	protected function _deactivate_messenger($messenger_name)
3670
+	{
3671
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
3672
+		$this->_message_resource_manager->deactivate_messenger($messenger_name);
3673
+
3674
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
3675
+	}
3676
+
3677
+
3678
+	/**
3679
+	 * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
3680
+	 *
3681
+	 * @param string $messenger_name    The name of the messenger the message type is being activated for.
3682
+	 * @param string $message_type_name The name of the message type being activated for the messenger
3683
+	 * @return bool
3684
+	 * @throws DomainException
3685
+	 * @throws EE_Error
3686
+	 * @throws InvalidArgumentException
3687
+	 * @throws ReflectionException
3688
+	 * @throws InvalidDataTypeException
3689
+	 * @throws InvalidInterfaceException
3690
+	 */
3691
+	protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
3692
+	{
3693
+		$active_messenger         = $this->_message_resource_manager->get_messenger($messenger_name);
3694
+		$message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
3695
+
3696
+		// ensure is active
3697
+		$this->_message_resource_manager->activate_messenger($active_messenger, $message_type_name);
3698
+
3699
+		// set response for load
3700
+		if (
3701
+			$this->_message_resource_manager->is_message_type_active_for_messenger(
3702
+				$messenger_name,
3703
+				$message_type_name
3704
+			)
3705
+		) {
3706
+			$this->_template_args['data']['active_mts'][] = $message_type_name;
3707
+			if ($message_type_to_activate->get_admin_settings_fields()) {
3708
+				$this->_template_args['data']['mt_reload'][] = $message_type_name;
3709
+			}
3710
+		}
3711
+
3712
+		return $this->_setup_response_message_for_activating_messenger_with_message_types(
3713
+			$active_messenger,
3714
+			$message_type_to_activate
3715
+		);
3716
+	}
3717
+
3718
+
3719
+	/**
3720
+	 * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
3721
+	 *
3722
+	 * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
3723
+	 * @param string $message_type_name The name of the message type being deactivated for the messenger
3724
+	 * @return bool
3725
+	 * @throws DomainException
3726
+	 * @throws EE_Error
3727
+	 * @throws InvalidArgumentException
3728
+	 * @throws ReflectionException
3729
+	 * @throws InvalidDataTypeException
3730
+	 * @throws InvalidInterfaceException
3731
+	 */
3732
+	protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
3733
+	{
3734
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
3735
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
3736
+		$message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
3737
+		$this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
3738
+
3739
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
3740
+			$active_messenger,
3741
+			$message_type_to_deactivate
3742
+		);
3743
+	}
3744
+
3745
+
3746
+	/**
3747
+	 * This just initializes the defaults for activating messenger and message type responses.
3748
+	 */
3749
+	protected function _prep_default_response_for_messenger_or_message_type_toggle()
3750
+	{
3751
+		$this->_template_args['data']['active_mts'] = [];
3752
+		$this->_template_args['data']['mt_reload']  = [];
3753
+	}
3754
+
3755
+
3756
+	/**
3757
+	 * Setup appropriate response for activating a messenger and/or message types
3758
+	 *
3759
+	 * @param EE_messenger         $messenger
3760
+	 * @param EE_message_type|null $message_type
3761
+	 * @return bool
3762
+	 * @throws DomainException
3763
+	 * @throws EE_Error
3764
+	 * @throws InvalidArgumentException
3765
+	 * @throws ReflectionException
3766
+	 * @throws InvalidDataTypeException
3767
+	 * @throws InvalidInterfaceException
3768
+	 */
3769
+	protected function _setup_response_message_for_activating_messenger_with_message_types(
3770
+		$messenger,
3771
+		EE_Message_Type $message_type = null
3772
+	) {
3773
+		// if $messenger isn't a valid messenger object then get out.
3774
+		if (! $messenger instanceof EE_Messenger) {
3775
+			EE_Error::add_error(
3776
+				esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
3777
+				__FILE__,
3778
+				__FUNCTION__,
3779
+				__LINE__
3780
+			);
3781
+			return false;
3782
+		}
3783
+		// activated
3784
+		if ($this->_template_args['data']['active_mts']) {
3785
+			EE_Error::overwrite_success();
3786
+			// activated a message type with the messenger
3787
+			if ($message_type instanceof EE_message_type) {
3788
+				EE_Error::add_success(
3789
+					sprintf(
3790
+						esc_html__(
3791
+							'%s message type has been successfully activated with the %s messenger',
3792
+							'event_espresso'
3793
+						),
3794
+						ucwords($message_type->label['singular']),
3795
+						ucwords($messenger->label['singular'])
3796
+					)
3797
+				);
3798
+
3799
+				// if message type was invoice then let's make sure we activate the invoice payment method.
3800
+				if ($message_type->name === 'invoice') {
3801
+					EE_Registry::instance()->load_lib('Payment_Method_Manager');
3802
+					$pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
3803
+					if ($pm instanceof EE_Payment_Method) {
3804
+						EE_Error::add_attention(
3805
+							esc_html__(
3806
+								'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
3807
+								'event_espresso'
3808
+							)
3809
+						);
3810
+					}
3811
+				}
3812
+				// just toggles the entire messenger
3813
+			} else {
3814
+				EE_Error::add_success(
3815
+					sprintf(
3816
+						esc_html__('%s messenger has been successfully activated', 'event_espresso'),
3817
+						ucwords($messenger->label['singular'])
3818
+					)
3819
+				);
3820
+			}
3821
+
3822
+			return true;
3823
+
3824
+			// possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
3825
+			// message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
3826
+			// in which case we just give a success message for the messenger being successfully activated.
3827
+		} else {
3828
+			if (! $messenger->get_default_message_types()) {
3829
+				// messenger doesn't have any default message types so still a success.
3830
+				EE_Error::add_success(
3831
+					sprintf(
3832
+						esc_html__('%s messenger was successfully activated.', 'event_espresso'),
3833
+						ucwords($messenger->label['singular'])
3834
+					)
3835
+				);
3836
+
3837
+				return true;
3838
+			} else {
3839
+				EE_Error::add_error(
3840
+					$message_type instanceof EE_message_type
3841
+						? sprintf(
3842
+						esc_html__(
3843
+							'%s message type was not successfully activated with the %s messenger',
3844
+							'event_espresso'
3845
+						),
3846
+						ucwords($message_type->label['singular']),
3847
+						ucwords($messenger->label['singular'])
3848
+					)
3849
+						: sprintf(
3850
+						esc_html__('%s messenger was not successfully activated', 'event_espresso'),
3851
+						ucwords($messenger->label['singular'])
3852
+					),
3853
+					__FILE__,
3854
+					__FUNCTION__,
3855
+					__LINE__
3856
+				);
3857
+
3858
+				return false;
3859
+			}
3860
+		}
3861
+	}
3862
+
3863
+
3864
+	/**
3865
+	 * This sets up the appropriate response for deactivating a messenger and/or message type.
3866
+	 *
3867
+	 * @param EE_messenger         $messenger
3868
+	 * @param EE_message_type|null $message_type
3869
+	 * @return bool
3870
+	 * @throws DomainException
3871
+	 * @throws EE_Error
3872
+	 * @throws InvalidArgumentException
3873
+	 * @throws ReflectionException
3874
+	 * @throws InvalidDataTypeException
3875
+	 * @throws InvalidInterfaceException
3876
+	 */
3877
+	protected function _setup_response_message_for_deactivating_messenger_with_message_types(
3878
+		$messenger,
3879
+		EE_message_type $message_type = null
3880
+	) {
3881
+		EE_Error::overwrite_success();
3882
+
3883
+		// if $messenger isn't a valid messenger object then get out.
3884
+		if (! $messenger instanceof EE_Messenger) {
3885
+			EE_Error::add_error(
3886
+				esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
3887
+				__FILE__,
3888
+				__FUNCTION__,
3889
+				__LINE__
3890
+			);
3891
+
3892
+			return false;
3893
+		}
3894
+
3895
+		if ($message_type instanceof EE_message_type) {
3896
+			$message_type_name = $message_type->name;
3897
+			EE_Error::add_success(
3898
+				sprintf(
3899
+					esc_html__(
3900
+						'%s message type has been successfully deactivated for the %s messenger.',
3901
+						'event_espresso'
3902
+					),
3903
+					ucwords($message_type->label['singular']),
3904
+					ucwords($messenger->label['singular'])
3905
+				)
3906
+			);
3907
+		} else {
3908
+			$message_type_name = '';
3909
+			EE_Error::add_success(
3910
+				sprintf(
3911
+					esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
3912
+					ucwords($messenger->label['singular'])
3913
+				)
3914
+			);
3915
+		}
3916
+
3917
+		// if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
3918
+		if (
3919
+			$messenger->name === 'html'
3920
+			&& (
3921
+				is_null($message_type)
3922
+				|| $message_type_name === 'invoice'
3923
+			)
3924
+		) {
3925
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
3926
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
3927
+			if ($count_updated > 0) {
3928
+				$msg = $message_type_name === 'invoice'
3929
+					? esc_html__(
3930
+						'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
3931
+						'event_espresso'
3932
+					)
3933
+					: esc_html__(
3934
+						'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
3935
+						'event_espresso'
3936
+					);
3937
+				EE_Error::add_attention($msg);
3938
+			}
3939
+		}
3940
+
3941
+		return true;
3942
+	}
3943
+
3944
+
3945
+	/**
3946
+	 * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
3947
+	 *
3948
+	 * @throws DomainException
3949
+	 * @throws EE_Error
3950
+	 * @throws EE_Error
3951
+	 */
3952
+	public function update_mt_form()
3953
+	{
3954
+		if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3955
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3956
+		}
3957
+		if (! $this->_active_messenger_name || ! $this->_active_message_type_name) {
3958
+			EE_Error::add_error(
3959
+				esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
3960
+				__FILE__,
3961
+				__FUNCTION__,
3962
+				__LINE__
3963
+			);
3964
+			$this->_return_json();
3965
+		}
3966
+
3967
+		$message_types = $this->get_installed_message_types();
3968
+		$message_type  = $message_types[ $this->_active_message_type_name ];
3969
+		$messenger     = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
3970
+		$content       = $this->_message_type_settings_content($message_type, $messenger, true);
3971
+
3972
+		$this->_template_args['success'] = true;
3973
+		$this->_template_args['content'] = $content;
3974
+		$this->_return_json();
3975
+	}
3976
+
3977
+
3978
+	/**
3979
+	 * this handles saving the settings for a messenger or message type
3980
+	 *
3981
+	 * @throws EE_Error
3982
+	 * @throws EE_Error
3983
+	 */
3984
+	public function save_settings()
3985
+	{
3986
+		if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3987
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3988
+		}
3989
+		$type = $this->request->getRequestParam('type');
3990
+		if (! $type) {
3991
+			EE_Error::add_error(
3992
+				esc_html__(
3993
+					'Cannot save settings because type is unknown (messenger settings or message type settings?)',
3994
+					'event_espresso'
3995
+				),
3996
+				__FILE__,
3997
+				__FUNCTION__,
3998
+				__LINE__
3999
+			);
4000
+			$this->_template_args['error'] = true;
4001
+			$this->_return_json();
4002
+		}
4003
+
4004
+
4005
+		if ($type === 'messenger') {
4006
+			// this should be an array.
4007
+			$settings  = $this->request->getRequestParam('messenger_settings', [], 'string', true);
4008
+			$messenger = $settings['messenger'];
4009
+			// remove messenger and message_types from settings array
4010
+			unset($settings['messenger'], $settings['message_types']);
4011
+			$this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4012
+		} elseif ($type === 'message_type') {
4013
+			$settings     = $this->request->getRequestParam('message_type_settings', [], 'string', true);
4014
+			$messenger    = $settings['messenger'];
4015
+			$message_type = $settings['message_type'];
4016
+			// remove messenger and message_types from settings array
4017
+			unset($settings['messenger'], $settings['message_types']);
4018
+			$this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4019
+		}
4020
+
4021
+		// okay we should have the data all setup.  Now we just update!
4022
+		$success = $this->_message_resource_manager->update_active_messengers_option();
4023
+
4024
+		if ($success) {
4025
+			EE_Error::add_success(esc_html__('Settings updated', 'event_espresso'));
4026
+		} else {
4027
+			EE_Error::add_error(
4028
+				esc_html__('Settings did not get updated', 'event_espresso'),
4029
+				__FILE__,
4030
+				__FUNCTION__,
4031
+				__LINE__
4032
+			);
4033
+		}
4034
+
4035
+		$this->_template_args['success'] = $success;
4036
+		$this->_return_json();
4037
+	}
4038
+
4039
+
4040
+
4041
+
4042
+	/**  EE MESSAGE PROCESSING ACTIONS **/
4043
+
4044
+
4045
+	/**
4046
+	 * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4047
+	 * However, this does not send immediately, it just queues for sending.
4048
+	 *
4049
+	 * @throws EE_Error
4050
+	 * @throws InvalidDataTypeException
4051
+	 * @throws InvalidInterfaceException
4052
+	 * @throws InvalidArgumentException
4053
+	 * @throws ReflectionException
4054
+	 * @since 4.9.0
4055
+	 */
4056
+	protected function _generate_now()
4057
+	{
4058
+		EED_Messages::generate_now($this->_get_msg_ids_from_request());
4059
+		$this->_redirect_after_action(false, '', '', [], true);
4060
+	}
4061
+
4062
+
4063
+	/**
4064
+	 * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4065
+	 * are EEM_Message::status_resend or EEM_Message::status_idle
4066
+	 *
4067
+	 * @throws EE_Error
4068
+	 * @throws InvalidDataTypeException
4069
+	 * @throws InvalidInterfaceException
4070
+	 * @throws InvalidArgumentException
4071
+	 * @throws ReflectionException
4072
+	 * @since 4.9.0
4073
+	 */
4074
+	protected function _generate_and_send_now()
4075
+	{
4076
+		EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4077
+		$this->_redirect_after_action(false, '', '', [], true);
4078
+	}
4079
+
4080
+
4081
+	/**
4082
+	 * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4083
+	 *
4084
+	 * @throws EE_Error
4085
+	 * @throws InvalidDataTypeException
4086
+	 * @throws InvalidInterfaceException
4087
+	 * @throws InvalidArgumentException
4088
+	 * @throws ReflectionException
4089
+	 * @since 4.9.0
4090
+	 */
4091
+	protected function _queue_for_resending()
4092
+	{
4093
+		EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4094
+		$this->_redirect_after_action(false, '', '', [], true);
4095
+	}
4096
+
4097
+
4098
+	/**
4099
+	 *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4100
+	 *
4101
+	 * @throws EE_Error
4102
+	 * @throws InvalidDataTypeException
4103
+	 * @throws InvalidInterfaceException
4104
+	 * @throws InvalidArgumentException
4105
+	 * @throws ReflectionException
4106
+	 * @since 4.9.0
4107
+	 */
4108
+	protected function _send_now()
4109
+	{
4110
+		EED_Messages::send_now($this->_get_msg_ids_from_request());
4111
+		$this->_redirect_after_action(false, '', '', [], true);
4112
+	}
4113
+
4114
+
4115
+	/**
4116
+	 * Deletes EE_messages for IDs in the request.
4117
+	 *
4118
+	 * @throws EE_Error
4119
+	 * @throws InvalidDataTypeException
4120
+	 * @throws InvalidInterfaceException
4121
+	 * @throws InvalidArgumentException
4122
+	 * @throws ReflectionException
4123
+	 * @since 4.9.0
4124
+	 */
4125
+	protected function _delete_ee_messages()
4126
+	{
4127
+		$MSG_IDs       = $this->_get_msg_ids_from_request();
4128
+		$deleted_count = 0;
4129
+		foreach ($MSG_IDs as $MSG_ID) {
4130
+			if ($this->getMsgModel()->delete_by_ID($MSG_ID)) {
4131
+				$deleted_count++;
4132
+			}
4133
+		}
4134
+		if ($deleted_count) {
4135
+			EE_Error::add_success(
4136
+				esc_html(
4137
+					_n(
4138
+						'Message successfully deleted',
4139
+						'Messages successfully deleted',
4140
+						$deleted_count,
4141
+						'event_espresso'
4142
+					)
4143
+				)
4144
+			);
4145
+		} else {
4146
+			EE_Error::add_error(
4147
+				_n('The message was not deleted.', 'The messages were not deleted', count($MSG_IDs), 'event_espresso'),
4148
+				__FILE__,
4149
+				__FUNCTION__,
4150
+				__LINE__
4151
+			);
4152
+		}
4153
+		$this->_redirect_after_action(false, '', '', [], true);
4154
+	}
4155
+
4156
+
4157
+	/**
4158
+	 *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4159
+	 *
4160
+	 * @return array
4161
+	 * @since 4.9.0
4162
+	 */
4163
+	protected function _get_msg_ids_from_request()
4164
+	{
4165
+		$MSG_IDs = $this->request->getRequestParam('MSG_ID', [], 'string', true);
4166
+		if (empty($MSG_IDs)) {
4167
+			return [];
4168
+		}
4169
+		// if 'MSG_ID' was just a single ID (not an array)
4170
+		// then $MSG_IDs will be something like [123] so $MSG_IDs[0] should be 123
4171
+		// otherwise, $MSG_IDs was already an array where message IDs were used as the keys
4172
+		return count($MSG_IDs) === 1 && isset($MSG_IDs[0])
4173
+			? $MSG_IDs
4174
+			: array_keys($MSG_IDs);
4175
+	}
4176 4176
 }
Please login to merge, or discard this patch.
Spacing   +221 added lines, -221 removed lines patch added patch discarded remove patch
@@ -86,7 +86,7 @@  discard block
 block discarded – undo
86 86
      */
87 87
     public function getMsgModel(): EEM_Message
88 88
     {
89
-        if (! $this->MSG_MODEL instanceof EEM_Message) {
89
+        if ( ! $this->MSG_MODEL instanceof EEM_Message) {
90 90
             $this->MSG_MODEL = EEM_Message::instance();
91 91
         }
92 92
         return $this->MSG_MODEL;
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
      */
101 101
     public function getMtpModel(): EEM_Message_Template
102 102
     {
103
-        if (! $this->MTP_MODEL instanceof EEM_Message_Template) {
103
+        if ( ! $this->MTP_MODEL instanceof EEM_Message_Template) {
104 104
             $this->MTP_MODEL = EEM_Message_Template::instance();
105 105
         }
106 106
         return $this->MTP_MODEL;
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
      */
115 115
     public function getMtgModel(): EEM_Message_Template_Group
116 116
     {
117
-        if (! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
117
+        if ( ! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
118 118
             $this->MTG_MODEL = EEM_Message_Template_Group::instance();
119 119
         }
120 120
         return $this->MTG_MODEL;
@@ -123,7 +123,7 @@  discard block
 block discarded – undo
123 123
 
124 124
     public function getMessageTemplateManager(): MessageTemplateManager
125 125
     {
126
-        if (! $this->message_template_manager instanceof MessageTemplateManager) {
126
+        if ( ! $this->message_template_manager instanceof MessageTemplateManager) {
127 127
             $this->message_template_manager = $this->loader->getShared(MessageTemplateManager::class);
128 128
         }
129 129
         return $this->message_template_manager;
@@ -152,7 +152,7 @@  discard block
 block discarded – undo
152 152
 
153 153
     protected function _load_message_resource_manager()
154 154
     {
155
-        if (! $this->_message_resource_manager instanceof EE_Message_Resource_Manager) {
155
+        if ( ! $this->_message_resource_manager instanceof EE_Message_Resource_Manager) {
156 156
             $this->_message_resource_manager = $this->loader->getShared(EE_Message_Resource_Manager::class);
157 157
         }
158 158
     }
@@ -180,7 +180,7 @@  discard block
 block discarded – undo
180 180
             ['none_selected' => esc_html__('Show All Messengers', 'event_espresso')],
181 181
             $messenger_options
182 182
         );
183
-        $input             = new EE_Select_Input(
183
+        $input = new EE_Select_Input(
184 184
             $messenger_options,
185 185
             [
186 186
                 'html_name'  => 'ee_messenger_filter_by',
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
             ['none_selected' => esc_html__('Show All Message Types', 'event_espresso')],
218 218
             $message_type_options
219 219
         );
220
-        $input                = new EE_Select_Input(
220
+        $input = new EE_Select_Input(
221 221
             $message_type_options,
222 222
             [
223 223
                 'html_name'  => 'ee_message_type_filter_by',
@@ -254,7 +254,7 @@  discard block
 block discarded – undo
254 254
             ['none_selected' => esc_html__('Show all Contexts', 'event_espresso')],
255 255
             $context_options
256 256
         );
257
-        $input           = new EE_Select_Input(
257
+        $input = new EE_Select_Input(
258 258
             $context_options,
259 259
             [
260 260
                 'html_name'  => 'ee_context_filter_by',
@@ -270,7 +270,7 @@  discard block
 block discarded – undo
270 270
 
271 271
     protected function _ajax_hooks()
272 272
     {
273
-        if (! $this->capabilities->current_user_can('ee_edit_messages', 'edit-message-settings')) {
273
+        if ( ! $this->capabilities->current_user_can('ee_edit_messages', 'edit-message-settings')) {
274 274
             return;
275 275
         }
276 276
         add_action('wp_ajax_activate_messenger', [$this, 'activate_messenger_toggle']);
@@ -636,53 +636,53 @@  discard block
 block discarded – undo
636 636
 
637 637
     public function messages_help_tab()
638 638
     {
639
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
639
+        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH.'ee_msg_messages_help_tab.template.php');
640 640
     }
641 641
 
642 642
 
643 643
     public function messengers_help_tab()
644 644
     {
645
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
645
+        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH.'ee_msg_messenger_help_tab.template.php');
646 646
     }
647 647
 
648 648
 
649 649
     public function message_types_help_tab()
650 650
     {
651
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
651
+        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH.'ee_msg_message_type_help_tab.template.php');
652 652
     }
653 653
 
654 654
 
655 655
     public function messages_overview_help_tab()
656 656
     {
657
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
657
+        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH.'ee_msg_overview_help_tab.template.php');
658 658
     }
659 659
 
660 660
 
661 661
     public function message_templates_help_tab()
662 662
     {
663
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
663
+        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH.'ee_msg_message_templates_help_tab.template.php');
664 664
     }
665 665
 
666 666
 
667 667
     public function edit_message_template_help_tab()
668 668
     {
669
-        $args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
669
+        $args['img1'] = '<img src="'.EE_MSG_ASSETS_URL.'images/editor.png'.'" alt="'
670 670
                         . esc_attr__('Editor Title', 'event_espresso')
671 671
                         . '" />';
672
-        $args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
672
+        $args['img2'] = '<img src="'.EE_MSG_ASSETS_URL.'images/switch-context.png'.'" alt="'
673 673
                         . esc_attr__('Context Switcher and Preview', 'event_espresso')
674 674
                         . '" />';
675
-        $args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
675
+        $args['img3'] = '<img class="left" src="'.EE_MSG_ASSETS_URL.'images/form-fields.png'.'" alt="'
676 676
                         . esc_attr__('Message Template Form Fields', 'event_espresso')
677 677
                         . '" />';
678
-        $args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
678
+        $args['img4'] = '<img class="right" src="'.EE_MSG_ASSETS_URL.'images/shortcodes-metabox.png'.'" alt="'
679 679
                         . esc_attr__('Shortcodes Metabox', 'event_espresso')
680 680
                         . '" />';
681
-        $args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
681
+        $args['img5'] = '<img class="right" src="'.EE_MSG_ASSETS_URL.'images/publish-meta-box.png'.'" alt="'
682 682
                         . esc_attr__('Publish Metabox', 'event_espresso')
683 683
                         . '" />';
684 684
         EEH_Template::display_template(
685
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
685
+            EE_MSG_TEMPLATE_PATH.'ee_msg_messages_templates_editor_help_tab.template.php',
686 686
             $args
687 687
         );
688 688
     }
@@ -697,7 +697,7 @@  discard block
 block discarded – undo
697 697
         $this->_set_shortcodes();
698 698
         $args['shortcodes'] = $this->_shortcodes;
699 699
         EEH_Template::display_template(
700
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
700
+            EE_MSG_TEMPLATE_PATH.'ee_msg_messages_shortcodes_help_tab.template.php',
701 701
             $args
702 702
         );
703 703
     }
@@ -705,16 +705,16 @@  discard block
 block discarded – undo
705 705
 
706 706
     public function preview_message_help_tab()
707 707
     {
708
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
708
+        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH.'ee_msg_preview_help_tab.template.php');
709 709
     }
710 710
 
711 711
 
712 712
     public function settings_help_tab()
713 713
     {
714
-        $args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
715
-                        . '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
716
-        $args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
717
-                        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
714
+        $args['img1'] = '<img class="inline-text" src="'.EE_MSG_ASSETS_URL.'images/email-tab-active.png'
715
+                        . '" alt="'.esc_attr__('Active Email Tab', 'event_espresso').'" />';
716
+        $args['img2'] = '<img class="inline-text" src="'.EE_MSG_ASSETS_URL.'images/email-tab-inactive.png'
717
+                        . '" alt="'.esc_attr__('Inactive Email Tab', 'event_espresso').'" />';
718 718
         $args['img3'] = '<div class="ee-switch">'
719 719
                         . '<input class="ee-switch__input" id="ee-on-off-toggle-on" type="checkbox" checked>'
720 720
                         . '<label class="ee-switch__toggle" for="ee-on-off-toggle-on"></label>'
@@ -723,7 +723,7 @@  discard block
 block discarded – undo
723 723
                         . '<input class="ee-switch__input" id="ee-on-off-toggle-off" type="checkbox">'
724 724
                         . '<label class="ee-switch__toggle" for="ee-on-off-toggle-off"></label>'
725 725
                         . '</div>';
726
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
726
+        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH.'ee_msg_messages_settings_help_tab.template.php', $args);
727 727
     }
728 728
 
729 729
 
@@ -731,27 +731,27 @@  discard block
 block discarded – undo
731 731
     {
732 732
         wp_enqueue_style(
733 733
             'espresso_ee_msg',
734
-            EE_MSG_ASSETS_URL . 'ee_message_admin.css',
734
+            EE_MSG_ASSETS_URL.'ee_message_admin.css',
735 735
             [EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
736 736
             EVENT_ESPRESSO_VERSION
737 737
         );
738 738
         wp_enqueue_style(
739 739
             'ee_message_shortcodes',
740
-            EE_MSG_ASSETS_URL . 'ee_message_shortcodes.css',
740
+            EE_MSG_ASSETS_URL.'ee_message_shortcodes.css',
741 741
             [EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
742 742
             EVENT_ESPRESSO_VERSION
743 743
         );
744 744
 
745 745
         wp_register_script(
746 746
             'ee-messages-settings',
747
-            EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
747
+            EE_MSG_ASSETS_URL.'ee-messages-settings.js',
748 748
             ['jquery-ui-droppable', 'ee-serialize-full-array'],
749 749
             EVENT_ESPRESSO_VERSION,
750 750
             true
751 751
         );
752 752
         wp_register_script(
753 753
             'ee-msg-list-table-js',
754
-            EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
754
+            EE_MSG_ASSETS_URL.'ee_message_admin_list_table.js',
755 755
             ['ee-dialog'],
756 756
             EVENT_ESPRESSO_VERSION
757 757
         );
@@ -793,7 +793,7 @@  discard block
 block discarded – undo
793 793
     {
794 794
         $this->_set_shortcodes();
795 795
 
796
-        EE_Registry::$i18n_js_strings['confirm_default_reset']        = sprintf(
796
+        EE_Registry::$i18n_js_strings['confirm_default_reset'] = sprintf(
797 797
             esc_html__(
798 798
                 'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
799 799
                 'event_espresso'
@@ -805,14 +805,14 @@  discard block
 block discarded – undo
805 805
             'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
806 806
             'event_espresso'
807 807
         );
808
-        EE_Registry::$i18n_js_strings['server_error']                 = esc_html__(
808
+        EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
809 809
             'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
810 810
             'event_espresso'
811 811
         );
812 812
 
813 813
         wp_register_script(
814 814
             'ee_msgs_edit_js',
815
-            EE_MSG_ASSETS_URL . 'ee_message_editor.js',
815
+            EE_MSG_ASSETS_URL.'ee_message_editor.js',
816 816
             ['jquery'],
817 817
             EVENT_ESPRESSO_VERSION
818 818
         );
@@ -855,7 +855,7 @@  discard block
 block discarded – undo
855 855
     {
856 856
         wp_register_style(
857 857
             'ee-message-settings',
858
-            EE_MSG_ASSETS_URL . 'ee_message_settings.css',
858
+            EE_MSG_ASSETS_URL.'ee_message_settings.css',
859 859
             [],
860 860
             EVENT_ESPRESSO_VERSION
861 861
         );
@@ -941,7 +941,7 @@  discard block
 block discarded – undo
941 941
             }
942 942
             $status_bulk_actions = $common_bulk_actions;
943 943
             // unset bulk actions not applying to status
944
-            if (! empty($status_bulk_actions)) {
944
+            if ( ! empty($status_bulk_actions)) {
945 945
                 switch ($status) {
946 946
                     case EEM_Message::status_idle:
947 947
                     case EEM_Message::status_resend:
@@ -970,7 +970,7 @@  discard block
 block discarded – undo
970 970
                 continue;
971 971
             }
972 972
 
973
-            $this->_views[ strtolower($status) ] = [
973
+            $this->_views[strtolower($status)] = [
974 974
                 'slug'        => strtolower($status),
975 975
                 'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
976 976
                 'count'       => 0,
@@ -1017,7 +1017,7 @@  discard block
 block discarded – undo
1017 1017
             if ($action_item === 'see_notifications_for') {
1018 1018
                 continue;
1019 1019
             }
1020
-            $action_items[ $action_item ] = [
1020
+            $action_items[$action_item] = [
1021 1021
                 'class' => $action_details['css_class'],
1022 1022
                 'desc'  => $action_details['label'],
1023 1023
             ];
@@ -1026,37 +1026,37 @@  discard block
 block discarded – undo
1026 1026
         /** @var array $status_items status legend setup */
1027 1027
         $status_items = [
1028 1028
             'sent_status'                => [
1029
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_sent,
1029
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_sent,
1030 1030
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1031 1031
             ],
1032 1032
             'idle_status'                => [
1033
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_idle,
1033
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_idle,
1034 1034
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1035 1035
             ],
1036 1036
             'failed_status'              => [
1037
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_failed,
1037
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_failed,
1038 1038
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1039 1039
             ],
1040 1040
             'messenger_executing_status' => [
1041
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_messenger_executing,
1041
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_messenger_executing,
1042 1042
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1043 1043
             ],
1044 1044
             'resend_status'              => [
1045
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_resend,
1045
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_resend,
1046 1046
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1047 1047
             ],
1048 1048
             'incomplete_status'          => [
1049
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_incomplete,
1049
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_incomplete,
1050 1050
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1051 1051
             ],
1052 1052
             'retry_status'               => [
1053
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_retry,
1053
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_retry,
1054 1054
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1055 1055
             ],
1056 1056
         ];
1057 1057
         if (EEM_Message::debug()) {
1058 1058
             $status_items['debug_only_status'] = [
1059
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_debug_only,
1059
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Message::status_debug_only,
1060 1060
                 'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1061 1061
             ];
1062 1062
         }
@@ -1071,11 +1071,11 @@  discard block
 block discarded – undo
1071 1071
     protected function _custom_mtps_preview()
1072 1072
     {
1073 1073
         $this->_admin_page_title              = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1074
-        $this->_template_args['preview_img']  = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1075
-                                                . ' alt="' . esc_attr__(
1074
+        $this->_template_args['preview_img']  = '<img src="'.EE_MSG_ASSETS_URL.'images/custom_mtps_preview.png"'
1075
+                                                . ' alt="'.esc_attr__(
1076 1076
                                                     'Preview Custom Message Templates screenshot',
1077 1077
                                                     'event_espresso'
1078
-                                                ) . '" />';
1078
+                                                ).'" />';
1079 1079
         $this->_template_args['preview_text'] = '<strong>'
1080 1080
                                                 . esc_html__(
1081 1081
                                                     'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
@@ -1151,7 +1151,7 @@  discard block
 block discarded – undo
1151 1151
         $installed               = [];
1152 1152
 
1153 1153
         foreach ($installed_message_types as $message_type) {
1154
-            $installed[ $message_type->name ] = $message_type;
1154
+            $installed[$message_type->name] = $message_type;
1155 1155
         }
1156 1156
 
1157 1157
         return $installed;
@@ -1247,7 +1247,7 @@  discard block
 block discarded – undo
1247 1247
         // we need to assemble the title from Various details
1248 1248
         $context_label = sprintf(
1249 1249
             esc_html__('(%s %s)', 'event_espresso'),
1250
-            $c_config[ $context ]['label'],
1250
+            $c_config[$context]['label'],
1251 1251
             ucwords($c_label['label'])
1252 1252
         );
1253 1253
 
@@ -1269,7 +1269,7 @@  discard block
 block discarded – undo
1269 1269
             $message_template_group->message_type()
1270 1270
         );
1271 1271
 
1272
-        if (! $template_field_structure) {
1272
+        if ( ! $template_field_structure) {
1273 1273
             $template_field_structure = false;
1274 1274
             $template_fields          = esc_html__(
1275 1275
                 'There was an error in assembling the fields for this display (you should see an error message)',
@@ -1281,21 +1281,21 @@  discard block
 block discarded – undo
1281 1281
 
1282 1282
         // if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1283 1283
         // will get handled in the "extra" array.
1284
-        if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1285
-            foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1286
-                unset($template_field_structure[ $context ][ $reference_field ]);
1284
+        if (is_array($template_field_structure[$context]) && isset($template_field_structure[$context]['extra'])) {
1285
+            foreach ($template_field_structure[$context]['extra'] as $reference_field => $new_fields) {
1286
+                unset($template_field_structure[$context][$reference_field]);
1287 1287
             }
1288 1288
         }
1289 1289
 
1290 1290
         // let's loop through the template_field_structure and actually assemble the input fields!
1291
-        if (! empty($template_field_structure)) {
1292
-            foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1291
+        if ( ! empty($template_field_structure)) {
1292
+            foreach ($template_field_structure[$context] as $template_field => $field_setup_array) {
1293 1293
                 // if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1294 1294
                 // the extra array and reset them.
1295 1295
                 if ($template_field === 'extra') {
1296 1296
                     $this->_template_args['is_extra_fields'] = true;
1297 1297
                     foreach ($field_setup_array as $reference_field => $new_fields_array) {
1298
-                        $message_template = $message_templates[ $context ][ $reference_field ];
1298
+                        $message_template = $message_templates[$context][$reference_field];
1299 1299
                         $content          = $message_template instanceof EE_Message_Template
1300 1300
                             ? $message_template->get('MTP_content')
1301 1301
                             : '';
@@ -1304,7 +1304,7 @@  discard block
 block discarded – undo
1304 1304
                             $continue = false;
1305 1305
                             if (isset($extra_array['shortcodes_required'])) {
1306 1306
                                 foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1307
-                                    if (! array_key_exists($shortcode, $this->_shortcodes)) {
1307
+                                    if ( ! array_key_exists($shortcode, $this->_shortcodes)) {
1308 1308
                                         $continue = true;
1309 1309
                                     }
1310 1310
                                 }
@@ -1313,51 +1313,51 @@  discard block
 block discarded – undo
1313 1313
                                 }
1314 1314
                             }
1315 1315
 
1316
-                            $field_id = $reference_field . '-' . $extra_field . '-content';
1316
+                            $field_id = $reference_field.'-'.$extra_field.'-content';
1317 1317
 
1318
-                            $template_form_fields[ $field_id ]         = $extra_array;
1319
-                            $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1318
+                            $template_form_fields[$field_id]         = $extra_array;
1319
+                            $template_form_fields[$field_id]['name'] = 'MTP_template_fields['
1320 1320
                                                                          . $reference_field
1321 1321
                                                                          . '][content]['
1322
-                                                                         . $extra_field . ']';
1323
-                            $css_class                                 = $extra_array['css_class'] ?? '';
1322
+                                                                         . $extra_field.']';
1323
+                            $css_class = $extra_array['css_class'] ?? '';
1324 1324
 
1325
-                            $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1325
+                            $template_form_fields[$field_id]['css_class'] = ! empty($v_fields)
1326 1326
                                                                               && in_array($extra_field, $v_fields, true)
1327 1327
                                                                               && (
1328
-                                                                                  is_array($validators[ $extra_field ])
1329
-                                                                                  && isset($validators[ $extra_field ]['msg'])
1328
+                                                                                  is_array($validators[$extra_field])
1329
+                                                                                  && isset($validators[$extra_field]['msg'])
1330 1330
                                                                               )
1331
-                                ? 'validate-error ' . $css_class
1331
+                                ? 'validate-error '.$css_class
1332 1332
                                 : $css_class;
1333 1333
 
1334
-                            $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1335
-                                                                          && isset($content[ $extra_field ])
1336
-                                ? $content[ $extra_field ]
1334
+                            $template_form_fields[$field_id]['value'] = ! empty($message_templates)
1335
+                                                                          && isset($content[$extra_field])
1336
+                                ? $content[$extra_field]
1337 1337
                                 : '';
1338 1338
 
1339 1339
                             // do we have a validation error?  if we do then let's use that value instead
1340
-                            $template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1341
-                                ? $validators[ $extra_field ]['value']
1342
-                                : $template_form_fields[ $field_id ]['value'];
1340
+                            $template_form_fields[$field_id]['value'] = isset($validators[$extra_field])
1341
+                                ? $validators[$extra_field]['value']
1342
+                                : $template_form_fields[$field_id]['value'];
1343 1343
 
1344 1344
 
1345
-                            $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1345
+                            $template_form_fields[$field_id]['db-col'] = 'MTP_content';
1346 1346
 
1347 1347
                             // shortcode selector
1348 1348
                             $field_name_to_use                                   = $extra_field === 'main'
1349 1349
                                 ? 'content'
1350 1350
                                 : $extra_field;
1351
-                            $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1351
+                            $template_form_fields[$field_id]['append_content'] = $this->_get_shortcode_selector(
1352 1352
                                 $field_name_to_use,
1353 1353
                                 $field_id
1354 1354
                             );
1355 1355
                         }
1356
-                        $template_field_MTP_id           = $reference_field . '-MTP_ID';
1357
-                        $template_field_template_name_id = $reference_field . '-name';
1356
+                        $template_field_MTP_id           = $reference_field.'-MTP_ID';
1357
+                        $template_field_template_name_id = $reference_field.'-name';
1358 1358
 
1359
-                        $template_form_fields[ $template_field_MTP_id ] = [
1360
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1359
+                        $template_form_fields[$template_field_MTP_id] = [
1360
+                            'name'       => 'MTP_template_fields['.$reference_field.'][MTP_ID]',
1361 1361
                             'label'      => null,
1362 1362
                             'input'      => 'hidden',
1363 1363
                             'type'       => 'int',
@@ -1369,8 +1369,8 @@  discard block
 block discarded – undo
1369 1369
                             'db-col'     => 'MTP_ID',
1370 1370
                         ];
1371 1371
 
1372
-                        $template_form_fields[ $template_field_template_name_id ] = [
1373
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1372
+                        $template_form_fields[$template_field_template_name_id] = [
1373
+                            'name'       => 'MTP_template_fields['.$reference_field.'][name]',
1374 1374
                             'label'      => null,
1375 1375
                             'input'      => 'hidden',
1376 1376
                             'type'       => 'string',
@@ -1384,34 +1384,34 @@  discard block
 block discarded – undo
1384 1384
                     }
1385 1385
                     continue; // skip the next stuff, we got the necessary fields here for this dataset.
1386 1386
                 } else {
1387
-                    $field_id                                   = $template_field . '-content';
1388
-                    $template_form_fields[ $field_id ]          = $field_setup_array;
1389
-                    $template_form_fields[ $field_id ]['name']  =
1390
-                        'MTP_template_fields[' . $template_field . '][content]';
1387
+                    $field_id                                   = $template_field.'-content';
1388
+                    $template_form_fields[$field_id]          = $field_setup_array;
1389
+                    $template_form_fields[$field_id]['name']  =
1390
+                        'MTP_template_fields['.$template_field.'][content]';
1391 1391
                     $message_template                           =
1392
-                        $message_templates[ $context ][ $template_field ] ?? null;
1393
-                    $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1394
-                                                                  && is_array($message_templates[ $context ])
1392
+                        $message_templates[$context][$template_field] ?? null;
1393
+                    $template_form_fields[$field_id]['value'] = ! empty($message_templates)
1394
+                                                                  && is_array($message_templates[$context])
1395 1395
                                                                   && $message_template instanceof EE_Message_Template
1396 1396
                         ? $message_template->get('MTP_content')
1397 1397
                         : '';
1398 1398
 
1399 1399
                     // do we have a validator error for this field?  if we do then we'll use that value instead
1400
-                    $template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1401
-                        ? $validators[ $template_field ]['value']
1402
-                        : $template_form_fields[ $field_id ]['value'];
1400
+                    $template_form_fields[$field_id]['value'] = isset($validators[$template_field])
1401
+                        ? $validators[$template_field]['value']
1402
+                        : $template_form_fields[$field_id]['value'];
1403 1403
 
1404 1404
 
1405
-                    $template_form_fields[ $field_id ]['db-col']    = 'MTP_content';
1405
+                    $template_form_fields[$field_id]['db-col']    = 'MTP_content';
1406 1406
                     $css_class                                      = $field_setup_array['css_class'] ?? '';
1407
-                    $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1407
+                    $template_form_fields[$field_id]['css_class'] = ! empty($v_fields)
1408 1408
                                                                       && in_array($template_field, $v_fields, true)
1409
-                                                                      && isset($validators[ $template_field ]['msg'])
1410
-                        ? 'validate-error ' . $css_class
1409
+                                                                      && isset($validators[$template_field]['msg'])
1410
+                        ? 'validate-error '.$css_class
1411 1411
                         : $css_class;
1412 1412
 
1413 1413
                     // shortcode selector
1414
-                    $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1414
+                    $template_form_fields[$field_id]['append_content'] = $this->_get_shortcode_selector(
1415 1415
                         $template_field,
1416 1416
                         $field_id
1417 1417
                     );
@@ -1419,12 +1419,12 @@  discard block
 block discarded – undo
1419 1419
 
1420 1420
                 // k took care of content field(s) now let's take care of others.
1421 1421
 
1422
-                $template_field_MTP_id                 = $template_field . '-MTP_ID';
1423
-                $template_field_field_template_name_id = $template_field . '-name';
1422
+                $template_field_MTP_id                 = $template_field.'-MTP_ID';
1423
+                $template_field_field_template_name_id = $template_field.'-name';
1424 1424
 
1425 1425
                 // foreach template field there are actually two form fields created
1426
-                $template_form_fields[ $template_field_MTP_id ] = [
1427
-                    'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1426
+                $template_form_fields[$template_field_MTP_id] = [
1427
+                    'name'       => 'MTP_template_fields['.$template_field.'][MTP_ID]',
1428 1428
                     'label'      => null,
1429 1429
                     'input'      => 'hidden',
1430 1430
                     'type'       => 'int',
@@ -1436,8 +1436,8 @@  discard block
 block discarded – undo
1436 1436
                     'db-col'     => 'MTP_ID',
1437 1437
                 ];
1438 1438
 
1439
-                $template_form_fields[ $template_field_field_template_name_id ] = [
1440
-                    'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1439
+                $template_form_fields[$template_field_field_template_name_id] = [
1440
+                    'name'       => 'MTP_template_fields['.$template_field.'][name]',
1441 1441
                     'label'      => null,
1442 1442
                     'input'      => 'hidden',
1443 1443
                     'type'       => 'string',
@@ -1554,7 +1554,7 @@  discard block
 block discarded – undo
1554 1554
                 'format'     => '%d',
1555 1555
                 'db-col'     => 'MTP_deleted',
1556 1556
             ];
1557
-            $sidebar_form_fields['ee-msg-author']  = [
1557
+            $sidebar_form_fields['ee-msg-author'] = [
1558 1558
                 'name'       => 'MTP_user_id',
1559 1559
                 'label'      => esc_html__('Author', 'event_espresso'),
1560 1560
                 'input'      => 'hidden',
@@ -1573,17 +1573,17 @@  discard block
 block discarded – undo
1573 1573
                 'value' => $action,
1574 1574
             ];
1575 1575
 
1576
-            $sidebar_form_fields['ee-msg-id']        = [
1576
+            $sidebar_form_fields['ee-msg-id'] = [
1577 1577
                 'name'  => 'id',
1578 1578
                 'input' => 'hidden',
1579 1579
                 'type'  => 'int',
1580 1580
                 'value' => $GRP_ID,
1581 1581
             ];
1582 1582
             $sidebar_form_fields['ee-msg-evt-nonce'] = [
1583
-                'name'  => $action . '_nonce',
1583
+                'name'  => $action.'_nonce',
1584 1584
                 'input' => 'hidden',
1585 1585
                 'type'  => 'string',
1586
-                'value' => wp_create_nonce($action . '_nonce'),
1586
+                'value' => wp_create_nonce($action.'_nonce'),
1587 1587
             ];
1588 1588
 
1589 1589
             $template_switch = $this->request->getRequestParam('template_switch');
@@ -1615,7 +1615,7 @@  discard block
 block discarded – undo
1615 1615
         );
1616 1616
 
1617 1617
         // add preview button
1618
-        $preview_url    = parent::add_query_args_and_nonce(
1618
+        $preview_url = parent::add_query_args_and_nonce(
1619 1619
             [
1620 1620
                 'message_type' => $message_template_group->message_type(),
1621 1621
                 'messenger'    => $message_template_group->messenger(),
@@ -1626,7 +1626,7 @@  discard block
 block discarded – undo
1626 1626
             ],
1627 1627
             $this->_admin_base_url
1628 1628
         );
1629
-        $preview_button = '<a href="' . $preview_url . '" class="button--secondary messages-preview-button">'
1629
+        $preview_button = '<a href="'.$preview_url.'" class="button--secondary messages-preview-button">'
1630 1630
                           . esc_html__('Preview', 'event_espresso')
1631 1631
                           . '</a>';
1632 1632
 
@@ -1662,11 +1662,11 @@  discard block
 block discarded – undo
1662 1662
         $this->_template_args['before_admin_page_content'] .= $this->add_context_switcher();
1663 1663
         $this->_template_args['before_admin_page_content'] .= '</div>';
1664 1664
         $this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1665
-        $this->_template_args['after_admin_page_content']  = $this->_add_form_element_after();
1665
+        $this->_template_args['after_admin_page_content'] = $this->_add_form_element_after();
1666 1666
 
1667 1667
         $this->_template_path = $this->_template_args['GRP_ID']
1668 1668
             ? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1669
-            : EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1669
+            : EE_MSG_TEMPLATE_PATH.'ee_msg_details_main_add_meta_box.template.php';
1670 1670
 
1671 1671
         // send along EE_Message_Template_Group object for further template use.
1672 1672
         $this->_template_args['MTP'] = $message_template_group;
@@ -1719,7 +1719,7 @@  discard block
 block discarded – undo
1719 1719
     ) {
1720 1720
         $template_args = [
1721 1721
             'context'                   => $context,
1722
-            'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1722
+            'nonce'                     => wp_create_nonce('activate_'.$context.'_toggle_nonce'),
1723 1723
             'is_active'                 => $message_template_group->is_context_active($context),
1724 1724
             'on_off_action'             => $message_template_group->is_context_active($context)
1725 1725
                 ? 'context-off'
@@ -1728,7 +1728,7 @@  discard block
 block discarded – undo
1728 1728
             'message_template_group_id' => $message_template_group->ID(),
1729 1729
         ];
1730 1730
         return EEH_Template::display_template(
1731
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1731
+            EE_MSG_TEMPLATE_PATH.'ee_msg_editor_active_context_element.template.php',
1732 1732
             $template_args,
1733 1733
             true
1734 1734
         );
@@ -1748,7 +1748,7 @@  discard block
 block discarded – undo
1748 1748
      */
1749 1749
     public function toggle_context_template()
1750 1750
     {
1751
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1751
+        if ( ! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1752 1752
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1753 1753
         }
1754 1754
         $success = true;
@@ -1789,7 +1789,7 @@  discard block
 block discarded – undo
1789 1789
         }
1790 1790
         $message_template_group_id = $this->request->getRequestParam('message_template_group_id', 0, DataType::INTEGER);
1791 1791
         $message_template_group    = $this->getMtgModel()->get_one_by_ID($message_template_group_id);
1792
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
1792
+        if ( ! $message_template_group instanceof EE_Message_Template_Group) {
1793 1793
             EE_Error::add_error(
1794 1794
                 sprintf(
1795 1795
                     esc_html__(
@@ -1841,7 +1841,7 @@  discard block
 block discarded – undo
1841 1841
      */
1842 1842
     public function switch_template_pack()
1843 1843
     {
1844
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1844
+        if ( ! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
1845 1845
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
1846 1846
         }
1847 1847
         $GRP_ID        = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
@@ -1922,7 +1922,7 @@  discard block
 block discarded – undo
1922 1922
         $messenger    = $this->request->getRequestParam('msgr');
1923 1923
         $message_type = $this->request->getRequestParam('mt');
1924 1924
         // we need to make sure we've got the info we need.
1925
-        if (! ($GRP_ID && $messenger && $message_type)) {
1925
+        if ( ! ($GRP_ID && $messenger && $message_type)) {
1926 1926
             EE_Error::add_error(
1927 1927
                 esc_html__(
1928 1928
                     'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
@@ -1964,7 +1964,7 @@  discard block
 block discarded – undo
1964 1964
         }
1965 1965
 
1966 1966
         // any error messages?
1967
-        if (! $success) {
1967
+        if ( ! $success) {
1968 1968
             EE_Error::add_error(
1969 1969
                 esc_html__(
1970 1970
                     'Something went wrong with deleting existing templates. Unable to reset to default',
@@ -2013,7 +2013,7 @@  discard block
 block discarded – undo
2013 2013
     {
2014 2014
         // first make sure we've got the necessary parameters
2015 2015
         $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, DataType::INTEGER);
2016
-        if (! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2016
+        if ( ! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2017 2017
             EE_Error::add_error(
2018 2018
                 esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2019 2019
                 __FILE__,
@@ -2039,7 +2039,7 @@  discard block
 block discarded – undo
2039 2039
         $EVT_ID = $this->request->getRequestParam('evt_id', 0, DataType::INTEGER);
2040 2040
 
2041 2041
         // let's add a button to go back to the edit view
2042
-        $query_args             = [
2042
+        $query_args = [
2043 2043
             'id'      => $GRP_ID,
2044 2044
             'evt_id'  => $EVT_ID,
2045 2045
             'context' => $context,
@@ -2060,7 +2060,7 @@  discard block
 block discarded – undo
2060 2060
         $preview_title = sprintf(
2061 2061
             esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2062 2062
             $active_messenger_label,
2063
-            ucwords($message_types[ $this->_active_message_type_name ]->label['singular'])
2063
+            ucwords($message_types[$this->_active_message_type_name]->label['singular'])
2064 2064
         );
2065 2065
         if (empty($preview)) {
2066 2066
             $this->noEventsErrorMessage();
@@ -2068,7 +2068,7 @@  discard block
 block discarded – undo
2068 2068
         // setup display of preview.
2069 2069
         $this->_admin_page_title                    = $preview_title;
2070 2070
         $this->_template_args['admin_page_title']   = $preview_title;
2071
-        $this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2071
+        $this->_template_args['admin_page_content'] = $preview_button.'<br />'.$preview;
2072 2072
         $this->_template_args['data']['force_json'] = true;
2073 2073
 
2074 2074
         return '';
@@ -2089,7 +2089,7 @@  discard block
 block discarded – undo
2089 2089
             ],
2090 2090
             admin_url('admin.php')
2091 2091
         );
2092
-        $message    = $test_send
2092
+        $message = $test_send
2093 2093
             ? esc_html__(
2094 2094
                 'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2095 2095
                 'event_espresso'
@@ -2181,10 +2181,10 @@  discard block
 block discarded – undo
2181 2181
             // only include template packs that support this messenger and message type!
2182 2182
             $supports = $tp->get_supports();
2183 2183
             if (
2184
-                ! isset($supports[ $this->_message_template_group->messenger() ])
2184
+                ! isset($supports[$this->_message_template_group->messenger()])
2185 2185
                 || ! in_array(
2186 2186
                     $this->_message_template_group->message_type(),
2187
-                    $supports[ $this->_message_template_group->messenger() ],
2187
+                    $supports[$this->_message_template_group->messenger()],
2188 2188
                     true
2189 2189
                 )
2190 2190
             ) {
@@ -2208,7 +2208,7 @@  discard block
 block discarded – undo
2208 2208
         }
2209 2209
 
2210 2210
         // setup variation select values for the currently selected template.
2211
-        $variations               = $this->_message_template_group->get_template_pack()->get_variations(
2211
+        $variations = $this->_message_template_group->get_template_pack()->get_variations(
2212 2212
             $this->_message_template_group->messenger(),
2213 2213
             $this->_message_template_group->message_type()
2214 2214
         );
@@ -2222,12 +2222,12 @@  discard block
 block discarded – undo
2222 2222
 
2223 2223
         $template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2224 2224
 
2225
-        $template_args['template_packs_selector']        = EEH_Form_Fields::select_input(
2225
+        $template_args['template_packs_selector'] = EEH_Form_Fields::select_input(
2226 2226
             'MTP_template_pack',
2227 2227
             $tp_select_values,
2228 2228
             $this->_message_template_group->get_template_pack_name()
2229 2229
         );
2230
-        $template_args['variations_selector']            = EEH_Form_Fields::select_input(
2230
+        $template_args['variations_selector'] = EEH_Form_Fields::select_input(
2231 2231
             'MTP_template_variation',
2232 2232
             $variations_select_values,
2233 2233
             $this->_message_template_group->get_template_pack_variation()
@@ -2237,7 +2237,7 @@  discard block
 block discarded – undo
2237 2237
         $template_args['template_pack_description']      = $template_pack_labels->template_pack_description;
2238 2238
         $template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2239 2239
 
2240
-        $template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2240
+        $template = EE_MSG_TEMPLATE_PATH.'template_pack_and_variations_metabox.template.php';
2241 2241
 
2242 2242
         EEH_Template::display_template($template, $template_args);
2243 2243
     }
@@ -2263,33 +2263,33 @@  discard block
 block discarded – undo
2263 2263
         // first we need to see if there are any fields
2264 2264
         $fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2265 2265
 
2266
-        if (! empty($fields)) {
2266
+        if ( ! empty($fields)) {
2267 2267
             // yup there be fields
2268 2268
             foreach ($fields as $field => $config) {
2269
-                $field_id = $this->_message_template_group->messenger() . '_' . $field;
2269
+                $field_id = $this->_message_template_group->messenger().'_'.$field;
2270 2270
                 $existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2271 2271
                 $default  = $config['default'] ?? '';
2272 2272
                 $default  = $config['value'] ?? $default;
2273 2273
 
2274 2274
                 // if type is hidden and the value is empty
2275 2275
                 // something may have gone wrong so let's correct with the defaults
2276
-                $fix                = $config['input'] === 'hidden'
2277
-                                      && isset($existing[ $field ])
2278
-                                      && empty($existing[ $field ])
2276
+                $fix = $config['input'] === 'hidden'
2277
+                                      && isset($existing[$field])
2278
+                                      && empty($existing[$field])
2279 2279
                     ? $default
2280 2280
                     : '';
2281
-                $existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2282
-                    ? $existing[ $field ]
2281
+                $existing[$field] = isset($existing[$field]) && empty($fix)
2282
+                    ? $existing[$field]
2283 2283
                     : $fix;
2284 2284
 
2285
-                $template_form_fields[ $field_id ] = [
2286
-                    'name'       => 'test_settings_fld[' . $field . ']',
2285
+                $template_form_fields[$field_id] = [
2286
+                    'name'       => 'test_settings_fld['.$field.']',
2287 2287
                     'label'      => $config['label'],
2288 2288
                     'input'      => $config['input'],
2289 2289
                     'type'       => $config['type'],
2290 2290
                     'required'   => $config['required'],
2291 2291
                     'validation' => $config['validation'],
2292
-                    'value'      => $existing[ $field ] ?? $default,
2292
+                    'value'      => $existing[$field] ?? $default,
2293 2293
                     'css_class'  => $config['css_class'],
2294 2294
                     'options'    => $config['options'] ?? [],
2295 2295
                     'default'    => $default,
@@ -2303,7 +2303,7 @@  discard block
 block discarded – undo
2303 2303
             : '';
2304 2304
 
2305 2305
         // print out $test_settings_fields
2306
-        if (! empty($test_settings_html)) {
2306
+        if ( ! empty($test_settings_html)) {
2307 2307
             $test_settings_html .= '<input type="submit" class="button--primary mtp-test-button alignright" ';
2308 2308
             $test_settings_html .= 'name="test_button" value="';
2309 2309
             $test_settings_html .= esc_html__('Test Send', 'event_espresso');
@@ -2349,7 +2349,7 @@  discard block
 block discarded – undo
2349 2349
         ];
2350 2350
 
2351 2351
         return EEH_Template::display_template(
2352
-            EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2352
+            EE_MSG_TEMPLATE_PATH.'shortcode_selector_skeleton.template.php',
2353 2353
             $template_args,
2354 2354
             true
2355 2355
         );
@@ -2375,7 +2375,7 @@  discard block
 block discarded – undo
2375 2375
         // $messenger = $this->_message_template_group->messenger_obj();
2376 2376
         // now let's set the content depending on the status of the shortcodes array
2377 2377
         if (empty($shortcodes)) {
2378
-            echo '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2378
+            echo '<p>'.esc_html__('There are no valid shortcodes available', 'event_espresso').'</p>';
2379 2379
             return;
2380 2380
         }
2381 2381
         ?>
@@ -2410,7 +2410,7 @@  discard block
 block discarded – undo
2410 2410
     protected function _set_shortcodes()
2411 2411
     {
2412 2412
         // no need to run this if the property is already set
2413
-        if (! empty($this->_shortcodes)) {
2413
+        if ( ! empty($this->_shortcodes)) {
2414 2414
             return;
2415 2415
         }
2416 2416
 
@@ -2465,7 +2465,7 @@  discard block
 block discarded – undo
2465 2465
     protected function _set_message_template_group()
2466 2466
     {
2467 2467
         // get out if this is already set.
2468
-        if (! empty($this->_message_template_group)) {
2468
+        if ( ! empty($this->_message_template_group)) {
2469 2469
             return;
2470 2470
         }
2471 2471
 
@@ -2511,8 +2511,8 @@  discard block
 block discarded – undo
2511 2511
                     <?php
2512 2512
                 }
2513 2513
                 // setup nonce_url
2514
-                wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2515
-                $id = 'ee-' . sanitize_key($context_label['label']) . '-select';
2514
+                wp_nonce_field($args['action'].'_nonce', $args['action'].'_nonce', false);
2515
+                $id = 'ee-'.sanitize_key($context_label['label']).'-select';
2516 2516
                 ?>
2517 2517
                 <label for='<?php echo esc_attr($id); ?>' class='screen-reader-text'>
2518 2518
                     <?php esc_html_e('message context options', 'event_espresso'); ?>
@@ -2525,7 +2525,7 @@  discard block
 block discarded – undo
2525 2525
                             $checked = ($context === $args['context']) ? 'selected' : '';
2526 2526
                             ?>
2527 2527
                             <option value="<?php echo esc_attr($context); ?>" <?php echo esc_attr($checked); ?>>
2528
-                                <?php echo esc_html($context_details[ $context ]['label']); ?>
2528
+                                <?php echo esc_html($context_details[$context]['label']); ?>
2529 2529
                             </option>
2530 2530
                         <?php endforeach;
2531 2531
                     endif; ?>
@@ -2645,7 +2645,7 @@  discard block
 block discarded – undo
2645 2645
 
2646 2646
         $context   = ucwords(str_replace('_', ' ', $context));
2647 2647
         $item_desc = $messenger_label && $message_type_label
2648
-            ? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2648
+            ? $messenger_label.' '.$message_type_label.' '.$context.' '
2649 2649
             : '';
2650 2650
         $item_desc .= 'Message Template';
2651 2651
         return $item_desc;
@@ -2763,7 +2763,7 @@  discard block
 block discarded – undo
2763 2763
         if ($all) {
2764 2764
             // Checkboxes
2765 2765
             $checkboxes = $this->request->getRequestParam('checkbox', [], DataType::INTEGER, true);
2766
-            if (! empty($checkboxes)) {
2766
+            if ( ! empty($checkboxes)) {
2767 2767
                 // if array has more than one element then success message should be plural.
2768 2768
                 // todo: what about nonce?
2769 2769
                 $success = count($checkboxes) > 1 ? 2 : 1;
@@ -2773,18 +2773,18 @@  discard block
 block discarded – undo
2773 2773
                     $trashed_or_restored = $trash
2774 2774
                         ? $this->getMessageTemplateManager()->trashMessageTemplate($GRP_ID)
2775 2775
                         : $this->getMessageTemplateManager()->restoreMessageTemplate($GRP_ID);
2776
-                    if (! $trashed_or_restored) {
2776
+                    if ( ! $trashed_or_restored) {
2777 2777
                         $success = 0;
2778 2778
                     }
2779 2779
                 }
2780 2780
             } else {
2781 2781
                 // grab single GRP_ID and handle
2782 2782
                 $GRP_ID = $this->request->getRequestParam('id', 0, DataType::INTEGER);
2783
-                if (! empty($GRP_ID)) {
2783
+                if ( ! empty($GRP_ID)) {
2784 2784
                     $trashed_or_restored = $trash
2785 2785
                         ? $this->getMessageTemplateManager()->trashMessageTemplate($GRP_ID)
2786 2786
                         : $this->getMessageTemplateManager()->restoreMessageTemplate($GRP_ID);
2787
-                    if (! $trashed_or_restored) {
2787
+                    if ( ! $trashed_or_restored) {
2788 2788
                         $success = 0;
2789 2789
                     }
2790 2790
                 } else {
@@ -2837,7 +2837,7 @@  discard block
 block discarded – undo
2837 2837
     {
2838 2838
         // checkboxes
2839 2839
         $checkboxes = $this->request->getRequestParam('checkbox', [], DataType::INTEGER, true);
2840
-        if (! empty($checkboxes)) {
2840
+        if ( ! empty($checkboxes)) {
2841 2841
             // if array has more than one element then success message should be plural
2842 2842
             $success = count($checkboxes) > 1 ? 2 : 1;
2843 2843
 
@@ -2913,7 +2913,7 @@  discard block
 block discarded – undo
2913 2913
     protected function _set_m_mt_settings()
2914 2914
     {
2915 2915
         // first if this is already set then lets get out no need to regenerate data.
2916
-        if (! empty($this->_m_mt_settings)) {
2916
+        if ( ! empty($this->_m_mt_settings)) {
2917 2917
             return;
2918 2918
         }
2919 2919
 
@@ -2928,8 +2928,8 @@  discard block
 block discarded – undo
2928 2928
             $active                                                     =
2929 2929
                 $this->_message_resource_manager->is_messenger_active($messenger->name);
2930 2930
             $class                                                      =
2931
-                'ee-messenger-' . sanitize_key($messenger->label['singular']);
2932
-            $this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = [
2931
+                'ee-messenger-'.sanitize_key($messenger->label['singular']);
2932
+            $this->_m_mt_settings['messenger_tabs'][$messenger->name] = [
2933 2933
                 'label' => ucwords($messenger->label['singular']),
2934 2934
                 'class' => $active ? "{$class} messenger-active" : $class,
2935 2935
                 'href'  => $messenger->name,
@@ -2947,7 +2947,7 @@  discard block
 block discarded – undo
2947 2947
             foreach ($message_types as $message_type) {
2948 2948
                 // first we need to verify that this message type is valid with this messenger. Cause if it isn't then
2949 2949
                 // it shouldn't show in either the inactive OR active metabox.
2950
-                if (! in_array($message_type->name, $message_types_for_messenger, true)) {
2950
+                if ( ! in_array($message_type->name, $message_types_for_messenger, true)) {
2951 2951
                     continue;
2952 2952
                 }
2953 2953
 
@@ -2958,12 +2958,12 @@  discard block
 block discarded – undo
2958 2958
                     ? 'active'
2959 2959
                     : 'inactive';
2960 2960
 
2961
-                $this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = [
2961
+                $this->_m_mt_settings['message_type_tabs'][$messenger->name][$a_or_i][$message_type->name] = [
2962 2962
                     'label'    => ucwords($message_type->label['singular']),
2963
-                    'class'    => 'message-type-' . $a_or_i,
2964
-                    'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
2965
-                    'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
2966
-                    'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
2963
+                    'class'    => 'message-type-'.$a_or_i,
2964
+                    'slug_id'  => $message_type->name.'-messagetype-'.$messenger->name,
2965
+                    'mt_nonce' => wp_create_nonce($message_type->name.'_nonce'),
2966
+                    'href'     => 'espresso_'.$message_type->name.'_message_type_settings',
2967 2967
                     'title'    => $a_or_i === 'active'
2968 2968
                         ? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
2969 2969
                         : esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
@@ -2994,20 +2994,20 @@  discard block
 block discarded – undo
2994 2994
         $fields                                         = $message_type->get_admin_settings_fields();
2995 2995
         $settings_template_args['template_form_fields'] = '';
2996 2996
 
2997
-        if (! empty($fields) && $active) {
2997
+        if ( ! empty($fields) && $active) {
2998 2998
             $existing_settings = $message_type->get_existing_admin_settings($messenger->name);
2999 2999
             foreach ($fields as $fldname => $fldprops) {
3000
-                $field_id                         = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3001
-                $template_form_field[ $field_id ] = [
3002
-                    'name'       => 'message_type_settings[' . $fldname . ']',
3000
+                $field_id                         = $messenger->name.'-'.$message_type->name.'-'.$fldname;
3001
+                $template_form_field[$field_id] = [
3002
+                    'name'       => 'message_type_settings['.$fldname.']',
3003 3003
                     'label'      => $fldprops['label'],
3004 3004
                     'input'      => $fldprops['field_type'],
3005 3005
                     'type'       => $fldprops['value_type'],
3006 3006
                     'required'   => $fldprops['required'],
3007 3007
                     'validation' => $fldprops['validation'],
3008
-                    'value'      => $existing_settings[ $fldname ] ?? $fldprops['default'],
3008
+                    'value'      => $existing_settings[$fldname] ?? $fldprops['default'],
3009 3009
                     'options'    => $fldprops['options'] ?? [],
3010
-                    'default'    => $existing_settings[ $fldname ] ?? $fldprops['default'],
3010
+                    'default'    => $existing_settings[$fldname] ?? $fldprops['default'],
3011 3011
                     'css_class'  => 'no-drag',
3012 3012
                     'format'     => $fldprops['format'],
3013 3013
                 ];
@@ -3026,15 +3026,15 @@  discard block
 block discarded – undo
3026 3026
         $settings_template_args['description'] = $message_type->description;
3027 3027
         // we also need some hidden fields
3028 3028
         $hidden_fields = [
3029
-            'message_type_settings[messenger]' . $message_type->name    => [
3029
+            'message_type_settings[messenger]'.$message_type->name    => [
3030 3030
                 'type'  => 'hidden',
3031 3031
                 'value' => $messenger->name,
3032 3032
             ],
3033
-            'message_type_settings[message_type]' . $message_type->name => [
3033
+            'message_type_settings[message_type]'.$message_type->name => [
3034 3034
                 'type'  => 'hidden',
3035 3035
                 'value' => $message_type->name,
3036 3036
             ],
3037
-            'type' . $message_type->name                                => [
3037
+            'type'.$message_type->name                                => [
3038 3038
                 'type'  => 'hidden',
3039 3039
                 'value' => 'message_type',
3040 3040
             ],
@@ -3044,12 +3044,12 @@  discard block
 block discarded – undo
3044 3044
             $hidden_fields,
3045 3045
             'array'
3046 3046
         );
3047
-        $settings_template_args['show_form']     = empty($settings_template_args['template_form_fields'])
3047
+        $settings_template_args['show_form'] = empty($settings_template_args['template_form_fields'])
3048 3048
             ? ' hidden'
3049 3049
             : '';
3050 3050
 
3051 3051
 
3052
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3052
+        $template = EE_MSG_TEMPLATE_PATH.'ee_msg_mt_settings_content.template.php';
3053 3053
         return EEH_Template::display_template($template, $settings_template_args, true);
3054 3054
     }
3055 3055
 
@@ -3077,19 +3077,19 @@  discard block
 block discarded – undo
3077 3077
 
3078 3078
                 // messenger meta boxes
3079 3079
                 $active         = $selected_messenger === $messenger;
3080
-                $active_mt_tabs = $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active'] ?? '';
3080
+                $active_mt_tabs = $this->_m_mt_settings['message_type_tabs'][$messenger]['active'] ?? '';
3081 3081
 
3082
-                $m_boxes[ $messenger . '_a_box' ] = sprintf(
3082
+                $m_boxes[$messenger.'_a_box'] = sprintf(
3083 3083
                     esc_html__('%s Settings', 'event_espresso'),
3084 3084
                     $tab_array['label']
3085 3085
                 );
3086 3086
 
3087
-                $m_template_args[ $messenger . '_a_box' ] = [
3087
+                $m_template_args[$messenger.'_a_box'] = [
3088 3088
                     'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3089 3089
                     'inactive_message_types' => isset(
3090
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3090
+                        $this->_m_mt_settings['message_type_tabs'][$messenger]['inactive']
3091 3091
                     )
3092
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3092
+                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][$messenger]['inactive'])
3093 3093
                         : '',
3094 3094
                     'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3095 3095
                     'hidden'                 => $active ? '' : ' hidden',
@@ -3101,13 +3101,13 @@  discard block
 block discarded – undo
3101 3101
                 // message type meta boxes
3102 3102
                 // (which is really just the inactive container for each messenger
3103 3103
                 // showing inactive message types for that messenger)
3104
-                $mt_boxes[ $messenger . '_i_box' ]         = esc_html__('Inactive Message Types', 'event_espresso');
3105
-                $mt_template_args[ $messenger . '_i_box' ] = [
3104
+                $mt_boxes[$messenger.'_i_box']         = esc_html__('Inactive Message Types', 'event_espresso');
3105
+                $mt_template_args[$messenger.'_i_box'] = [
3106 3106
                     'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3107 3107
                     'inactive_message_types' => isset(
3108
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3108
+                        $this->_m_mt_settings['message_type_tabs'][$messenger]['inactive']
3109 3109
                     )
3110
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3110
+                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][$messenger]['inactive'])
3111 3111
                         : '',
3112 3112
                     'hidden'                 => $active ? '' : ' hidden',
3113 3113
                     'hide_on_message'        => $hide_on_message,
@@ -3120,14 +3120,14 @@  discard block
 block discarded – undo
3120 3120
 
3121 3121
 
3122 3122
         // register messenger metaboxes
3123
-        $m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3123
+        $m_template_path = EE_MSG_TEMPLATE_PATH.'ee_msg_details_messenger_mt_meta_box.template.php';
3124 3124
         foreach ($m_boxes as $box => $label) {
3125
-            $callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]];
3125
+            $callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[$box]];
3126 3126
             $msgr          = str_replace('_a_box', '', $box);
3127 3127
             $this->addMetaBox(
3128
-                'espresso_' . $msgr . '_settings',
3128
+                'espresso_'.$msgr.'_settings',
3129 3129
                 $label,
3130
-                function ($post, $metabox) {
3130
+                function($post, $metabox) {
3131 3131
                     EEH_Template::display_template(
3132 3132
                         $metabox['args']['template_path'],
3133 3133
                         $metabox['args']['template_args']
@@ -3141,17 +3141,17 @@  discard block
 block discarded – undo
3141 3141
         }
3142 3142
 
3143 3143
         // register message type metaboxes
3144
-        $mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3144
+        $mt_template_path = EE_MSG_TEMPLATE_PATH.'ee_msg_details_messenger_meta_box.template.php';
3145 3145
         foreach ($mt_boxes as $box => $label) {
3146 3146
             $callback_args = [
3147 3147
                 'template_path' => $mt_template_path,
3148
-                'template_args' => $mt_template_args[ $box ],
3148
+                'template_args' => $mt_template_args[$box],
3149 3149
             ];
3150
-            $mt            = str_replace('_i_box', '', $box);
3150
+            $mt = str_replace('_i_box', '', $box);
3151 3151
             $this->addMetaBox(
3152
-                'espresso_' . $mt . '_inactive_mts',
3152
+                'espresso_'.$mt.'_inactive_mts',
3153 3153
                 $label,
3154
-                function ($post, $metabox) {
3154
+                function($post, $metabox) {
3155 3155
                     EEH_Template::display_template(
3156 3156
                         $metabox['args']['template_path'],
3157 3157
                         $metabox['args']['template_args']
@@ -3299,7 +3299,7 @@  discard block
 block discarded – undo
3299 3299
                 $valid_data = $form->valid_data();
3300 3300
                 // \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 3);
3301 3301
                 foreach ($valid_data as $property => $value) {
3302
-                    $setter = 'set_' . $property;
3302
+                    $setter = 'set_'.$property;
3303 3303
                     if (method_exists($network_config, $setter)) {
3304 3304
                         $network_config->{$setter}($value);
3305 3305
                     } elseif (
@@ -3335,7 +3335,7 @@  discard block
 block discarded – undo
3335 3335
     protected function _get_mt_tabs($tab_array)
3336 3336
     {
3337 3337
         $tab_array = (array) $tab_array;
3338
-        $template  = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3338
+        $template  = EE_MSG_TEMPLATE_PATH.'ee_msg_details_mt_settings_tab_item.template.php';
3339 3339
         $tabs      = '';
3340 3340
 
3341 3341
         foreach ($tab_array as $tab) {
@@ -3362,19 +3362,19 @@  discard block
 block discarded – undo
3362 3362
         $settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3363 3363
 
3364 3364
 
3365
-        if (! empty($fields)) {
3365
+        if ( ! empty($fields)) {
3366 3366
             $existing_settings = $messenger->get_existing_admin_settings();
3367 3367
 
3368 3368
             foreach ($fields as $field_name => $field_props) {
3369
-                $field_id                         = $messenger->name . '-' . $field_name;
3370
-                $template_form_field[ $field_id ] = [
3371
-                    'name'       => 'messenger_settings[' . $field_id . ']',
3369
+                $field_id                         = $messenger->name.'-'.$field_name;
3370
+                $template_form_field[$field_id] = [
3371
+                    'name'       => 'messenger_settings['.$field_id.']',
3372 3372
                     'label'      => $field_props['label'],
3373 3373
                     'input'      => $field_props['field_type'],
3374 3374
                     'type'       => $field_props['value_type'],
3375 3375
                     'required'   => $field_props['required'],
3376 3376
                     'validation' => $field_props['validation'],
3377
-                    'value'      => $existing_settings[ $field_id ] ?? $field_props['default'],
3377
+                    'value'      => $existing_settings[$field_id] ?? $field_props['default'],
3378 3378
                     'css_class'  => '',
3379 3379
                     'format'     => $field_props['format'],
3380 3380
                 ];
@@ -3387,20 +3387,20 @@  discard block
 block discarded – undo
3387 3387
 
3388 3388
         // we also need some hidden fields
3389 3389
         $settings_template_args['hidden_fields'] = [
3390
-            'messenger_settings[messenger]' . $messenger->name => [
3390
+            'messenger_settings[messenger]'.$messenger->name => [
3391 3391
                 'type'  => 'hidden',
3392 3392
                 'value' => $messenger->name,
3393 3393
             ],
3394
-            'type' . $messenger->name                          => [
3394
+            'type'.$messenger->name                          => [
3395 3395
                 'type'  => 'hidden',
3396 3396
                 'value' => 'messenger',
3397 3397
             ],
3398 3398
         ];
3399 3399
 
3400 3400
         // make sure any active message types that are existing are included in the hidden fields
3401
-        if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3402
-            foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3403
-                $settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = [
3401
+        if (isset($this->_m_mt_settings['message_type_tabs'][$messenger->name]['active'])) {
3402
+            foreach ($this->_m_mt_settings['message_type_tabs'][$messenger->name]['active'] as $mt => $values) {
3403
+                $settings_template_args['hidden_fields']['messenger_settings[message_types]['.$mt.']'] = [
3404 3404
                     'type'  => 'hidden',
3405 3405
                     'value' => $mt,
3406 3406
                 ];
@@ -3410,7 +3410,7 @@  discard block
 block discarded – undo
3410 3410
             $settings_template_args['hidden_fields'],
3411 3411
             'array'
3412 3412
         );
3413
-        $active                                  =
3413
+        $active =
3414 3414
             $this->_message_resource_manager->is_messenger_active($messenger->name);
3415 3415
 
3416 3416
         $settings_template_args['messenger']           = $messenger->name;
@@ -3430,9 +3430,9 @@  discard block
 block discarded – undo
3430 3430
 
3431 3431
 
3432 3432
         $settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3433
-        $settings_template_args['nonce']         = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3433
+        $settings_template_args['nonce']         = wp_create_nonce('activate_'.$messenger->name.'_toggle_nonce');
3434 3434
         $settings_template_args['on_off_status'] = $active;
3435
-        $template                                = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3435
+        $template                                = EE_MSG_TEMPLATE_PATH.'ee_msg_m_settings_content.template.php';
3436 3436
         return EEH_Template::display_template(
3437 3437
             $template,
3438 3438
             $settings_template_args,
@@ -3453,14 +3453,14 @@  discard block
 block discarded – undo
3453 3453
      */
3454 3454
     public function activate_messenger_toggle()
3455 3455
     {
3456
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3456
+        if ( ! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3457 3457
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3458 3458
         }
3459 3459
         $success = true;
3460 3460
         $this->_prep_default_response_for_messenger_or_message_type_toggle();
3461 3461
         // let's check that we have required data
3462 3462
 
3463
-        if (! $this->_active_messenger_name) {
3463
+        if ( ! $this->_active_messenger_name) {
3464 3464
             EE_Error::add_error(
3465 3465
                 esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3466 3466
                 __FILE__,
@@ -3478,7 +3478,7 @@  discard block
 block discarded – undo
3478 3478
 
3479 3479
 
3480 3480
         $status = $this->request->getRequestParam('status');
3481
-        if (! $status) {
3481
+        if ( ! $status) {
3482 3482
             EE_Error::add_error(
3483 3483
                 esc_html__(
3484 3484
                     'Messenger status needed to know whether activation or deactivation is happening. No status is given',
@@ -3531,14 +3531,14 @@  discard block
 block discarded – undo
3531 3531
      */
3532 3532
     public function activate_mt_toggle()
3533 3533
     {
3534
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3534
+        if ( ! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3535 3535
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3536 3536
         }
3537 3537
         $success = true;
3538 3538
         $this->_prep_default_response_for_messenger_or_message_type_toggle();
3539 3539
 
3540 3540
         // let's make sure we have the necessary data
3541
-        if (! $this->_active_message_type_name) {
3541
+        if ( ! $this->_active_message_type_name) {
3542 3542
             EE_Error::add_error(
3543 3543
                 esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3544 3544
                 __FILE__,
@@ -3548,7 +3548,7 @@  discard block
 block discarded – undo
3548 3548
             $success = false;
3549 3549
         }
3550 3550
 
3551
-        if (! $this->_active_messenger_name) {
3551
+        if ( ! $this->_active_messenger_name) {
3552 3552
             EE_Error::add_error(
3553 3553
                 esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3554 3554
                 __FILE__,
@@ -3559,7 +3559,7 @@  discard block
 block discarded – undo
3559 3559
         }
3560 3560
 
3561 3561
         $status = $this->request->getRequestParam('status');
3562
-        if (! $status) {
3562
+        if ( ! $status) {
3563 3563
             EE_Error::add_error(
3564 3564
                 esc_html__(
3565 3565
                     'Messenger status needed to know whether activation or deactivation is happening. No status is given',
@@ -3771,7 +3771,7 @@  discard block
 block discarded – undo
3771 3771
         EE_Message_Type $message_type = null
3772 3772
     ) {
3773 3773
         // if $messenger isn't a valid messenger object then get out.
3774
-        if (! $messenger instanceof EE_Messenger) {
3774
+        if ( ! $messenger instanceof EE_Messenger) {
3775 3775
             EE_Error::add_error(
3776 3776
                 esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
3777 3777
                 __FILE__,
@@ -3825,7 +3825,7 @@  discard block
 block discarded – undo
3825 3825
             // message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
3826 3826
             // in which case we just give a success message for the messenger being successfully activated.
3827 3827
         } else {
3828
-            if (! $messenger->get_default_message_types()) {
3828
+            if ( ! $messenger->get_default_message_types()) {
3829 3829
                 // messenger doesn't have any default message types so still a success.
3830 3830
                 EE_Error::add_success(
3831 3831
                     sprintf(
@@ -3881,7 +3881,7 @@  discard block
 block discarded – undo
3881 3881
         EE_Error::overwrite_success();
3882 3882
 
3883 3883
         // if $messenger isn't a valid messenger object then get out.
3884
-        if (! $messenger instanceof EE_Messenger) {
3884
+        if ( ! $messenger instanceof EE_Messenger) {
3885 3885
             EE_Error::add_error(
3886 3886
                 esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
3887 3887
                 __FILE__,
@@ -3951,10 +3951,10 @@  discard block
 block discarded – undo
3951 3951
      */
3952 3952
     public function update_mt_form()
3953 3953
     {
3954
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3954
+        if ( ! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3955 3955
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3956 3956
         }
3957
-        if (! $this->_active_messenger_name || ! $this->_active_message_type_name) {
3957
+        if ( ! $this->_active_messenger_name || ! $this->_active_message_type_name) {
3958 3958
             EE_Error::add_error(
3959 3959
                 esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
3960 3960
                 __FILE__,
@@ -3965,7 +3965,7 @@  discard block
 block discarded – undo
3965 3965
         }
3966 3966
 
3967 3967
         $message_types = $this->get_installed_message_types();
3968
-        $message_type  = $message_types[ $this->_active_message_type_name ];
3968
+        $message_type  = $message_types[$this->_active_message_type_name];
3969 3969
         $messenger     = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
3970 3970
         $content       = $this->_message_type_settings_content($message_type, $messenger, true);
3971 3971
 
@@ -3983,11 +3983,11 @@  discard block
 block discarded – undo
3983 3983
      */
3984 3984
     public function save_settings()
3985 3985
     {
3986
-        if (! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3986
+        if ( ! $this->capabilities->current_user_can('ee_edit_messages', __FUNCTION__)) {
3987 3987
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
3988 3988
         }
3989 3989
         $type = $this->request->getRequestParam('type');
3990
-        if (! $type) {
3990
+        if ( ! $type) {
3991 3991
             EE_Error::add_error(
3992 3992
                 esc_html__(
3993 3993
                     'Cannot save settings because type is unknown (messenger settings or message type settings?)',
Please login to merge, or discard this patch.
admin_pages/venues/Venues_Admin_Page.core.php 1 patch
Indentation   +1548 added lines, -1548 removed lines patch added patch discarded remove patch
@@ -14,1558 +14,1558 @@
 block discarded – undo
14 14
  */
15 15
 class Venues_Admin_Page extends EE_Admin_Page_CPT
16 16
 {
17
-    /**
18
-     * primary key for the venue model
19
-     */
20
-    private int $VNU_ID = 0;
21
-
22
-    /**
23
-     * This will hold the venue object for venue_details screen.
24
-     *
25
-     * @var EE_Venue|EE_CPT_Base|null $_cpt_model_obj
26
-     */
27
-    protected $_cpt_model_obj;
28
-
29
-
30
-    /**
31
-     * This will hold the category object for category_details screen.
32
-     *
33
-     * @var stdClass|null $_category
34
-     */
35
-    protected ?stdClass $_category = null;
36
-
37
-
38
-    /**
39
-     * This property will hold the venue model instance
40
-     *
41
-     * @var EEM_Venue|null $_venue_model
42
-     */
43
-    protected ?EEM_Venue $_venue_model = null;
44
-
45
-
46
-    /**
47
-     * @throws EE_Error
48
-     * @throws ReflectionException
49
-     */
50
-    protected function _init_page_props()
51
-    {
52
-        // is there a vnu_id in the request?
53
-        $this->VNU_ID = $this->request->getRequestParam('VNU_ID', 0, DataType::INT);
54
-        $this->VNU_ID = $this->request->getRequestParam('post', $this->VNU_ID, DataType::INT);
55
-        $this->VNU_ID = $this->request->getRequestParam('post_ID', $this->VNU_ID, DataType::INT);
56
-
57
-        $this->page_slug        = EE_VENUES_PG_SLUG;
58
-        $this->_admin_base_url  = EE_VENUES_ADMIN_URL;
59
-        $this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
60
-        $this->page_label       = esc_html__('Event Venues', 'event_espresso');
61
-        $this->_cpt_model_names = [
62
-            'create_new' => 'EEM_Venue',
63
-            'edit'       => 'EEM_Venue',
64
-        ];
65
-        $this->_cpt_edit_routes = [
66
-            'espresso_venues' => 'edit',
67
-        ];
68
-        $this->_venue_model     = EEM_Venue::instance();
69
-    }
70
-
71
-
72
-    protected function _ajax_hooks()
73
-    {
74
-        // todo: all hooks for ee_venues ajax goes in here.
75
-    }
76
-
77
-
78
-    protected function _define_page_props()
79
-    {
80
-        $this->_admin_page_title = $this->page_label;
81
-        $this->_labels           = [
82
-            'buttons'      => [
83
-                'add'             => esc_html__('Add New Venue', 'event_espresso'),
84
-                'edit'            => esc_html__('Edit Venue', 'event_espresso'),
85
-                'delete'          => esc_html__('Delete Venue', 'event_espresso'),
86
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
87
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
88
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
89
-            ],
90
-            'editor_title' => [
91
-                'espresso_venues' => esc_html__('Edit Venue', 'event_espresso'),
92
-            ],
93
-            'publishbox'   => [
94
-                'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
95
-                'edit'                => esc_html__('Update Venue', 'event_espresso'),
96
-                'add_category'        => esc_html__('Save New Category', 'event_espresso'),
97
-                'edit_category'       => esc_html__('Update Category', 'event_espresso'),
98
-                'google_map_settings' => esc_html__('Update Settings', 'event_espresso'),
99
-            ],
100
-        ];
101
-    }
102
-
103
-
104
-    protected function _set_page_routes()
105
-    {
106
-        // load formatter helper
107
-        // load field generator helper
108
-
109
-
110
-        $this->_page_routes = [
111
-            'default'                    => [
112
-                'func'       => [$this, '_overview_list_table'],
113
-                'capability' => 'ee_read_venues',
114
-            ],
115
-            'create_new'                 => [
116
-                'func'       => [$this, '_create_new_cpt_item'],
117
-                'capability' => 'ee_edit_venues',
118
-            ],
119
-            'edit'                       => [
120
-                'func'       => [$this, '_edit_cpt_item'],
121
-                'capability' => 'ee_edit_venue',
122
-                'obj_id'     => $this->VNU_ID,
123
-            ],
124
-            'trash_venue'                => [
125
-                'func'       => [$this, '_trash_or_restore_venue'],
126
-                'args'       => ['venue_status' => 'trash'],
127
-                'noheader'   => true,
128
-                'capability' => 'ee_delete_venue',
129
-                'obj_id'     => $this->VNU_ID,
130
-            ],
131
-            'trash_venues'               => [
132
-                'func'       => [$this, '_trash_or_restore_venues'],
133
-                'args'       => ['venue_status' => 'trash'],
134
-                'noheader'   => true,
135
-                'capability' => 'ee_delete_venues',
136
-            ],
137
-            'restore_venue'              => [
138
-                'func'       => [$this, '_trash_or_restore_venue'],
139
-                'args'       => ['venue_status' => 'draft'],
140
-                'noheader'   => true,
141
-                'capability' => 'ee_delete_venue',
142
-                'obj_id'     => $this->VNU_ID,
143
-            ],
144
-            'restore_venues'             => [
145
-                'func'       => [$this, '_trash_or_restore_venues'],
146
-                'args'       => ['venue_status' => 'draft'],
147
-                'noheader'   => true,
148
-                'capability' => 'ee_delete_venues',
149
-            ],
150
-            'delete_venues'              => [
151
-                'func'       => [$this, '_delete_venues'],
152
-                'noheader'   => true,
153
-                'capability' => 'ee_delete_venues',
154
-            ],
155
-            'delete_venue'               => [
156
-                'func'       => [$this, '_delete_venue'],
157
-                'args'       => ['redirect_after' => true],
158
-                'noheader'   => true,
159
-                'capability' => 'ee_delete_venue',
160
-                'obj_id'     => $this->VNU_ID,
161
-            ],
162
-            // settings related
163
-            'google_map_settings'        => [
164
-                'func'       => [$this, '_google_map_settings'],
165
-                'capability' => 'manage_options',
166
-            ],
167
-            'update_google_map_settings' => [
168
-                'func'       => [$this, '_update_google_map_settings'],
169
-                'capability' => 'manage_options',
170
-                'noheader'   => true,
171
-            ],
172
-            // venue category tab related
173
-            'add_category'               => [
174
-                'func'       => [$this, '_category_details'],
175
-                'args'       => ['add'],
176
-                'capability' => 'ee_edit_venue_category',
177
-            ],
178
-            'edit_category'              => [
179
-                'func'       => [$this, '_category_details'],
180
-                'args'       => ['edit'],
181
-                'capability' => 'ee_edit_venue_category',
182
-            ],
183
-            'delete_categories'          => [
184
-                'func'       => [$this, '_delete_categories'],
185
-                'noheader'   => true,
186
-                'capability' => 'ee_delete_venue_category',
187
-            ],
188
-
189
-            'delete_category' => [
190
-                'func'       => [$this, '_delete_categories'],
191
-                'noheader'   => true,
192
-                'capability' => 'ee_delete_venue_category',
193
-            ],
194
-
195
-            'insert_category' => [
196
-                'func'       => [$this, '_insert_or_update_category'],
197
-                'args'       => ['new_category' => true],
198
-                'noheader'   => true,
199
-                'capability' => 'ee_edit_venue_category',
200
-            ],
201
-
202
-            'update_category'   => [
203
-                'func'       => [$this, '_insert_or_update_category'],
204
-                'args'       => ['new_category' => false],
205
-                'noheader'   => true,
206
-                'capability' => 'ee_edit_venue_category',
207
-            ],
208
-            'export_categories' => [
209
-                'func'       => [$this, '_categories_export'],
210
-                'noheader'   => true,
211
-                'capability' => 'export',
212
-            ],
213
-            'import_categories' => [
214
-                'func'       => [$this, '_import_categories'],
215
-                'capability' => 'import',
216
-            ],
217
-            'category_list'     => [
218
-                'func'       => [$this, '_category_list_table'],
219
-                'capability' => 'ee_manage_venue_categories',
220
-            ],
221
-        ];
222
-    }
223
-
224
-
225
-    protected function _set_page_config()
226
-    {
227
-        $EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
228
-        $help_tabs  = [
229
-            'venues_editor_help_tab'                                               => [
230
-                'title'    => esc_html__('Venue Editor', 'event_espresso'),
231
-                'filename' => 'venues_editor',
232
-            ],
233
-            'venues_editor_title_richtexteditor_help_tab'                          => [
234
-                'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
235
-                'filename' => 'venues_editor_title_richtexteditor',
236
-            ],
237
-            'venues_editor_tags_categories_help_tab'                               => [
238
-                'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
239
-                'filename' => 'venues_editor_tags_categories',
240
-            ],
241
-            'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
242
-                'title'    => esc_html__(
243
-                    'Venue Editor Physical Location & Google Map & Virtual Location',
244
-                    'event_espresso'
245
-                ),
246
-                'filename' => 'venues_editor_physical_location_google_map_virtual_location',
247
-            ],
248
-            'venues_editor_save_new_venue_help_tab'                                => [
249
-                'title'    => esc_html__('Save New Venue', 'event_espresso'),
250
-                'filename' => 'venues_editor_save_new_venue',
251
-            ],
252
-            'venues_editor_other_help_tab'                                         => [
253
-                'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
254
-                'filename' => 'venues_editor_other',
255
-            ],
256
-        ];
257
-
258
-        $this->_page_config = [
259
-            'default'             => [
260
-                'nav'           => [
261
-                    'label' => esc_html__('Overview', 'event_espresso'),
262
-                    'icon'  => 'dashicons-list-view',
263
-                    'order' => 10,
264
-                ],
265
-                'list_table'    => 'Venues_Admin_List_Table',
266
-                'help_tabs'     => [
267
-                    'venues_overview_help_tab'                           => [
268
-                        'title'    => esc_html__('Venues Overview', 'event_espresso'),
269
-                        'filename' => 'venues_overview',
270
-                    ],
271
-                    'venues_overview_table_column_headings_help_tab'     => [
272
-                        'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
273
-                        'filename' => 'venues_overview_table_column_headings',
274
-                    ],
275
-                    'venues_overview_views_bulk_actions_search_help_tab' => [
276
-                        'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
277
-                        'filename' => 'venues_overview_views_bulk_actions_search',
278
-                    ],
279
-                ],
280
-                'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
281
-                'require_nonce' => false,
282
-            ],
283
-            'create_new'          => [
284
-                'nav'           => [
285
-                    'label'      => esc_html__('Add Venue', 'event_espresso'),
286
-                    'icon'       => 'dashicons-plus-alt',
287
-                    'order'      => 15,
288
-                    'persistent' => false,
289
-                ],
290
-                'help_tabs'     => $help_tabs,
291
-                'metaboxes'     => ['_venue_editor_metaboxes'],
292
-                'require_nonce' => false,
293
-            ],
294
-            'edit'                => [
295
-                'nav'           => [
296
-                    'label'      => esc_html__('Edit Venue', 'event_espresso'),
297
-                    'icon'       => 'dashicons-edit-large',
298
-                    'order'      => 15,
299
-                    'persistent' => false,
300
-                    'url'        => $this->VNU_ID
301
-                        ? add_query_arg(['post' => $this->VNU_ID], $this->_current_page_view_url)
302
-                        : $this->_admin_base_url,
303
-                ],
304
-                'help_tabs'     => $help_tabs,
305
-                'metaboxes'     => ['_venue_editor_metaboxes'],
306
-                'require_nonce' => false,
307
-            ],
308
-            'google_map_settings' => [
309
-                'nav'           => [
310
-                    'label' => esc_html__('Google Maps', 'event_espresso'),
311
-                    'icon'  => 'dashicons-location-alt',
312
-                    'order' => 40,
313
-                ],
314
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
315
-                'help_tabs'     => [
316
-                    'general_settings_google_maps_help_tab' => [
317
-                        'title'    => esc_html__('Google Maps', 'event_espresso'),
318
-                        'filename' => 'general_settings_google_maps',
319
-                    ],
320
-                ],
321
-                'require_nonce' => false,
322
-            ],
323
-            // venue category stuff
324
-            'add_category'        => [
325
-                'nav'           => [
326
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
327
-                    'icon'       => 'dashicons-plus-alt',
328
-                    'order'      => 25,
329
-                    'persistent' => false,
330
-                ],
331
-                'metaboxes'     => ['_publish_post_box'],
332
-                'help_tabs'     => [
333
-                    'venues_add_category_help_tab' => [
334
-                        'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
335
-                        'filename' => 'venues_add_category',
336
-                    ],
337
-                ],
338
-                'require_nonce' => false,
339
-            ],
340
-            'edit_category'       => [
341
-                'nav'           => [
342
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
343
-                    'icon'       => 'dashicons-edit-large',
344
-                    'order'      => 25,
345
-                    'persistent' => false,
346
-                    'url'        => $EVT_CAT_ID
347
-                        ? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
348
-                        : $this->_admin_base_url,
349
-                ],
350
-                'metaboxes'     => ['_publish_post_box'],
351
-                'help_tabs'     => [
352
-                    'venues_edit_category_help_tab' => [
353
-                        'title'    => esc_html__('Edit Venue Category', 'event_espresso'),
354
-                        'filename' => 'venues_edit_category',
355
-                    ],
356
-                ],
357
-                'require_nonce' => false,
358
-            ],
359
-            'category_list'       => [
360
-                'nav'           => [
361
-                    'label' => esc_html__('Categories', 'event_espresso'),
362
-                    'icon'  => 'dashicons-networking',
363
-                    'order' => 20,
364
-                ],
365
-                'list_table'    => 'Venue_Categories_Admin_List_Table',
366
-                'help_tabs'     => [
367
-                    'venues_categories_help_tab'                       => [
368
-                        'title'    => esc_html__('Venue Categories', 'event_espresso'),
369
-                        'filename' => 'venues_categories',
370
-                    ],
371
-                    'venues_categories_table_column_headings_help_tab' => [
372
-                        'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
373
-                        'filename' => 'venues_categories_table_column_headings',
374
-                    ],
375
-                    'venues_categories_views_help_tab'                 => [
376
-                        'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
377
-                        'filename' => 'venues_categories_views',
378
-                    ],
379
-                    'venues_categories_other_help_tab'                 => [
380
-                        'title'    => esc_html__('Venue Categories Other', 'event_espresso'),
381
-                        'filename' => 'venues_categories_other',
382
-                    ],
383
-                ],
384
-                'metaboxes'     => $this->_default_espresso_metaboxes,
385
-                'require_nonce' => false,
386
-            ],
387
-        ];
388
-    }
389
-
390
-
391
-    protected function _add_screen_options()
392
-    {
393
-        // todo
394
-    }
395
-
396
-
397
-    protected function _add_screen_options_default()
398
-    {
399
-        $this->_per_page_screen_option();
400
-    }
401
-
402
-
403
-    protected function _add_screen_options_category_list()
404
-    {
405
-        $page_title              = $this->_admin_page_title;
406
-        $this->_admin_page_title = esc_html__('Venue Categories', 'event_espresso');
407
-        $this->_per_page_screen_option();
408
-        $this->_admin_page_title = $page_title;
409
-    }
410
-
411
-
412
-    // none of the below group are currently used for Event Venues
413
-    protected function _add_feature_pointers()
414
-    {
415
-    }
416
-
417
-
418
-    public function admin_init()
419
-    {
420
-    }
421
-
422
-
423
-    public function admin_notices()
424
-    {
425
-    }
426
-
427
-
428
-    public function admin_footer_scripts()
429
-    {
430
-    }
431
-
432
-
433
-    public function load_scripts_styles_create_new()
434
-    {
435
-        $this->load_scripts_styles_edit();
436
-    }
437
-
438
-
439
-    public function load_scripts_styles()
440
-    {
441
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
442
-        wp_enqueue_style('ee-cat-admin');
443
-    }
444
-
445
-
446
-    public function load_scripts_styles_add_category()
447
-    {
448
-        $this->load_scripts_styles_edit_category();
449
-    }
450
-
451
-
452
-    public function load_scripts_styles_edit_category()
453
-    {
454
-        wp_enqueue_style('editor-buttons');
455
-    }
456
-
457
-
458
-    public function load_scripts_styles_edit()
459
-    {
460
-        // styles
461
-        wp_enqueue_style('espresso-ui-theme');
462
-        wp_register_style(
463
-            'espresso_venues',
464
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
465
-            [],
466
-            EVENT_ESPRESSO_VERSION
467
-        );
468
-        wp_enqueue_style('espresso_venues');
469
-    }
470
-
471
-
472
-    protected function _set_list_table_views_default()
473
-    {
474
-        $this->_views = [
475
-            'all' => [
476
-                'slug'        => 'all',
477
-                'label'       => esc_html__('View All Venues', 'event_espresso'),
478
-                'count'       => 0,
479
-                'bulk_action' => [],
480
-            ],
481
-        ];
482
-
483
-        if ($this->capabilities->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
484
-            $this->_views['all']['bulk_action'] = [
485
-                'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
486
-            ];
487
-            $this->_views['trash']              = [
488
-                'slug'        => 'trash',
489
-                'label'       => esc_html__('Trash', 'event_espresso'),
490
-                'count'       => 0,
491
-                'bulk_action' => [
492
-                    'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
493
-                    'delete_venues'  => esc_html__('Delete', 'event_espresso'),
494
-                ],
495
-            ];
496
-        }
497
-    }
498
-
499
-
500
-    protected function _set_list_table_views_category_list()
501
-    {
502
-        $this->_views = [
503
-            'all' => [
504
-                'slug'        => 'all',
505
-                'label'       => esc_html__('All', 'event_espresso'),
506
-                'count'       => 0,
507
-                'bulk_action' => [
508
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
509
-                ],
510
-            ],
511
-        ];
512
-    }
513
-
514
-
515
-    /**
516
-     * @throws EE_Error
517
-     */
518
-    protected function _overview_list_table()
519
-    {
520
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
521
-        $this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
522
-            get_post_type_archive_link(EspressoPostType::VENUES),
523
-            esc_html__("View Venue Archive Page", "event_espresso"),
524
-            'button'
525
-        );
526
-
527
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
528
-                'create_new',
529
-                'add',
530
-                [],
531
-                'add-new-h2'
532
-            );
533
-
534
-        $this->_search_btn_label = esc_html__('Venues', 'event_espresso');
535
-        $this->display_admin_list_table_page_with_sidebar();
536
-    }
537
-
538
-
539
-    /**
540
-     * @throws EE_Error
541
-     * @throws ReflectionException
542
-     */
543
-    public function extra_misc_actions_publish_box()
544
-    {
545
-        $extra_rows = [
546
-            'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
547
-            'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
548
-            'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
549
-        ];
550
-        $template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
551
-        EEH_Template::display_template($template, $extra_rows);
552
-    }
553
-
554
-
555
-    /*************        Google Maps        *************
17
+	/**
18
+	 * primary key for the venue model
19
+	 */
20
+	private int $VNU_ID = 0;
21
+
22
+	/**
23
+	 * This will hold the venue object for venue_details screen.
24
+	 *
25
+	 * @var EE_Venue|EE_CPT_Base|null $_cpt_model_obj
26
+	 */
27
+	protected $_cpt_model_obj;
28
+
29
+
30
+	/**
31
+	 * This will hold the category object for category_details screen.
32
+	 *
33
+	 * @var stdClass|null $_category
34
+	 */
35
+	protected ?stdClass $_category = null;
36
+
37
+
38
+	/**
39
+	 * This property will hold the venue model instance
40
+	 *
41
+	 * @var EEM_Venue|null $_venue_model
42
+	 */
43
+	protected ?EEM_Venue $_venue_model = null;
44
+
45
+
46
+	/**
47
+	 * @throws EE_Error
48
+	 * @throws ReflectionException
49
+	 */
50
+	protected function _init_page_props()
51
+	{
52
+		// is there a vnu_id in the request?
53
+		$this->VNU_ID = $this->request->getRequestParam('VNU_ID', 0, DataType::INT);
54
+		$this->VNU_ID = $this->request->getRequestParam('post', $this->VNU_ID, DataType::INT);
55
+		$this->VNU_ID = $this->request->getRequestParam('post_ID', $this->VNU_ID, DataType::INT);
56
+
57
+		$this->page_slug        = EE_VENUES_PG_SLUG;
58
+		$this->_admin_base_url  = EE_VENUES_ADMIN_URL;
59
+		$this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
60
+		$this->page_label       = esc_html__('Event Venues', 'event_espresso');
61
+		$this->_cpt_model_names = [
62
+			'create_new' => 'EEM_Venue',
63
+			'edit'       => 'EEM_Venue',
64
+		];
65
+		$this->_cpt_edit_routes = [
66
+			'espresso_venues' => 'edit',
67
+		];
68
+		$this->_venue_model     = EEM_Venue::instance();
69
+	}
70
+
71
+
72
+	protected function _ajax_hooks()
73
+	{
74
+		// todo: all hooks for ee_venues ajax goes in here.
75
+	}
76
+
77
+
78
+	protected function _define_page_props()
79
+	{
80
+		$this->_admin_page_title = $this->page_label;
81
+		$this->_labels           = [
82
+			'buttons'      => [
83
+				'add'             => esc_html__('Add New Venue', 'event_espresso'),
84
+				'edit'            => esc_html__('Edit Venue', 'event_espresso'),
85
+				'delete'          => esc_html__('Delete Venue', 'event_espresso'),
86
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
87
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
88
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
89
+			],
90
+			'editor_title' => [
91
+				'espresso_venues' => esc_html__('Edit Venue', 'event_espresso'),
92
+			],
93
+			'publishbox'   => [
94
+				'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
95
+				'edit'                => esc_html__('Update Venue', 'event_espresso'),
96
+				'add_category'        => esc_html__('Save New Category', 'event_espresso'),
97
+				'edit_category'       => esc_html__('Update Category', 'event_espresso'),
98
+				'google_map_settings' => esc_html__('Update Settings', 'event_espresso'),
99
+			],
100
+		];
101
+	}
102
+
103
+
104
+	protected function _set_page_routes()
105
+	{
106
+		// load formatter helper
107
+		// load field generator helper
108
+
109
+
110
+		$this->_page_routes = [
111
+			'default'                    => [
112
+				'func'       => [$this, '_overview_list_table'],
113
+				'capability' => 'ee_read_venues',
114
+			],
115
+			'create_new'                 => [
116
+				'func'       => [$this, '_create_new_cpt_item'],
117
+				'capability' => 'ee_edit_venues',
118
+			],
119
+			'edit'                       => [
120
+				'func'       => [$this, '_edit_cpt_item'],
121
+				'capability' => 'ee_edit_venue',
122
+				'obj_id'     => $this->VNU_ID,
123
+			],
124
+			'trash_venue'                => [
125
+				'func'       => [$this, '_trash_or_restore_venue'],
126
+				'args'       => ['venue_status' => 'trash'],
127
+				'noheader'   => true,
128
+				'capability' => 'ee_delete_venue',
129
+				'obj_id'     => $this->VNU_ID,
130
+			],
131
+			'trash_venues'               => [
132
+				'func'       => [$this, '_trash_or_restore_venues'],
133
+				'args'       => ['venue_status' => 'trash'],
134
+				'noheader'   => true,
135
+				'capability' => 'ee_delete_venues',
136
+			],
137
+			'restore_venue'              => [
138
+				'func'       => [$this, '_trash_or_restore_venue'],
139
+				'args'       => ['venue_status' => 'draft'],
140
+				'noheader'   => true,
141
+				'capability' => 'ee_delete_venue',
142
+				'obj_id'     => $this->VNU_ID,
143
+			],
144
+			'restore_venues'             => [
145
+				'func'       => [$this, '_trash_or_restore_venues'],
146
+				'args'       => ['venue_status' => 'draft'],
147
+				'noheader'   => true,
148
+				'capability' => 'ee_delete_venues',
149
+			],
150
+			'delete_venues'              => [
151
+				'func'       => [$this, '_delete_venues'],
152
+				'noheader'   => true,
153
+				'capability' => 'ee_delete_venues',
154
+			],
155
+			'delete_venue'               => [
156
+				'func'       => [$this, '_delete_venue'],
157
+				'args'       => ['redirect_after' => true],
158
+				'noheader'   => true,
159
+				'capability' => 'ee_delete_venue',
160
+				'obj_id'     => $this->VNU_ID,
161
+			],
162
+			// settings related
163
+			'google_map_settings'        => [
164
+				'func'       => [$this, '_google_map_settings'],
165
+				'capability' => 'manage_options',
166
+			],
167
+			'update_google_map_settings' => [
168
+				'func'       => [$this, '_update_google_map_settings'],
169
+				'capability' => 'manage_options',
170
+				'noheader'   => true,
171
+			],
172
+			// venue category tab related
173
+			'add_category'               => [
174
+				'func'       => [$this, '_category_details'],
175
+				'args'       => ['add'],
176
+				'capability' => 'ee_edit_venue_category',
177
+			],
178
+			'edit_category'              => [
179
+				'func'       => [$this, '_category_details'],
180
+				'args'       => ['edit'],
181
+				'capability' => 'ee_edit_venue_category',
182
+			],
183
+			'delete_categories'          => [
184
+				'func'       => [$this, '_delete_categories'],
185
+				'noheader'   => true,
186
+				'capability' => 'ee_delete_venue_category',
187
+			],
188
+
189
+			'delete_category' => [
190
+				'func'       => [$this, '_delete_categories'],
191
+				'noheader'   => true,
192
+				'capability' => 'ee_delete_venue_category',
193
+			],
194
+
195
+			'insert_category' => [
196
+				'func'       => [$this, '_insert_or_update_category'],
197
+				'args'       => ['new_category' => true],
198
+				'noheader'   => true,
199
+				'capability' => 'ee_edit_venue_category',
200
+			],
201
+
202
+			'update_category'   => [
203
+				'func'       => [$this, '_insert_or_update_category'],
204
+				'args'       => ['new_category' => false],
205
+				'noheader'   => true,
206
+				'capability' => 'ee_edit_venue_category',
207
+			],
208
+			'export_categories' => [
209
+				'func'       => [$this, '_categories_export'],
210
+				'noheader'   => true,
211
+				'capability' => 'export',
212
+			],
213
+			'import_categories' => [
214
+				'func'       => [$this, '_import_categories'],
215
+				'capability' => 'import',
216
+			],
217
+			'category_list'     => [
218
+				'func'       => [$this, '_category_list_table'],
219
+				'capability' => 'ee_manage_venue_categories',
220
+			],
221
+		];
222
+	}
223
+
224
+
225
+	protected function _set_page_config()
226
+	{
227
+		$EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
228
+		$help_tabs  = [
229
+			'venues_editor_help_tab'                                               => [
230
+				'title'    => esc_html__('Venue Editor', 'event_espresso'),
231
+				'filename' => 'venues_editor',
232
+			],
233
+			'venues_editor_title_richtexteditor_help_tab'                          => [
234
+				'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
235
+				'filename' => 'venues_editor_title_richtexteditor',
236
+			],
237
+			'venues_editor_tags_categories_help_tab'                               => [
238
+				'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
239
+				'filename' => 'venues_editor_tags_categories',
240
+			],
241
+			'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
242
+				'title'    => esc_html__(
243
+					'Venue Editor Physical Location & Google Map & Virtual Location',
244
+					'event_espresso'
245
+				),
246
+				'filename' => 'venues_editor_physical_location_google_map_virtual_location',
247
+			],
248
+			'venues_editor_save_new_venue_help_tab'                                => [
249
+				'title'    => esc_html__('Save New Venue', 'event_espresso'),
250
+				'filename' => 'venues_editor_save_new_venue',
251
+			],
252
+			'venues_editor_other_help_tab'                                         => [
253
+				'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
254
+				'filename' => 'venues_editor_other',
255
+			],
256
+		];
257
+
258
+		$this->_page_config = [
259
+			'default'             => [
260
+				'nav'           => [
261
+					'label' => esc_html__('Overview', 'event_espresso'),
262
+					'icon'  => 'dashicons-list-view',
263
+					'order' => 10,
264
+				],
265
+				'list_table'    => 'Venues_Admin_List_Table',
266
+				'help_tabs'     => [
267
+					'venues_overview_help_tab'                           => [
268
+						'title'    => esc_html__('Venues Overview', 'event_espresso'),
269
+						'filename' => 'venues_overview',
270
+					],
271
+					'venues_overview_table_column_headings_help_tab'     => [
272
+						'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
273
+						'filename' => 'venues_overview_table_column_headings',
274
+					],
275
+					'venues_overview_views_bulk_actions_search_help_tab' => [
276
+						'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
277
+						'filename' => 'venues_overview_views_bulk_actions_search',
278
+					],
279
+				],
280
+				'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
281
+				'require_nonce' => false,
282
+			],
283
+			'create_new'          => [
284
+				'nav'           => [
285
+					'label'      => esc_html__('Add Venue', 'event_espresso'),
286
+					'icon'       => 'dashicons-plus-alt',
287
+					'order'      => 15,
288
+					'persistent' => false,
289
+				],
290
+				'help_tabs'     => $help_tabs,
291
+				'metaboxes'     => ['_venue_editor_metaboxes'],
292
+				'require_nonce' => false,
293
+			],
294
+			'edit'                => [
295
+				'nav'           => [
296
+					'label'      => esc_html__('Edit Venue', 'event_espresso'),
297
+					'icon'       => 'dashicons-edit-large',
298
+					'order'      => 15,
299
+					'persistent' => false,
300
+					'url'        => $this->VNU_ID
301
+						? add_query_arg(['post' => $this->VNU_ID], $this->_current_page_view_url)
302
+						: $this->_admin_base_url,
303
+				],
304
+				'help_tabs'     => $help_tabs,
305
+				'metaboxes'     => ['_venue_editor_metaboxes'],
306
+				'require_nonce' => false,
307
+			],
308
+			'google_map_settings' => [
309
+				'nav'           => [
310
+					'label' => esc_html__('Google Maps', 'event_espresso'),
311
+					'icon'  => 'dashicons-location-alt',
312
+					'order' => 40,
313
+				],
314
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
315
+				'help_tabs'     => [
316
+					'general_settings_google_maps_help_tab' => [
317
+						'title'    => esc_html__('Google Maps', 'event_espresso'),
318
+						'filename' => 'general_settings_google_maps',
319
+					],
320
+				],
321
+				'require_nonce' => false,
322
+			],
323
+			// venue category stuff
324
+			'add_category'        => [
325
+				'nav'           => [
326
+					'label'      => esc_html__('Add Category', 'event_espresso'),
327
+					'icon'       => 'dashicons-plus-alt',
328
+					'order'      => 25,
329
+					'persistent' => false,
330
+				],
331
+				'metaboxes'     => ['_publish_post_box'],
332
+				'help_tabs'     => [
333
+					'venues_add_category_help_tab' => [
334
+						'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
335
+						'filename' => 'venues_add_category',
336
+					],
337
+				],
338
+				'require_nonce' => false,
339
+			],
340
+			'edit_category'       => [
341
+				'nav'           => [
342
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
343
+					'icon'       => 'dashicons-edit-large',
344
+					'order'      => 25,
345
+					'persistent' => false,
346
+					'url'        => $EVT_CAT_ID
347
+						? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
348
+						: $this->_admin_base_url,
349
+				],
350
+				'metaboxes'     => ['_publish_post_box'],
351
+				'help_tabs'     => [
352
+					'venues_edit_category_help_tab' => [
353
+						'title'    => esc_html__('Edit Venue Category', 'event_espresso'),
354
+						'filename' => 'venues_edit_category',
355
+					],
356
+				],
357
+				'require_nonce' => false,
358
+			],
359
+			'category_list'       => [
360
+				'nav'           => [
361
+					'label' => esc_html__('Categories', 'event_espresso'),
362
+					'icon'  => 'dashicons-networking',
363
+					'order' => 20,
364
+				],
365
+				'list_table'    => 'Venue_Categories_Admin_List_Table',
366
+				'help_tabs'     => [
367
+					'venues_categories_help_tab'                       => [
368
+						'title'    => esc_html__('Venue Categories', 'event_espresso'),
369
+						'filename' => 'venues_categories',
370
+					],
371
+					'venues_categories_table_column_headings_help_tab' => [
372
+						'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
373
+						'filename' => 'venues_categories_table_column_headings',
374
+					],
375
+					'venues_categories_views_help_tab'                 => [
376
+						'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
377
+						'filename' => 'venues_categories_views',
378
+					],
379
+					'venues_categories_other_help_tab'                 => [
380
+						'title'    => esc_html__('Venue Categories Other', 'event_espresso'),
381
+						'filename' => 'venues_categories_other',
382
+					],
383
+				],
384
+				'metaboxes'     => $this->_default_espresso_metaboxes,
385
+				'require_nonce' => false,
386
+			],
387
+		];
388
+	}
389
+
390
+
391
+	protected function _add_screen_options()
392
+	{
393
+		// todo
394
+	}
395
+
396
+
397
+	protected function _add_screen_options_default()
398
+	{
399
+		$this->_per_page_screen_option();
400
+	}
401
+
402
+
403
+	protected function _add_screen_options_category_list()
404
+	{
405
+		$page_title              = $this->_admin_page_title;
406
+		$this->_admin_page_title = esc_html__('Venue Categories', 'event_espresso');
407
+		$this->_per_page_screen_option();
408
+		$this->_admin_page_title = $page_title;
409
+	}
410
+
411
+
412
+	// none of the below group are currently used for Event Venues
413
+	protected function _add_feature_pointers()
414
+	{
415
+	}
416
+
417
+
418
+	public function admin_init()
419
+	{
420
+	}
421
+
422
+
423
+	public function admin_notices()
424
+	{
425
+	}
426
+
427
+
428
+	public function admin_footer_scripts()
429
+	{
430
+	}
431
+
432
+
433
+	public function load_scripts_styles_create_new()
434
+	{
435
+		$this->load_scripts_styles_edit();
436
+	}
437
+
438
+
439
+	public function load_scripts_styles()
440
+	{
441
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
442
+		wp_enqueue_style('ee-cat-admin');
443
+	}
444
+
445
+
446
+	public function load_scripts_styles_add_category()
447
+	{
448
+		$this->load_scripts_styles_edit_category();
449
+	}
450
+
451
+
452
+	public function load_scripts_styles_edit_category()
453
+	{
454
+		wp_enqueue_style('editor-buttons');
455
+	}
456
+
457
+
458
+	public function load_scripts_styles_edit()
459
+	{
460
+		// styles
461
+		wp_enqueue_style('espresso-ui-theme');
462
+		wp_register_style(
463
+			'espresso_venues',
464
+			EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
465
+			[],
466
+			EVENT_ESPRESSO_VERSION
467
+		);
468
+		wp_enqueue_style('espresso_venues');
469
+	}
470
+
471
+
472
+	protected function _set_list_table_views_default()
473
+	{
474
+		$this->_views = [
475
+			'all' => [
476
+				'slug'        => 'all',
477
+				'label'       => esc_html__('View All Venues', 'event_espresso'),
478
+				'count'       => 0,
479
+				'bulk_action' => [],
480
+			],
481
+		];
482
+
483
+		if ($this->capabilities->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
484
+			$this->_views['all']['bulk_action'] = [
485
+				'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
486
+			];
487
+			$this->_views['trash']              = [
488
+				'slug'        => 'trash',
489
+				'label'       => esc_html__('Trash', 'event_espresso'),
490
+				'count'       => 0,
491
+				'bulk_action' => [
492
+					'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
493
+					'delete_venues'  => esc_html__('Delete', 'event_espresso'),
494
+				],
495
+			];
496
+		}
497
+	}
498
+
499
+
500
+	protected function _set_list_table_views_category_list()
501
+	{
502
+		$this->_views = [
503
+			'all' => [
504
+				'slug'        => 'all',
505
+				'label'       => esc_html__('All', 'event_espresso'),
506
+				'count'       => 0,
507
+				'bulk_action' => [
508
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
509
+				],
510
+			],
511
+		];
512
+	}
513
+
514
+
515
+	/**
516
+	 * @throws EE_Error
517
+	 */
518
+	protected function _overview_list_table()
519
+	{
520
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
521
+		$this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
522
+			get_post_type_archive_link(EspressoPostType::VENUES),
523
+			esc_html__("View Venue Archive Page", "event_espresso"),
524
+			'button'
525
+		);
526
+
527
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
528
+				'create_new',
529
+				'add',
530
+				[],
531
+				'add-new-h2'
532
+			);
533
+
534
+		$this->_search_btn_label = esc_html__('Venues', 'event_espresso');
535
+		$this->display_admin_list_table_page_with_sidebar();
536
+	}
537
+
538
+
539
+	/**
540
+	 * @throws EE_Error
541
+	 * @throws ReflectionException
542
+	 */
543
+	public function extra_misc_actions_publish_box()
544
+	{
545
+		$extra_rows = [
546
+			'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
547
+			'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
548
+			'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
549
+		];
550
+		$template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
551
+		EEH_Template::display_template($template, $extra_rows);
552
+	}
553
+
554
+
555
+	/*************        Google Maps        *************
556 556
      *
557 557
      * @throws EE_Error
558 558
      * @throws EE_Error
559 559
      */
560 560
 
561 561
 
562
-    protected function _google_map_settings()
563
-    {
564
-        $this->_template_args['values']           = $this->_yes_no_values;
565
-        $default_map_settings                     = new stdClass();
566
-        $default_map_settings->use_google_maps    = true;
567
-        $default_map_settings->google_map_api_key = '';
568
-        // for event details pages (reg page)
569
-        $default_map_settings->event_details_map_width = 585;
570
-        // ee_map_width_single
571
-        $default_map_settings->event_details_map_height = 362;
572
-        // ee_map_height_single
573
-        $default_map_settings->event_details_map_zoom = 14;
574
-        // ee_map_zoom_single
575
-        $default_map_settings->event_details_display_nav = true;
576
-        // ee_map_nav_display_single
577
-        $default_map_settings->event_details_nav_size = false;
578
-        // ee_map_nav_size_single
579
-        $default_map_settings->event_details_control_type = 'default';
580
-        // ee_map_type_control_single
581
-        $default_map_settings->event_details_map_align = 'center';
582
-        // ee_map_align_single
583
-
584
-        // for event list pages
585
-        $default_map_settings->event_list_map_width = 300;
586
-        // ee_map_width
587
-        $default_map_settings->event_list_map_height = 185;
588
-        // ee_map_height
589
-        $default_map_settings->event_list_map_zoom = 12;
590
-        // ee_map_zoom
591
-        $default_map_settings->event_list_display_nav = false;
592
-        // ee_map_nav_display
593
-        $default_map_settings->event_list_nav_size = true;
594
-        // ee_map_nav_size
595
-        $default_map_settings->event_list_control_type = 'dropdown';
596
-        // ee_map_type_control
597
-        $default_map_settings->event_list_map_align = 'center';
598
-        // ee_map_align
599
-
600
-        $this->_template_args['map_settings'] =
601
-            isset(EE_Registry::instance()->CFG->map_settings)
602
-            && ! empty(EE_Registry::instance()->CFG->map_settings)
603
-                ? (object) array_merge(
604
-                (array) $default_map_settings,
605
-                (array) EE_Registry::instance()->CFG->map_settings
606
-            )
607
-                : $default_map_settings;
608
-
609
-        $this->_set_add_edit_form_tags('update_google_map_settings');
610
-        $this->_set_publish_post_box_vars();
611
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
612
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
613
-            $this->_template_args,
614
-            true
615
-        );
616
-        $this->display_admin_page_with_sidebar();
617
-    }
618
-
619
-
620
-    /**
621
-     * @throws EE_Error
622
-     */
623
-    protected function _update_google_map_settings()
624
-    {
625
-        $map_settings = EE_Registry::instance()->CFG->map_settings;
626
-
627
-        $settings = [
628
-            'use_google_maps'            => 'int',
629
-            'google_map_api_key'         => 'string',
630
-            'event_details_map_width'    => 'int',
631
-            'event_details_map_zoom'     => 'int',
632
-            'event_details_display_nav'  => 'int',
633
-            'event_details_nav_size'     => 'int',
634
-            'event_details_control_type' => 'string',
635
-            'event_details_map_align'    => 'string',
636
-            'event_list_map_width'       => 'int',
637
-            'event_list_map_height'      => 'int',
638
-            'event_list_map_zoom'        => 'int',
639
-            'event_list_display_nav'     => 'int',
640
-            'event_list_nav_size'        => 'int',
641
-            'event_list_control_type'    => 'string',
642
-            'event_list_map_align'       => 'string',
643
-        ];
644
-
645
-        foreach ($settings as $setting => $type) {
646
-            $map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
647
-        }
648
-
649
-        EE_Registry::instance()->CFG->map_settings = apply_filters(
650
-            'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
651
-            $map_settings
652
-        );
653
-
654
-        $what    = 'Google Map Settings';
655
-        $success = $this->_update_espresso_configuration(
656
-            $what,
657
-            EE_Registry::instance()->CFG->map_settings,
658
-            __FILE__,
659
-            __FUNCTION__,
660
-            __LINE__
661
-        );
662
-        $this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
663
-    }
664
-
665
-
666
-    /**
667
-     * @throws EE_Error
668
-     * @throws ReflectionException
669
-     */
670
-    protected function _venue_editor_metaboxes()
671
-    {
672
-        $this->verify_cpt_object();
673
-
674
-        $this->addMetaBox(
675
-            'espresso_venue_address_options',
676
-            esc_html__('Physical Location', 'event_espresso'),
677
-            [$this, 'venue_address_metabox'],
678
-            $this->page_slug,
679
-            'side',
680
-            'core'
681
-        );
682
-        $this->addMetaBox(
683
-            'espresso_venue_gmap_options',
684
-            esc_html__('Google Map', 'event_espresso'),
685
-            [$this, 'venue_gmap_metabox'],
686
-            $this->page_slug,
687
-            'side'
688
-        );
689
-        $this->addMetaBox(
690
-            'espresso_venue_virtual_loc_options',
691
-            esc_html__('Virtual Location', 'event_espresso'),
692
-            [$this, 'venue_virtual_loc_metabox'],
693
-            $this->page_slug,
694
-            'side'
695
-        );
696
-    }
697
-
698
-
699
-    /**
700
-     * @throws EE_Error
701
-     * @throws ReflectionException
702
-     */
703
-    public function venue_gmap_metabox()
704
-    {
705
-        $template_args = [
706
-            'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
707
-                'vnu_enable_for_gmap',
708
-                $this->get_yes_no_values(),
709
-                $this->_cpt_model_obj instanceof EE_Venue && $this->_cpt_model_obj->enable_for_gmap()
710
-            ),
711
-            'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
712
-        ];
713
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
714
-        EEH_Template::display_template($template, $template_args);
715
-    }
716
-
717
-
718
-    /**
719
-     * @throws EE_Error
720
-     * @throws ReflectionException
721
-     */
722
-    public function venue_address_metabox()
723
-    {
724
-        $template_args['_venue'] = $this->_cpt_model_obj;
725
-
726
-        $template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
727
-            new EE_Question_Form_Input(
728
-                EE_Question::new_instance(
729
-                    ['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
730
-                ),
731
-                EE_Answer::new_instance(
732
-                    [
733
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
734
-                            ? $this->_cpt_model_obj->state_ID()
735
-                            : 0,
736
-                    ]
737
-                ),
738
-                [
739
-                    'input_name'     => 'sta_id',
740
-                    'input_id'       => 'sta_id',
741
-                    'input_class'    => '',
742
-                    'input_prefix'   => '',
743
-                    'append_qstn_id' => false,
744
-                ]
745
-            )
746
-        );
747
-        $template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
748
-            new EE_Question_Form_Input(
749
-                EE_Question::new_instance(
750
-                    ['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
751
-                ),
752
-                EE_Answer::new_instance(
753
-                    [
754
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
755
-                            ? $this->_cpt_model_obj->country_ID()
756
-                            : 0,
757
-                    ]
758
-                ),
759
-                [
760
-                    'input_name'     => 'cnt_iso',
761
-                    'input_id'       => 'cnt_iso',
762
-                    'input_class'    => '',
763
-                    'input_prefix'   => '',
764
-                    'append_qstn_id' => false,
765
-                ]
766
-            )
767
-        );
768
-
769
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
770
-        EEH_Template::display_template($template, $template_args);
771
-    }
772
-
773
-
774
-    public function venue_virtual_loc_metabox()
775
-    {
776
-        $template_args = [
777
-            '_venue' => $this->_cpt_model_obj,
778
-        ];
779
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
780
-        EEH_Template::display_template($template, $template_args);
781
-    }
782
-
783
-
784
-    /**
785
-     * @throws EE_Error
786
-     * @throws ReflectionException
787
-     */
788
-    protected function _restore_cpt_item($post_id, $revision_id)
789
-    {
790
-        $this->_cpt_model_obj = $this->_venue_model->get_one_by_ID($post_id);
791
-        // meta revision restore
792
-        $this->_cpt_model_obj->restore_revision($revision_id);
793
-    }
794
-
795
-
796
-    /**
797
-     * Handles updates for venue cpts
798
-     *
799
-     * @param int     $post_id ID of Venue CPT
800
-     * @param WP_Post $post    Post object (with "blessed" WP properties)
801
-     * @return void
802
-     * @throws EE_Error
803
-     * @throws ReflectionException
804
-     */
805
-    protected function _insert_update_cpt_item($post_id, $post)
806
-    {
807
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
808
-            return;// get out we're not processing the saving of venues.
809
-        }
810
-
811
-        $wheres = [$this->_venue_model->primary_key_name() => $post_id];
812
-
813
-        $venue_values = [
814
-            'VNU_address'         => $this->request->getRequestParam('vnu_address'),
815
-            'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
816
-            'VNU_city'            => $this->request->getRequestParam('vnu_city'),
817
-            'STA_ID'              => $this->request->getRequestParam('sta_id'),
818
-            'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
819
-            'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
820
-            'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
821
-            'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
822
-                ? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
823
-                : EE_INF,
824
-            'VNU_url'             => $this->request->getRequestParam('vnu_url'),
825
-            'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
826
-            'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
827
-            'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
828
-            'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
829
-        ];
830
-
831
-        // update venue
832
-        $success = $this->_venue_model->update($venue_values, [$wheres]);
833
-
834
-        // get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
835
-        $get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
836
-        $venue         = $this->_venue_model->get_one([$get_one_where]);
837
-
838
-        // notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
839
-        $venue_update_callbacks = apply_filters(
840
-            'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
841
-            []
842
-        );
843
-        $att_success            = true;
844
-        foreach ($venue_update_callbacks as $v_callback) {
845
-            // if ANY of these updates fail then we want the appropriate global error message
846
-            $att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
847
-                ? $att_success
848
-                : false;
849
-        }
850
-
851
-        // any errors?
852
-        if ($success && ! $att_success) {
853
-            EE_Error::add_error(
854
-                esc_html__(
855
-                    'Venue Details saved successfully but something went wrong with saving attachments.',
856
-                    'event_espresso'
857
-                ),
858
-                __FILE__,
859
-                __FUNCTION__,
860
-                __LINE__
861
-            );
862
-        } elseif ($success === false) {
863
-            EE_Error::add_error(
864
-                esc_html__('Venue Details did not save successfully.', 'event_espresso'),
865
-                __FILE__,
866
-                __FUNCTION__,
867
-                __LINE__
868
-            );
869
-        }
870
-    }
871
-
872
-
873
-    /**
874
-     * @param int $post_id
875
-     * @throws EE_Error
876
-     * @throws ReflectionException
877
-     */
878
-    public function trash_cpt_item($post_id)
879
-    {
880
-        $this->request->setRequestParam('VNU_ID', $post_id);
881
-        $this->_trash_or_restore_venue('trash', false);
882
-    }
883
-
884
-
885
-    /**
886
-     * @param int $post_id
887
-     * @throws EE_Error
888
-     * @throws ReflectionException
889
-     */
890
-    public function restore_cpt_item($post_id)
891
-    {
892
-        $this->request->setRequestParam('VNU_ID', $post_id);
893
-        $this->_trash_or_restore_venue('draft', false);
894
-    }
895
-
896
-
897
-    /**
898
-     * @param int $post_id
899
-     * @throws EE_Error
900
-     * @throws ReflectionException
901
-     */
902
-    public function delete_cpt_item($post_id)
903
-    {
904
-        $this->request->setRequestParam('VNU_ID', $post_id);
905
-        $this->_delete_venue(false);
906
-    }
907
-
908
-
909
-    public function get_venue_object()
910
-    {
911
-        return $this->_cpt_model_obj;
912
-    }
913
-
914
-
915
-    /**
916
-     * @param string    $venue_status
917
-     * @param bool|null $redirect_after
918
-     * @throws EE_Error
919
-     * @throws ReflectionException
920
-     */
921
-    protected function _trash_or_restore_venue(string $venue_status = 'trash', ?bool $redirect_after = true)
922
-    {
923
-        // loop thru venues
924
-        if ($this->VNU_ID) {
925
-            // clean status
926
-            $venue_status = sanitize_key($venue_status);
927
-            // grab status
928
-            if (! empty($venue_status)) {
929
-                $success = $this->_change_venue_status($this->VNU_ID, $venue_status);
930
-            } else {
931
-                $success = false;
932
-                $msg     = esc_html__(
933
-                    'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
934
-                    'event_espresso'
935
-                );
936
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
937
-            }
938
-        } else {
939
-            $success = false;
940
-            $msg     = esc_html__(
941
-                'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
942
-                'event_espresso'
943
-            );
944
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
945
-        }
946
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
947
-
948
-        if ($redirect_after) {
949
-            $this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
950
-        }
951
-    }
952
-
953
-
954
-    /**
955
-     * @param string $venue_status
956
-     * @throws EE_Error
957
-     * @throws ReflectionException
958
-     */
959
-    protected function _trash_or_restore_venues(string $venue_status = 'trash')
960
-    {
961
-        // clean status
962
-        $venue_status = sanitize_key($venue_status);
963
-        // grab status
964
-        if (! empty($venue_status)) {
965
-            $success = true;
966
-            // determine the event id and set to array.
967
-            $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
968
-            // loop thru events
969
-            foreach ($VNU_IDs as $VNU_ID) {
970
-                if ($VNU_ID = absint($VNU_ID)) {
971
-                    $results = $this->_change_venue_status($VNU_ID, $venue_status);
972
-                    $success = $results !== false ? $success : false;
973
-                } else {
974
-                    $msg = sprintf(
975
-                        esc_html__(
976
-                            'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
977
-                            'event_espresso'
978
-                        ),
979
-                        $VNU_ID
980
-                    );
981
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
982
-                    $success = false;
983
-                }
984
-            }
985
-        } else {
986
-            $success = false;
987
-            $msg     = esc_html__(
988
-                'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
989
-                'event_espresso'
990
-            );
991
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
992
-        }
993
-        // in order to force a pluralized result message we need to send back a success status greater than 1
994
-        $success = $success ? 2 : false;
995
-        $action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
996
-        $this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
997
-    }
998
-
999
-
1000
-    /**
1001
-     * _trash_or_restore_venues
1002
-     * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1003
-     * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1004
-     * accepting a certain number of params.
1005
-     *
1006
-     * @param int|null $VNU_ID
1007
-     * @param string   $venue_status
1008
-     * @return bool
1009
-     * @throws EE_Error
1010
-     * @throws ReflectionException
1011
-     */
1012
-    private function _change_venue_status(?int $VNU_ID = 0, string $venue_status = ''): bool
1013
-    {
1014
-        // grab venue id
1015
-        if (! $VNU_ID) {
1016
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1017
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1018
-            return false;
1019
-        }
1020
-
1021
-        $this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1022
-
1023
-        // clean status
1024
-        $venue_status = sanitize_key($venue_status);
1025
-        // grab status
1026
-        if (! $venue_status) {
1027
-            $msg = esc_html__(
1028
-                'An error occurred. No Venue Status or an invalid Venue Status was received.',
1029
-                'event_espresso'
1030
-            );
1031
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1032
-            return false;
1033
-        }
1034
-
1035
-        // was event trashed or restored ?
1036
-        switch ($venue_status) {
1037
-            case 'draft':
1038
-                $action = 'restored from the trash';
1039
-                $hook   = 'AHEE_venue_restored_from_trash';
1040
-                break;
1041
-            case 'trash':
1042
-                $action = 'moved to the trash';
1043
-                $hook   = 'AHEE_venue_moved_to_trash';
1044
-                break;
1045
-            default:
1046
-                $action = 'updated';
1047
-                $hook   = false;
1048
-        }
1049
-        // use class to change status
1050
-        $this->_cpt_model_obj->set_status($venue_status);
1051
-        $success = $this->_cpt_model_obj->save();
1052
-
1053
-        if ($success === false) {
1054
-            $msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1055
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1056
-            return false;
1057
-        }
1058
-        if ($hook) {
1059
-            do_action($hook);
1060
-        }
1061
-        return true;
1062
-    }
1063
-
1064
-
1065
-    /**
1066
-     * @param bool $redirect_after
1067
-     * @return void
1068
-     * @throws EE_Error
1069
-     * @throws ReflectionException
1070
-     */
1071
-    protected function _delete_venue(bool $redirect_after = true)
1072
-    {
1073
-        // loop thru venues
1074
-        if ($this->VNU_ID) {
1075
-            $success = $this->_delete_or_trash_venue($this->VNU_ID);
1076
-        } else {
1077
-            $success = false;
1078
-            $msg     = esc_html__(
1079
-                'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1080
-                'event_espresso'
1081
-            );
1082
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1083
-        }
1084
-        if ($redirect_after) {
1085
-            $this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1086
-        }
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * @throws EE_Error
1092
-     * @throws ReflectionException
1093
-     */
1094
-    protected function _delete_venues()
1095
-    {
1096
-        $success = true;
1097
-        // determine the event id and set to array.
1098
-        $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1099
-        // loop thru events
1100
-        foreach ($VNU_IDs as $VNU_ID) {
1101
-            if ($VNU_ID = absint($VNU_ID)) {
1102
-                $results = $this->_delete_or_trash_venue($VNU_ID);
1103
-                $success = $results !== false ? $success : false;
1104
-            } else {
1105
-                $success = false;
1106
-                $msg     = esc_html__(
1107
-                    'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1108
-                    'event_espresso'
1109
-                );
1110
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1111
-            }
1112
-        }
1113
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1114
-        $success = $success ? 2 : false;
1115
-        $this->_redirect_after_action(
1116
-            $success,
1117
-            esc_html__('Venues', 'event_espresso'),
1118
-            esc_html__('deleted', 'event_espresso'),
1119
-            ['action' => 'default']
1120
-        );
1121
-    }
1122
-
1123
-
1124
-    // todo: put in parent
1125
-
1126
-
1127
-    /**
1128
-     * @param int|null $VNU_ID
1129
-     * @return bool
1130
-     * @throws EE_Error
1131
-     * @throws ReflectionException
1132
-     */
1133
-    private function _delete_or_trash_venue(?int $VNU_ID = 0): bool
1134
-    {
1135
-        // grab event id
1136
-        if (! $VNU_ID = absint($VNU_ID)) {
1137
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1138
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1139
-            return false;
1140
-        }
1141
-
1142
-
1143
-        $venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1144
-        // first need to remove all term relationships
1145
-        $venue->_remove_relations('Term_Taxonomy');
1146
-        $success = $venue->delete_permanently();
1147
-        // did it all go as planned ?
1148
-        if (! $success) {
1149
-            EE_Error::add_error(
1150
-                sprintf(
1151
-                    esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1152
-                    $VNU_ID
1153
-                ),
1154
-                __FILE__,
1155
-                __FUNCTION__,
1156
-                __LINE__
1157
-            );
1158
-            return false;
1159
-        }
1160
-        EE_Error::add_success(
1161
-            sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID)
1162
-        );
1163
-        do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1164
-        return true;
1165
-    }
1166
-
1167
-
1168
-
1169
-
1170
-    /***********/
1171
-    /* QUERIES */
1172
-
1173
-
1174
-    /**
1175
-     * @throws EE_Error
1176
-     * @throws ReflectionException
1177
-     */
1178
-    public function get_venues($per_page = 10, $count = false)
1179
-    {
1180
-        $orderby = $this->request->getRequestParam('orderby', '');
1181
-
1182
-        switch ($orderby) {
1183
-            case 'id':
1184
-                $orderby = 'VNU_ID';
1185
-                break;
1186
-
1187
-            case 'capacity':
1188
-                $orderby = 'VNU_capacity';
1189
-                break;
1190
-
1191
-            case 'city':
1192
-                $orderby = 'VNU_city';
1193
-                break;
1194
-
1195
-            default:
1196
-                $orderby = 'VNU_name';
1197
-        }
1198
-
1199
-        $sort         = $this->request->getRequestParam('order', 'ASC');
1200
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1201
-        $per_page     = ! empty($per_page) ? $per_page : 10;
1202
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1203
-
1204
-        $offset = ($current_page - 1) * $per_page;
1205
-        $limit  = [$offset, $per_page];
1206
-
1207
-        $category = $this->request->getRequestParam('category');
1208
-        $category = $category > 0 ? $category : null;
1209
-
1210
-        $where = [];
1211
-
1212
-        // only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1213
-        $status = $this->request->getRequestParam('status');
1214
-        if ($status && $status !== 'all') {
1215
-            $where['status'] = $status;
1216
-        }
1217
-
1218
-        $venue_status = $this->request->getRequestParam('venue_status');
1219
-        if ($venue_status) {
1220
-            $where['status'] = $venue_status;
1221
-        }
1222
-
1223
-
1224
-        if ($category) {
1225
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1226
-            $where['Term_Taxonomy.term_id']  = $category;
1227
-        }
1228
-
1229
-
1230
-        if (! $this->capabilities->current_user_can('ee_read_others_venues', 'get_venues')) {
1231
-            $where['VNU_wp_user'] = get_current_user_id();
1232
-        } else {
1233
-            if (! $this->capabilities->current_user_can('ee_read_private_venues', 'get_venues')) {
1234
-                $where['OR'] = [
1235
-                    'status*restrict_private' => ['!=', 'private'],
1236
-                    'AND'                     => [
1237
-                        'status*inclusive' => ['=', 'private'],
1238
-                        'VNU_wp_user'      => get_current_user_id(),
1239
-                    ],
1240
-                ];
1241
-            }
1242
-        }
1243
-
1244
-        $search_term = $this->request->getRequestParam('s');
1245
-        if ($search_term) {
1246
-            $search_term = '%' . $search_term . '%';
1247
-            $where['OR'] = [
1248
-                'VNU_name'               => ['LIKE', $search_term],
1249
-                'VNU_desc'               => ['LIKE', $search_term],
1250
-                'VNU_short_desc'         => ['LIKE', $search_term],
1251
-                'VNU_address'            => ['LIKE', $search_term],
1252
-                'VNU_address2'           => ['LIKE', $search_term],
1253
-                'VNU_city'               => ['LIKE', $search_term],
1254
-                'VNU_zip'                => ['LIKE', $search_term],
1255
-                'VNU_phone'              => ['LIKE', $search_term],
1256
-                'VNU_url'                => ['LIKE', $search_term],
1257
-                'VNU_virtual_phone'      => ['LIKE', $search_term],
1258
-                'VNU_virtual_url'        => ['LIKE', $search_term],
1259
-                'VNU_google_map_link'    => ['LIKE', $search_term],
1260
-                'Event.EVT_name'         => ['LIKE', $search_term],
1261
-                'Event.EVT_desc'         => ['LIKE', $search_term],
1262
-                'Event.EVT_phone'        => ['LIKE', $search_term],
1263
-                'Event.EVT_external_URL' => ['LIKE', $search_term],
1264
-            ];
1265
-        }
1266
-
1267
-
1268
-        return $count
1269
-            ? $this->_venue_model->count([$where], 'VNU_ID')
1270
-            : $this->_venue_model->get_all(
1271
-                [$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1272
-            );
1273
-    }
1274
-
1275
-
1276
-
1277
-
1278
-    /** Venue Category Stuff **/
1279
-
1280
-    /**
1281
-     * set the _category property with the category object for the loaded page.
1282
-     *
1283
-     * @access private
1284
-     * @return void
1285
-     */
1286
-    private function _set_category_object()
1287
-    {
1288
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
1289
-            return;
1290
-        } // already have the category object so get out.
1291
-
1292
-        // set default category object
1293
-        $this->_set_empty_category_object();
1294
-
1295
-        // only set if we've got an id
1296
-        $category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1297
-        if (! $category_ID) {
1298
-            return;
1299
-        }
1300
-
1301
-        $term = get_term($category_ID, 'espresso_venue_categories');
1302
-
1303
-
1304
-        if (! empty($term)) {
1305
-            $this->_category->category_name       = $term->name;
1306
-            $this->_category->category_identifier = $term->slug;
1307
-            $this->_category->category_desc       = $term->description;
1308
-            $this->_category->id                  = $term->term_id;
1309
-            $this->_category->parent              = $term->parent;
1310
-        }
1311
-    }
1312
-
1313
-
1314
-    private function _set_empty_category_object()
1315
-    {
1316
-        $this->_category                = new stdClass();
1317
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1318
-        $this->_category->id            = $this->_category->parent = 0;
1319
-    }
1320
-
1321
-
1322
-    /**
1323
-     * @throws EE_Error
1324
-     */
1325
-    protected function _category_list_table()
1326
-    {
1327
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1328
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1329
-                'add_category',
1330
-                'add_category',
1331
-                [],
1332
-                'add-new-h2'
1333
-            );
1334
-        $this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1335
-        $this->display_admin_list_table_page_with_sidebar();
1336
-    }
1337
-
1338
-
1339
-    /**
1340
-     * @throws EE_Error
1341
-     */
1342
-    protected function _category_details($view)
1343
-    {
1344
-        // load formatter helper
1345
-        // load field generator helper
1346
-
1347
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
1348
-        $this->_set_add_edit_form_tags($route);
1349
-
1350
-        $this->_set_category_object();
1351
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
1352
-
1353
-        $delete_action = 'delete_category';
1354
-
1355
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1356
-
1357
-        $this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1358
-
1359
-        // take care of contents
1360
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
1361
-        $this->display_admin_page_with_sidebar();
1362
-    }
1363
-
1364
-
1365
-    protected function _category_details_content(): string
1366
-    {
1367
-        $editor_args['category_desc'] = [
1368
-            'type'          => 'wp_editor',
1369
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1370
-            'class'         => 'my_editor_custom',
1371
-            'wpeditor_args' => ['media_buttons' => false],
1372
-        ];
1373
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1374
-
1375
-        $all_terms = get_terms(
1376
-            ['espresso_venue_categories'],
1377
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1378
-        );
1379
-
1380
-        // setup category select for term parents.
1381
-        $category_select_values[] = [
1382
-            'text' => esc_html__('No Parent', 'event_espresso'),
1383
-            'id'   => 0,
1384
-        ];
1385
-        foreach ($all_terms as $term) {
1386
-            $category_select_values[] = [
1387
-                'text' => $term->name,
1388
-                'id'   => $term->term_id,
1389
-            ];
1390
-        }
1391
-
1392
-        $category_select = EEH_Form_Fields::select_input(
1393
-            'category_parent',
1394
-            $category_select_values,
1395
-            $this->_category->parent
1396
-        );
1397
-        $template_args   = [
1398
-            'category'                 => $this->_category,
1399
-            'category_select'          => $category_select,
1400
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1401
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1402
-            'disable'                  => '',
1403
-            'disabled_message'         => false,
1404
-        ];
1405
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1406
-        return EEH_Template::display_template($template, $template_args, true);
1407
-    }
1408
-
1409
-
1410
-    /**
1411
-     * @throws EE_Error
1412
-     */
1413
-    protected function _delete_categories()
1414
-    {
1415
-        $category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1416
-        $category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1417
-
1418
-        foreach ($category_IDs as $cat_id) {
1419
-            $this->_delete_category($cat_id);
1420
-        }
1421
-
1422
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
1423
-        $query_args = [
1424
-            'action' => 'category_list',
1425
-        ];
1426
-        $this->_redirect_after_action(0, '', '', $query_args);
1427
-    }
1428
-
1429
-
1430
-    protected function _delete_category($cat_id)
1431
-    {
1432
-        $cat_id = absint($cat_id);
1433
-        wp_delete_term($cat_id, 'espresso_venue_categories');
1434
-    }
1435
-
1436
-
1437
-    /**
1438
-     * @throws EE_Error
1439
-     */
1440
-    protected function _insert_or_update_category($new_category)
1441
-    {
1442
-        $cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1443
-        $success = 0; // we already have a success message so lets not send another.
1444
-        if ($cat_id) {
1445
-            $query_args = [
1446
-                'action'     => 'edit_category',
1447
-                'VEN_CAT_ID' => $cat_id,
1448
-            ];
1449
-        } else {
1450
-            $query_args = ['action' => 'add_category'];
1451
-        }
1452
-        $this->_redirect_after_action($success, '', '', $query_args, true);
1453
-    }
1454
-
1455
-
1456
-    private function _insert_category($update = false)
1457
-    {
1458
-        $category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1459
-        $category_name   = $this->request->getRequestParam('category_name', '');
1460
-        $category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1461
-        $category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1462
-
1463
-        if (empty($category_name)) {
1464
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
1465
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1466
-            return false;
1467
-        }
1468
-
1469
-
1470
-        $term_args = [
1471
-            'name'        => $category_name,
1472
-            'description' => $category_desc,
1473
-            'parent'      => $category_parent,
1474
-        ];
1475
-
1476
-        $insert_ids = $update
1477
-            ? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1478
-            : wp_insert_term(
1479
-                $category_name,
1480
-                'espresso_venue_categories',
1481
-                $term_args
1482
-            );
1483
-
1484
-        if (! is_array($insert_ids)) {
1485
-            EE_Error::add_error(
1486
-                esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1487
-                __FILE__,
1488
-                __FUNCTION__,
1489
-                __LINE__
1490
-            );
1491
-        } else {
1492
-            $category_ID = $insert_ids['term_id'];
1493
-            EE_Error::add_success(
1494
-                sprintf(
1495
-                    esc_html__('The category %s was successfully created', 'event_espresso'),
1496
-                    $category_name
1497
-                )
1498
-            );
1499
-        }
1500
-
1501
-        return $category_ID;
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * TODO handle category exports()
1507
-     *
1508
-     * @return void
1509
-     */
1510
-    protected function _categories_export()
1511
-    {
1512
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
1513
-        $this->request->mergeRequestParams(
1514
-            [
1515
-                'export'       => 'report',
1516
-                'action'       => 'categories',
1517
-                'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1518
-            ]
1519
-        );
1520
-
1521
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1522
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1523
-            $EE_Export = EE_Export::instance($this->request->requestParams());
1524
-            $EE_Export->export();
1525
-        }
1526
-    }
1527
-
1528
-
1529
-    protected function _import_categories()
1530
-    {
1531
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1532
-        EE_Import::instance()->import();
1533
-    }
1534
-
1535
-
1536
-    /**
1537
-     * @throws EE_Error
1538
-     * @throws ReflectionException
1539
-     */
1540
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
1541
-    {
1542
-        // testing term stuff
1543
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1544
-        $order       = $this->request->getRequestParam('order', 'DESC');
1545
-        $limit       = ($current_page - 1) * $per_page;
1546
-        $where       = ['taxonomy' => 'espresso_venue_categories'];
1547
-        $search_term = $this->request->getRequestParam('s');
1548
-        if ($search_term) {
1549
-            $search_term = '%' . $search_term . '%';
1550
-            $where['OR'] = [
1551
-                'Term.name'   => ['LIKE', $search_term],
1552
-                'description' => ['LIKE', $search_term],
1553
-            ];
1554
-        }
1555
-
1556
-        $query_params = [
1557
-            $where,
1558
-            'order_by'   => [$orderby => $order],
1559
-            'limit'      => $limit . ',' . $per_page,
1560
-            'force_join' => ['Term'],
1561
-        ];
1562
-
1563
-        return $count
1564
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1565
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
1566
-    }
1567
-
1568
-
1569
-    /* end category stuff */
1570
-    /**************/
562
+	protected function _google_map_settings()
563
+	{
564
+		$this->_template_args['values']           = $this->_yes_no_values;
565
+		$default_map_settings                     = new stdClass();
566
+		$default_map_settings->use_google_maps    = true;
567
+		$default_map_settings->google_map_api_key = '';
568
+		// for event details pages (reg page)
569
+		$default_map_settings->event_details_map_width = 585;
570
+		// ee_map_width_single
571
+		$default_map_settings->event_details_map_height = 362;
572
+		// ee_map_height_single
573
+		$default_map_settings->event_details_map_zoom = 14;
574
+		// ee_map_zoom_single
575
+		$default_map_settings->event_details_display_nav = true;
576
+		// ee_map_nav_display_single
577
+		$default_map_settings->event_details_nav_size = false;
578
+		// ee_map_nav_size_single
579
+		$default_map_settings->event_details_control_type = 'default';
580
+		// ee_map_type_control_single
581
+		$default_map_settings->event_details_map_align = 'center';
582
+		// ee_map_align_single
583
+
584
+		// for event list pages
585
+		$default_map_settings->event_list_map_width = 300;
586
+		// ee_map_width
587
+		$default_map_settings->event_list_map_height = 185;
588
+		// ee_map_height
589
+		$default_map_settings->event_list_map_zoom = 12;
590
+		// ee_map_zoom
591
+		$default_map_settings->event_list_display_nav = false;
592
+		// ee_map_nav_display
593
+		$default_map_settings->event_list_nav_size = true;
594
+		// ee_map_nav_size
595
+		$default_map_settings->event_list_control_type = 'dropdown';
596
+		// ee_map_type_control
597
+		$default_map_settings->event_list_map_align = 'center';
598
+		// ee_map_align
599
+
600
+		$this->_template_args['map_settings'] =
601
+			isset(EE_Registry::instance()->CFG->map_settings)
602
+			&& ! empty(EE_Registry::instance()->CFG->map_settings)
603
+				? (object) array_merge(
604
+				(array) $default_map_settings,
605
+				(array) EE_Registry::instance()->CFG->map_settings
606
+			)
607
+				: $default_map_settings;
608
+
609
+		$this->_set_add_edit_form_tags('update_google_map_settings');
610
+		$this->_set_publish_post_box_vars();
611
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
612
+			EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
613
+			$this->_template_args,
614
+			true
615
+		);
616
+		$this->display_admin_page_with_sidebar();
617
+	}
618
+
619
+
620
+	/**
621
+	 * @throws EE_Error
622
+	 */
623
+	protected function _update_google_map_settings()
624
+	{
625
+		$map_settings = EE_Registry::instance()->CFG->map_settings;
626
+
627
+		$settings = [
628
+			'use_google_maps'            => 'int',
629
+			'google_map_api_key'         => 'string',
630
+			'event_details_map_width'    => 'int',
631
+			'event_details_map_zoom'     => 'int',
632
+			'event_details_display_nav'  => 'int',
633
+			'event_details_nav_size'     => 'int',
634
+			'event_details_control_type' => 'string',
635
+			'event_details_map_align'    => 'string',
636
+			'event_list_map_width'       => 'int',
637
+			'event_list_map_height'      => 'int',
638
+			'event_list_map_zoom'        => 'int',
639
+			'event_list_display_nav'     => 'int',
640
+			'event_list_nav_size'        => 'int',
641
+			'event_list_control_type'    => 'string',
642
+			'event_list_map_align'       => 'string',
643
+		];
644
+
645
+		foreach ($settings as $setting => $type) {
646
+			$map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
647
+		}
648
+
649
+		EE_Registry::instance()->CFG->map_settings = apply_filters(
650
+			'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
651
+			$map_settings
652
+		);
653
+
654
+		$what    = 'Google Map Settings';
655
+		$success = $this->_update_espresso_configuration(
656
+			$what,
657
+			EE_Registry::instance()->CFG->map_settings,
658
+			__FILE__,
659
+			__FUNCTION__,
660
+			__LINE__
661
+		);
662
+		$this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
663
+	}
664
+
665
+
666
+	/**
667
+	 * @throws EE_Error
668
+	 * @throws ReflectionException
669
+	 */
670
+	protected function _venue_editor_metaboxes()
671
+	{
672
+		$this->verify_cpt_object();
673
+
674
+		$this->addMetaBox(
675
+			'espresso_venue_address_options',
676
+			esc_html__('Physical Location', 'event_espresso'),
677
+			[$this, 'venue_address_metabox'],
678
+			$this->page_slug,
679
+			'side',
680
+			'core'
681
+		);
682
+		$this->addMetaBox(
683
+			'espresso_venue_gmap_options',
684
+			esc_html__('Google Map', 'event_espresso'),
685
+			[$this, 'venue_gmap_metabox'],
686
+			$this->page_slug,
687
+			'side'
688
+		);
689
+		$this->addMetaBox(
690
+			'espresso_venue_virtual_loc_options',
691
+			esc_html__('Virtual Location', 'event_espresso'),
692
+			[$this, 'venue_virtual_loc_metabox'],
693
+			$this->page_slug,
694
+			'side'
695
+		);
696
+	}
697
+
698
+
699
+	/**
700
+	 * @throws EE_Error
701
+	 * @throws ReflectionException
702
+	 */
703
+	public function venue_gmap_metabox()
704
+	{
705
+		$template_args = [
706
+			'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
707
+				'vnu_enable_for_gmap',
708
+				$this->get_yes_no_values(),
709
+				$this->_cpt_model_obj instanceof EE_Venue && $this->_cpt_model_obj->enable_for_gmap()
710
+			),
711
+			'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
712
+		];
713
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
714
+		EEH_Template::display_template($template, $template_args);
715
+	}
716
+
717
+
718
+	/**
719
+	 * @throws EE_Error
720
+	 * @throws ReflectionException
721
+	 */
722
+	public function venue_address_metabox()
723
+	{
724
+		$template_args['_venue'] = $this->_cpt_model_obj;
725
+
726
+		$template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
727
+			new EE_Question_Form_Input(
728
+				EE_Question::new_instance(
729
+					['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
730
+				),
731
+				EE_Answer::new_instance(
732
+					[
733
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
734
+							? $this->_cpt_model_obj->state_ID()
735
+							: 0,
736
+					]
737
+				),
738
+				[
739
+					'input_name'     => 'sta_id',
740
+					'input_id'       => 'sta_id',
741
+					'input_class'    => '',
742
+					'input_prefix'   => '',
743
+					'append_qstn_id' => false,
744
+				]
745
+			)
746
+		);
747
+		$template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
748
+			new EE_Question_Form_Input(
749
+				EE_Question::new_instance(
750
+					['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
751
+				),
752
+				EE_Answer::new_instance(
753
+					[
754
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
755
+							? $this->_cpt_model_obj->country_ID()
756
+							: 0,
757
+					]
758
+				),
759
+				[
760
+					'input_name'     => 'cnt_iso',
761
+					'input_id'       => 'cnt_iso',
762
+					'input_class'    => '',
763
+					'input_prefix'   => '',
764
+					'append_qstn_id' => false,
765
+				]
766
+			)
767
+		);
768
+
769
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
770
+		EEH_Template::display_template($template, $template_args);
771
+	}
772
+
773
+
774
+	public function venue_virtual_loc_metabox()
775
+	{
776
+		$template_args = [
777
+			'_venue' => $this->_cpt_model_obj,
778
+		];
779
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
780
+		EEH_Template::display_template($template, $template_args);
781
+	}
782
+
783
+
784
+	/**
785
+	 * @throws EE_Error
786
+	 * @throws ReflectionException
787
+	 */
788
+	protected function _restore_cpt_item($post_id, $revision_id)
789
+	{
790
+		$this->_cpt_model_obj = $this->_venue_model->get_one_by_ID($post_id);
791
+		// meta revision restore
792
+		$this->_cpt_model_obj->restore_revision($revision_id);
793
+	}
794
+
795
+
796
+	/**
797
+	 * Handles updates for venue cpts
798
+	 *
799
+	 * @param int     $post_id ID of Venue CPT
800
+	 * @param WP_Post $post    Post object (with "blessed" WP properties)
801
+	 * @return void
802
+	 * @throws EE_Error
803
+	 * @throws ReflectionException
804
+	 */
805
+	protected function _insert_update_cpt_item($post_id, $post)
806
+	{
807
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
808
+			return;// get out we're not processing the saving of venues.
809
+		}
810
+
811
+		$wheres = [$this->_venue_model->primary_key_name() => $post_id];
812
+
813
+		$venue_values = [
814
+			'VNU_address'         => $this->request->getRequestParam('vnu_address'),
815
+			'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
816
+			'VNU_city'            => $this->request->getRequestParam('vnu_city'),
817
+			'STA_ID'              => $this->request->getRequestParam('sta_id'),
818
+			'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
819
+			'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
820
+			'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
821
+			'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
822
+				? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
823
+				: EE_INF,
824
+			'VNU_url'             => $this->request->getRequestParam('vnu_url'),
825
+			'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
826
+			'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
827
+			'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
828
+			'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
829
+		];
830
+
831
+		// update venue
832
+		$success = $this->_venue_model->update($venue_values, [$wheres]);
833
+
834
+		// get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
835
+		$get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
836
+		$venue         = $this->_venue_model->get_one([$get_one_where]);
837
+
838
+		// notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
839
+		$venue_update_callbacks = apply_filters(
840
+			'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
841
+			[]
842
+		);
843
+		$att_success            = true;
844
+		foreach ($venue_update_callbacks as $v_callback) {
845
+			// if ANY of these updates fail then we want the appropriate global error message
846
+			$att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
847
+				? $att_success
848
+				: false;
849
+		}
850
+
851
+		// any errors?
852
+		if ($success && ! $att_success) {
853
+			EE_Error::add_error(
854
+				esc_html__(
855
+					'Venue Details saved successfully but something went wrong with saving attachments.',
856
+					'event_espresso'
857
+				),
858
+				__FILE__,
859
+				__FUNCTION__,
860
+				__LINE__
861
+			);
862
+		} elseif ($success === false) {
863
+			EE_Error::add_error(
864
+				esc_html__('Venue Details did not save successfully.', 'event_espresso'),
865
+				__FILE__,
866
+				__FUNCTION__,
867
+				__LINE__
868
+			);
869
+		}
870
+	}
871
+
872
+
873
+	/**
874
+	 * @param int $post_id
875
+	 * @throws EE_Error
876
+	 * @throws ReflectionException
877
+	 */
878
+	public function trash_cpt_item($post_id)
879
+	{
880
+		$this->request->setRequestParam('VNU_ID', $post_id);
881
+		$this->_trash_or_restore_venue('trash', false);
882
+	}
883
+
884
+
885
+	/**
886
+	 * @param int $post_id
887
+	 * @throws EE_Error
888
+	 * @throws ReflectionException
889
+	 */
890
+	public function restore_cpt_item($post_id)
891
+	{
892
+		$this->request->setRequestParam('VNU_ID', $post_id);
893
+		$this->_trash_or_restore_venue('draft', false);
894
+	}
895
+
896
+
897
+	/**
898
+	 * @param int $post_id
899
+	 * @throws EE_Error
900
+	 * @throws ReflectionException
901
+	 */
902
+	public function delete_cpt_item($post_id)
903
+	{
904
+		$this->request->setRequestParam('VNU_ID', $post_id);
905
+		$this->_delete_venue(false);
906
+	}
907
+
908
+
909
+	public function get_venue_object()
910
+	{
911
+		return $this->_cpt_model_obj;
912
+	}
913
+
914
+
915
+	/**
916
+	 * @param string    $venue_status
917
+	 * @param bool|null $redirect_after
918
+	 * @throws EE_Error
919
+	 * @throws ReflectionException
920
+	 */
921
+	protected function _trash_or_restore_venue(string $venue_status = 'trash', ?bool $redirect_after = true)
922
+	{
923
+		// loop thru venues
924
+		if ($this->VNU_ID) {
925
+			// clean status
926
+			$venue_status = sanitize_key($venue_status);
927
+			// grab status
928
+			if (! empty($venue_status)) {
929
+				$success = $this->_change_venue_status($this->VNU_ID, $venue_status);
930
+			} else {
931
+				$success = false;
932
+				$msg     = esc_html__(
933
+					'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
934
+					'event_espresso'
935
+				);
936
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
937
+			}
938
+		} else {
939
+			$success = false;
940
+			$msg     = esc_html__(
941
+				'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
942
+				'event_espresso'
943
+			);
944
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
945
+		}
946
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
947
+
948
+		if ($redirect_after) {
949
+			$this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
950
+		}
951
+	}
952
+
953
+
954
+	/**
955
+	 * @param string $venue_status
956
+	 * @throws EE_Error
957
+	 * @throws ReflectionException
958
+	 */
959
+	protected function _trash_or_restore_venues(string $venue_status = 'trash')
960
+	{
961
+		// clean status
962
+		$venue_status = sanitize_key($venue_status);
963
+		// grab status
964
+		if (! empty($venue_status)) {
965
+			$success = true;
966
+			// determine the event id and set to array.
967
+			$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
968
+			// loop thru events
969
+			foreach ($VNU_IDs as $VNU_ID) {
970
+				if ($VNU_ID = absint($VNU_ID)) {
971
+					$results = $this->_change_venue_status($VNU_ID, $venue_status);
972
+					$success = $results !== false ? $success : false;
973
+				} else {
974
+					$msg = sprintf(
975
+						esc_html__(
976
+							'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
977
+							'event_espresso'
978
+						),
979
+						$VNU_ID
980
+					);
981
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
982
+					$success = false;
983
+				}
984
+			}
985
+		} else {
986
+			$success = false;
987
+			$msg     = esc_html__(
988
+				'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
989
+				'event_espresso'
990
+			);
991
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
992
+		}
993
+		// in order to force a pluralized result message we need to send back a success status greater than 1
994
+		$success = $success ? 2 : false;
995
+		$action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
996
+		$this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
997
+	}
998
+
999
+
1000
+	/**
1001
+	 * _trash_or_restore_venues
1002
+	 * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1003
+	 * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1004
+	 * accepting a certain number of params.
1005
+	 *
1006
+	 * @param int|null $VNU_ID
1007
+	 * @param string   $venue_status
1008
+	 * @return bool
1009
+	 * @throws EE_Error
1010
+	 * @throws ReflectionException
1011
+	 */
1012
+	private function _change_venue_status(?int $VNU_ID = 0, string $venue_status = ''): bool
1013
+	{
1014
+		// grab venue id
1015
+		if (! $VNU_ID) {
1016
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1017
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1018
+			return false;
1019
+		}
1020
+
1021
+		$this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1022
+
1023
+		// clean status
1024
+		$venue_status = sanitize_key($venue_status);
1025
+		// grab status
1026
+		if (! $venue_status) {
1027
+			$msg = esc_html__(
1028
+				'An error occurred. No Venue Status or an invalid Venue Status was received.',
1029
+				'event_espresso'
1030
+			);
1031
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1032
+			return false;
1033
+		}
1034
+
1035
+		// was event trashed or restored ?
1036
+		switch ($venue_status) {
1037
+			case 'draft':
1038
+				$action = 'restored from the trash';
1039
+				$hook   = 'AHEE_venue_restored_from_trash';
1040
+				break;
1041
+			case 'trash':
1042
+				$action = 'moved to the trash';
1043
+				$hook   = 'AHEE_venue_moved_to_trash';
1044
+				break;
1045
+			default:
1046
+				$action = 'updated';
1047
+				$hook   = false;
1048
+		}
1049
+		// use class to change status
1050
+		$this->_cpt_model_obj->set_status($venue_status);
1051
+		$success = $this->_cpt_model_obj->save();
1052
+
1053
+		if ($success === false) {
1054
+			$msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1055
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1056
+			return false;
1057
+		}
1058
+		if ($hook) {
1059
+			do_action($hook);
1060
+		}
1061
+		return true;
1062
+	}
1063
+
1064
+
1065
+	/**
1066
+	 * @param bool $redirect_after
1067
+	 * @return void
1068
+	 * @throws EE_Error
1069
+	 * @throws ReflectionException
1070
+	 */
1071
+	protected function _delete_venue(bool $redirect_after = true)
1072
+	{
1073
+		// loop thru venues
1074
+		if ($this->VNU_ID) {
1075
+			$success = $this->_delete_or_trash_venue($this->VNU_ID);
1076
+		} else {
1077
+			$success = false;
1078
+			$msg     = esc_html__(
1079
+				'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1080
+				'event_espresso'
1081
+			);
1082
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1083
+		}
1084
+		if ($redirect_after) {
1085
+			$this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1086
+		}
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * @throws EE_Error
1092
+	 * @throws ReflectionException
1093
+	 */
1094
+	protected function _delete_venues()
1095
+	{
1096
+		$success = true;
1097
+		// determine the event id and set to array.
1098
+		$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1099
+		// loop thru events
1100
+		foreach ($VNU_IDs as $VNU_ID) {
1101
+			if ($VNU_ID = absint($VNU_ID)) {
1102
+				$results = $this->_delete_or_trash_venue($VNU_ID);
1103
+				$success = $results !== false ? $success : false;
1104
+			} else {
1105
+				$success = false;
1106
+				$msg     = esc_html__(
1107
+					'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1108
+					'event_espresso'
1109
+				);
1110
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1111
+			}
1112
+		}
1113
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1114
+		$success = $success ? 2 : false;
1115
+		$this->_redirect_after_action(
1116
+			$success,
1117
+			esc_html__('Venues', 'event_espresso'),
1118
+			esc_html__('deleted', 'event_espresso'),
1119
+			['action' => 'default']
1120
+		);
1121
+	}
1122
+
1123
+
1124
+	// todo: put in parent
1125
+
1126
+
1127
+	/**
1128
+	 * @param int|null $VNU_ID
1129
+	 * @return bool
1130
+	 * @throws EE_Error
1131
+	 * @throws ReflectionException
1132
+	 */
1133
+	private function _delete_or_trash_venue(?int $VNU_ID = 0): bool
1134
+	{
1135
+		// grab event id
1136
+		if (! $VNU_ID = absint($VNU_ID)) {
1137
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1138
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1139
+			return false;
1140
+		}
1141
+
1142
+
1143
+		$venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1144
+		// first need to remove all term relationships
1145
+		$venue->_remove_relations('Term_Taxonomy');
1146
+		$success = $venue->delete_permanently();
1147
+		// did it all go as planned ?
1148
+		if (! $success) {
1149
+			EE_Error::add_error(
1150
+				sprintf(
1151
+					esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1152
+					$VNU_ID
1153
+				),
1154
+				__FILE__,
1155
+				__FUNCTION__,
1156
+				__LINE__
1157
+			);
1158
+			return false;
1159
+		}
1160
+		EE_Error::add_success(
1161
+			sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID)
1162
+		);
1163
+		do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1164
+		return true;
1165
+	}
1166
+
1167
+
1168
+
1169
+
1170
+	/***********/
1171
+	/* QUERIES */
1172
+
1173
+
1174
+	/**
1175
+	 * @throws EE_Error
1176
+	 * @throws ReflectionException
1177
+	 */
1178
+	public function get_venues($per_page = 10, $count = false)
1179
+	{
1180
+		$orderby = $this->request->getRequestParam('orderby', '');
1181
+
1182
+		switch ($orderby) {
1183
+			case 'id':
1184
+				$orderby = 'VNU_ID';
1185
+				break;
1186
+
1187
+			case 'capacity':
1188
+				$orderby = 'VNU_capacity';
1189
+				break;
1190
+
1191
+			case 'city':
1192
+				$orderby = 'VNU_city';
1193
+				break;
1194
+
1195
+			default:
1196
+				$orderby = 'VNU_name';
1197
+		}
1198
+
1199
+		$sort         = $this->request->getRequestParam('order', 'ASC');
1200
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1201
+		$per_page     = ! empty($per_page) ? $per_page : 10;
1202
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1203
+
1204
+		$offset = ($current_page - 1) * $per_page;
1205
+		$limit  = [$offset, $per_page];
1206
+
1207
+		$category = $this->request->getRequestParam('category');
1208
+		$category = $category > 0 ? $category : null;
1209
+
1210
+		$where = [];
1211
+
1212
+		// only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1213
+		$status = $this->request->getRequestParam('status');
1214
+		if ($status && $status !== 'all') {
1215
+			$where['status'] = $status;
1216
+		}
1217
+
1218
+		$venue_status = $this->request->getRequestParam('venue_status');
1219
+		if ($venue_status) {
1220
+			$where['status'] = $venue_status;
1221
+		}
1222
+
1223
+
1224
+		if ($category) {
1225
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1226
+			$where['Term_Taxonomy.term_id']  = $category;
1227
+		}
1228
+
1229
+
1230
+		if (! $this->capabilities->current_user_can('ee_read_others_venues', 'get_venues')) {
1231
+			$where['VNU_wp_user'] = get_current_user_id();
1232
+		} else {
1233
+			if (! $this->capabilities->current_user_can('ee_read_private_venues', 'get_venues')) {
1234
+				$where['OR'] = [
1235
+					'status*restrict_private' => ['!=', 'private'],
1236
+					'AND'                     => [
1237
+						'status*inclusive' => ['=', 'private'],
1238
+						'VNU_wp_user'      => get_current_user_id(),
1239
+					],
1240
+				];
1241
+			}
1242
+		}
1243
+
1244
+		$search_term = $this->request->getRequestParam('s');
1245
+		if ($search_term) {
1246
+			$search_term = '%' . $search_term . '%';
1247
+			$where['OR'] = [
1248
+				'VNU_name'               => ['LIKE', $search_term],
1249
+				'VNU_desc'               => ['LIKE', $search_term],
1250
+				'VNU_short_desc'         => ['LIKE', $search_term],
1251
+				'VNU_address'            => ['LIKE', $search_term],
1252
+				'VNU_address2'           => ['LIKE', $search_term],
1253
+				'VNU_city'               => ['LIKE', $search_term],
1254
+				'VNU_zip'                => ['LIKE', $search_term],
1255
+				'VNU_phone'              => ['LIKE', $search_term],
1256
+				'VNU_url'                => ['LIKE', $search_term],
1257
+				'VNU_virtual_phone'      => ['LIKE', $search_term],
1258
+				'VNU_virtual_url'        => ['LIKE', $search_term],
1259
+				'VNU_google_map_link'    => ['LIKE', $search_term],
1260
+				'Event.EVT_name'         => ['LIKE', $search_term],
1261
+				'Event.EVT_desc'         => ['LIKE', $search_term],
1262
+				'Event.EVT_phone'        => ['LIKE', $search_term],
1263
+				'Event.EVT_external_URL' => ['LIKE', $search_term],
1264
+			];
1265
+		}
1266
+
1267
+
1268
+		return $count
1269
+			? $this->_venue_model->count([$where], 'VNU_ID')
1270
+			: $this->_venue_model->get_all(
1271
+				[$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1272
+			);
1273
+	}
1274
+
1275
+
1276
+
1277
+
1278
+	/** Venue Category Stuff **/
1279
+
1280
+	/**
1281
+	 * set the _category property with the category object for the loaded page.
1282
+	 *
1283
+	 * @access private
1284
+	 * @return void
1285
+	 */
1286
+	private function _set_category_object()
1287
+	{
1288
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
1289
+			return;
1290
+		} // already have the category object so get out.
1291
+
1292
+		// set default category object
1293
+		$this->_set_empty_category_object();
1294
+
1295
+		// only set if we've got an id
1296
+		$category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1297
+		if (! $category_ID) {
1298
+			return;
1299
+		}
1300
+
1301
+		$term = get_term($category_ID, 'espresso_venue_categories');
1302
+
1303
+
1304
+		if (! empty($term)) {
1305
+			$this->_category->category_name       = $term->name;
1306
+			$this->_category->category_identifier = $term->slug;
1307
+			$this->_category->category_desc       = $term->description;
1308
+			$this->_category->id                  = $term->term_id;
1309
+			$this->_category->parent              = $term->parent;
1310
+		}
1311
+	}
1312
+
1313
+
1314
+	private function _set_empty_category_object()
1315
+	{
1316
+		$this->_category                = new stdClass();
1317
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1318
+		$this->_category->id            = $this->_category->parent = 0;
1319
+	}
1320
+
1321
+
1322
+	/**
1323
+	 * @throws EE_Error
1324
+	 */
1325
+	protected function _category_list_table()
1326
+	{
1327
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1328
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1329
+				'add_category',
1330
+				'add_category',
1331
+				[],
1332
+				'add-new-h2'
1333
+			);
1334
+		$this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1335
+		$this->display_admin_list_table_page_with_sidebar();
1336
+	}
1337
+
1338
+
1339
+	/**
1340
+	 * @throws EE_Error
1341
+	 */
1342
+	protected function _category_details($view)
1343
+	{
1344
+		// load formatter helper
1345
+		// load field generator helper
1346
+
1347
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
1348
+		$this->_set_add_edit_form_tags($route);
1349
+
1350
+		$this->_set_category_object();
1351
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
1352
+
1353
+		$delete_action = 'delete_category';
1354
+
1355
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1356
+
1357
+		$this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1358
+
1359
+		// take care of contents
1360
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
1361
+		$this->display_admin_page_with_sidebar();
1362
+	}
1363
+
1364
+
1365
+	protected function _category_details_content(): string
1366
+	{
1367
+		$editor_args['category_desc'] = [
1368
+			'type'          => 'wp_editor',
1369
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1370
+			'class'         => 'my_editor_custom',
1371
+			'wpeditor_args' => ['media_buttons' => false],
1372
+		];
1373
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1374
+
1375
+		$all_terms = get_terms(
1376
+			['espresso_venue_categories'],
1377
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1378
+		);
1379
+
1380
+		// setup category select for term parents.
1381
+		$category_select_values[] = [
1382
+			'text' => esc_html__('No Parent', 'event_espresso'),
1383
+			'id'   => 0,
1384
+		];
1385
+		foreach ($all_terms as $term) {
1386
+			$category_select_values[] = [
1387
+				'text' => $term->name,
1388
+				'id'   => $term->term_id,
1389
+			];
1390
+		}
1391
+
1392
+		$category_select = EEH_Form_Fields::select_input(
1393
+			'category_parent',
1394
+			$category_select_values,
1395
+			$this->_category->parent
1396
+		);
1397
+		$template_args   = [
1398
+			'category'                 => $this->_category,
1399
+			'category_select'          => $category_select,
1400
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1401
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1402
+			'disable'                  => '',
1403
+			'disabled_message'         => false,
1404
+		];
1405
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1406
+		return EEH_Template::display_template($template, $template_args, true);
1407
+	}
1408
+
1409
+
1410
+	/**
1411
+	 * @throws EE_Error
1412
+	 */
1413
+	protected function _delete_categories()
1414
+	{
1415
+		$category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1416
+		$category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1417
+
1418
+		foreach ($category_IDs as $cat_id) {
1419
+			$this->_delete_category($cat_id);
1420
+		}
1421
+
1422
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
1423
+		$query_args = [
1424
+			'action' => 'category_list',
1425
+		];
1426
+		$this->_redirect_after_action(0, '', '', $query_args);
1427
+	}
1428
+
1429
+
1430
+	protected function _delete_category($cat_id)
1431
+	{
1432
+		$cat_id = absint($cat_id);
1433
+		wp_delete_term($cat_id, 'espresso_venue_categories');
1434
+	}
1435
+
1436
+
1437
+	/**
1438
+	 * @throws EE_Error
1439
+	 */
1440
+	protected function _insert_or_update_category($new_category)
1441
+	{
1442
+		$cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1443
+		$success = 0; // we already have a success message so lets not send another.
1444
+		if ($cat_id) {
1445
+			$query_args = [
1446
+				'action'     => 'edit_category',
1447
+				'VEN_CAT_ID' => $cat_id,
1448
+			];
1449
+		} else {
1450
+			$query_args = ['action' => 'add_category'];
1451
+		}
1452
+		$this->_redirect_after_action($success, '', '', $query_args, true);
1453
+	}
1454
+
1455
+
1456
+	private function _insert_category($update = false)
1457
+	{
1458
+		$category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1459
+		$category_name   = $this->request->getRequestParam('category_name', '');
1460
+		$category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1461
+		$category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1462
+
1463
+		if (empty($category_name)) {
1464
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
1465
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1466
+			return false;
1467
+		}
1468
+
1469
+
1470
+		$term_args = [
1471
+			'name'        => $category_name,
1472
+			'description' => $category_desc,
1473
+			'parent'      => $category_parent,
1474
+		];
1475
+
1476
+		$insert_ids = $update
1477
+			? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1478
+			: wp_insert_term(
1479
+				$category_name,
1480
+				'espresso_venue_categories',
1481
+				$term_args
1482
+			);
1483
+
1484
+		if (! is_array($insert_ids)) {
1485
+			EE_Error::add_error(
1486
+				esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1487
+				__FILE__,
1488
+				__FUNCTION__,
1489
+				__LINE__
1490
+			);
1491
+		} else {
1492
+			$category_ID = $insert_ids['term_id'];
1493
+			EE_Error::add_success(
1494
+				sprintf(
1495
+					esc_html__('The category %s was successfully created', 'event_espresso'),
1496
+					$category_name
1497
+				)
1498
+			);
1499
+		}
1500
+
1501
+		return $category_ID;
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * TODO handle category exports()
1507
+	 *
1508
+	 * @return void
1509
+	 */
1510
+	protected function _categories_export()
1511
+	{
1512
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
1513
+		$this->request->mergeRequestParams(
1514
+			[
1515
+				'export'       => 'report',
1516
+				'action'       => 'categories',
1517
+				'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1518
+			]
1519
+		);
1520
+
1521
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1522
+			require_once(EE_CLASSES . 'EE_Export.class.php');
1523
+			$EE_Export = EE_Export::instance($this->request->requestParams());
1524
+			$EE_Export->export();
1525
+		}
1526
+	}
1527
+
1528
+
1529
+	protected function _import_categories()
1530
+	{
1531
+		require_once(EE_CLASSES . 'EE_Import.class.php');
1532
+		EE_Import::instance()->import();
1533
+	}
1534
+
1535
+
1536
+	/**
1537
+	 * @throws EE_Error
1538
+	 * @throws ReflectionException
1539
+	 */
1540
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
1541
+	{
1542
+		// testing term stuff
1543
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1544
+		$order       = $this->request->getRequestParam('order', 'DESC');
1545
+		$limit       = ($current_page - 1) * $per_page;
1546
+		$where       = ['taxonomy' => 'espresso_venue_categories'];
1547
+		$search_term = $this->request->getRequestParam('s');
1548
+		if ($search_term) {
1549
+			$search_term = '%' . $search_term . '%';
1550
+			$where['OR'] = [
1551
+				'Term.name'   => ['LIKE', $search_term],
1552
+				'description' => ['LIKE', $search_term],
1553
+			];
1554
+		}
1555
+
1556
+		$query_params = [
1557
+			$where,
1558
+			'order_by'   => [$orderby => $order],
1559
+			'limit'      => $limit . ',' . $per_page,
1560
+			'force_join' => ['Term'],
1561
+		];
1562
+
1563
+		return $count
1564
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1565
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
1566
+	}
1567
+
1568
+
1569
+	/* end category stuff */
1570
+	/**************/
1571 1571
 }
Please login to merge, or discard this patch.