Completed
Branch master (16095c)
by
unknown
09:17 queued 04:49
created
caffeinated/core/services/licensing/UserExperienceForm.php 1 patch
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -16,130 +16,130 @@
 block discarded – undo
16 16
 
17 17
 class UserExperienceForm
18 18
 {
19
-    /**
20
-     * @var EE_Core_Config
21
-     */
22
-    protected $core_config;
19
+	/**
20
+	 * @var EE_Core_Config
21
+	 */
22
+	protected $core_config;
23 23
 
24
-    /**
25
-     * @var EE_Network_Core_Config
26
-     */
27
-    protected $network_core_config;
24
+	/**
25
+	 * @var EE_Network_Core_Config
26
+	 */
27
+	protected $network_core_config;
28 28
 
29 29
 
30
-    /**
31
-     * @param EE_Core_Config         $core_config
32
-     * @param EE_Network_Core_Config $network_core_config
33
-     */
34
-    public function __construct(EE_Core_Config $core_config, EE_Network_Core_Config $network_core_config)
35
-    {
36
-        $this->core_config         = $core_config;
37
-        $this->network_core_config = $network_core_config;
38
-    }
30
+	/**
31
+	 * @param EE_Core_Config         $core_config
32
+	 * @param EE_Network_Core_Config $network_core_config
33
+	 */
34
+	public function __construct(EE_Core_Config $core_config, EE_Network_Core_Config $network_core_config)
35
+	{
36
+		$this->core_config         = $core_config;
37
+		$this->network_core_config = $network_core_config;
38
+	}
39 39
 
40 40
 
41
-    /**
42
-     * @throws EE_Error
43
-     */
44
-    public function uxipFormSections(EE_Form_Section_Proper $org_settings_form): EE_Form_Section_Proper
45
-    {
46
-        if (is_main_site()) {
47
-            $org_settings_form->add_subsections(
48
-                [
49
-                    'site_license_key_hdr' => new EE_Form_Section_HTML(
50
-                        EEH_HTML::h2(
51
-                            esc_html__('Your Event Espresso License Key', 'event_espresso')
52
-                            . ' '
53
-                            . EEH_HTML::span(
54
-                                EEH_Template::get_help_tab_link('site_license_key_info')
55
-                            ),
56
-                            '',
57
-                            'site-license-key-hdr'
58
-                        )
59
-                    ),
60
-                    'site_license_key'     => new EE_Text_Input(
61
-                        [
62
-                            'html_name'        => 'ee_site_license_key',
63
-                            'html_id'          => 'site_license_key',
64
-                            'html_label_text'  => esc_html__('Support License Key', 'event_espresso'),
65
-                            /** phpcs:disable WordPress.WP.I18n.UnorderedPlaceholdersText */
66
-                            'html_help_text'   => sprintf(
67
-                                esc_html__(
68
-                                    'Adding a valid Support License Key will enable automatic update notifications and backend updates for Event Espresso Core and any installed add-ons. If this is a Development or Test site, %sDO NOT%s enter your Support License Key.',
69
-                                    'event_espresso'
70
-                                ),
71
-                                '<strong>',
72
-                                '</strong>'
73
-                            ),
74
-                            /** phpcs:enable */
75
-                            'default'          => $this->network_core_config->site_license_key ?? '',
76
-                            'required'         => false,
77
-                            'form_html_filter' => new VsprintfFilter(
78
-                                '%1$s %4$s %2$s %3$s',
79
-                                ['<div class="ee-layout-row--fixed">', $this->getValidationIndicator(), '</div>']
80
-                            )
81
-                        ]
82
-                    )
83
-                ]
84
-            );
85
-            $org_settings_form->add_subsections(
86
-                [
87
-                    'uxip_optin_hdr' => new EE_Form_Section_HTML(Stats::optinText(false)),
88
-                    'uxip_optin' => new EE_Checkbox_Multi_Input(
89
-                        [
90
-                            true => esc_html__('Yes! I want to help improve Event Espresso!', 'event_espresso'),
91
-                        ],
92
-                        [
93
-                            'html_name'       => EE_Core_Config::OPTION_NAME_UXIP,
94
-                            'html_label_text' => esc_html__(
95
-                                'UXIP Opt In?',
96
-                                'event_espresso'
97
-                            ),
98
-                            'default'         => isset($this->core_config->ee_ueip_optin)
99
-                                ? filter_var($this->core_config->ee_ueip_optin, FILTER_VALIDATE_BOOLEAN)
100
-                                : false,
101
-                            'required'        => false,
102
-                            'label_size'      => 100,
103
-                        ]
104
-                    ),
105
-                ],
106
-                'organization_instagram',
107
-                false
108
-            );
109
-        }
110
-        return $org_settings_form;
111
-    }
41
+	/**
42
+	 * @throws EE_Error
43
+	 */
44
+	public function uxipFormSections(EE_Form_Section_Proper $org_settings_form): EE_Form_Section_Proper
45
+	{
46
+		if (is_main_site()) {
47
+			$org_settings_form->add_subsections(
48
+				[
49
+					'site_license_key_hdr' => new EE_Form_Section_HTML(
50
+						EEH_HTML::h2(
51
+							esc_html__('Your Event Espresso License Key', 'event_espresso')
52
+							. ' '
53
+							. EEH_HTML::span(
54
+								EEH_Template::get_help_tab_link('site_license_key_info')
55
+							),
56
+							'',
57
+							'site-license-key-hdr'
58
+						)
59
+					),
60
+					'site_license_key'     => new EE_Text_Input(
61
+						[
62
+							'html_name'        => 'ee_site_license_key',
63
+							'html_id'          => 'site_license_key',
64
+							'html_label_text'  => esc_html__('Support License Key', 'event_espresso'),
65
+							/** phpcs:disable WordPress.WP.I18n.UnorderedPlaceholdersText */
66
+							'html_help_text'   => sprintf(
67
+								esc_html__(
68
+									'Adding a valid Support License Key will enable automatic update notifications and backend updates for Event Espresso Core and any installed add-ons. If this is a Development or Test site, %sDO NOT%s enter your Support License Key.',
69
+									'event_espresso'
70
+								),
71
+								'<strong>',
72
+								'</strong>'
73
+							),
74
+							/** phpcs:enable */
75
+							'default'          => $this->network_core_config->site_license_key ?? '',
76
+							'required'         => false,
77
+							'form_html_filter' => new VsprintfFilter(
78
+								'%1$s %4$s %2$s %3$s',
79
+								['<div class="ee-layout-row--fixed">', $this->getValidationIndicator(), '</div>']
80
+							)
81
+						]
82
+					)
83
+				]
84
+			);
85
+			$org_settings_form->add_subsections(
86
+				[
87
+					'uxip_optin_hdr' => new EE_Form_Section_HTML(Stats::optinText(false)),
88
+					'uxip_optin' => new EE_Checkbox_Multi_Input(
89
+						[
90
+							true => esc_html__('Yes! I want to help improve Event Espresso!', 'event_espresso'),
91
+						],
92
+						[
93
+							'html_name'       => EE_Core_Config::OPTION_NAME_UXIP,
94
+							'html_label_text' => esc_html__(
95
+								'UXIP Opt In?',
96
+								'event_espresso'
97
+							),
98
+							'default'         => isset($this->core_config->ee_ueip_optin)
99
+								? filter_var($this->core_config->ee_ueip_optin, FILTER_VALIDATE_BOOLEAN)
100
+								: false,
101
+							'required'        => false,
102
+							'label_size'      => 100,
103
+						]
104
+					),
105
+				],
106
+				'organization_instagram',
107
+				false
108
+			);
109
+		}
110
+		return $org_settings_form;
111
+	}
112 112
 
113 113
 
114 114
 
115
-    /**
116
-     * Return whether the site license key has been verified or not.
117
-     *
118
-     * @return bool
119
-     */
120
-    private function licenseKeyVerified(): bool
121
-    {
122
-        if (empty($this->network_core_config->site_license_key)) {
123
-            return false;
124
-        }
125
-        $verify_fail = get_option(
126
-            'puvererr_' . basename(EE_PLUGIN_BASENAME),
127
-            false
128
-        );
129
-        return $verify_fail === false
130
-               || (
131
-                   ! empty($this->network_core_config->site_license_key)
132
-                   && $verify_fail === false
133
-               );
134
-    }
115
+	/**
116
+	 * Return whether the site license key has been verified or not.
117
+	 *
118
+	 * @return bool
119
+	 */
120
+	private function licenseKeyVerified(): bool
121
+	{
122
+		if (empty($this->network_core_config->site_license_key)) {
123
+			return false;
124
+		}
125
+		$verify_fail = get_option(
126
+			'puvererr_' . basename(EE_PLUGIN_BASENAME),
127
+			false
128
+		);
129
+		return $verify_fail === false
130
+			   || (
131
+				   ! empty($this->network_core_config->site_license_key)
132
+				   && $verify_fail === false
133
+			   );
134
+	}
135 135
 
136 136
 
137
-    /**
138
-     * @return string
139
-     */
140
-    private function getValidationIndicator(): string
141
-    {
142
-        $verified_class = $this->licenseKeyVerified() ? 'ee-status--success' : 'ee-status--error';
143
-        return '<span class="dashicons dashicons-admin-network ' . $verified_class . '"></span>';
144
-    }
137
+	/**
138
+	 * @return string
139
+	 */
140
+	private function getValidationIndicator(): string
141
+	{
142
+		$verified_class = $this->licenseKeyVerified() ? 'ee-status--success' : 'ee-status--error';
143
+		return '<span class="dashicons dashicons-admin-network ' . $verified_class . '"></span>';
144
+	}
145 145
 }
Please login to merge, or discard this patch.
PaymentMethods/PayPalCommerce/tools/logging/PayPalLogger.php 1 patch
Indentation   +124 added lines, -124 removed lines patch added patch discarded remove patch
@@ -19,117 +19,117 @@  discard block
 block discarded – undo
19 19
  */
20 20
 class PayPalLogger
21 21
 {
22
-    /**
23
-     * Log an error, return a json message and maybe exit.
24
-     *
25
-     * @param string                 $error_message
26
-     * @param array                  $data
27
-     * @param EE_Payment_Method|null $paypal_pm
28
-     * @param bool                   $return_json Should we echo json and exit
29
-     * @param bool                   $popup_log
30
-     * @param bool                   $show_alert  Show an alert on the front end or not
31
-     * @return void
32
-     * @throws EE_Error
33
-     */
34
-    public static function errorLogAndExit(
35
-        string $error_message = '',
36
-        array $data = [],
37
-        ?EE_Payment_Method $paypal_pm = null,
38
-        bool $return_json = true,
39
-        bool $popup_log = false,
40
-        bool $show_alert = false
41
-    ) {
42
-        self::errorLog($error_message, $data, $paypal_pm, $popup_log);
43
-        // Do we echo json and exit ?
44
-        if ($return_json) {
45
-            EED_PayPalOnboard::exitWithError($error_message, $show_alert);
46
-        }
47
-        if ($popup_log) {
48
-            self::logInWindow($error_message);
49
-        }
50
-        self::closeWindowAndExit();
51
-    }
22
+	/**
23
+	 * Log an error, return a json message and maybe exit.
24
+	 *
25
+	 * @param string                 $error_message
26
+	 * @param array                  $data
27
+	 * @param EE_Payment_Method|null $paypal_pm
28
+	 * @param bool                   $return_json Should we echo json and exit
29
+	 * @param bool                   $popup_log
30
+	 * @param bool                   $show_alert  Show an alert on the front end or not
31
+	 * @return void
32
+	 * @throws EE_Error
33
+	 */
34
+	public static function errorLogAndExit(
35
+		string $error_message = '',
36
+		array $data = [],
37
+		?EE_Payment_Method $paypal_pm = null,
38
+		bool $return_json = true,
39
+		bool $popup_log = false,
40
+		bool $show_alert = false
41
+	) {
42
+		self::errorLog($error_message, $data, $paypal_pm, $popup_log);
43
+		// Do we echo json and exit ?
44
+		if ($return_json) {
45
+			EED_PayPalOnboard::exitWithError($error_message, $show_alert);
46
+		}
47
+		if ($popup_log) {
48
+			self::logInWindow($error_message);
49
+		}
50
+		self::closeWindowAndExit();
51
+	}
52 52
 
53 53
 
54
-    /**
55
-     * Log an error, return a json message.
56
-     *
57
-     * @param string                 $error_message
58
-     * @param array                  $data
59
-     * @param EE_Payment_Method|null $paypal_pm
60
-     * @param bool                   $popup_log
61
-     * @return bool
62
-     * @throws EE_Error|ReflectionException
63
-     */
64
-    public static function errorLog(
65
-        string $error_message = '',
66
-        array $data = [],
67
-        ?EE_Payment_Method $paypal_pm = null,
68
-        bool $popup_log = false
69
-    ): bool {
70
-        $default_msg = 'PayPal Commerce error';
71
-        if ($data) {
72
-            $data        = self::cleanDataArray($data);
73
-            $default_msg = $error_message;
74
-        }
75
-        if (! $paypal_pm instanceof EE_Payment_Method) {
76
-            // Default to the standard PP Commerce PM.
77
-            $paypal_pm = EEM_Payment_Method::instance()->get_one_by_slug(Domain::PM_SLUG);
78
-        }
79
-        $paypal_gateway = $paypal_pm->type_obj()->get_gateway();
80
-        if ($paypal_gateway instanceof EE_Gateway) {
81
-            $paypal_gateway->log([$default_msg => $data], $paypal_pm);
82
-        }
83
-        if ($popup_log) {
84
-            self::logInWindow(json_encode($data));
85
-        }
86
-        // Yes, always return true.
87
-        return true;
88
-    }
54
+	/**
55
+	 * Log an error, return a json message.
56
+	 *
57
+	 * @param string                 $error_message
58
+	 * @param array                  $data
59
+	 * @param EE_Payment_Method|null $paypal_pm
60
+	 * @param bool                   $popup_log
61
+	 * @return bool
62
+	 * @throws EE_Error|ReflectionException
63
+	 */
64
+	public static function errorLog(
65
+		string $error_message = '',
66
+		array $data = [],
67
+		?EE_Payment_Method $paypal_pm = null,
68
+		bool $popup_log = false
69
+	): bool {
70
+		$default_msg = 'PayPal Commerce error';
71
+		if ($data) {
72
+			$data        = self::cleanDataArray($data);
73
+			$default_msg = $error_message;
74
+		}
75
+		if (! $paypal_pm instanceof EE_Payment_Method) {
76
+			// Default to the standard PP Commerce PM.
77
+			$paypal_pm = EEM_Payment_Method::instance()->get_one_by_slug(Domain::PM_SLUG);
78
+		}
79
+		$paypal_gateway = $paypal_pm->type_obj()->get_gateway();
80
+		if ($paypal_gateway instanceof EE_Gateway) {
81
+			$paypal_gateway->log([$default_msg => $data], $paypal_pm);
82
+		}
83
+		if ($popup_log) {
84
+			self::logInWindow(json_encode($data));
85
+		}
86
+		// Yes, always return true.
87
+		return true;
88
+	}
89 89
 
90 90
 
91
-    /**
92
-     * Clean the array of data from sensitive information.
93
-     *
94
-     * @param array $data
95
-     * @return array
96
-     */
97
-    private static function cleanDataArray(array $data): array
98
-    {
99
-        $sensitive_data = [
100
-            'access_token',
101
-            'refresh_token',
102
-            'nonce',
103
-            'seller_nonce',
104
-            'client_secret',
105
-            Domain::API_KEY_AUTH_CODE,
106
-            'Authorization',
107
-        ];
108
-        foreach ($data as $key => $value) {
109
-            if (is_string($value)) {
110
-                // Json encoded ?
111
-                $value = json_decode($value) ?? $value;
112
-            }
113
-            $value = is_array($value) ? self::cleanDataArray($value) : $value;
114
-            if (is_string($key) && in_array($key, $sensitive_data)) {
115
-                $data[ $key ] = empty($value) ? '**empty**' : '**hidden**';
116
-            } else {
117
-                $data[ $key ] = $value;
118
-            }
119
-        }
120
-        return $data;
121
-    }
91
+	/**
92
+	 * Clean the array of data from sensitive information.
93
+	 *
94
+	 * @param array $data
95
+	 * @return array
96
+	 */
97
+	private static function cleanDataArray(array $data): array
98
+	{
99
+		$sensitive_data = [
100
+			'access_token',
101
+			'refresh_token',
102
+			'nonce',
103
+			'seller_nonce',
104
+			'client_secret',
105
+			Domain::API_KEY_AUTH_CODE,
106
+			'Authorization',
107
+		];
108
+		foreach ($data as $key => $value) {
109
+			if (is_string($value)) {
110
+				// Json encoded ?
111
+				$value = json_decode($value) ?? $value;
112
+			}
113
+			$value = is_array($value) ? self::cleanDataArray($value) : $value;
114
+			if (is_string($key) && in_array($key, $sensitive_data)) {
115
+				$data[ $key ] = empty($value) ? '**empty**' : '**hidden**';
116
+			} else {
117
+				$data[ $key ] = $value;
118
+			}
119
+		}
120
+		return $data;
121
+	}
122 122
 
123 123
 
124
-    /**
125
-     * Close the OAuth window with JS.
126
-     *
127
-     * @param string $message
128
-     * @return void
129
-     */
130
-    public static function logInWindow(string $message)
131
-    {
132
-        $js_out = '<script type="text/javascript">
124
+	/**
125
+	 * Close the OAuth window with JS.
126
+	 *
127
+	 * @param string $message
128
+	 * @return void
129
+	 */
130
+	public static function logInWindow(string $message)
131
+	{
132
+		$js_out = '<script type="text/javascript">
133 133
                 if (window.opener) {
134 134
                     try {
135 135
                         window.opener.console.log("' . $message . '");
@@ -138,22 +138,22 @@  discard block
 block discarded – undo
138 138
                     }
139 139
                 }
140 140
             </script>';
141
-        echo $js_out;
142
-        exit();
143
-    }
141
+		echo $js_out;
142
+		exit();
143
+	}
144 144
 
145 145
 
146
-    /**
147
-     * Close the JS opened auth window.
148
-     *
149
-     * @param string $message
150
-     * @return void
151
-     */
152
-    public static function closeWindowAndExit(string $message = '')
153
-    {
154
-        $js_out = '<script type="text/javascript">';
155
-        if (! empty($message)) {
156
-            $js_out .= '
146
+	/**
147
+	 * Close the JS opened auth window.
148
+	 *
149
+	 * @param string $message
150
+	 * @return void
151
+	 */
152
+	public static function closeWindowAndExit(string $message = '')
153
+	{
154
+		$js_out = '<script type="text/javascript">';
155
+		if (! empty($message)) {
156
+			$js_out .= '
157 157
                 if (window.opener) {
158 158
                     try {
159 159
                         window.opener.console.log("' . $message . '");
@@ -162,11 +162,11 @@  discard block
 block discarded – undo
162 162
                     }
163 163
                 }
164 164
             ';
165
-        }
166
-        $js_out .= 'window.opener = self;
165
+		}
166
+		$js_out .= 'window.opener = self;
167 167
             window.close();
168 168
             </script>';
169
-        echo $js_out;
170
-        exit();
171
-    }
169
+		echo $js_out;
170
+		exit();
171
+	}
172 172
 }
Please login to merge, or discard this patch.
PaymentMethods/PayPalCommerce/modules/EED_PayPalCommerce.module.php 2 patches
Indentation   +332 added lines, -332 removed lines patch added patch discarded remove patch
@@ -17,364 +17,364 @@
 block discarded – undo
17 17
  */
18 18
 class EED_PayPalCommerce extends EED_Module
19 19
 {
20
-    /**
21
-     * @return EED_Module
22
-     * @throws EE_Error
23
-     * @throws ReflectionException
24
-     */
25
-    public static function instance(): EED_Module
26
-    {
27
-        return parent::get_instance(__CLASS__);
28
-    }
20
+	/**
21
+	 * @return EED_Module
22
+	 * @throws EE_Error
23
+	 * @throws ReflectionException
24
+	 */
25
+	public static function instance(): EED_Module
26
+	{
27
+		return parent::get_instance(__CLASS__);
28
+	}
29 29
 
30 30
 
31
-    /**
32
-     * Run - initial module setup.
33
-     *
34
-     * @param WP $WP
35
-     * @return void
36
-     */
37
-    public function run($WP)
38
-    {
39
-        // TODO: Implement run() method.
40
-    }
31
+	/**
32
+	 * Run - initial module setup.
33
+	 *
34
+	 * @param WP $WP
35
+	 * @return void
36
+	 */
37
+	public function run($WP)
38
+	{
39
+		// TODO: Implement run() method.
40
+	}
41 41
 
42 42
 
43
-    /**
44
-     * For hooking into EE Core and other modules.
45
-     *
46
-     * @return void
47
-     */
48
-    public static function set_hooks()
49
-    {
50
-    }
43
+	/**
44
+	 * For hooking into EE Core and other modules.
45
+	 *
46
+	 * @return void
47
+	 */
48
+	public static function set_hooks()
49
+	{
50
+	}
51 51
 
52 52
 
53
-    /**
54
-     * For hooking into EE Admin Core and other modules.
55
-     *
56
-     * @return void
57
-     */
58
-    public static function set_hooks_admin()
59
-    {
60
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
61
-            // Create an Order.
62
-            add_action('wp_ajax_eeaPpCreateOrder', [__CLASS__, 'createOrderRequest']);
63
-            add_action('wp_ajax_nopriv_eeaPpCreateOrder', [__CLASS__, 'createOrderRequest']);
64
-            // Capture the Order.
65
-            add_action('wp_ajax_eeaPpCaptureOrder', [__CLASS__, 'captureOrderRequest']);
66
-            add_action('wp_ajax_nopriv_eeaPpCaptureOrder', [__CLASS__, 'captureOrderRequest']);
67
-            // Log errors from the JS side.
68
-            add_action('wp_ajax_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
69
-            add_action('wp_ajax_nopriv_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
70
-            // Don't load PM on the front-end if not Connected.
71
-            add_filter(
72
-                'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
73
-                [__CLASS__, 'filterPaymentMethods'],
74
-                10,
75
-                3
76
-            );
77
-        }
78
-    }
53
+	/**
54
+	 * For hooking into EE Admin Core and other modules.
55
+	 *
56
+	 * @return void
57
+	 */
58
+	public static function set_hooks_admin()
59
+	{
60
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
61
+			// Create an Order.
62
+			add_action('wp_ajax_eeaPpCreateOrder', [__CLASS__, 'createOrderRequest']);
63
+			add_action('wp_ajax_nopriv_eeaPpCreateOrder', [__CLASS__, 'createOrderRequest']);
64
+			// Capture the Order.
65
+			add_action('wp_ajax_eeaPpCaptureOrder', [__CLASS__, 'captureOrderRequest']);
66
+			add_action('wp_ajax_nopriv_eeaPpCaptureOrder', [__CLASS__, 'captureOrderRequest']);
67
+			// Log errors from the JS side.
68
+			add_action('wp_ajax_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
69
+			add_action('wp_ajax_nopriv_eeaPPCommerceLogError', [__CLASS__, 'logJsError']);
70
+			// Don't load PM on the front-end if not Connected.
71
+			add_filter(
72
+				'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
73
+				[__CLASS__, 'filterPaymentMethods'],
74
+				10,
75
+				3
76
+			);
77
+		}
78
+	}
79 79
 
80 80
 
81
-    /**
82
-     * Create the order and return its data as JSON.
83
-     * (AJAX)
84
-     *
85
-     * @return void
86
-     * @throws EE_Error
87
-     * @throws ReflectionException
88
-     */
89
-    public static function createOrderRequest()
90
-    {
91
-        $paypal_pm   = self::getPaymentMethod();
92
-        $request     = EED_Module::getRequest();
93
-        $post_params = $request->postParams();
94
-        if (! $paypal_pm instanceof EE_Payment_Method) {
95
-            PayPalLogger::errorLogAndExit(
96
-                esc_html__('Related payment method not found (create Order).', 'event_espresso'),
97
-                $post_params
98
-            );
99
-        }
100
-        $transaction  = self::getTransaction();
101
-        $billing_info = $post_params['billing_info'] ?? [];
102
-        if ($billing_info) {
103
-            $billing_info_decoded = json_decode(stripslashes($billing_info), true);
104
-            if (is_array($billing_info_decoded)) {
105
-                $billing_info = $billing_info_decoded;
106
-            }
107
-        }
108
-        if (! $transaction || ! $billing_info || ! is_array($billing_info)) {
109
-            PayPalLogger::errorLogAndExit(
110
-                esc_html__('Transaction or billing info not found.', 'event_espresso'),
111
-                $post_params,
112
-                $paypal_pm
113
-            );
114
-        }
115
-        $order_data = self::createOrder($transaction, $billing_info, $paypal_pm);
116
-        echo json_encode($order_data);
117
-        exit();
118
-    }
81
+	/**
82
+	 * Create the order and return its data as JSON.
83
+	 * (AJAX)
84
+	 *
85
+	 * @return void
86
+	 * @throws EE_Error
87
+	 * @throws ReflectionException
88
+	 */
89
+	public static function createOrderRequest()
90
+	{
91
+		$paypal_pm   = self::getPaymentMethod();
92
+		$request     = EED_Module::getRequest();
93
+		$post_params = $request->postParams();
94
+		if (! $paypal_pm instanceof EE_Payment_Method) {
95
+			PayPalLogger::errorLogAndExit(
96
+				esc_html__('Related payment method not found (create Order).', 'event_espresso'),
97
+				$post_params
98
+			);
99
+		}
100
+		$transaction  = self::getTransaction();
101
+		$billing_info = $post_params['billing_info'] ?? [];
102
+		if ($billing_info) {
103
+			$billing_info_decoded = json_decode(stripslashes($billing_info), true);
104
+			if (is_array($billing_info_decoded)) {
105
+				$billing_info = $billing_info_decoded;
106
+			}
107
+		}
108
+		if (! $transaction || ! $billing_info || ! is_array($billing_info)) {
109
+			PayPalLogger::errorLogAndExit(
110
+				esc_html__('Transaction or billing info not found.', 'event_espresso'),
111
+				$post_params,
112
+				$paypal_pm
113
+			);
114
+		}
115
+		$order_data = self::createOrder($transaction, $billing_info, $paypal_pm);
116
+		echo json_encode($order_data);
117
+		exit();
118
+	}
119 119
 
120 120
 
121
-    /**
122
-     * Capture the order and return status in JSON.
123
-     * (AJAX)
124
-     *
125
-     * @return void
126
-     * @throws EE_Error
127
-     * @throws ReflectionException
128
-     */
129
-    public static function captureOrderRequest()
130
-    {
131
-        $error_message = false;
132
-        $paypal_pm     = self::getPaymentMethod();
133
-        if (! $paypal_pm instanceof EE_Payment_Method) {
134
-            $error_message = esc_html__('Payment method not found (capture Order).', 'event_espresso');
135
-        }
136
-        $transaction = self::getTransaction();
137
-        if (! $transaction) {
138
-            $error_message = esc_html__('Transaction not found.', 'event_espresso');
139
-        }
140
-        $order_id = EED_Module::getRequest()->getRequestParam('order_id', '', DataType::STRING);
141
-        if (! $order_id) {
142
-            $error_message = esc_html__('Order ID missing.', 'event_espresso');
143
-        }
144
-        // We had an error. Log and EXIT.
145
-        if ($error_message) {
146
-            PayPalLogger::errorLogAndExit($error_message, EED_Module::getRequest()->postParams(), $paypal_pm);
147
-        }
148
-        $capture_response = self::captureOrder($transaction, $paypal_pm, $order_id);
149
-        echo json_encode($capture_response);
150
-        exit();
151
-    }
121
+	/**
122
+	 * Capture the order and return status in JSON.
123
+	 * (AJAX)
124
+	 *
125
+	 * @return void
126
+	 * @throws EE_Error
127
+	 * @throws ReflectionException
128
+	 */
129
+	public static function captureOrderRequest()
130
+	{
131
+		$error_message = false;
132
+		$paypal_pm     = self::getPaymentMethod();
133
+		if (! $paypal_pm instanceof EE_Payment_Method) {
134
+			$error_message = esc_html__('Payment method not found (capture Order).', 'event_espresso');
135
+		}
136
+		$transaction = self::getTransaction();
137
+		if (! $transaction) {
138
+			$error_message = esc_html__('Transaction not found.', 'event_espresso');
139
+		}
140
+		$order_id = EED_Module::getRequest()->getRequestParam('order_id', '', DataType::STRING);
141
+		if (! $order_id) {
142
+			$error_message = esc_html__('Order ID missing.', 'event_espresso');
143
+		}
144
+		// We had an error. Log and EXIT.
145
+		if ($error_message) {
146
+			PayPalLogger::errorLogAndExit($error_message, EED_Module::getRequest()->postParams(), $paypal_pm);
147
+		}
148
+		$capture_response = self::captureOrder($transaction, $paypal_pm, $order_id);
149
+		echo json_encode($capture_response);
150
+		exit();
151
+	}
152 152
 
153 153
 
154
-    /**
155
-     * Create a new Order using the PP API.
156
-     *
157
-     * @param EE_Transaction    $transaction
158
-     * @param array             $billing_info
159
-     * @param EE_Payment_Method $paypal_pm
160
-     * @return array
161
-     * @throws EE_Error
162
-     * @throws ReflectionException
163
-     * @throws Exception
164
-     */
165
-    public static function createOrder(
166
-        EE_Transaction $transaction,
167
-        array $billing_info,
168
-        EE_Payment_Method $paypal_pm
169
-    ): array {
170
-        $create_order_api = self::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
171
-        if (! $create_order_api instanceof CreateOrder) {
172
-            return [
173
-                'error'   => 'CREATE_ORDER_API_FAULT',
174
-                'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
175
-            ];
176
-        }
177
-        $order = $create_order_api->create();
178
-        if (isset($order['error'])) {
179
-            return [
180
-                'error'   => 'CREATE_ORDER_API_RESPONSE_ERROR',
181
-                'message' => $order['message'],
182
-            ];
183
-        }
184
-        return [
185
-            'pp_order_id' => $order['id'],
186
-        ];
187
-    }
154
+	/**
155
+	 * Create a new Order using the PP API.
156
+	 *
157
+	 * @param EE_Transaction    $transaction
158
+	 * @param array             $billing_info
159
+	 * @param EE_Payment_Method $paypal_pm
160
+	 * @return array
161
+	 * @throws EE_Error
162
+	 * @throws ReflectionException
163
+	 * @throws Exception
164
+	 */
165
+	public static function createOrder(
166
+		EE_Transaction $transaction,
167
+		array $billing_info,
168
+		EE_Payment_Method $paypal_pm
169
+	): array {
170
+		$create_order_api = self::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
171
+		if (! $create_order_api instanceof CreateOrder) {
172
+			return [
173
+				'error'   => 'CREATE_ORDER_API_FAULT',
174
+				'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
175
+			];
176
+		}
177
+		$order = $create_order_api->create();
178
+		if (isset($order['error'])) {
179
+			return [
180
+				'error'   => 'CREATE_ORDER_API_RESPONSE_ERROR',
181
+				'message' => $order['message'],
182
+			];
183
+		}
184
+		return [
185
+			'pp_order_id' => $order['id'],
186
+		];
187
+	}
188 188
 
189 189
 
190
-    /**
191
-     * Create a new Order using the PP API.
192
-     *
193
-     * @param EE_Transaction    $transaction
194
-     * @param EE_Payment_Method $paypal_pm
195
-     * @param string            $order_id
196
-     * @return array
197
-     * @throws EE_Error
198
-     * @throws ReflectionException
199
-     * @throws Exception
200
-     */
201
-    public static function captureOrder(
202
-        EE_Transaction $transaction,
203
-        EE_Payment_Method $paypal_pm,
204
-        string $order_id
205
-    ): array {
206
-        $capture_order_api = self::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
207
-        if (! $capture_order_api instanceof CaptureOrder) {
208
-            return [
209
-                'error'   => 'CAPTURE_ORDER_API_FAULT',
210
-                'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
211
-            ];
212
-        }
213
-        $order = $capture_order_api->capture();
214
-        if (isset($order['error'])) {
215
-            return $order;
216
-        }
217
-        // Attach the transaction ID to this order.
218
-        $order['ee_txn_id'] = $transaction->ID();
219
-        // Save this order details.
220
-        PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_LAST_ORDER, $order);
221
-        $nonce = wp_create_nonce(Domain::CAPTURE_ORDER_NONCE_NAME);
222
-        return [
223
-            'pp_order_nonce'         => $nonce,
224
-            'pp_order_id'            => $order['id'],
225
-            'pp_order_status'        => $order['status'],
226
-            'pp_order_amount'        => $order['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
227
-        ];
228
-    }
190
+	/**
191
+	 * Create a new Order using the PP API.
192
+	 *
193
+	 * @param EE_Transaction    $transaction
194
+	 * @param EE_Payment_Method $paypal_pm
195
+	 * @param string            $order_id
196
+	 * @return array
197
+	 * @throws EE_Error
198
+	 * @throws ReflectionException
199
+	 * @throws Exception
200
+	 */
201
+	public static function captureOrder(
202
+		EE_Transaction $transaction,
203
+		EE_Payment_Method $paypal_pm,
204
+		string $order_id
205
+	): array {
206
+		$capture_order_api = self::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
207
+		if (! $capture_order_api instanceof CaptureOrder) {
208
+			return [
209
+				'error'   => 'CAPTURE_ORDER_API_FAULT',
210
+				'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
211
+			];
212
+		}
213
+		$order = $capture_order_api->capture();
214
+		if (isset($order['error'])) {
215
+			return $order;
216
+		}
217
+		// Attach the transaction ID to this order.
218
+		$order['ee_txn_id'] = $transaction->ID();
219
+		// Save this order details.
220
+		PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_LAST_ORDER, $order);
221
+		$nonce = wp_create_nonce(Domain::CAPTURE_ORDER_NONCE_NAME);
222
+		return [
223
+			'pp_order_nonce'         => $nonce,
224
+			'pp_order_id'            => $order['id'],
225
+			'pp_order_status'        => $order['status'],
226
+			'pp_order_amount'        => $order['purchase_units'][0]['payments']['captures'][0]['amount']['value'],
227
+		];
228
+	}
229 229
 
230 230
 
231
-    /**
232
-     * Create an Order for this transaction.
233
-     *
234
-     * @param EE_Transaction    $transaction
235
-     * @param array             $billing_info
236
-     * @param EE_Payment_Method $paypal_pm
237
-     * @return CreateOrder|null
238
-     * @throws Exception
239
-     */
240
-    public static function getCreateOrderApi(
241
-        EE_Transaction $transaction,
242
-        array $billing_info,
243
-        EE_Payment_Method $paypal_pm
244
-    ): ?CreateOrder {
245
-        $paypal_api = self::getPayPalApi($paypal_pm);
246
-        if (! $paypal_api) {
247
-            return null;
248
-        }
249
-        return new CreateOrder($paypal_api, $transaction, $billing_info);
250
-    }
231
+	/**
232
+	 * Create an Order for this transaction.
233
+	 *
234
+	 * @param EE_Transaction    $transaction
235
+	 * @param array             $billing_info
236
+	 * @param EE_Payment_Method $paypal_pm
237
+	 * @return CreateOrder|null
238
+	 * @throws Exception
239
+	 */
240
+	public static function getCreateOrderApi(
241
+		EE_Transaction $transaction,
242
+		array $billing_info,
243
+		EE_Payment_Method $paypal_pm
244
+	): ?CreateOrder {
245
+		$paypal_api = self::getPayPalApi($paypal_pm);
246
+		if (! $paypal_api) {
247
+			return null;
248
+		}
249
+		return new CreateOrder($paypal_api, $transaction, $billing_info);
250
+	}
251 251
 
252 252
 
253
-    /**
254
-     * Create an Order for this transaction.
255
-     *
256
-     * @param EE_Transaction    $transaction
257
-     * @param EE_Payment_Method $paypal_pm
258
-     * @param string            $order_id
259
-     * @return CaptureOrder|null
260
-     * @throws Exception
261
-     */
262
-    public static function getCaptureOrderApi(
263
-        EE_Transaction $transaction,
264
-        EE_Payment_Method $paypal_pm,
265
-        string $order_id
266
-    ): ?CaptureOrder {
267
-        $paypal_api = self::getPayPalApi($paypal_pm);
268
-        if (! $paypal_api) {
269
-            return null;
270
-        }
271
-        return new CaptureOrder($paypal_api, $transaction, $order_id);
272
-    }
253
+	/**
254
+	 * Create an Order for this transaction.
255
+	 *
256
+	 * @param EE_Transaction    $transaction
257
+	 * @param EE_Payment_Method $paypal_pm
258
+	 * @param string            $order_id
259
+	 * @return CaptureOrder|null
260
+	 * @throws Exception
261
+	 */
262
+	public static function getCaptureOrderApi(
263
+		EE_Transaction $transaction,
264
+		EE_Payment_Method $paypal_pm,
265
+		string $order_id
266
+	): ?CaptureOrder {
267
+		$paypal_api = self::getPayPalApi($paypal_pm);
268
+		if (! $paypal_api) {
269
+			return null;
270
+		}
271
+		return new CaptureOrder($paypal_api, $transaction, $order_id);
272
+	}
273 273
 
274 274
 
275
-    /**
276
-     * Return a PayPal API object, or false on failure.
277
-     *
278
-     * @param EE_Payment_Method $paypal_pm
279
-     * @return PayPalApi|null
280
-     * @throws Exception
281
-     */
282
-    public static function getPayPalApi(EE_Payment_Method $paypal_pm): ?PayPalApi
283
-    {
284
-        $client_id     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_ID);
285
-        $client_secret = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_SECRET);
286
-        $bn_code       = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
287
-        if (! $client_id || ! $client_secret || ! $bn_code) {
288
-            return null;
289
-        }
290
-        return new PayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
291
-    }
275
+	/**
276
+	 * Return a PayPal API object, or false on failure.
277
+	 *
278
+	 * @param EE_Payment_Method $paypal_pm
279
+	 * @return PayPalApi|null
280
+	 * @throws Exception
281
+	 */
282
+	public static function getPayPalApi(EE_Payment_Method $paypal_pm): ?PayPalApi
283
+	{
284
+		$client_id     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_ID);
285
+		$client_secret = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_SECRET);
286
+		$bn_code       = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
287
+		if (! $client_id || ! $client_secret || ! $bn_code) {
288
+			return null;
289
+		}
290
+		return new PayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
291
+	}
292 292
 
293 293
 
294
-    /**
295
-     * Retrieve the payment method from the provided data.
296
-     *
297
-     * @return EE_Transaction|null
298
-     * @throws EE_Error
299
-     */
300
-    public static function getTransaction(): ?EE_Transaction
301
-    {
302
-        $txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
303
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
304
-        if (! $transaction instanceof EE_Transaction) {
305
-            PayPalLogger::errorLog(
306
-                esc_html__('No transaction found by ID:', 'event_espresso'),
307
-                EED_Module::getRequest()->postParams()
308
-            );
309
-            return null;
310
-        }
311
-        return $transaction;
312
-    }
294
+	/**
295
+	 * Retrieve the payment method from the provided data.
296
+	 *
297
+	 * @return EE_Transaction|null
298
+	 * @throws EE_Error
299
+	 */
300
+	public static function getTransaction(): ?EE_Transaction
301
+	{
302
+		$txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
303
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
304
+		if (! $transaction instanceof EE_Transaction) {
305
+			PayPalLogger::errorLog(
306
+				esc_html__('No transaction found by ID:', 'event_espresso'),
307
+				EED_Module::getRequest()->postParams()
308
+			);
309
+			return null;
310
+		}
311
+		return $transaction;
312
+	}
313 313
 
314 314
 
315
-    /**
316
-     * Retrieve the payment method from the provided data.
317
-     *
318
-     * @return EE_Payment_Method|null
319
-     */
320
-    public static function getPaymentMethod(): ?EE_Payment_Method
321
-    {
322
-        try {
323
-            // Check if all required parameters are present.
324
-            $pm_slug        = EED_Module::getRequest()->getRequestParam('payment_method');
325
-            $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_slug);
326
-            if ($payment_method instanceof EE_Payment_Method) {
327
-                return $payment_method;
328
-            }
329
-        } catch (EE_Error $e) {
330
-            return null;
331
-        }
332
-        return null;
333
-    }
315
+	/**
316
+	 * Retrieve the payment method from the provided data.
317
+	 *
318
+	 * @return EE_Payment_Method|null
319
+	 */
320
+	public static function getPaymentMethod(): ?EE_Payment_Method
321
+	{
322
+		try {
323
+			// Check if all required parameters are present.
324
+			$pm_slug        = EED_Module::getRequest()->getRequestParam('payment_method');
325
+			$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_slug);
326
+			if ($payment_method instanceof EE_Payment_Method) {
327
+				return $payment_method;
328
+			}
329
+		} catch (EE_Error $e) {
330
+			return null;
331
+		}
332
+		return null;
333
+	}
334 334
 
335 335
 
336
-    /**
337
-     * Log JS error.
338
-     *
339
-     * @return void
340
-     * @throws EE_Error
341
-     * @throws ReflectionException
342
-     */
343
-    public static function logJsError()
344
-    {
345
-        // Default to the "first" PayPal checkout PM.
346
-        $request        = EED_Module::getRequest();
347
-        $pm_slug        = $request->getRequestParam('pm_slug', Domain::PM_SLUG);
348
-        $payment_method = null;
349
-        $txn_id         = 'unknown';
350
-        try {
351
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pm_slug);
352
-            $txn_id         = sanitize_text_field($request->getRequestParam('txn_id', '-'));
353
-        } catch (Exception $e) {
354
-            // Don't throw out anything, log at least something.
355
-        }
356
-        PayPalLogger::errorLog("JS Error on transaction: {$txn_id}", $request->postParams(), $payment_method);
357
-    }
336
+	/**
337
+	 * Log JS error.
338
+	 *
339
+	 * @return void
340
+	 * @throws EE_Error
341
+	 * @throws ReflectionException
342
+	 */
343
+	public static function logJsError()
344
+	{
345
+		// Default to the "first" PayPal checkout PM.
346
+		$request        = EED_Module::getRequest();
347
+		$pm_slug        = $request->getRequestParam('pm_slug', Domain::PM_SLUG);
348
+		$payment_method = null;
349
+		$txn_id         = 'unknown';
350
+		try {
351
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pm_slug);
352
+			$txn_id         = sanitize_text_field($request->getRequestParam('txn_id', '-'));
353
+		} catch (Exception $e) {
354
+			// Don't throw out anything, log at least something.
355
+		}
356
+		PayPalLogger::errorLog("JS Error on transaction: {$txn_id}", $request->postParams(), $payment_method);
357
+	}
358 358
 
359 359
 
360
-    /**
361
-     * Filter the Payment Methods list.
362
-     *
363
-     * @param EE_Payment_Method[] $payment_methods
364
-     * @param EE_Transaction      $transaction
365
-     * @param string              $scope @see EEM_Payment_Method::get_all_for_events
366
-     * @return array
367
-     * @throws EE_Error
368
-     */
369
-    public static function filterPaymentMethods(array $payment_methods, $transaction, $scope): array
370
-    {
371
-        // Don't allow this PM on the checkout page if not Connected.
372
-        foreach ($payment_methods as $key => $pm) {
373
-            // It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
374
-            if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
375
-                unset($payment_methods[ $key ]);
376
-            }
377
-        }
378
-        return $payment_methods;
379
-    }
360
+	/**
361
+	 * Filter the Payment Methods list.
362
+	 *
363
+	 * @param EE_Payment_Method[] $payment_methods
364
+	 * @param EE_Transaction      $transaction
365
+	 * @param string              $scope @see EEM_Payment_Method::get_all_for_events
366
+	 * @return array
367
+	 * @throws EE_Error
368
+	 */
369
+	public static function filterPaymentMethods(array $payment_methods, $transaction, $scope): array
370
+	{
371
+		// Don't allow this PM on the checkout page if not Connected.
372
+		foreach ($payment_methods as $key => $pm) {
373
+			// It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
374
+			if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
375
+				unset($payment_methods[ $key ]);
376
+			}
377
+		}
378
+		return $payment_methods;
379
+	}
380 380
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -91,7 +91,7 @@  discard block
 block discarded – undo
91 91
         $paypal_pm   = self::getPaymentMethod();
92 92
         $request     = EED_Module::getRequest();
93 93
         $post_params = $request->postParams();
94
-        if (! $paypal_pm instanceof EE_Payment_Method) {
94
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
95 95
             PayPalLogger::errorLogAndExit(
96 96
                 esc_html__('Related payment method not found (create Order).', 'event_espresso'),
97 97
                 $post_params
@@ -105,7 +105,7 @@  discard block
 block discarded – undo
105 105
                 $billing_info = $billing_info_decoded;
106 106
             }
107 107
         }
108
-        if (! $transaction || ! $billing_info || ! is_array($billing_info)) {
108
+        if ( ! $transaction || ! $billing_info || ! is_array($billing_info)) {
109 109
             PayPalLogger::errorLogAndExit(
110 110
                 esc_html__('Transaction or billing info not found.', 'event_espresso'),
111 111
                 $post_params,
@@ -130,15 +130,15 @@  discard block
 block discarded – undo
130 130
     {
131 131
         $error_message = false;
132 132
         $paypal_pm     = self::getPaymentMethod();
133
-        if (! $paypal_pm instanceof EE_Payment_Method) {
133
+        if ( ! $paypal_pm instanceof EE_Payment_Method) {
134 134
             $error_message = esc_html__('Payment method not found (capture Order).', 'event_espresso');
135 135
         }
136 136
         $transaction = self::getTransaction();
137
-        if (! $transaction) {
137
+        if ( ! $transaction) {
138 138
             $error_message = esc_html__('Transaction not found.', 'event_espresso');
139 139
         }
140 140
         $order_id = EED_Module::getRequest()->getRequestParam('order_id', '', DataType::STRING);
141
-        if (! $order_id) {
141
+        if ( ! $order_id) {
142 142
             $error_message = esc_html__('Order ID missing.', 'event_espresso');
143 143
         }
144 144
         // We had an error. Log and EXIT.
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
         EE_Payment_Method $paypal_pm
169 169
     ): array {
170 170
         $create_order_api = self::getCreateOrderApi($transaction, $billing_info, $paypal_pm);
171
-        if (! $create_order_api instanceof CreateOrder) {
171
+        if ( ! $create_order_api instanceof CreateOrder) {
172 172
             return [
173 173
                 'error'   => 'CREATE_ORDER_API_FAULT',
174 174
                 'message' => esc_html__('The Create Order API request fault.', 'event_espresso'),
@@ -204,7 +204,7 @@  discard block
 block discarded – undo
204 204
         string $order_id
205 205
     ): array {
206 206
         $capture_order_api = self::getCaptureOrderApi($transaction, $paypal_pm, $order_id);
207
-        if (! $capture_order_api instanceof CaptureOrder) {
207
+        if ( ! $capture_order_api instanceof CaptureOrder) {
208 208
             return [
209 209
                 'error'   => 'CAPTURE_ORDER_API_FAULT',
210 210
                 'message' => esc_html__('A capture Order API request fault.', 'event_espresso'),
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
         EE_Payment_Method $paypal_pm
244 244
     ): ?CreateOrder {
245 245
         $paypal_api = self::getPayPalApi($paypal_pm);
246
-        if (! $paypal_api) {
246
+        if ( ! $paypal_api) {
247 247
             return null;
248 248
         }
249 249
         return new CreateOrder($paypal_api, $transaction, $billing_info);
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
         string $order_id
266 266
     ): ?CaptureOrder {
267 267
         $paypal_api = self::getPayPalApi($paypal_pm);
268
-        if (! $paypal_api) {
268
+        if ( ! $paypal_api) {
269 269
             return null;
270 270
         }
271 271
         return new CaptureOrder($paypal_api, $transaction, $order_id);
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
         $client_id     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_ID);
285 285
         $client_secret = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_CLIENT_SECRET);
286 286
         $bn_code       = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
287
-        if (! $client_id || ! $client_secret || ! $bn_code) {
287
+        if ( ! $client_id || ! $client_secret || ! $bn_code) {
288 288
             return null;
289 289
         }
290 290
         return new PayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
@@ -301,7 +301,7 @@  discard block
 block discarded – undo
301 301
     {
302 302
         $txn_id      = EED_Module::getRequest()->getRequestParam('txn_id', 0, DataType::INT);
303 303
         $transaction = EEM_Transaction::instance()->get_one_by_ID($txn_id);
304
-        if (! $transaction instanceof EE_Transaction) {
304
+        if ( ! $transaction instanceof EE_Transaction) {
305 305
             PayPalLogger::errorLog(
306 306
                 esc_html__('No transaction found by ID:', 'event_espresso'),
307 307
                 EED_Module::getRequest()->postParams()
@@ -372,7 +372,7 @@  discard block
 block discarded – undo
372 372
         foreach ($payment_methods as $key => $pm) {
373 373
             // It is a PayPal Commerce payment method. Check if it's connected. If not - remove from the list.
374 374
             if (str_contains($pm->slug(), Domain::PM_SLUG) && ! EED_PayPalOnboard::isOnboard($pm)) {
375
-                unset($payment_methods[ $key ]);
375
+                unset($payment_methods[$key]);
376 376
             }
377 377
         }
378 378
         return $payment_methods;
Please login to merge, or discard this patch.
admin_pages/general_settings/General_Settings_Admin_Page.core.php 1 patch
Indentation   +1446 added lines, -1446 removed lines patch added patch discarded remove patch
@@ -22,1463 +22,1463 @@
 block discarded – undo
22 22
  */
23 23
 class General_Settings_Admin_Page extends EE_Admin_Page
24 24
 {
25
-    /**
26
-     * @var EE_Core_Config
27
-     */
28
-    public $core_config;
29
-
30
-
31
-    /**
32
-     * Initialize basic properties.
33
-     */
34
-    protected function _init_page_props()
35
-    {
36
-        $this->page_slug        = GEN_SET_PG_SLUG;
37
-        $this->page_label       = GEN_SET_LABEL;
38
-        $this->_admin_base_url  = GEN_SET_ADMIN_URL;
39
-        $this->_admin_base_path = GEN_SET_ADMIN;
40
-
41
-        $this->core_config = EE_Registry::instance()->CFG->core;
42
-    }
43
-
44
-
45
-    /**
46
-     * Set ajax hooks
47
-     */
48
-    protected function _ajax_hooks()
49
-    {
50
-        add_action('wp_ajax_espresso_display_country_settings', [$this, 'display_country_settings']);
51
-        add_action('wp_ajax_espresso_display_country_states', [$this, 'display_country_states']);
52
-        add_action('wp_ajax_espresso_delete_state', [$this, 'delete_state'], 10, 3);
53
-        add_action('wp_ajax_espresso_add_new_state', [$this, 'add_new_state']);
54
-    }
55
-
56
-
57
-    /**
58
-     * More page properties initialization.
59
-     */
60
-    protected function _define_page_props()
61
-    {
62
-        $this->_admin_page_title = GEN_SET_LABEL;
63
-        $this->_labels           = ['publishbox' => esc_html__('Update Settings', 'event_espresso')];
64
-    }
65
-
66
-
67
-    /**
68
-     * Set page routes property.
69
-     */
70
-    protected function _set_page_routes()
71
-    {
72
-        $this->_page_routes = [
73
-            'critical_pages'                => [
74
-                'func'       => [$this, '_espresso_page_settings'],
75
-                'capability' => 'manage_options',
76
-            ],
77
-            'update_espresso_page_settings' => [
78
-                'func'       => [$this, '_update_espresso_page_settings'],
79
-                'capability' => 'manage_options',
80
-                'noheader'   => true,
81
-            ],
82
-            'default'                       => [
83
-                'func'       => [$this, '_your_organization_settings'],
84
-                'capability' => 'manage_options',
85
-            ],
86
-
87
-            'update_your_organization_settings' => [
88
-                'func'       => [$this, '_update_your_organization_settings'],
89
-                'capability' => 'manage_options',
90
-                'noheader'   => true,
91
-            ],
92
-
93
-            'admin_option_settings' => [
94
-                'func'       => [$this, '_admin_option_settings'],
95
-                'capability' => 'manage_options',
96
-            ],
97
-
98
-            'update_admin_option_settings' => [
99
-                'func'       => [$this, '_update_admin_option_settings'],
100
-                'capability' => 'manage_options',
101
-                'noheader'   => true,
102
-            ],
103
-
104
-            'country_settings' => [
105
-                'func'       => [$this, '_country_settings'],
106
-                'capability' => 'manage_options',
107
-            ],
108
-
109
-            'update_country_settings' => [
110
-                'func'       => [$this, '_update_country_settings'],
111
-                'capability' => 'manage_options',
112
-                'noheader'   => true,
113
-            ],
114
-
115
-            'display_country_settings' => [
116
-                'func'       => [$this, 'display_country_settings'],
117
-                'capability' => 'manage_options',
118
-                'noheader'   => true,
119
-            ],
120
-
121
-            'add_new_state' => [
122
-                'func'       => [$this, 'add_new_state'],
123
-                'capability' => 'manage_options',
124
-                'noheader'   => true,
125
-            ],
126
-
127
-            'delete_state'            => [
128
-                'func'       => [$this, 'delete_state'],
129
-                'capability' => 'manage_options',
130
-                'noheader'   => true,
131
-            ],
132
-
133
-            'privacy_settings'        => [
134
-                'func'       => [$this, 'privacySettings'],
135
-                'capability' => 'manage_options',
136
-            ],
137
-
138
-            'update_privacy_settings' => [
139
-                'func'               => [$this, 'updatePrivacySettings'],
140
-                'capability'         => 'manage_options',
141
-                'noheader'           => true,
142
-                'headers_sent_route' => 'privacy_settings',
143
-            ],
144
-
145
-            'set_font_size'            => [
146
-                'func'       => [$this, 'setFontSize'],
147
-                'noheader'   => true,
148
-            ],
149
-        ];
150
-    }
151
-
152
-
153
-    /**
154
-     * Set page configuration property
155
-     */
156
-    protected function _set_page_config()
157
-    {
158
-        $this->_page_config = [
159
-            'critical_pages'        => [
160
-                'nav'           => [
161
-                    'label' => esc_html__('Critical Pages', 'event_espresso'),
162
-                    'icon' => 'dashicons-warning',
163
-                    'order' => 50,
164
-                ],
165
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
166
-                'help_tabs'     => [
167
-                    'general_settings_critical_pages_help_tab' => [
168
-                        'title'    => esc_html__('Critical Pages', 'event_espresso'),
169
-                        'filename' => 'general_settings_critical_pages',
170
-                    ],
171
-                ],
172
-                'require_nonce' => false,
173
-            ],
174
-            'default'               => [
175
-                'nav'           => [
176
-                    'label' => esc_html__('Your Organization', 'event_espresso'),
177
-                    'icon' => 'dashicons-admin-home',
178
-                    'order' => 20,
179
-                ],
180
-                'help_tabs'     => [
181
-                    'general_settings_your_organization_help_tab' => [
182
-                        'title'    => esc_html__('Your Organization', 'event_espresso'),
183
-                        'filename' => 'general_settings_your_organization',
184
-                    ],
185
-                ],
186
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
187
-                'require_nonce' => false,
188
-            ],
189
-            'admin_option_settings' => [
190
-                'nav'           => [
191
-                    'label' => esc_html__('Admin Options', 'event_espresso'),
192
-                    'icon' => 'dashicons-admin-settings',
193
-                    'order' => 60,
194
-                ],
195
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
196
-                'help_tabs'     => [
197
-                    'general_settings_admin_options_help_tab' => [
198
-                        'title'    => esc_html__('Admin Options', 'event_espresso'),
199
-                        'filename' => 'general_settings_admin_options',
200
-                    ],
201
-                ],
202
-                'require_nonce' => false,
203
-            ],
204
-            'country_settings'      => [
205
-                'nav'           => [
206
-                    'label' => esc_html__('Countries', 'event_espresso'),
207
-                    'icon' => 'dashicons-admin-site',
208
-                    'order' => 70,
209
-                ],
210
-                'help_tabs'     => [
211
-                    'general_settings_countries_help_tab' => [
212
-                        'title'    => esc_html__('Countries', 'event_espresso'),
213
-                        'filename' => 'general_settings_countries',
214
-                    ],
215
-                ],
216
-                'require_nonce' => false,
217
-            ],
218
-            'privacy_settings'      => [
219
-                'nav'           => [
220
-                    'label' => esc_html__('Privacy', 'event_espresso'),
221
-                    'icon' => 'dashicons-privacy',
222
-                    'order' => 80,
223
-                ],
224
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
225
-                'require_nonce' => false,
226
-            ],
227
-        ];
228
-    }
229
-
230
-
231
-    protected function _add_screen_options()
232
-    {
233
-    }
234
-
235
-
236
-    protected function _add_feature_pointers()
237
-    {
238
-    }
239
-
240
-
241
-    /**
242
-     * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
243
-     */
244
-    public function load_scripts_styles()
245
-    {
246
-        // styles
247
-        wp_enqueue_style('espresso-ui-theme');
248
-        // scripts
249
-        wp_enqueue_script('ee_admin_js');
250
-    }
251
-
252
-
253
-    /**
254
-     * Execute logic running on `admin_init`
255
-     */
256
-    public function admin_init()
257
-    {
258
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(
259
-            esc_html__(
260
-                'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
261
-                'event_espresso'
262
-            )
263
-        );
264
-        EE_Registry::$i18n_js_strings['error_occurred']          = wp_strip_all_tags(
265
-            esc_html__(
266
-                'An error occurred! Please refresh the page and try again.',
267
-                'event_espresso'
268
-            )
269
-        );
270
-        EE_Registry::$i18n_js_strings['confirm_delete_state']    = wp_strip_all_tags(
271
-            esc_html__(
272
-                'Are you sure you want to delete this State / Province?',
273
-                'event_espresso'
274
-            )
275
-        );
276
-        EE_Registry::$i18n_js_strings['ajax_url']                = admin_url(
277
-            'admin-ajax.php?page=espresso_general_settings',
278
-            is_ssl() ? 'https://' : 'http://'
279
-        );
280
-    }
281
-
282
-
283
-    public function admin_notices()
284
-    {
285
-    }
286
-
287
-
288
-    public function admin_footer_scripts()
289
-    {
290
-    }
291
-
292
-
293
-    /**
294
-     * Enqueue scripts and styles for the default route.
295
-     */
296
-    public function load_scripts_styles_default()
297
-    {
298
-        // styles
299
-        wp_enqueue_style('thickbox');
300
-        // scripts
301
-        wp_enqueue_script('media-upload');
302
-        wp_enqueue_script('thickbox');
303
-        wp_register_script(
304
-            'organization_settings',
305
-            GEN_SET_ASSETS_URL . 'your_organization_settings.js',
306
-            ['jquery', 'media-upload', 'thickbox'],
307
-            EVENT_ESPRESSO_VERSION,
308
-            true
309
-        );
310
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
311
-        wp_enqueue_script('organization_settings');
312
-        wp_enqueue_style('organization-css');
313
-        $confirm_image_delete = [
314
-            'text' => wp_strip_all_tags(
315
-                esc_html__(
316
-                    'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
317
-                    'event_espresso'
318
-                )
319
-            ),
320
-        ];
321
-        wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
322
-    }
323
-
324
-
325
-    /**
326
-     * Enqueue scripts and styles for the country settings route.
327
-     */
328
-    public function load_scripts_styles_country_settings()
329
-    {
330
-        // scripts
331
-        wp_register_script(
332
-            'gen_settings_countries',
333
-            GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
334
-            ['ee_admin_js'],
335
-            EVENT_ESPRESSO_VERSION,
336
-            true
337
-        );
338
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
339
-        wp_enqueue_script('gen_settings_countries');
340
-        wp_enqueue_style('organization-css');
341
-    }
342
-
343
-
344
-    /*************        Espresso Pages        *************/
345
-    /**
346
-     * _espresso_page_settings
347
-     *
348
-     * @throws EE_Error
349
-     * @throws DomainException
350
-     * @throws DomainException
351
-     * @throws InvalidDataTypeException
352
-     * @throws InvalidArgumentException
353
-     */
354
-    protected function _espresso_page_settings()
355
-    {
356
-        // Check to make sure all of the main pages are set up properly,
357
-        // if not create the default pages and display an admin notice
358
-        EEH_Activation::verify_default_pages_exist();
359
-        $this->_transient_garbage_collection();
360
-
361
-        $this->_template_args['values'] = $this->_yes_no_values;
362
-
363
-        $this->_template_args['reg_page_id']  = $this->core_config->reg_page_id ?? null;
364
-        $this->_template_args['reg_page_obj'] = isset($this->core_config->reg_page_id)
365
-            ? get_post($this->core_config->reg_page_id)
366
-            : false;
367
-
368
-        $this->_template_args['txn_page_id']  = $this->core_config->txn_page_id ?? null;
369
-        $this->_template_args['txn_page_obj'] = isset($this->core_config->txn_page_id)
370
-            ? get_post($this->core_config->txn_page_id)
371
-            : false;
372
-
373
-        $this->_template_args['thank_you_page_id']  = $this->core_config->thank_you_page_id ?? null;
374
-        $this->_template_args['thank_you_page_obj'] = isset($this->core_config->thank_you_page_id)
375
-            ? get_post($this->core_config->thank_you_page_id)
376
-            : false;
377
-
378
-        $this->_template_args['cancel_page_id']  = $this->core_config->cancel_page_id ?? null;
379
-        $this->_template_args['cancel_page_obj'] = isset($this->core_config->cancel_page_id)
380
-            ? get_post($this->core_config->cancel_page_id)
381
-            : false;
382
-
383
-        $this->_set_add_edit_form_tags('update_espresso_page_settings');
384
-        $this->_set_publish_post_box_vars();
385
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
386
-            GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
387
-            $this->_template_args,
388
-            true
389
-        );
390
-        $this->display_admin_page_with_sidebar();
391
-    }
392
-
393
-
394
-    /**
395
-     * Handler for updating espresso page settings.
396
-     *
397
-     * @throws EE_Error
398
-     */
399
-    protected function _update_espresso_page_settings()
400
-    {
401
-        $this->core_config = EE_Registry::instance()->CFG->core;
402
-        // capture incoming request data && set page IDs
403
-        $this->core_config->reg_page_id       = $this->request->getRequestParam(
404
-            'reg_page_id',
405
-            $this->core_config->reg_page_id,
406
-            DataType::INT
407
-        );
408
-        $this->core_config->txn_page_id       = $this->request->getRequestParam(
409
-            'txn_page_id',
410
-            $this->core_config->txn_page_id,
411
-            DataType::INT
412
-        );
413
-        $this->core_config->thank_you_page_id = $this->request->getRequestParam(
414
-            'thank_you_page_id',
415
-            $this->core_config->thank_you_page_id,
416
-            DataType::INT
417
-        );
418
-        $this->core_config->cancel_page_id    = $this->request->getRequestParam(
419
-            'cancel_page_id',
420
-            $this->core_config->cancel_page_id,
421
-            DataType::INT
422
-        );
423
-
424
-        $this->core_config = apply_filters(
425
-            'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
426
-            $this->core_config,
427
-            $this->request->requestParams()
428
-        );
429
-
430
-        $what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
431
-        $this->_redirect_after_action(
432
-            $this->_update_espresso_configuration(
433
-                $what,
434
-                $this->core_config,
435
-                __FILE__,
436
-                __FUNCTION__,
437
-                __LINE__
438
-            ),
439
-            $what,
440
-            '',
441
-            [
442
-                'action' => 'critical_pages',
443
-            ],
444
-            true
445
-        );
446
-    }
447
-
448
-
449
-    /*************        Your Organization        *************/
450
-
451
-
452
-    /**
453
-     * @throws DomainException
454
-     * @throws EE_Error
455
-     * @throws InvalidArgumentException
456
-     * @throws InvalidDataTypeException
457
-     * @throws InvalidInterfaceException
458
-     */
459
-    protected function _your_organization_settings()
460
-    {
461
-        $this->_template_args['admin_page_content'] = '';
462
-        try {
463
-            /** @var OrganizationSettings $organization_settings_form */
464
-            $organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
465
-
466
-            $this->_template_args['admin_page_content'] = EEH_HTML::div(
467
-                $organization_settings_form->display(),
468
-                '',
469
-                'padding'
470
-            );
471
-        } catch (Exception $e) {
472
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
473
-        }
474
-        $this->_set_add_edit_form_tags('update_your_organization_settings');
475
-        $this->_set_publish_post_box_vars();
476
-        $this->display_admin_page_with_sidebar();
477
-    }
478
-
479
-
480
-    /**
481
-     * Handler for updating organization settings.
482
-     *
483
-     * @throws EE_Error
484
-     */
485
-    protected function _update_your_organization_settings()
486
-    {
487
-        try {
488
-            /** @var OrganizationSettings $organization_settings_form */
489
-            $organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
490
-
491
-            $success = $organization_settings_form->process($this->request->requestParams());
492
-
493
-            EE_Registry::instance()->CFG = apply_filters(
494
-                'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
495
-                EE_Registry::instance()->CFG
496
-            );
497
-        } catch (Exception $e) {
498
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
499
-            $success = false;
500
-        }
501
-
502
-        if ($success) {
503
-            $success = $this->_update_espresso_configuration(
504
-                esc_html__('Your Organization Settings', 'event_espresso'),
505
-                EE_Registry::instance()->CFG,
506
-                __FILE__,
507
-                __FUNCTION__,
508
-                __LINE__
509
-            );
510
-        }
511
-
512
-        $this->_redirect_after_action($success, '', '', ['action' => 'default'], true);
513
-    }
514
-
515
-
516
-
517
-    /*************        Admin Options        *************/
518
-
519
-
520
-    /**
521
-     * _admin_option_settings
522
-     *
523
-     * @throws EE_Error
524
-     * @throws LogicException
525
-     */
526
-    protected function _admin_option_settings()
527
-    {
528
-        $this->_template_args['admin_page_content'] = '';
529
-        try {
530
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
531
-            // still need this for the old school form in Extend_General_Settings_Admin_Page
532
-            $this->_template_args['values'] = $this->_yes_no_values;
533
-            // also need to account for the do_action that was in the old template
534
-            $admin_options_settings_form->setTemplateArgs($this->_template_args);
535
-            $this->_template_args['admin_page_content'] = EEH_HTML::div(
536
-                $admin_options_settings_form->display(),
537
-                '',
538
-                'padding'
539
-            );
540
-        } catch (Exception $e) {
541
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
542
-        }
543
-        $this->_set_add_edit_form_tags('update_admin_option_settings');
544
-        $this->_set_publish_post_box_vars();
545
-        $this->display_admin_page_with_sidebar();
546
-    }
547
-
548
-
549
-    /**
550
-     * _update_admin_option_settings
551
-     *
552
-     * @throws EE_Error
553
-     * @throws InvalidDataTypeException
554
-     * @throws InvalidFormSubmissionException
555
-     * @throws InvalidArgumentException
556
-     * @throws LogicException
557
-     */
558
-    protected function _update_admin_option_settings()
559
-    {
560
-        try {
561
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
562
-            $admin_options_settings_form->process(
563
-                $this->request->getRequestParam(
564
-                    $admin_options_settings_form->slug(),
565
-                    [],
566
-                    DataType::STRING,
567
-                    true
568
-                )
569
-            );
570
-            EE_Registry::instance()->CFG->admin = apply_filters(
571
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
572
-                EE_Registry::instance()->CFG->admin
573
-            );
574
-        } catch (Exception $e) {
575
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
576
-        }
577
-        $this->_redirect_after_action(
578
-            apply_filters(
579
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
580
-                $this->_update_espresso_configuration(
581
-                    esc_html__('Admin Options', 'event_espresso'),
582
-                    EE_Registry::instance()->CFG->admin,
583
-                    __FILE__,
584
-                    __FUNCTION__,
585
-                    __LINE__
586
-                )
587
-            ),
588
-            esc_html__('Admin Options', 'event_espresso'),
589
-            'updated',
590
-            ['action' => 'admin_option_settings']
591
-        );
592
-    }
593
-
594
-
595
-    /*************        Countries        *************/
596
-
597
-
598
-    /**
599
-     * @param string|null $default
600
-     * @return string
601
-     */
602
-    protected function getCountryISO(?string $default = null): string
603
-    {
604
-        $default = $default ?? $this->getCountryIsoForSite();
605
-        $CNT_ISO = $this->request->getRequestParam('country', $default);
606
-        $CNT_ISO = $this->request->getRequestParam('CNT_ISO', $CNT_ISO);
607
-        return strtoupper($CNT_ISO);
608
-    }
609
-
610
-
611
-    /**
612
-     * @return string
613
-     */
614
-    protected function getCountryIsoForSite(): string
615
-    {
616
-        return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
617
-            ? EE_Registry::instance()->CFG->organization->CNT_ISO
618
-            : 'US';
619
-    }
620
-
621
-
622
-    /**
623
-     * @param string          $CNT_ISO
624
-     * @param EE_Country|null $country
625
-     * @return EE_Base_Class|EE_Country
626
-     * @throws EE_Error
627
-     * @throws InvalidArgumentException
628
-     * @throws InvalidDataTypeException
629
-     * @throws InvalidInterfaceException
630
-     * @throws ReflectionException
631
-     */
632
-    protected function verifyOrGetCountryFromIso(string $CNT_ISO, ?EE_Country $country = null)
633
-    {
634
-        /** @var EE_Country $country */
635
-        return $country instanceof EE_Country && $country->ID() === $CNT_ISO
636
-            ? $country
637
-            : EEM_Country::instance()->get_one_by_ID($CNT_ISO);
638
-    }
639
-
640
-
641
-    /**
642
-     * Output Country Settings view.
643
-     *
644
-     * @throws DomainException
645
-     * @throws EE_Error
646
-     * @throws InvalidArgumentException
647
-     * @throws InvalidDataTypeException
648
-     * @throws InvalidInterfaceException
649
-     * @throws ReflectionException
650
-     */
651
-    protected function _country_settings()
652
-    {
653
-        $CNT_ISO = $this->getCountryISO();
654
-
655
-        $this->_template_args['values']    = $this->_yes_no_values;
656
-        $this->_template_args['countries'] = new EE_Question_Form_Input(
657
-            EE_Question::new_instance(
658
-                [
659
-                  'QST_ID'           => 0,
660
-                  'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
661
-                  'QST_system'       => 'admin-country',
662
-                ]
663
-            ),
664
-            EE_Answer::new_instance(
665
-                [
666
-                    'ANS_ID'    => 0,
667
-                    'ANS_value' => $CNT_ISO,
668
-                ]
669
-            ),
670
-            [
671
-                'input_id'       => 'country',
672
-                'input_name'     => 'country',
673
-                'input_prefix'   => '',
674
-                'append_qstn_id' => false,
675
-            ]
676
-        );
677
-
678
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO);
679
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10);
680
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10);
681
-        $this->_template_args['country_details_settings'] = $this->display_country_settings(
682
-            $country->ID(),
683
-            $country
684
-        );
685
-        $this->_template_args['country_states_settings']  = $this->display_country_states(
686
-            $country->ID(),
687
-            $country
688
-        );
689
-        $this->_template_args['CNT_name_for_site']        = $country->name();
690
-
691
-        $this->_set_add_edit_form_tags('update_country_settings');
692
-        $this->_set_publish_post_box_vars();
693
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
694
-            GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
695
-            $this->_template_args,
696
-            true
697
-        );
698
-        $this->display_admin_page_with_no_sidebar();
699
-    }
700
-
701
-
702
-    /**
703
-     * @param string          $CNT_ISO
704
-     * @param EE_Country|null $country
705
-     * @return string
706
-     * @throws DomainException
707
-     * @throws EE_Error
708
-     * @throws InvalidArgumentException
709
-     * @throws InvalidDataTypeException
710
-     * @throws InvalidInterfaceException
711
-     * @throws ReflectionException
712
-     */
713
-    public function display_country_settings(string $CNT_ISO = '', ?EE_Country $country = null): string
714
-    {
715
-        $CNT_ISO          = $this->getCountryISO($CNT_ISO);
716
-        $CNT_ISO_for_site = $this->getCountryIsoForSite();
717
-
718
-        if (! $CNT_ISO) {
719
-            return '';
720
-        }
721
-
722
-        // for ajax
723
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
724
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
725
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10, 2);
726
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10, 2);
727
-        $country                                  = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
728
-        $CNT_cur_disabled                         = $CNT_ISO !== $CNT_ISO_for_site;
729
-        $this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
730
-
731
-        $country_input_types            = [
732
-            'CNT_active'      => [
733
-                'type'             => 'RADIO_BTN',
734
-                'input_name'       => "cntry[$CNT_ISO]",
735
-                'class'            => '',
736
-                'options'          => $this->_yes_no_values,
737
-                'use_desc_4_label' => true,
738
-            ],
739
-            'CNT_ISO'         => [
740
-                'type'       => 'TEXT',
741
-                'input_name' => "cntry[$CNT_ISO]",
742
-                'class'      => 'ee-input-width--small',
743
-            ],
744
-            'CNT_ISO3'        => [
745
-                'type'       => 'TEXT',
746
-                'input_name' => "cntry[$CNT_ISO]",
747
-                'class'      => 'ee-input-width--small',
748
-            ],
749
-            // 'RGN_ID'          => [
750
-            //     'type'       => 'TEXT',
751
-            //     'input_name' => "cntry[$CNT_ISO]",
752
-            //     'class'      => 'ee-input-width--small',
753
-            // ],
754
-            'CNT_name'        => [
755
-                'type'       => 'TEXT',
756
-                'input_name' => "cntry[$CNT_ISO]",
757
-                'class'      => 'ee-input-width--big',
758
-            ],
759
-            'CNT_cur_code'    => [
760
-                'type'       => 'TEXT',
761
-                'input_name' => "cntry[$CNT_ISO]",
762
-                'class'      => 'ee-input-width--small',
763
-                'disabled'   => $CNT_cur_disabled,
764
-            ],
765
-            'CNT_cur_single'  => [
766
-                'type'       => 'TEXT',
767
-                'input_name' => "cntry[$CNT_ISO]",
768
-                'class'      => 'ee-input-width--reg',
769
-                'disabled'   => $CNT_cur_disabled,
770
-            ],
771
-            'CNT_cur_plural'  => [
772
-                'type'       => 'TEXT',
773
-                'input_name' => "cntry[$CNT_ISO]",
774
-                'class'      => 'ee-input-width--reg',
775
-                'disabled'   => $CNT_cur_disabled,
776
-            ],
777
-            'CNT_cur_sign'    => [
778
-                'type'         => 'TEXT',
779
-                'input_name'   => "cntry[$CNT_ISO]",
780
-                'class'        => 'ee-input-width--small',
781
-                'htmlentities' => false,
782
-                'disabled'     => $CNT_cur_disabled,
783
-            ],
784
-            'CNT_cur_sign_b4' => [
785
-                'type'             => 'RADIO_BTN',
786
-                'input_name'       => "cntry[$CNT_ISO]",
787
-                'class'            => '',
788
-                'options'          => $this->_yes_no_values,
789
-                'use_desc_4_label' => true,
790
-                'disabled'         => $CNT_cur_disabled,
791
-            ],
792
-            'CNT_cur_dec_plc' => [
793
-                'type'       => 'RADIO_BTN',
794
-                'input_name' => "cntry[$CNT_ISO]",
795
-                'class'      => '',
796
-                'options'    => [
797
-                    ['id' => 0, 'text' => ''],
798
-                    ['id' => 1, 'text' => ''],
799
-                    ['id' => 2, 'text' => ''],
800
-                    ['id' => 3, 'text' => ''],
801
-                ],
802
-                'disabled'   => $CNT_cur_disabled,
803
-            ],
804
-            'CNT_cur_dec_mrk' => [
805
-                'type'             => 'RADIO_BTN',
806
-                'input_name'       => "cntry[$CNT_ISO]",
807
-                'class'            => '',
808
-                'options'          => [
809
-                    [
810
-                        'id'   => ',',
811
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
812
-                    ],
813
-                    ['id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')],
814
-                ],
815
-                'use_desc_4_label' => true,
816
-                'disabled'         => $CNT_cur_disabled,
817
-            ],
818
-            'CNT_cur_thsnds'  => [
819
-                'type'             => 'RADIO_BTN',
820
-                'input_name'       => "cntry[$CNT_ISO]",
821
-                'class'            => '',
822
-                'options'          => [
823
-                    [
824
-                        'id'   => ',',
825
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
826
-                    ],
827
-                    [
828
-                        'id'   => '.',
829
-                        'text' => esc_html__('. (decimal)', 'event_espresso'),
830
-                    ],
831
-                    [
832
-                        'id'   => '&nbsp;',
833
-                        'text' => esc_html__('(space)', 'event_espresso'),
834
-                    ],
835
-                    [
836
-                        'id'   => '_',
837
-                        'text' => esc_html__('_ (underscore)', 'event_espresso'),
838
-                    ],
839
-                    [
840
-                        'id'   => "'",
841
-                        'text' => esc_html__("' (apostrophe)", 'event_espresso'),
842
-                    ],
843
-                ],
844
-                'use_desc_4_label' => true,
845
-                'disabled'         => $CNT_cur_disabled,
846
-            ],
847
-            'CNT_tel_code'    => [
848
-                'type'       => 'TEXT',
849
-                'input_name' => "cntry[$CNT_ISO]",
850
-                'class'      => 'ee-input-width--small',
851
-            ],
852
-            'CNT_is_EU'       => [
853
-                'type'             => 'RADIO_BTN',
854
-                'input_name'       => "cntry[$CNT_ISO]",
855
-                'class'            => '',
856
-                'options'          => $this->_yes_no_values,
857
-                'use_desc_4_label' => true,
858
-            ],
859
-        ];
860
-        $this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
861
-            $country,
862
-            $country_input_types
863
-        );
864
-        $country_details_settings       = EEH_Template::display_template(
865
-            GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
866
-            $this->_template_args,
867
-            true
868
-        );
869
-
870
-        if (defined('DOING_AJAX')) {
871
-            $notices = EE_Error::get_notices(false, false, false);
872
-            echo wp_json_encode(
873
-                [
874
-                    'return_data' => $country_details_settings,
875
-                    'success'     => $notices['success'],
876
-                    'errors'      => $notices['errors'],
877
-                ]
878
-            );
879
-            die();
880
-        }
881
-        return $country_details_settings;
882
-    }
883
-
884
-
885
-    /**
886
-     * @param string          $CNT_ISO
887
-     * @param EE_Country|null $country
888
-     * @return string
889
-     * @throws DomainException
890
-     * @throws EE_Error
891
-     * @throws InvalidArgumentException
892
-     * @throws InvalidDataTypeException
893
-     * @throws InvalidInterfaceException
894
-     * @throws ReflectionException
895
-     */
896
-    public function display_country_states(string $CNT_ISO = '', ?EE_Country $country = null): string
897
-    {
898
-        $CNT_ISO = $this->getCountryISO($CNT_ISO);
899
-        if (! $CNT_ISO) {
900
-            return '';
901
-        }
902
-        // for ajax
903
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
904
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
905
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'state_form_field_label_wrap'], 10, 2);
906
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'state_form_field_input__wrap'], 10);
907
-        $states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
908
-        if (empty($states)) {
909
-            /** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
910
-            $countrySubRegionDao = $this->loader->getShared(
911
-                'EventEspresso\core\services\address\CountrySubRegionDao'
912
-            );
913
-            if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
914
-                $country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
915
-                if ($countrySubRegionDao->saveCountrySubRegions($country)) {
916
-                    $states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
917
-                }
918
-            }
919
-        }
920
-        if (is_array($states)) {
921
-            foreach ($states as $STA_ID => $state) {
922
-                if ($state instanceof EE_State) {
923
-                    $inputs = EE_Question_Form_Input::generate_question_form_inputs_for_object(
924
-                        $state,
925
-                        [
926
-                            'STA_abbrev' => [
927
-                                'type'             => 'TEXT',
928
-                                'label'            => esc_html__('Code', 'event_espresso'),
929
-                                'input_name'       => "states[$STA_ID]",
930
-                                'class'            => 'ee-input-width--tiny',
931
-                                'add_mobile_label' => true,
932
-                            ],
933
-                            'STA_name'   => [
934
-                                'type'             => 'TEXT',
935
-                                'label'            => esc_html__('Name', 'event_espresso'),
936
-                                'input_name'       => "states[$STA_ID]",
937
-                                'class'            => 'ee-input-width--big',
938
-                                'add_mobile_label' => true,
939
-                            ],
940
-                            'STA_active' => [
941
-                                'type'             => 'RADIO_BTN',
942
-                                'label'            => esc_html__(
943
-                                    'State Appears in Dropdown Select Lists',
944
-                                    'event_espresso'
945
-                                ),
946
-                                'input_name'       => "states[$STA_ID]",
947
-                                'options'          => $this->_yes_no_values,
948
-                                'use_desc_4_label' => true,
949
-                                'add_mobile_label' => true,
950
-                            ],
951
-                        ]
952
-                    );
953
-
954
-                    $delete_state_url = EE_Admin_Page::add_query_args_and_nonce(
955
-                        [
956
-                            'action'     => 'delete_state',
957
-                            'STA_ID'     => $STA_ID,
958
-                            'CNT_ISO'    => $CNT_ISO,
959
-                            'STA_abbrev' => $state->abbrev(),
960
-                        ],
961
-                        GEN_SET_ADMIN_URL
962
-                    );
963
-
964
-                    $this->_template_args['states'][ $STA_ID ]['inputs']           = $inputs;
965
-                    $this->_template_args['states'][ $STA_ID ]['delete_state_url'] = $delete_state_url;
966
-                }
967
-            }
968
-        } else {
969
-            $this->_template_args['states'] = false;
970
-        }
971
-
972
-        $this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
973
-            ['action' => 'add_new_state'],
974
-            GEN_SET_ADMIN_URL
975
-        );
976
-
977
-        $state_details_settings = EEH_Template::display_template(
978
-            GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
979
-            $this->_template_args,
980
-            true
981
-        );
982
-
983
-        if (defined('DOING_AJAX')) {
984
-            $notices = EE_Error::get_notices(false, false, false);
985
-            echo wp_json_encode(
986
-                [
987
-                    'return_data' => $state_details_settings,
988
-                    'success'     => $notices['success'],
989
-                    'errors'      => $notices['errors'],
990
-                ]
991
-            );
992
-            die();
993
-        }
994
-        return $state_details_settings;
995
-    }
996
-
997
-
998
-    /**
999
-     * @return void
1000
-     * @throws EE_Error
1001
-     * @throws InvalidArgumentException
1002
-     * @throws InvalidDataTypeException
1003
-     * @throws InvalidInterfaceException
1004
-     * @throws ReflectionException
1005
-     */
1006
-    public function add_new_state()
1007
-    {
1008
-        $success = true;
1009
-        $CNT_ISO = $this->getCountryISO('');
1010
-        if (! $CNT_ISO) {
1011
-            EE_Error::add_error(
1012
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1013
-                __FILE__,
1014
-                __FUNCTION__,
1015
-                __LINE__
1016
-            );
1017
-            $success = false;
1018
-        }
1019
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1020
-        if (! $STA_abbrev) {
1021
-            EE_Error::add_error(
1022
-                esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1023
-                __FILE__,
1024
-                __FUNCTION__,
1025
-                __LINE__
1026
-            );
1027
-            $success = false;
1028
-        }
1029
-        $STA_name = $this->request->getRequestParam('STA_name');
1030
-        if (! $STA_name) {
1031
-            EE_Error::add_error(
1032
-                esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1033
-                __FILE__,
1034
-                __FUNCTION__,
1035
-                __LINE__
1036
-            );
1037
-            $success = false;
1038
-        }
1039
-
1040
-        if ($success) {
1041
-            $cols_n_values = [
1042
-                'CNT_ISO'    => $CNT_ISO,
1043
-                'STA_abbrev' => $STA_abbrev,
1044
-                'STA_name'   => $STA_name,
1045
-                'STA_active' => true,
1046
-            ];
1047
-            $success       = EEM_State::instance()->insert($cols_n_values);
1048
-            EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1049
-        }
1050
-
1051
-        if (defined('DOING_AJAX')) {
1052
-            $notices = EE_Error::get_notices(false, false, false);
1053
-            echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1054
-            die();
1055
-        }
1056
-        $this->_redirect_after_action(
1057
-            $success,
1058
-            esc_html__('State', 'event_espresso'),
1059
-            'added',
1060
-            ['action' => 'country_settings']
1061
-        );
1062
-    }
1063
-
1064
-
1065
-    /**
1066
-     * @return void
1067
-     * @throws EE_Error
1068
-     * @throws InvalidArgumentException
1069
-     * @throws InvalidDataTypeException
1070
-     * @throws InvalidInterfaceException
1071
-     * @throws ReflectionException
1072
-     */
1073
-    public function delete_state()
1074
-    {
1075
-        $CNT_ISO    = $this->getCountryISO();
1076
-        $STA_ID     = $this->request->getRequestParam('STA_ID');
1077
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1078
-
1079
-        if (! $STA_ID) {
1080
-            EE_Error::add_error(
1081
-                esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1082
-                __FILE__,
1083
-                __FUNCTION__,
1084
-                __LINE__
1085
-            );
1086
-            return;
1087
-        }
1088
-
1089
-        $success = EEM_State::instance()->delete_by_ID($STA_ID);
1090
-        if ($success !== false) {
1091
-            do_action(
1092
-                'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1093
-                $CNT_ISO,
1094
-                $STA_ID,
1095
-                ['STA_abbrev' => $STA_abbrev]
1096
-            );
1097
-            EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1098
-        }
1099
-        if (defined('DOING_AJAX')) {
1100
-            $notices                = EE_Error::get_notices(false);
1101
-            $notices['return_data'] = true;
1102
-            echo wp_json_encode($notices);
1103
-            die();
1104
-        }
1105
-        $this->_redirect_after_action(
1106
-            $success,
1107
-            esc_html__('State', 'event_espresso'),
1108
-            'deleted',
1109
-            ['action' => 'country_settings']
1110
-        );
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     * @return void
1116
-     * @throws EE_Error
1117
-     * @throws InvalidArgumentException
1118
-     * @throws InvalidDataTypeException
1119
-     * @throws InvalidInterfaceException
1120
-     * @throws ReflectionException
1121
-     */
1122
-    protected function _update_country_settings()
1123
-    {
1124
-        $CNT_ISO = $this->getCountryISO();
1125
-        if (! $CNT_ISO) {
1126
-            EE_Error::add_error(
1127
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1128
-                __FILE__,
1129
-                __FUNCTION__,
1130
-                __LINE__
1131
-            );
1132
-            return;
1133
-        }
1134
-
1135
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1136
-
1137
-        $cols_n_values                    = [];
1138
-        $cols_n_values['CNT_ISO3']        = strtoupper(
1139
-            $this->request->getRequestParam(
1140
-                "cntry[$CNT_ISO][CNT_ISO3]",
1141
-                $country->ISO3()
1142
-            )
1143
-        );
1144
-        $cols_n_values['CNT_name']        = $this->request->getRequestParam(
1145
-            "cntry[$CNT_ISO][CNT_name]",
1146
-            $country->name()
1147
-        );
1148
-        $cols_n_values['CNT_cur_code']    = strtoupper(
1149
-            $this->request->getRequestParam(
1150
-                "cntry[$CNT_ISO][CNT_cur_code]",
1151
-                $country->currency_code()
1152
-            )
1153
-        );
1154
-        $cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1155
-            "cntry[$CNT_ISO][CNT_cur_single]",
1156
-            $country->currency_name_single()
1157
-        );
1158
-        $cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1159
-            "cntry[$CNT_ISO][CNT_cur_plural]",
1160
-            $country->currency_name_plural()
1161
-        );
1162
-        $cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1163
-            "cntry[$CNT_ISO][CNT_cur_sign]",
1164
-            $country->currency_sign()
1165
-        );
1166
-        $cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1167
-            "cntry[$CNT_ISO][CNT_cur_sign_b4]",
1168
-            $country->currency_sign_before(),
1169
-            DataType::BOOL
1170
-        );
1171
-        $cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1172
-            "cntry[$CNT_ISO][CNT_cur_dec_plc]",
1173
-            $country->currency_decimal_places()
1174
-        );
1175
-        $cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1176
-            "cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1177
-            $country->currency_decimal_mark()
1178
-        );
1179
-        $cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1180
-            "cntry[$CNT_ISO][CNT_cur_thsnds]",
1181
-            $country->currency_thousands_separator()
1182
-        );
1183
-        $cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1184
-            "cntry[$CNT_ISO][CNT_tel_code]",
1185
-            $country->telephoneCode()
1186
-        );
1187
-        $cols_n_values['CNT_active']      = $this->request->getRequestParam(
1188
-            "cntry[$CNT_ISO][CNT_active]",
1189
-            $country->isActive(),
1190
-            DataType::BOOL
1191
-        );
1192
-
1193
-        // allow filtering of country data
1194
-        $cols_n_values = apply_filters(
1195
-            'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1196
-            $cols_n_values
1197
-        );
1198
-
1199
-        // where values
1200
-        $where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1201
-        // run the update
1202
-        $success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1203
-
1204
-        // allow filtering of states data
1205
-        $states = apply_filters(
1206
-            'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1207
-            $this->request->getRequestParam('states', [], DataType::STRING, true)
1208
-        );
1209
-
1210
-        if (! empty($states) && $success !== false) {
1211
-            // loop thru state data ( looks like : states[75][STA_name] )
1212
-            foreach ($states as $STA_ID => $state) {
1213
-                $cols_n_values = [
1214
-                    'CNT_ISO'    => $CNT_ISO,
1215
-                    'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1216
-                    'STA_name'   => sanitize_text_field($state['STA_name']),
1217
-                    'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1218
-                ];
1219
-                // where values
1220
-                $where_cols_n_values = [['STA_ID' => $STA_ID]];
1221
-                // run the update
1222
-                $success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1223
-                if ($success !== false) {
1224
-                    do_action(
1225
-                        'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1226
-                        $CNT_ISO,
1227
-                        $STA_ID,
1228
-                        $cols_n_values
1229
-                    );
1230
-                }
1231
-            }
1232
-        }
1233
-        // check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1234
-        if (
1235
-            isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1236
-            && $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1237
-        ) {
1238
-            EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1239
-            EE_Registry::instance()->CFG->update_espresso_config();
1240
-        }
1241
-
1242
-        if ($success !== false) {
1243
-            EE_Error::add_success(
1244
-                esc_html__('Country Settings updated successfully.', 'event_espresso')
1245
-            );
1246
-        }
1247
-        $this->_redirect_after_action(
1248
-            $success,
1249
-            '',
1250
-            '',
1251
-            ['action' => 'country_settings', 'country' => $CNT_ISO],
1252
-            true
1253
-        );
1254
-    }
1255
-
1256
-
1257
-    /**
1258
-     * form_form_field_label_wrap
1259
-     *
1260
-     * @param string $label
1261
-     * @return string
1262
-     */
1263
-    public function country_form_field_label_wrap(string $label): string
1264
-    {
1265
-        return '
25
+	/**
26
+	 * @var EE_Core_Config
27
+	 */
28
+	public $core_config;
29
+
30
+
31
+	/**
32
+	 * Initialize basic properties.
33
+	 */
34
+	protected function _init_page_props()
35
+	{
36
+		$this->page_slug        = GEN_SET_PG_SLUG;
37
+		$this->page_label       = GEN_SET_LABEL;
38
+		$this->_admin_base_url  = GEN_SET_ADMIN_URL;
39
+		$this->_admin_base_path = GEN_SET_ADMIN;
40
+
41
+		$this->core_config = EE_Registry::instance()->CFG->core;
42
+	}
43
+
44
+
45
+	/**
46
+	 * Set ajax hooks
47
+	 */
48
+	protected function _ajax_hooks()
49
+	{
50
+		add_action('wp_ajax_espresso_display_country_settings', [$this, 'display_country_settings']);
51
+		add_action('wp_ajax_espresso_display_country_states', [$this, 'display_country_states']);
52
+		add_action('wp_ajax_espresso_delete_state', [$this, 'delete_state'], 10, 3);
53
+		add_action('wp_ajax_espresso_add_new_state', [$this, 'add_new_state']);
54
+	}
55
+
56
+
57
+	/**
58
+	 * More page properties initialization.
59
+	 */
60
+	protected function _define_page_props()
61
+	{
62
+		$this->_admin_page_title = GEN_SET_LABEL;
63
+		$this->_labels           = ['publishbox' => esc_html__('Update Settings', 'event_espresso')];
64
+	}
65
+
66
+
67
+	/**
68
+	 * Set page routes property.
69
+	 */
70
+	protected function _set_page_routes()
71
+	{
72
+		$this->_page_routes = [
73
+			'critical_pages'                => [
74
+				'func'       => [$this, '_espresso_page_settings'],
75
+				'capability' => 'manage_options',
76
+			],
77
+			'update_espresso_page_settings' => [
78
+				'func'       => [$this, '_update_espresso_page_settings'],
79
+				'capability' => 'manage_options',
80
+				'noheader'   => true,
81
+			],
82
+			'default'                       => [
83
+				'func'       => [$this, '_your_organization_settings'],
84
+				'capability' => 'manage_options',
85
+			],
86
+
87
+			'update_your_organization_settings' => [
88
+				'func'       => [$this, '_update_your_organization_settings'],
89
+				'capability' => 'manage_options',
90
+				'noheader'   => true,
91
+			],
92
+
93
+			'admin_option_settings' => [
94
+				'func'       => [$this, '_admin_option_settings'],
95
+				'capability' => 'manage_options',
96
+			],
97
+
98
+			'update_admin_option_settings' => [
99
+				'func'       => [$this, '_update_admin_option_settings'],
100
+				'capability' => 'manage_options',
101
+				'noheader'   => true,
102
+			],
103
+
104
+			'country_settings' => [
105
+				'func'       => [$this, '_country_settings'],
106
+				'capability' => 'manage_options',
107
+			],
108
+
109
+			'update_country_settings' => [
110
+				'func'       => [$this, '_update_country_settings'],
111
+				'capability' => 'manage_options',
112
+				'noheader'   => true,
113
+			],
114
+
115
+			'display_country_settings' => [
116
+				'func'       => [$this, 'display_country_settings'],
117
+				'capability' => 'manage_options',
118
+				'noheader'   => true,
119
+			],
120
+
121
+			'add_new_state' => [
122
+				'func'       => [$this, 'add_new_state'],
123
+				'capability' => 'manage_options',
124
+				'noheader'   => true,
125
+			],
126
+
127
+			'delete_state'            => [
128
+				'func'       => [$this, 'delete_state'],
129
+				'capability' => 'manage_options',
130
+				'noheader'   => true,
131
+			],
132
+
133
+			'privacy_settings'        => [
134
+				'func'       => [$this, 'privacySettings'],
135
+				'capability' => 'manage_options',
136
+			],
137
+
138
+			'update_privacy_settings' => [
139
+				'func'               => [$this, 'updatePrivacySettings'],
140
+				'capability'         => 'manage_options',
141
+				'noheader'           => true,
142
+				'headers_sent_route' => 'privacy_settings',
143
+			],
144
+
145
+			'set_font_size'            => [
146
+				'func'       => [$this, 'setFontSize'],
147
+				'noheader'   => true,
148
+			],
149
+		];
150
+	}
151
+
152
+
153
+	/**
154
+	 * Set page configuration property
155
+	 */
156
+	protected function _set_page_config()
157
+	{
158
+		$this->_page_config = [
159
+			'critical_pages'        => [
160
+				'nav'           => [
161
+					'label' => esc_html__('Critical Pages', 'event_espresso'),
162
+					'icon' => 'dashicons-warning',
163
+					'order' => 50,
164
+				],
165
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
166
+				'help_tabs'     => [
167
+					'general_settings_critical_pages_help_tab' => [
168
+						'title'    => esc_html__('Critical Pages', 'event_espresso'),
169
+						'filename' => 'general_settings_critical_pages',
170
+					],
171
+				],
172
+				'require_nonce' => false,
173
+			],
174
+			'default'               => [
175
+				'nav'           => [
176
+					'label' => esc_html__('Your Organization', 'event_espresso'),
177
+					'icon' => 'dashicons-admin-home',
178
+					'order' => 20,
179
+				],
180
+				'help_tabs'     => [
181
+					'general_settings_your_organization_help_tab' => [
182
+						'title'    => esc_html__('Your Organization', 'event_espresso'),
183
+						'filename' => 'general_settings_your_organization',
184
+					],
185
+				],
186
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
187
+				'require_nonce' => false,
188
+			],
189
+			'admin_option_settings' => [
190
+				'nav'           => [
191
+					'label' => esc_html__('Admin Options', 'event_espresso'),
192
+					'icon' => 'dashicons-admin-settings',
193
+					'order' => 60,
194
+				],
195
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
196
+				'help_tabs'     => [
197
+					'general_settings_admin_options_help_tab' => [
198
+						'title'    => esc_html__('Admin Options', 'event_espresso'),
199
+						'filename' => 'general_settings_admin_options',
200
+					],
201
+				],
202
+				'require_nonce' => false,
203
+			],
204
+			'country_settings'      => [
205
+				'nav'           => [
206
+					'label' => esc_html__('Countries', 'event_espresso'),
207
+					'icon' => 'dashicons-admin-site',
208
+					'order' => 70,
209
+				],
210
+				'help_tabs'     => [
211
+					'general_settings_countries_help_tab' => [
212
+						'title'    => esc_html__('Countries', 'event_espresso'),
213
+						'filename' => 'general_settings_countries',
214
+					],
215
+				],
216
+				'require_nonce' => false,
217
+			],
218
+			'privacy_settings'      => [
219
+				'nav'           => [
220
+					'label' => esc_html__('Privacy', 'event_espresso'),
221
+					'icon' => 'dashicons-privacy',
222
+					'order' => 80,
223
+				],
224
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
225
+				'require_nonce' => false,
226
+			],
227
+		];
228
+	}
229
+
230
+
231
+	protected function _add_screen_options()
232
+	{
233
+	}
234
+
235
+
236
+	protected function _add_feature_pointers()
237
+	{
238
+	}
239
+
240
+
241
+	/**
242
+	 * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
243
+	 */
244
+	public function load_scripts_styles()
245
+	{
246
+		// styles
247
+		wp_enqueue_style('espresso-ui-theme');
248
+		// scripts
249
+		wp_enqueue_script('ee_admin_js');
250
+	}
251
+
252
+
253
+	/**
254
+	 * Execute logic running on `admin_init`
255
+	 */
256
+	public function admin_init()
257
+	{
258
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(
259
+			esc_html__(
260
+				'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
261
+				'event_espresso'
262
+			)
263
+		);
264
+		EE_Registry::$i18n_js_strings['error_occurred']          = wp_strip_all_tags(
265
+			esc_html__(
266
+				'An error occurred! Please refresh the page and try again.',
267
+				'event_espresso'
268
+			)
269
+		);
270
+		EE_Registry::$i18n_js_strings['confirm_delete_state']    = wp_strip_all_tags(
271
+			esc_html__(
272
+				'Are you sure you want to delete this State / Province?',
273
+				'event_espresso'
274
+			)
275
+		);
276
+		EE_Registry::$i18n_js_strings['ajax_url']                = admin_url(
277
+			'admin-ajax.php?page=espresso_general_settings',
278
+			is_ssl() ? 'https://' : 'http://'
279
+		);
280
+	}
281
+
282
+
283
+	public function admin_notices()
284
+	{
285
+	}
286
+
287
+
288
+	public function admin_footer_scripts()
289
+	{
290
+	}
291
+
292
+
293
+	/**
294
+	 * Enqueue scripts and styles for the default route.
295
+	 */
296
+	public function load_scripts_styles_default()
297
+	{
298
+		// styles
299
+		wp_enqueue_style('thickbox');
300
+		// scripts
301
+		wp_enqueue_script('media-upload');
302
+		wp_enqueue_script('thickbox');
303
+		wp_register_script(
304
+			'organization_settings',
305
+			GEN_SET_ASSETS_URL . 'your_organization_settings.js',
306
+			['jquery', 'media-upload', 'thickbox'],
307
+			EVENT_ESPRESSO_VERSION,
308
+			true
309
+		);
310
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
311
+		wp_enqueue_script('organization_settings');
312
+		wp_enqueue_style('organization-css');
313
+		$confirm_image_delete = [
314
+			'text' => wp_strip_all_tags(
315
+				esc_html__(
316
+					'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
317
+					'event_espresso'
318
+				)
319
+			),
320
+		];
321
+		wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
322
+	}
323
+
324
+
325
+	/**
326
+	 * Enqueue scripts and styles for the country settings route.
327
+	 */
328
+	public function load_scripts_styles_country_settings()
329
+	{
330
+		// scripts
331
+		wp_register_script(
332
+			'gen_settings_countries',
333
+			GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
334
+			['ee_admin_js'],
335
+			EVENT_ESPRESSO_VERSION,
336
+			true
337
+		);
338
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
339
+		wp_enqueue_script('gen_settings_countries');
340
+		wp_enqueue_style('organization-css');
341
+	}
342
+
343
+
344
+	/*************        Espresso Pages        *************/
345
+	/**
346
+	 * _espresso_page_settings
347
+	 *
348
+	 * @throws EE_Error
349
+	 * @throws DomainException
350
+	 * @throws DomainException
351
+	 * @throws InvalidDataTypeException
352
+	 * @throws InvalidArgumentException
353
+	 */
354
+	protected function _espresso_page_settings()
355
+	{
356
+		// Check to make sure all of the main pages are set up properly,
357
+		// if not create the default pages and display an admin notice
358
+		EEH_Activation::verify_default_pages_exist();
359
+		$this->_transient_garbage_collection();
360
+
361
+		$this->_template_args['values'] = $this->_yes_no_values;
362
+
363
+		$this->_template_args['reg_page_id']  = $this->core_config->reg_page_id ?? null;
364
+		$this->_template_args['reg_page_obj'] = isset($this->core_config->reg_page_id)
365
+			? get_post($this->core_config->reg_page_id)
366
+			: false;
367
+
368
+		$this->_template_args['txn_page_id']  = $this->core_config->txn_page_id ?? null;
369
+		$this->_template_args['txn_page_obj'] = isset($this->core_config->txn_page_id)
370
+			? get_post($this->core_config->txn_page_id)
371
+			: false;
372
+
373
+		$this->_template_args['thank_you_page_id']  = $this->core_config->thank_you_page_id ?? null;
374
+		$this->_template_args['thank_you_page_obj'] = isset($this->core_config->thank_you_page_id)
375
+			? get_post($this->core_config->thank_you_page_id)
376
+			: false;
377
+
378
+		$this->_template_args['cancel_page_id']  = $this->core_config->cancel_page_id ?? null;
379
+		$this->_template_args['cancel_page_obj'] = isset($this->core_config->cancel_page_id)
380
+			? get_post($this->core_config->cancel_page_id)
381
+			: false;
382
+
383
+		$this->_set_add_edit_form_tags('update_espresso_page_settings');
384
+		$this->_set_publish_post_box_vars();
385
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
386
+			GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
387
+			$this->_template_args,
388
+			true
389
+		);
390
+		$this->display_admin_page_with_sidebar();
391
+	}
392
+
393
+
394
+	/**
395
+	 * Handler for updating espresso page settings.
396
+	 *
397
+	 * @throws EE_Error
398
+	 */
399
+	protected function _update_espresso_page_settings()
400
+	{
401
+		$this->core_config = EE_Registry::instance()->CFG->core;
402
+		// capture incoming request data && set page IDs
403
+		$this->core_config->reg_page_id       = $this->request->getRequestParam(
404
+			'reg_page_id',
405
+			$this->core_config->reg_page_id,
406
+			DataType::INT
407
+		);
408
+		$this->core_config->txn_page_id       = $this->request->getRequestParam(
409
+			'txn_page_id',
410
+			$this->core_config->txn_page_id,
411
+			DataType::INT
412
+		);
413
+		$this->core_config->thank_you_page_id = $this->request->getRequestParam(
414
+			'thank_you_page_id',
415
+			$this->core_config->thank_you_page_id,
416
+			DataType::INT
417
+		);
418
+		$this->core_config->cancel_page_id    = $this->request->getRequestParam(
419
+			'cancel_page_id',
420
+			$this->core_config->cancel_page_id,
421
+			DataType::INT
422
+		);
423
+
424
+		$this->core_config = apply_filters(
425
+			'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
426
+			$this->core_config,
427
+			$this->request->requestParams()
428
+		);
429
+
430
+		$what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
431
+		$this->_redirect_after_action(
432
+			$this->_update_espresso_configuration(
433
+				$what,
434
+				$this->core_config,
435
+				__FILE__,
436
+				__FUNCTION__,
437
+				__LINE__
438
+			),
439
+			$what,
440
+			'',
441
+			[
442
+				'action' => 'critical_pages',
443
+			],
444
+			true
445
+		);
446
+	}
447
+
448
+
449
+	/*************        Your Organization        *************/
450
+
451
+
452
+	/**
453
+	 * @throws DomainException
454
+	 * @throws EE_Error
455
+	 * @throws InvalidArgumentException
456
+	 * @throws InvalidDataTypeException
457
+	 * @throws InvalidInterfaceException
458
+	 */
459
+	protected function _your_organization_settings()
460
+	{
461
+		$this->_template_args['admin_page_content'] = '';
462
+		try {
463
+			/** @var OrganizationSettings $organization_settings_form */
464
+			$organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
465
+
466
+			$this->_template_args['admin_page_content'] = EEH_HTML::div(
467
+				$organization_settings_form->display(),
468
+				'',
469
+				'padding'
470
+			);
471
+		} catch (Exception $e) {
472
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
473
+		}
474
+		$this->_set_add_edit_form_tags('update_your_organization_settings');
475
+		$this->_set_publish_post_box_vars();
476
+		$this->display_admin_page_with_sidebar();
477
+	}
478
+
479
+
480
+	/**
481
+	 * Handler for updating organization settings.
482
+	 *
483
+	 * @throws EE_Error
484
+	 */
485
+	protected function _update_your_organization_settings()
486
+	{
487
+		try {
488
+			/** @var OrganizationSettings $organization_settings_form */
489
+			$organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
490
+
491
+			$success = $organization_settings_form->process($this->request->requestParams());
492
+
493
+			EE_Registry::instance()->CFG = apply_filters(
494
+				'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
495
+				EE_Registry::instance()->CFG
496
+			);
497
+		} catch (Exception $e) {
498
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
499
+			$success = false;
500
+		}
501
+
502
+		if ($success) {
503
+			$success = $this->_update_espresso_configuration(
504
+				esc_html__('Your Organization Settings', 'event_espresso'),
505
+				EE_Registry::instance()->CFG,
506
+				__FILE__,
507
+				__FUNCTION__,
508
+				__LINE__
509
+			);
510
+		}
511
+
512
+		$this->_redirect_after_action($success, '', '', ['action' => 'default'], true);
513
+	}
514
+
515
+
516
+
517
+	/*************        Admin Options        *************/
518
+
519
+
520
+	/**
521
+	 * _admin_option_settings
522
+	 *
523
+	 * @throws EE_Error
524
+	 * @throws LogicException
525
+	 */
526
+	protected function _admin_option_settings()
527
+	{
528
+		$this->_template_args['admin_page_content'] = '';
529
+		try {
530
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
531
+			// still need this for the old school form in Extend_General_Settings_Admin_Page
532
+			$this->_template_args['values'] = $this->_yes_no_values;
533
+			// also need to account for the do_action that was in the old template
534
+			$admin_options_settings_form->setTemplateArgs($this->_template_args);
535
+			$this->_template_args['admin_page_content'] = EEH_HTML::div(
536
+				$admin_options_settings_form->display(),
537
+				'',
538
+				'padding'
539
+			);
540
+		} catch (Exception $e) {
541
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
542
+		}
543
+		$this->_set_add_edit_form_tags('update_admin_option_settings');
544
+		$this->_set_publish_post_box_vars();
545
+		$this->display_admin_page_with_sidebar();
546
+	}
547
+
548
+
549
+	/**
550
+	 * _update_admin_option_settings
551
+	 *
552
+	 * @throws EE_Error
553
+	 * @throws InvalidDataTypeException
554
+	 * @throws InvalidFormSubmissionException
555
+	 * @throws InvalidArgumentException
556
+	 * @throws LogicException
557
+	 */
558
+	protected function _update_admin_option_settings()
559
+	{
560
+		try {
561
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
562
+			$admin_options_settings_form->process(
563
+				$this->request->getRequestParam(
564
+					$admin_options_settings_form->slug(),
565
+					[],
566
+					DataType::STRING,
567
+					true
568
+				)
569
+			);
570
+			EE_Registry::instance()->CFG->admin = apply_filters(
571
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
572
+				EE_Registry::instance()->CFG->admin
573
+			);
574
+		} catch (Exception $e) {
575
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
576
+		}
577
+		$this->_redirect_after_action(
578
+			apply_filters(
579
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
580
+				$this->_update_espresso_configuration(
581
+					esc_html__('Admin Options', 'event_espresso'),
582
+					EE_Registry::instance()->CFG->admin,
583
+					__FILE__,
584
+					__FUNCTION__,
585
+					__LINE__
586
+				)
587
+			),
588
+			esc_html__('Admin Options', 'event_espresso'),
589
+			'updated',
590
+			['action' => 'admin_option_settings']
591
+		);
592
+	}
593
+
594
+
595
+	/*************        Countries        *************/
596
+
597
+
598
+	/**
599
+	 * @param string|null $default
600
+	 * @return string
601
+	 */
602
+	protected function getCountryISO(?string $default = null): string
603
+	{
604
+		$default = $default ?? $this->getCountryIsoForSite();
605
+		$CNT_ISO = $this->request->getRequestParam('country', $default);
606
+		$CNT_ISO = $this->request->getRequestParam('CNT_ISO', $CNT_ISO);
607
+		return strtoupper($CNT_ISO);
608
+	}
609
+
610
+
611
+	/**
612
+	 * @return string
613
+	 */
614
+	protected function getCountryIsoForSite(): string
615
+	{
616
+		return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
617
+			? EE_Registry::instance()->CFG->organization->CNT_ISO
618
+			: 'US';
619
+	}
620
+
621
+
622
+	/**
623
+	 * @param string          $CNT_ISO
624
+	 * @param EE_Country|null $country
625
+	 * @return EE_Base_Class|EE_Country
626
+	 * @throws EE_Error
627
+	 * @throws InvalidArgumentException
628
+	 * @throws InvalidDataTypeException
629
+	 * @throws InvalidInterfaceException
630
+	 * @throws ReflectionException
631
+	 */
632
+	protected function verifyOrGetCountryFromIso(string $CNT_ISO, ?EE_Country $country = null)
633
+	{
634
+		/** @var EE_Country $country */
635
+		return $country instanceof EE_Country && $country->ID() === $CNT_ISO
636
+			? $country
637
+			: EEM_Country::instance()->get_one_by_ID($CNT_ISO);
638
+	}
639
+
640
+
641
+	/**
642
+	 * Output Country Settings view.
643
+	 *
644
+	 * @throws DomainException
645
+	 * @throws EE_Error
646
+	 * @throws InvalidArgumentException
647
+	 * @throws InvalidDataTypeException
648
+	 * @throws InvalidInterfaceException
649
+	 * @throws ReflectionException
650
+	 */
651
+	protected function _country_settings()
652
+	{
653
+		$CNT_ISO = $this->getCountryISO();
654
+
655
+		$this->_template_args['values']    = $this->_yes_no_values;
656
+		$this->_template_args['countries'] = new EE_Question_Form_Input(
657
+			EE_Question::new_instance(
658
+				[
659
+				  'QST_ID'           => 0,
660
+				  'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
661
+				  'QST_system'       => 'admin-country',
662
+				]
663
+			),
664
+			EE_Answer::new_instance(
665
+				[
666
+					'ANS_ID'    => 0,
667
+					'ANS_value' => $CNT_ISO,
668
+				]
669
+			),
670
+			[
671
+				'input_id'       => 'country',
672
+				'input_name'     => 'country',
673
+				'input_prefix'   => '',
674
+				'append_qstn_id' => false,
675
+			]
676
+		);
677
+
678
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO);
679
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10);
680
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10);
681
+		$this->_template_args['country_details_settings'] = $this->display_country_settings(
682
+			$country->ID(),
683
+			$country
684
+		);
685
+		$this->_template_args['country_states_settings']  = $this->display_country_states(
686
+			$country->ID(),
687
+			$country
688
+		);
689
+		$this->_template_args['CNT_name_for_site']        = $country->name();
690
+
691
+		$this->_set_add_edit_form_tags('update_country_settings');
692
+		$this->_set_publish_post_box_vars();
693
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
694
+			GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
695
+			$this->_template_args,
696
+			true
697
+		);
698
+		$this->display_admin_page_with_no_sidebar();
699
+	}
700
+
701
+
702
+	/**
703
+	 * @param string          $CNT_ISO
704
+	 * @param EE_Country|null $country
705
+	 * @return string
706
+	 * @throws DomainException
707
+	 * @throws EE_Error
708
+	 * @throws InvalidArgumentException
709
+	 * @throws InvalidDataTypeException
710
+	 * @throws InvalidInterfaceException
711
+	 * @throws ReflectionException
712
+	 */
713
+	public function display_country_settings(string $CNT_ISO = '', ?EE_Country $country = null): string
714
+	{
715
+		$CNT_ISO          = $this->getCountryISO($CNT_ISO);
716
+		$CNT_ISO_for_site = $this->getCountryIsoForSite();
717
+
718
+		if (! $CNT_ISO) {
719
+			return '';
720
+		}
721
+
722
+		// for ajax
723
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
724
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
725
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10, 2);
726
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10, 2);
727
+		$country                                  = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
728
+		$CNT_cur_disabled                         = $CNT_ISO !== $CNT_ISO_for_site;
729
+		$this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
730
+
731
+		$country_input_types            = [
732
+			'CNT_active'      => [
733
+				'type'             => 'RADIO_BTN',
734
+				'input_name'       => "cntry[$CNT_ISO]",
735
+				'class'            => '',
736
+				'options'          => $this->_yes_no_values,
737
+				'use_desc_4_label' => true,
738
+			],
739
+			'CNT_ISO'         => [
740
+				'type'       => 'TEXT',
741
+				'input_name' => "cntry[$CNT_ISO]",
742
+				'class'      => 'ee-input-width--small',
743
+			],
744
+			'CNT_ISO3'        => [
745
+				'type'       => 'TEXT',
746
+				'input_name' => "cntry[$CNT_ISO]",
747
+				'class'      => 'ee-input-width--small',
748
+			],
749
+			// 'RGN_ID'          => [
750
+			//     'type'       => 'TEXT',
751
+			//     'input_name' => "cntry[$CNT_ISO]",
752
+			//     'class'      => 'ee-input-width--small',
753
+			// ],
754
+			'CNT_name'        => [
755
+				'type'       => 'TEXT',
756
+				'input_name' => "cntry[$CNT_ISO]",
757
+				'class'      => 'ee-input-width--big',
758
+			],
759
+			'CNT_cur_code'    => [
760
+				'type'       => 'TEXT',
761
+				'input_name' => "cntry[$CNT_ISO]",
762
+				'class'      => 'ee-input-width--small',
763
+				'disabled'   => $CNT_cur_disabled,
764
+			],
765
+			'CNT_cur_single'  => [
766
+				'type'       => 'TEXT',
767
+				'input_name' => "cntry[$CNT_ISO]",
768
+				'class'      => 'ee-input-width--reg',
769
+				'disabled'   => $CNT_cur_disabled,
770
+			],
771
+			'CNT_cur_plural'  => [
772
+				'type'       => 'TEXT',
773
+				'input_name' => "cntry[$CNT_ISO]",
774
+				'class'      => 'ee-input-width--reg',
775
+				'disabled'   => $CNT_cur_disabled,
776
+			],
777
+			'CNT_cur_sign'    => [
778
+				'type'         => 'TEXT',
779
+				'input_name'   => "cntry[$CNT_ISO]",
780
+				'class'        => 'ee-input-width--small',
781
+				'htmlentities' => false,
782
+				'disabled'     => $CNT_cur_disabled,
783
+			],
784
+			'CNT_cur_sign_b4' => [
785
+				'type'             => 'RADIO_BTN',
786
+				'input_name'       => "cntry[$CNT_ISO]",
787
+				'class'            => '',
788
+				'options'          => $this->_yes_no_values,
789
+				'use_desc_4_label' => true,
790
+				'disabled'         => $CNT_cur_disabled,
791
+			],
792
+			'CNT_cur_dec_plc' => [
793
+				'type'       => 'RADIO_BTN',
794
+				'input_name' => "cntry[$CNT_ISO]",
795
+				'class'      => '',
796
+				'options'    => [
797
+					['id' => 0, 'text' => ''],
798
+					['id' => 1, 'text' => ''],
799
+					['id' => 2, 'text' => ''],
800
+					['id' => 3, 'text' => ''],
801
+				],
802
+				'disabled'   => $CNT_cur_disabled,
803
+			],
804
+			'CNT_cur_dec_mrk' => [
805
+				'type'             => 'RADIO_BTN',
806
+				'input_name'       => "cntry[$CNT_ISO]",
807
+				'class'            => '',
808
+				'options'          => [
809
+					[
810
+						'id'   => ',',
811
+						'text' => esc_html__(', (comma)', 'event_espresso'),
812
+					],
813
+					['id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')],
814
+				],
815
+				'use_desc_4_label' => true,
816
+				'disabled'         => $CNT_cur_disabled,
817
+			],
818
+			'CNT_cur_thsnds'  => [
819
+				'type'             => 'RADIO_BTN',
820
+				'input_name'       => "cntry[$CNT_ISO]",
821
+				'class'            => '',
822
+				'options'          => [
823
+					[
824
+						'id'   => ',',
825
+						'text' => esc_html__(', (comma)', 'event_espresso'),
826
+					],
827
+					[
828
+						'id'   => '.',
829
+						'text' => esc_html__('. (decimal)', 'event_espresso'),
830
+					],
831
+					[
832
+						'id'   => '&nbsp;',
833
+						'text' => esc_html__('(space)', 'event_espresso'),
834
+					],
835
+					[
836
+						'id'   => '_',
837
+						'text' => esc_html__('_ (underscore)', 'event_espresso'),
838
+					],
839
+					[
840
+						'id'   => "'",
841
+						'text' => esc_html__("' (apostrophe)", 'event_espresso'),
842
+					],
843
+				],
844
+				'use_desc_4_label' => true,
845
+				'disabled'         => $CNT_cur_disabled,
846
+			],
847
+			'CNT_tel_code'    => [
848
+				'type'       => 'TEXT',
849
+				'input_name' => "cntry[$CNT_ISO]",
850
+				'class'      => 'ee-input-width--small',
851
+			],
852
+			'CNT_is_EU'       => [
853
+				'type'             => 'RADIO_BTN',
854
+				'input_name'       => "cntry[$CNT_ISO]",
855
+				'class'            => '',
856
+				'options'          => $this->_yes_no_values,
857
+				'use_desc_4_label' => true,
858
+			],
859
+		];
860
+		$this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
861
+			$country,
862
+			$country_input_types
863
+		);
864
+		$country_details_settings       = EEH_Template::display_template(
865
+			GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
866
+			$this->_template_args,
867
+			true
868
+		);
869
+
870
+		if (defined('DOING_AJAX')) {
871
+			$notices = EE_Error::get_notices(false, false, false);
872
+			echo wp_json_encode(
873
+				[
874
+					'return_data' => $country_details_settings,
875
+					'success'     => $notices['success'],
876
+					'errors'      => $notices['errors'],
877
+				]
878
+			);
879
+			die();
880
+		}
881
+		return $country_details_settings;
882
+	}
883
+
884
+
885
+	/**
886
+	 * @param string          $CNT_ISO
887
+	 * @param EE_Country|null $country
888
+	 * @return string
889
+	 * @throws DomainException
890
+	 * @throws EE_Error
891
+	 * @throws InvalidArgumentException
892
+	 * @throws InvalidDataTypeException
893
+	 * @throws InvalidInterfaceException
894
+	 * @throws ReflectionException
895
+	 */
896
+	public function display_country_states(string $CNT_ISO = '', ?EE_Country $country = null): string
897
+	{
898
+		$CNT_ISO = $this->getCountryISO($CNT_ISO);
899
+		if (! $CNT_ISO) {
900
+			return '';
901
+		}
902
+		// for ajax
903
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
904
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
905
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'state_form_field_label_wrap'], 10, 2);
906
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'state_form_field_input__wrap'], 10);
907
+		$states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
908
+		if (empty($states)) {
909
+			/** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
910
+			$countrySubRegionDao = $this->loader->getShared(
911
+				'EventEspresso\core\services\address\CountrySubRegionDao'
912
+			);
913
+			if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
914
+				$country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
915
+				if ($countrySubRegionDao->saveCountrySubRegions($country)) {
916
+					$states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
917
+				}
918
+			}
919
+		}
920
+		if (is_array($states)) {
921
+			foreach ($states as $STA_ID => $state) {
922
+				if ($state instanceof EE_State) {
923
+					$inputs = EE_Question_Form_Input::generate_question_form_inputs_for_object(
924
+						$state,
925
+						[
926
+							'STA_abbrev' => [
927
+								'type'             => 'TEXT',
928
+								'label'            => esc_html__('Code', 'event_espresso'),
929
+								'input_name'       => "states[$STA_ID]",
930
+								'class'            => 'ee-input-width--tiny',
931
+								'add_mobile_label' => true,
932
+							],
933
+							'STA_name'   => [
934
+								'type'             => 'TEXT',
935
+								'label'            => esc_html__('Name', 'event_espresso'),
936
+								'input_name'       => "states[$STA_ID]",
937
+								'class'            => 'ee-input-width--big',
938
+								'add_mobile_label' => true,
939
+							],
940
+							'STA_active' => [
941
+								'type'             => 'RADIO_BTN',
942
+								'label'            => esc_html__(
943
+									'State Appears in Dropdown Select Lists',
944
+									'event_espresso'
945
+								),
946
+								'input_name'       => "states[$STA_ID]",
947
+								'options'          => $this->_yes_no_values,
948
+								'use_desc_4_label' => true,
949
+								'add_mobile_label' => true,
950
+							],
951
+						]
952
+					);
953
+
954
+					$delete_state_url = EE_Admin_Page::add_query_args_and_nonce(
955
+						[
956
+							'action'     => 'delete_state',
957
+							'STA_ID'     => $STA_ID,
958
+							'CNT_ISO'    => $CNT_ISO,
959
+							'STA_abbrev' => $state->abbrev(),
960
+						],
961
+						GEN_SET_ADMIN_URL
962
+					);
963
+
964
+					$this->_template_args['states'][ $STA_ID ]['inputs']           = $inputs;
965
+					$this->_template_args['states'][ $STA_ID ]['delete_state_url'] = $delete_state_url;
966
+				}
967
+			}
968
+		} else {
969
+			$this->_template_args['states'] = false;
970
+		}
971
+
972
+		$this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
973
+			['action' => 'add_new_state'],
974
+			GEN_SET_ADMIN_URL
975
+		);
976
+
977
+		$state_details_settings = EEH_Template::display_template(
978
+			GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
979
+			$this->_template_args,
980
+			true
981
+		);
982
+
983
+		if (defined('DOING_AJAX')) {
984
+			$notices = EE_Error::get_notices(false, false, false);
985
+			echo wp_json_encode(
986
+				[
987
+					'return_data' => $state_details_settings,
988
+					'success'     => $notices['success'],
989
+					'errors'      => $notices['errors'],
990
+				]
991
+			);
992
+			die();
993
+		}
994
+		return $state_details_settings;
995
+	}
996
+
997
+
998
+	/**
999
+	 * @return void
1000
+	 * @throws EE_Error
1001
+	 * @throws InvalidArgumentException
1002
+	 * @throws InvalidDataTypeException
1003
+	 * @throws InvalidInterfaceException
1004
+	 * @throws ReflectionException
1005
+	 */
1006
+	public function add_new_state()
1007
+	{
1008
+		$success = true;
1009
+		$CNT_ISO = $this->getCountryISO('');
1010
+		if (! $CNT_ISO) {
1011
+			EE_Error::add_error(
1012
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1013
+				__FILE__,
1014
+				__FUNCTION__,
1015
+				__LINE__
1016
+			);
1017
+			$success = false;
1018
+		}
1019
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1020
+		if (! $STA_abbrev) {
1021
+			EE_Error::add_error(
1022
+				esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1023
+				__FILE__,
1024
+				__FUNCTION__,
1025
+				__LINE__
1026
+			);
1027
+			$success = false;
1028
+		}
1029
+		$STA_name = $this->request->getRequestParam('STA_name');
1030
+		if (! $STA_name) {
1031
+			EE_Error::add_error(
1032
+				esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1033
+				__FILE__,
1034
+				__FUNCTION__,
1035
+				__LINE__
1036
+			);
1037
+			$success = false;
1038
+		}
1039
+
1040
+		if ($success) {
1041
+			$cols_n_values = [
1042
+				'CNT_ISO'    => $CNT_ISO,
1043
+				'STA_abbrev' => $STA_abbrev,
1044
+				'STA_name'   => $STA_name,
1045
+				'STA_active' => true,
1046
+			];
1047
+			$success       = EEM_State::instance()->insert($cols_n_values);
1048
+			EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1049
+		}
1050
+
1051
+		if (defined('DOING_AJAX')) {
1052
+			$notices = EE_Error::get_notices(false, false, false);
1053
+			echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1054
+			die();
1055
+		}
1056
+		$this->_redirect_after_action(
1057
+			$success,
1058
+			esc_html__('State', 'event_espresso'),
1059
+			'added',
1060
+			['action' => 'country_settings']
1061
+		);
1062
+	}
1063
+
1064
+
1065
+	/**
1066
+	 * @return void
1067
+	 * @throws EE_Error
1068
+	 * @throws InvalidArgumentException
1069
+	 * @throws InvalidDataTypeException
1070
+	 * @throws InvalidInterfaceException
1071
+	 * @throws ReflectionException
1072
+	 */
1073
+	public function delete_state()
1074
+	{
1075
+		$CNT_ISO    = $this->getCountryISO();
1076
+		$STA_ID     = $this->request->getRequestParam('STA_ID');
1077
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1078
+
1079
+		if (! $STA_ID) {
1080
+			EE_Error::add_error(
1081
+				esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1082
+				__FILE__,
1083
+				__FUNCTION__,
1084
+				__LINE__
1085
+			);
1086
+			return;
1087
+		}
1088
+
1089
+		$success = EEM_State::instance()->delete_by_ID($STA_ID);
1090
+		if ($success !== false) {
1091
+			do_action(
1092
+				'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1093
+				$CNT_ISO,
1094
+				$STA_ID,
1095
+				['STA_abbrev' => $STA_abbrev]
1096
+			);
1097
+			EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1098
+		}
1099
+		if (defined('DOING_AJAX')) {
1100
+			$notices                = EE_Error::get_notices(false);
1101
+			$notices['return_data'] = true;
1102
+			echo wp_json_encode($notices);
1103
+			die();
1104
+		}
1105
+		$this->_redirect_after_action(
1106
+			$success,
1107
+			esc_html__('State', 'event_espresso'),
1108
+			'deleted',
1109
+			['action' => 'country_settings']
1110
+		);
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 * @return void
1116
+	 * @throws EE_Error
1117
+	 * @throws InvalidArgumentException
1118
+	 * @throws InvalidDataTypeException
1119
+	 * @throws InvalidInterfaceException
1120
+	 * @throws ReflectionException
1121
+	 */
1122
+	protected function _update_country_settings()
1123
+	{
1124
+		$CNT_ISO = $this->getCountryISO();
1125
+		if (! $CNT_ISO) {
1126
+			EE_Error::add_error(
1127
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1128
+				__FILE__,
1129
+				__FUNCTION__,
1130
+				__LINE__
1131
+			);
1132
+			return;
1133
+		}
1134
+
1135
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1136
+
1137
+		$cols_n_values                    = [];
1138
+		$cols_n_values['CNT_ISO3']        = strtoupper(
1139
+			$this->request->getRequestParam(
1140
+				"cntry[$CNT_ISO][CNT_ISO3]",
1141
+				$country->ISO3()
1142
+			)
1143
+		);
1144
+		$cols_n_values['CNT_name']        = $this->request->getRequestParam(
1145
+			"cntry[$CNT_ISO][CNT_name]",
1146
+			$country->name()
1147
+		);
1148
+		$cols_n_values['CNT_cur_code']    = strtoupper(
1149
+			$this->request->getRequestParam(
1150
+				"cntry[$CNT_ISO][CNT_cur_code]",
1151
+				$country->currency_code()
1152
+			)
1153
+		);
1154
+		$cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1155
+			"cntry[$CNT_ISO][CNT_cur_single]",
1156
+			$country->currency_name_single()
1157
+		);
1158
+		$cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1159
+			"cntry[$CNT_ISO][CNT_cur_plural]",
1160
+			$country->currency_name_plural()
1161
+		);
1162
+		$cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1163
+			"cntry[$CNT_ISO][CNT_cur_sign]",
1164
+			$country->currency_sign()
1165
+		);
1166
+		$cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1167
+			"cntry[$CNT_ISO][CNT_cur_sign_b4]",
1168
+			$country->currency_sign_before(),
1169
+			DataType::BOOL
1170
+		);
1171
+		$cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1172
+			"cntry[$CNT_ISO][CNT_cur_dec_plc]",
1173
+			$country->currency_decimal_places()
1174
+		);
1175
+		$cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1176
+			"cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1177
+			$country->currency_decimal_mark()
1178
+		);
1179
+		$cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1180
+			"cntry[$CNT_ISO][CNT_cur_thsnds]",
1181
+			$country->currency_thousands_separator()
1182
+		);
1183
+		$cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1184
+			"cntry[$CNT_ISO][CNT_tel_code]",
1185
+			$country->telephoneCode()
1186
+		);
1187
+		$cols_n_values['CNT_active']      = $this->request->getRequestParam(
1188
+			"cntry[$CNT_ISO][CNT_active]",
1189
+			$country->isActive(),
1190
+			DataType::BOOL
1191
+		);
1192
+
1193
+		// allow filtering of country data
1194
+		$cols_n_values = apply_filters(
1195
+			'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1196
+			$cols_n_values
1197
+		);
1198
+
1199
+		// where values
1200
+		$where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1201
+		// run the update
1202
+		$success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1203
+
1204
+		// allow filtering of states data
1205
+		$states = apply_filters(
1206
+			'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1207
+			$this->request->getRequestParam('states', [], DataType::STRING, true)
1208
+		);
1209
+
1210
+		if (! empty($states) && $success !== false) {
1211
+			// loop thru state data ( looks like : states[75][STA_name] )
1212
+			foreach ($states as $STA_ID => $state) {
1213
+				$cols_n_values = [
1214
+					'CNT_ISO'    => $CNT_ISO,
1215
+					'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1216
+					'STA_name'   => sanitize_text_field($state['STA_name']),
1217
+					'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1218
+				];
1219
+				// where values
1220
+				$where_cols_n_values = [['STA_ID' => $STA_ID]];
1221
+				// run the update
1222
+				$success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1223
+				if ($success !== false) {
1224
+					do_action(
1225
+						'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1226
+						$CNT_ISO,
1227
+						$STA_ID,
1228
+						$cols_n_values
1229
+					);
1230
+				}
1231
+			}
1232
+		}
1233
+		// check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1234
+		if (
1235
+			isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1236
+			&& $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1237
+		) {
1238
+			EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1239
+			EE_Registry::instance()->CFG->update_espresso_config();
1240
+		}
1241
+
1242
+		if ($success !== false) {
1243
+			EE_Error::add_success(
1244
+				esc_html__('Country Settings updated successfully.', 'event_espresso')
1245
+			);
1246
+		}
1247
+		$this->_redirect_after_action(
1248
+			$success,
1249
+			'',
1250
+			'',
1251
+			['action' => 'country_settings', 'country' => $CNT_ISO],
1252
+			true
1253
+		);
1254
+	}
1255
+
1256
+
1257
+	/**
1258
+	 * form_form_field_label_wrap
1259
+	 *
1260
+	 * @param string $label
1261
+	 * @return string
1262
+	 */
1263
+	public function country_form_field_label_wrap(string $label): string
1264
+	{
1265
+		return '
1266 1266
 			<tr>
1267 1267
 				<th>
1268 1268
 					' . $label . '
1269 1269
 				</th>';
1270
-    }
1271
-
1272
-
1273
-    /**
1274
-     * form_form_field_input__wrap
1275
-     *
1276
-     * @param string $input
1277
-     * @return string
1278
-     */
1279
-    public function country_form_field_input__wrap(string $input): string
1280
-    {
1281
-        return '
1270
+	}
1271
+
1272
+
1273
+	/**
1274
+	 * form_form_field_input__wrap
1275
+	 *
1276
+	 * @param string $input
1277
+	 * @return string
1278
+	 */
1279
+	public function country_form_field_input__wrap(string $input): string
1280
+	{
1281
+		return '
1282 1282
 				<td class="general-settings-country-input-td">
1283 1283
 					' . $input . '
1284 1284
 				</td>
1285 1285
 			</tr>';
1286
-    }
1287
-
1288
-
1289
-    /**
1290
-     * form_form_field_label_wrap
1291
-     *
1292
-     * @param string $label
1293
-     * @param string $required_text
1294
-     * @return string
1295
-     */
1296
-    public function state_form_field_label_wrap(string $label, string $required_text): string
1297
-    {
1298
-        return $required_text;
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     * form_form_field_input__wrap
1304
-     *
1305
-     * @param string $input
1306
-     * @return string
1307
-     */
1308
-    public function state_form_field_input__wrap(string $input): string
1309
-    {
1310
-        return '
1286
+	}
1287
+
1288
+
1289
+	/**
1290
+	 * form_form_field_label_wrap
1291
+	 *
1292
+	 * @param string $label
1293
+	 * @param string $required_text
1294
+	 * @return string
1295
+	 */
1296
+	public function state_form_field_label_wrap(string $label, string $required_text): string
1297
+	{
1298
+		return $required_text;
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 * form_form_field_input__wrap
1304
+	 *
1305
+	 * @param string $input
1306
+	 * @return string
1307
+	 */
1308
+	public function state_form_field_input__wrap(string $input): string
1309
+	{
1310
+		return '
1311 1311
 				<td class="general-settings-country-state-input-td">
1312 1312
 					' . $input . '
1313 1313
 				</td>';
1314
-    }
1315
-
1316
-
1317
-    /***********/
1318
-
1319
-
1320
-    /**
1321
-     * displays edit and view links for critical EE pages
1322
-     *
1323
-     * @param int $ee_page_id
1324
-     * @return string
1325
-     */
1326
-    public static function edit_view_links(int $ee_page_id): string
1327
-    {
1328
-        $edit_url = add_query_arg(
1329
-            ['post' => $ee_page_id, 'action' => 'edit'],
1330
-            admin_url('post.php')
1331
-        );
1332
-        $links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1333
-        $links    .= ' &nbsp;|&nbsp; ';
1334
-        $links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1335
-
1336
-        return $links;
1337
-    }
1338
-
1339
-
1340
-    /**
1341
-     * displays page and shortcode status for critical EE pages
1342
-     *
1343
-     * @param WP_Post $ee_page
1344
-     * @param string  $shortcode
1345
-     * @return string
1346
-     */
1347
-    public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1348
-    {
1349
-        // page status
1350
-        if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1351
-            $pg_class  = 'ee-status-bg--success';
1352
-            $pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1353
-        } else {
1354
-            $pg_class  = 'ee-status-bg--error';
1355
-            $pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1356
-        }
1357
-
1358
-        // shortcode status
1359
-        if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1360
-            $sc_class  = 'ee-status-bg--success';
1361
-            $sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1362
-        } else {
1363
-            $sc_class  = 'ee-status-bg--error';
1364
-            $sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1365
-        }
1366
-
1367
-        return '
1314
+	}
1315
+
1316
+
1317
+	/***********/
1318
+
1319
+
1320
+	/**
1321
+	 * displays edit and view links for critical EE pages
1322
+	 *
1323
+	 * @param int $ee_page_id
1324
+	 * @return string
1325
+	 */
1326
+	public static function edit_view_links(int $ee_page_id): string
1327
+	{
1328
+		$edit_url = add_query_arg(
1329
+			['post' => $ee_page_id, 'action' => 'edit'],
1330
+			admin_url('post.php')
1331
+		);
1332
+		$links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1333
+		$links    .= ' &nbsp;|&nbsp; ';
1334
+		$links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1335
+
1336
+		return $links;
1337
+	}
1338
+
1339
+
1340
+	/**
1341
+	 * displays page and shortcode status for critical EE pages
1342
+	 *
1343
+	 * @param WP_Post $ee_page
1344
+	 * @param string  $shortcode
1345
+	 * @return string
1346
+	 */
1347
+	public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1348
+	{
1349
+		// page status
1350
+		if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1351
+			$pg_class  = 'ee-status-bg--success';
1352
+			$pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1353
+		} else {
1354
+			$pg_class  = 'ee-status-bg--error';
1355
+			$pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1356
+		}
1357
+
1358
+		// shortcode status
1359
+		if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1360
+			$sc_class  = 'ee-status-bg--success';
1361
+			$sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1362
+		} else {
1363
+			$sc_class  = 'ee-status-bg--error';
1364
+			$sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1365
+		}
1366
+
1367
+		return '
1368 1368
         <span class="ee-page-status ' . $pg_class . '"><strong>' . $pg_status . '</strong></span>
1369 1369
         <span class="ee-page-status ' . $sc_class . '"><strong>' . $sc_status . '</strong></span>';
1370
-    }
1371
-
1372
-
1373
-    /**
1374
-     * generates a dropdown of all parent pages - copied from WP core
1375
-     *
1376
-     * @param int  $default
1377
-     * @param int  $parent
1378
-     * @param int  $level
1379
-     * @param bool $echo
1380
-     * @return string;
1381
-     */
1382
-    public static function page_settings_dropdown(
1383
-        int $default = 0,
1384
-        int $parent = 0,
1385
-        int $level = 0,
1386
-        bool $echo = true
1387
-    ): string {
1388
-        global $wpdb;
1389
-        $items  = $wpdb->get_results(
1390
-            $wpdb->prepare(
1391
-                "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",
1392
-                $parent
1393
-            )
1394
-        );
1395
-        $output = '';
1396
-
1397
-        if ($items) {
1398
-            $level = absint($level);
1399
-            foreach ($items as $item) {
1400
-                $ID         = absint($item->ID);
1401
-                $post_title = wp_strip_all_tags($item->post_title);
1402
-                $pad        = str_repeat('&nbsp;', $level * 3);
1403
-                $option     = "\n\t";
1404
-                $option     .= '<option class="level-' . $level . '" ';
1405
-                $option     .= 'value="' . $ID . '" ';
1406
-                $option     .= $ID === absint($default) ? ' selected' : '';
1407
-                $option     .= '>';
1408
-                $option     .= "$pad {$post_title}";
1409
-                $option     .= '</option>';
1410
-                $output     .= $option;
1411
-                ob_start();
1412
-                parent_dropdown($default, $item->ID, $level + 1);
1413
-                $output .= ob_get_clean();
1414
-            }
1415
-        }
1416
-        if ($echo) {
1417
-            echo wp_kses($output, AllowedTags::getWithFormTags());
1418
-            return '';
1419
-        }
1420
-        return $output;
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * Loads the scripts for the privacy settings form
1426
-     */
1427
-    public function load_scripts_styles_privacy_settings()
1428
-    {
1429
-        $form_handler = $this->loader->getShared(
1430
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1431
-        );
1432
-        $form_handler->enqueueStylesAndScripts();
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * display the privacy settings form
1438
-     *
1439
-     * @throws EE_Error
1440
-     */
1441
-    public function privacySettings()
1442
-    {
1443
-        $this->_set_add_edit_form_tags('update_privacy_settings');
1444
-        $this->_set_publish_post_box_vars();
1445
-        $form_handler                               = $this->loader->getShared(
1446
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1447
-        );
1448
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
1449
-            $form_handler->display(),
1450
-            '',
1451
-            'padding'
1452
-        );
1453
-        $this->display_admin_page_with_sidebar();
1454
-    }
1455
-
1456
-
1457
-    /**
1458
-     * Update the privacy settings from form data
1459
-     *
1460
-     * @throws EE_Error
1461
-     */
1462
-    public function updatePrivacySettings()
1463
-    {
1464
-        $form_handler = $this->loader->getShared(
1465
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1466
-        );
1467
-        $success      = $form_handler->process($this->get_request_data());
1468
-        $this->_redirect_after_action(
1469
-            $success,
1470
-            esc_html__('Registration Form Options', 'event_espresso'),
1471
-            'updated',
1472
-            ['action' => 'privacy_settings']
1473
-        );
1474
-    }
1475
-
1476
-
1477
-    public function setFontSize()
1478
-    {
1479
-        AdminFontSize::setAdminFontSize(
1480
-            $this->request->getRequestParam('font_size', AdminFontSize::FONT_SIZE_DEFAULT)
1481
-        );
1482
-        wp_safe_redirect($this->request->getServerParam('HTTP_REFERER'));
1483
-    }
1370
+	}
1371
+
1372
+
1373
+	/**
1374
+	 * generates a dropdown of all parent pages - copied from WP core
1375
+	 *
1376
+	 * @param int  $default
1377
+	 * @param int  $parent
1378
+	 * @param int  $level
1379
+	 * @param bool $echo
1380
+	 * @return string;
1381
+	 */
1382
+	public static function page_settings_dropdown(
1383
+		int $default = 0,
1384
+		int $parent = 0,
1385
+		int $level = 0,
1386
+		bool $echo = true
1387
+	): string {
1388
+		global $wpdb;
1389
+		$items  = $wpdb->get_results(
1390
+			$wpdb->prepare(
1391
+				"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",
1392
+				$parent
1393
+			)
1394
+		);
1395
+		$output = '';
1396
+
1397
+		if ($items) {
1398
+			$level = absint($level);
1399
+			foreach ($items as $item) {
1400
+				$ID         = absint($item->ID);
1401
+				$post_title = wp_strip_all_tags($item->post_title);
1402
+				$pad        = str_repeat('&nbsp;', $level * 3);
1403
+				$option     = "\n\t";
1404
+				$option     .= '<option class="level-' . $level . '" ';
1405
+				$option     .= 'value="' . $ID . '" ';
1406
+				$option     .= $ID === absint($default) ? ' selected' : '';
1407
+				$option     .= '>';
1408
+				$option     .= "$pad {$post_title}";
1409
+				$option     .= '</option>';
1410
+				$output     .= $option;
1411
+				ob_start();
1412
+				parent_dropdown($default, $item->ID, $level + 1);
1413
+				$output .= ob_get_clean();
1414
+			}
1415
+		}
1416
+		if ($echo) {
1417
+			echo wp_kses($output, AllowedTags::getWithFormTags());
1418
+			return '';
1419
+		}
1420
+		return $output;
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * Loads the scripts for the privacy settings form
1426
+	 */
1427
+	public function load_scripts_styles_privacy_settings()
1428
+	{
1429
+		$form_handler = $this->loader->getShared(
1430
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1431
+		);
1432
+		$form_handler->enqueueStylesAndScripts();
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * display the privacy settings form
1438
+	 *
1439
+	 * @throws EE_Error
1440
+	 */
1441
+	public function privacySettings()
1442
+	{
1443
+		$this->_set_add_edit_form_tags('update_privacy_settings');
1444
+		$this->_set_publish_post_box_vars();
1445
+		$form_handler                               = $this->loader->getShared(
1446
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1447
+		);
1448
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
1449
+			$form_handler->display(),
1450
+			'',
1451
+			'padding'
1452
+		);
1453
+		$this->display_admin_page_with_sidebar();
1454
+	}
1455
+
1456
+
1457
+	/**
1458
+	 * Update the privacy settings from form data
1459
+	 *
1460
+	 * @throws EE_Error
1461
+	 */
1462
+	public function updatePrivacySettings()
1463
+	{
1464
+		$form_handler = $this->loader->getShared(
1465
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1466
+		);
1467
+		$success      = $form_handler->process($this->get_request_data());
1468
+		$this->_redirect_after_action(
1469
+			$success,
1470
+			esc_html__('Registration Form Options', 'event_espresso'),
1471
+			'updated',
1472
+			['action' => 'privacy_settings']
1473
+		);
1474
+	}
1475
+
1476
+
1477
+	public function setFontSize()
1478
+	{
1479
+		AdminFontSize::setAdminFontSize(
1480
+			$this->request->getRequestParam('font_size', AdminFontSize::FONT_SIZE_DEFAULT)
1481
+		);
1482
+		wp_safe_redirect($this->request->getServerParam('HTTP_REFERER'));
1483
+	}
1484 1484
 }
Please login to merge, or discard this patch.
admin_pages/transactions/templates/txn_admin_details_header.template.php 2 patches
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -19,14 +19,14 @@  discard block
 block discarded – undo
19 19
 <div class="ee-admin-page-nav-strip-wrap">
20 20
     <div class='ee-admin-page-nav-strip'>
21 21
     <?php
22
-    echo wp_kses($previous_transaction, AllowedTags::getAllowedTags());
23
-    echo '&nbsp;' . sprintf(
24
-        /* translators: %s: transaction number */
25
-        esc_html__('Transaction # %1$s', 'event_espresso'),
26
-        esc_html($txn_nmbr['value'])
27
-    ) . '&nbsp;';
28
-    echo wp_kses($next_transaction, AllowedTags::getAllowedTags());
29
-    ?>
22
+	echo wp_kses($previous_transaction, AllowedTags::getAllowedTags());
23
+	echo '&nbsp;' . sprintf(
24
+		/* translators: %s: transaction number */
25
+		esc_html__('Transaction # %1$s', 'event_espresso'),
26
+		esc_html($txn_nmbr['value'])
27
+	) . '&nbsp;';
28
+	echo wp_kses($next_transaction, AllowedTags::getAllowedTags());
29
+	?>
30 30
     </div>
31 31
 </div>
32 32
 
@@ -42,7 +42,7 @@  discard block
 block discarded – undo
42 42
     <div class='ee-admin-container <?php echo esc_attr($amount_due_class); ?>'>
43 43
         <label><?php echo esc_html__('Total Amount Due: ', 'event_espresso'); ?></label>
44 44
         <span id="txn-admin-total-amount-due" data-due="<?php echo esc_attr($amount_due_raw); ?>"><?php echo esc_html
45
-            ($amount_due); ?></span>
45
+			($amount_due); ?></span>
46 46
     </div>
47 47
     <div class='ee-admin-container'>
48 48
         <label><?php echo esc_html__('Last Method of Payment: ', 'event_espresso'); ?></label>
Please login to merge, or discard this patch.
Spacing   +3 added lines, -4 removed lines patch added patch discarded remove patch
@@ -20,11 +20,11 @@  discard block
 block discarded – undo
20 20
     <div class='ee-admin-page-nav-strip'>
21 21
     <?php
22 22
     echo wp_kses($previous_transaction, AllowedTags::getAllowedTags());
23
-    echo '&nbsp;' . sprintf(
23
+    echo '&nbsp;'.sprintf(
24 24
         /* translators: %s: transaction number */
25 25
         esc_html__('Transaction # %1$s', 'event_espresso'),
26 26
         esc_html($txn_nmbr['value'])
27
-    ) . '&nbsp;';
27
+    ).'&nbsp;';
28 28
     echo wp_kses($next_transaction, AllowedTags::getAllowedTags());
29 29
     ?>
30 30
     </div>
@@ -41,8 +41,7 @@  discard block
 block discarded – undo
41 41
     </div>
42 42
     <div class='ee-admin-container <?php echo esc_attr($amount_due_class); ?>'>
43 43
         <label><?php echo esc_html__('Total Amount Due: ', 'event_espresso'); ?></label>
44
-        <span id="txn-admin-total-amount-due" data-due="<?php echo esc_attr($amount_due_raw); ?>"><?php echo esc_html
45
-            ($amount_due); ?></span>
44
+        <span id="txn-admin-total-amount-due" data-due="<?php echo esc_attr($amount_due_raw); ?>"><?php echo esc_html($amount_due); ?></span>
46 45
     </div>
47 46
     <div class='ee-admin-container'>
48 47
         <label><?php echo esc_html__('Last Method of Payment: ', 'event_espresso'); ?></label>
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +2520 added lines, -2520 removed lines patch added patch discarded remove patch
@@ -13,2524 +13,2524 @@
 block discarded – undo
13 13
  */
14 14
 class Transactions_Admin_Page extends EE_Admin_Page
15 15
 {
16
-    /**
17
-     * @var EE_Transaction
18
-     */
19
-    private $_transaction;
20
-
21
-    /**
22
-     * @var EE_Session
23
-     */
24
-    private $_session;
25
-
26
-    /**
27
-     * @var array $_txn_status
28
-     */
29
-    private static $_txn_status;
30
-
31
-    /**
32
-     * @var array $_pay_status
33
-     */
34
-    private static $_pay_status;
35
-
36
-    /**
37
-     * @var array $_existing_reg_payment_REG_IDs
38
-     */
39
-    protected $_existing_reg_payment_REG_IDs;
40
-
41
-
42
-    /**
43
-     *    _init_page_props
44
-     *
45
-     * @return void
46
-     */
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug        = TXN_PG_SLUG;
50
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
51
-        $this->_admin_base_url  = TXN_ADMIN_URL;
52
-        $this->_admin_base_path = TXN_ADMIN;
53
-    }
54
-
55
-
56
-    /**
57
-     *    _ajax_hooks
58
-     *
59
-     * @return void
60
-     */
61
-    protected function _ajax_hooks()
62
-    {
63
-        // add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
64
-        // add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
65
-        // add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
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'       => 'apply_payments_or_refunds',
124
-                'noheader'   => true,
125
-                'capability' => 'ee_edit_payments',
126
-            ],
127
-
128
-            'espresso_apply_refund' => [
129
-                'func'       => '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
-        EE_Registry::instance()->CAP->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
-            && EE_Registry::instance()->CAP->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
-            EE_Registry::instance()->CAP->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
-            && EE_Registry::instance()->CAP->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
-        EE_Registry::instance()->CAP->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']   = EE_Registry::instance()->CAP->current_user_can(
1004
-            'ee_edit_payments',
1005
-            'apply_payment_or_refund_from_registration_details'
1006
-        );
1007
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->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) ? $taxes : false;
1028
-
1029
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1030
-            $this->_transaction->total(),
1031
-            false,
1032
-            false
1033
-        );
1034
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1035
-        $this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1036
-
1037
-        // process payment details
1038
-        $payments = $this->_transaction->payments();
1039
-        if (! empty($payments)) {
1040
-            $this->_template_args['payments']              = $payments;
1041
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1042
-        } else {
1043
-            $this->_template_args['payments']              = false;
1044
-            $this->_template_args['existing_reg_payments'] = [];
1045
-        }
1046
-
1047
-        $this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1048
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1049
-            ['action' => 'espresso_delete_payment'],
1050
-            TXN_ADMIN_URL
1051
-        );
1052
-
1053
-        if (isset($txn_details['invoice_number'])) {
1054
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1055
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1056
-                'Invoice Number',
1057
-                'event_espresso'
1058
-            );
1059
-        }
1060
-
1061
-        $this->_template_args['txn_details']['registration_session']['value'] =
1062
-            $this->_transaction->primary_registration() instanceof EE_Registration
1063
-                ? $this->_transaction->primary_registration()->session_ID()
1064
-                : null;
1065
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1066
-            'Registration Session',
1067
-            'event_espresso'
1068
-        );
1069
-
1070
-        $this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1071
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1072
-            'Transaction placed from IP',
1073
-            'event_espresso'
1074
-        );
1075
-
1076
-        $this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1077
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1078
-            'Registrant User Agent',
1079
-            'event_espresso'
1080
-        );
1081
-
1082
-        $reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1083
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1084
-            if ($reg_step_status === true) {
1085
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1086
-                              . sprintf(
1087
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1088
-                                  ucwords(str_replace('_', ' ', $reg_step))
1089
-                              )
1090
-                              . '</div>';
1091
-            } elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1092
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1093
-                              . sprintf(
1094
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1095
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1096
-                                  date(
1097
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1098
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1099
-                                  )
1100
-                              )
1101
-                              . '</div>';
1102
-            } else {
1103
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1104
-                              . sprintf(
1105
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1106
-                                  ucwords(str_replace('_', ' ', $reg_step))
1107
-                              )
1108
-                              . '</div>';
1109
-            }
1110
-        }
1111
-        $reg_steps                                                 .= '</ul>';
1112
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1113
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1114
-            'Registration Step Progress',
1115
-            'event_espresso'
1116
-        );
1117
-
1118
-
1119
-        $this->_get_registrations_to_apply_payment_to();
1120
-        $this->_get_payment_methods($payments);
1121
-        $this->_get_payment_status_array();
1122
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1123
-
1124
-        $this->_template_args['transaction_form_url']    = add_query_arg(
1125
-            [
1126
-                'action'  => 'edit_transaction',
1127
-                'process' => 'transaction',
1128
-            ],
1129
-            TXN_ADMIN_URL
1130
-        );
1131
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(
1132
-            [
1133
-                'page'   => 'espresso_transactions',
1134
-                'action' => 'espresso_apply_payment',
1135
-            ],
1136
-            TXN_ADMIN_URL
1137
-        );
1138
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1139
-            [
1140
-                'page'   => 'espresso_transactions',
1141
-                'action' => 'espresso_delete_payment',
1142
-            ],
1143
-            TXN_ADMIN_URL
1144
-        );
1145
-
1146
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1147
-
1148
-        // 'espresso_delete_payment_nonce'
1149
-
1150
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1151
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1152
-    }
1153
-
1154
-
1155
-    /**
1156
-     * _get_registration_payment_IDs
1157
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1158
-     *
1159
-     * @access protected
1160
-     * @param EE_Payment[] $payments
1161
-     * @return array
1162
-     * @throws EE_Error
1163
-     * @throws InvalidArgumentException
1164
-     * @throws InvalidDataTypeException
1165
-     * @throws InvalidInterfaceException
1166
-     * @throws ReflectionException
1167
-     */
1168
-    protected function _get_registration_payment_IDs($payments = [])
1169
-    {
1170
-        $existing_reg_payments = [];
1171
-        // get all reg payments for these payments
1172
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1173
-            [
1174
-                [
1175
-                    'PAY_ID' => [
1176
-                        'IN',
1177
-                        array_keys($payments),
1178
-                    ],
1179
-                ],
1180
-            ]
1181
-        );
1182
-        if (! empty($reg_payments)) {
1183
-            foreach ($payments as $payment) {
1184
-                if (! $payment instanceof EE_Payment) {
1185
-                    continue;
1186
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1187
-                    $existing_reg_payments[ $payment->ID() ] = [];
1188
-                }
1189
-                foreach ($reg_payments as $reg_payment) {
1190
-                    if (
1191
-                        $reg_payment instanceof EE_Registration_Payment
1192
-                        && $reg_payment->payment_ID() === $payment->ID()
1193
-                    ) {
1194
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1195
-                    }
1196
-                }
1197
-            }
1198
-        }
1199
-
1200
-        return $existing_reg_payments;
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     * _get_registrations_to_apply_payment_to
1206
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1207
-     * which allows the admin to only apply the payment to the specific registrations
1208
-     *
1209
-     * @access protected
1210
-     * @return void
1211
-     * @throws EE_Error
1212
-     * @throws InvalidArgumentException
1213
-     * @throws InvalidDataTypeException
1214
-     * @throws InvalidInterfaceException
1215
-     * @throws ReflectionException
1216
-     */
1217
-    protected function _get_registrations_to_apply_payment_to()
1218
-    {
1219
-        // we want any registration with an active status (ie: not deleted or cancelled)
1220
-        $query_params                      = [
1221
-            [
1222
-                'STS_ID' => [
1223
-                    'IN',
1224
-                    [
1225
-                        EEM_Registration::status_id_approved,
1226
-                        EEM_Registration::status_id_pending_payment,
1227
-                        EEM_Registration::status_id_not_approved,
1228
-                    ],
1229
-                ],
1230
-            ],
1231
-        ];
1232
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1233
-                '',
1234
-                'txn-admin-apply-payment-to-registrations-dv',
1235
-                '',
1236
-                'clear: both; margin: 1.5em 0 0; display: none;'
1237
-            );
1238
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1239
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1240
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1241
-            EEH_HTML::tr(
1242
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1243
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1244
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1245
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1246
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1247
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1248
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1249
-            )
1250
-        );
1251
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1252
-        // get registrations for TXN
1253
-        $registrations         = $this->_transaction->registrations($query_params);
1254
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1255
-        foreach ($registrations as $registration) {
1256
-            if ($registration instanceof EE_Registration) {
1257
-                $attendee_name                     = $registration->attendee() instanceof EE_Attendee
1258
-                    ? $registration->attendee()->full_name()
1259
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1260
-                $owing                             = $registration->final_price() - $registration->paid();
1261
-                $taxable                           = $registration->ticket()->taxable()
1262
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1263
-                    : '';
1264
-                $checked                           = empty($existing_reg_payments)
1265
-                                                     || in_array($registration->ID(), $existing_reg_payments, true)
1266
-                    ? ' checked'
1267
-                    : '';
1268
-                $disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1269
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1270
-                    EEH_HTML::td($registration->ID()) .
1271
-                    EEH_HTML::td($attendee_name) .
1272
-                    EEH_HTML::td(
1273
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1274
-                    ) .
1275
-                    EEH_HTML::td($registration->event_name()) .
1276
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1277
-                    EEH_HTML::td(
1278
-                        EEH_Template::format_currency($owing),
1279
-                        '',
1280
-                        'txn-admin-payment-owing-td jst-cntr'
1281
-                    ) .
1282
-                    EEH_HTML::td(
1283
-                        '<input type="checkbox" value="' . $registration->ID()
1284
-                        . '" name="txn_admin_payment[registrations]"'
1285
-                        . $checked . $disabled . '>',
1286
-                        '',
1287
-                        'jst-cntr'
1288
-                    ),
1289
-                    'apply-payment-registration-row-' . $registration->ID()
1290
-                );
1291
-            }
1292
-        }
1293
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1294
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1295
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1296
-        $registrations_to_apply_payment_to                         .= EEH_HTML::p(
1297
-            esc_html__(
1298
-                '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.',
1299
-                'event_espresso'
1300
-            ),
1301
-            '',
1302
-            'clear description'
1303
-        );
1304
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1305
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1306
-    }
1307
-
1308
-
1309
-    /**
1310
-     * _get_reg_status_selection
1311
-     *
1312
-     * @return void
1313
-     * @throws EE_Error
1314
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1315
-     *         instead of events.
1316
-     * @access protected
1317
-     */
1318
-    protected function _get_reg_status_selection()
1319
-    {
1320
-        // first get all possible statuses
1321
-        $statuses = EEM_Registration::reg_status_array([], true);
1322
-        // let's add a "don't change" option.
1323
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1324
-        $status_array                                        = array_merge($status_array, $statuses);
1325
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1326
-            'txn_reg_status_change[reg_status]',
1327
-            $status_array,
1328
-            'NAN',
1329
-            'id="txn-admin-payment-reg-status-inp"',
1330
-            'txn-reg-status-change-reg-status'
1331
-        );
1332
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1333
-            'delete_txn_reg_status_change[reg_status]',
1334
-            $status_array,
1335
-            'NAN',
1336
-            'delete-txn-admin-payment-reg-status-inp',
1337
-            'delete-txn-reg-status-change-reg-status'
1338
-        );
1339
-    }
1340
-
1341
-
1342
-    /**
1343
-     *    _get_payment_methods
1344
-     * Gets all the payment methods available generally, or the ones that are already
1345
-     * selected on these payments (in case their payment methods are no longer active).
1346
-     * Has the side-effect of updating the template args' payment_methods item
1347
-     *
1348
-     * @access private
1349
-     * @param EE_Payment[] to show on this page
1350
-     * @return void
1351
-     * @throws EE_Error
1352
-     * @throws InvalidArgumentException
1353
-     * @throws InvalidDataTypeException
1354
-     * @throws InvalidInterfaceException
1355
-     * @throws ReflectionException
1356
-     */
1357
-    private function _get_payment_methods($payments = [])
1358
-    {
1359
-        $payment_methods_of_payments = [];
1360
-        foreach ($payments as $payment) {
1361
-            if ($payment instanceof EE_Payment) {
1362
-                $payment_methods_of_payments[] = $payment->ID();
1363
-            }
1364
-        }
1365
-        if ($payment_methods_of_payments) {
1366
-            $query_args = [
1367
-                [
1368
-                    'OR*payment_method_for_payment' => [
1369
-                        'PMD_ID'    => ['IN', $payment_methods_of_payments],
1370
-                        'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1371
-                    ],
1372
-                ],
1373
-            ];
1374
-        } else {
1375
-            $query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1376
-        }
1377
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1378
-    }
1379
-
1380
-
1381
-    /**
1382
-     * txn_attendees_meta_box
1383
-     *    generates HTML for the Attendees Transaction main meta box
1384
-     *
1385
-     * @access public
1386
-     * @param WP_Post $post
1387
-     * @param array   $metabox
1388
-     * @return void
1389
-     * @throws DomainException
1390
-     * @throws EE_Error
1391
-     * @throws InvalidArgumentException
1392
-     * @throws InvalidDataTypeException
1393
-     * @throws InvalidInterfaceException
1394
-     * @throws ReflectionException
1395
-     */
1396
-    public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1397
-    {
1398
-        /** @noinspection NonSecureExtractUsageInspection */
1399
-        extract($metabox['args']);
1400
-        $this->_template_args['post']            = $post;
1401
-        $this->_template_args['event_attendees'] = [];
1402
-        // process items in cart
1403
-        $line_items = $this->_transaction->get_many_related(
1404
-            'Line_Item',
1405
-            [['LIN_type' => 'line-item']]
1406
-        );
1407
-        if (! empty($line_items)) {
1408
-            foreach ($line_items as $item) {
1409
-                if ($item instanceof EE_Line_Item) {
1410
-                    switch ($item->OBJ_type()) {
1411
-                        case 'Event':
1412
-                            break;
1413
-                        case 'Ticket':
1414
-                            $ticket = $item->ticket();
1415
-                            // right now we're only handling tickets here.
1416
-                            // Cause its expected that only tickets will have attendees right?
1417
-                            if (! $ticket instanceof EE_Ticket) {
1418
-                                break;
1419
-                            }
1420
-                            try {
1421
-                                $event_name = $ticket->get_event_name();
1422
-                            } catch (Exception $e) {
1423
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1424
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1425
-                            }
1426
-                            $event_name   .= ' - ' . $item->name();
1427
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1428
-                            // now get all of the registrations for this transaction that use this ticket
1429
-                            $registrations = $ticket->registrations(
1430
-                                [['TXN_ID' => $this->_transaction->ID()]]
1431
-                            );
1432
-                            foreach ($registrations as $registration) {
1433
-                                if (! $registration instanceof EE_Registration) {
1434
-                                    break;
1435
-                                }
1436
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1437
-                                    = $registration->status_ID();
1438
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1439
-                                    = $registration->count();
1440
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1441
-                                    = $event_name;
1442
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1443
-                                    = $ticket_price;
1444
-                                // attendee info
1445
-                                $attendee = $registration->get_first_related('Attendee');
1446
-                                if ($attendee instanceof EE_Attendee) {
1447
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1448
-                                        = $attendee->ID();
1449
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1450
-                                        = $attendee->full_name();
1451
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1452
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1453
-                                          . esc_html__(
1454
-                                              ' Event',
1455
-                                              'event_espresso'
1456
-                                          )
1457
-                                          . '">' . $attendee->email() . '</a>';
1458
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1459
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1460
-                                } else {
1461
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1462
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1463
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1464
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1465
-                                }
1466
-                            }
1467
-                            break;
1468
-                    }
1469
-                }
1470
-            }
1471
-
1472
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1473
-                [
1474
-                    'action'  => 'edit_transaction',
1475
-                    'process' => 'attendees',
1476
-                ],
1477
-                TXN_ADMIN_URL
1478
-            );
1479
-            echo EEH_Template::display_template(
1480
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1481
-                $this->_template_args,
1482
-                true
1483
-            );
1484
-        } else {
1485
-            printf(
1486
-                esc_html__(
1487
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1488
-                    'event_espresso'
1489
-                ),
1490
-                '<p class="important-notice">',
1491
-                '</p>'
1492
-            );
1493
-        }
1494
-    }
1495
-
1496
-
1497
-    /**
1498
-     * txn_registrant_side_meta_box
1499
-     * generates HTML for the Edit Transaction side meta box
1500
-     *
1501
-     * @access public
1502
-     * @return void
1503
-     * @throws DomainException
1504
-     * @throws EE_Error
1505
-     * @throws InvalidArgumentException
1506
-     * @throws InvalidDataTypeException
1507
-     * @throws InvalidInterfaceException
1508
-     * @throws ReflectionException
1509
-     */
1510
-    public function txn_registrant_side_meta_box()
1511
-    {
1512
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1513
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1514
-            : null;
1515
-        if (! $primary_att instanceof EE_Attendee) {
1516
-            $this->_template_args['no_attendee_message'] = esc_html__(
1517
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1518
-                'event_espresso'
1519
-            );
1520
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1521
-        }
1522
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1523
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1524
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1525
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1526
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1527
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1528
-            [
1529
-                'action' => 'edit_attendee',
1530
-                'post'   => $primary_att->ID(),
1531
-            ],
1532
-            REG_ADMIN_URL
1533
-        );
1534
-        // get formatted address for registrant
1535
-        $formatted_address                         = EEH_Address::format($primary_att);
1536
-        $formatted_address                         =
1537
-            $formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1538
-                ? $formatted_address
1539
-                : '';
1540
-        $this->_template_args['formatted_address'] = $formatted_address;
1541
-        echo EEH_Template::display_template(
1542
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1543
-            $this->_template_args,
1544
-            true
1545
-        );
1546
-    }
1547
-
1548
-
1549
-    /**
1550
-     * txn_billing_info_side_meta_box
1551
-     *    generates HTML for the Edit Transaction side meta box
1552
-     *
1553
-     * @access public
1554
-     * @return void
1555
-     * @throws DomainException
1556
-     * @throws EE_Error
1557
-     * @throws ReflectionException
1558
-     */
1559
-    public function txn_billing_info_side_meta_box()
1560
-    {
1561
-        $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1562
-        $this->_template_args['billing_form_url'] = add_query_arg(
1563
-            ['action' => 'edit_transaction', 'process' => 'billing'],
1564
-            TXN_ADMIN_URL
1565
-        );
1566
-
1567
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1568
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1569
-    }
1570
-
1571
-
1572
-    /**
1573
-     * apply_payments_or_refunds
1574
-     *    registers a payment or refund made towards a transaction
1575
-     *
1576
-     * @access public
1577
-     * @return void
1578
-     * @throws EE_Error
1579
-     * @throws InvalidArgumentException
1580
-     * @throws ReflectionException
1581
-     * @throws RuntimeException
1582
-     * @throws InvalidDataTypeException
1583
-     * @throws InvalidInterfaceException
1584
-     */
1585
-    public function apply_payments_or_refunds()
1586
-    {
1587
-        $valid_data = $this->_validate_payment_request_data();
1588
-        $has_access = EE_Registry::instance()->CAP->current_user_can(
1589
-            'ee_edit_payments',
1590
-            'apply_payment_or_refund_from_registration_details'
1591
-        );
1592
-        $TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1593
-        $amount     = 0;
1594
-        if (! empty($valid_data) && $has_access) {
1595
-            $PAY_ID = $valid_data['PAY_ID'];
1596
-            // save  the new payment
1597
-            $payment = $this->_create_payment_from_request_data($valid_data);
1598
-            $amount  = $payment->amount();
1599
-            // get the TXN for this payment
1600
-            $transaction = $payment->transaction();
1601
-            // verify transaction
1602
-            if ($transaction instanceof EE_Transaction) {
1603
-                // calculate_total_payments_and_update_status
1604
-                $this->_process_transaction_payments($transaction);
1605
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1606
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1607
-                // apply payment to registrations (if applicable)
1608
-                if (! empty($REG_IDs)) {
1609
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1610
-                    $this->_maybe_send_notifications();
1611
-                    // now process status changes for the same registrations
1612
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1613
-                }
1614
-                $this->_maybe_send_notifications($payment);
1615
-                // prepare to render page
1616
-                do_action(
1617
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1618
-                    $transaction,
1619
-                    $payment
1620
-                );
1621
-            } else {
1622
-                EE_Error::add_error(
1623
-                    esc_html__(
1624
-                        'A valid Transaction for this payment could not be retrieved.',
1625
-                        'event_espresso'
1626
-                    ),
1627
-                    __FILE__,
1628
-                    __FUNCTION__,
1629
-                    __LINE__
1630
-                );
1631
-            }
1632
-        } elseif ($has_access) {
1633
-            EE_Error::add_error(
1634
-                esc_html__(
1635
-                    'The payment form data could not be processed. Please try again.',
1636
-                    'event_espresso'
1637
-                ),
1638
-                __FILE__,
1639
-                __FUNCTION__,
1640
-                __LINE__
1641
-            );
1642
-        } else {
1643
-            EE_Error::add_error(
1644
-                esc_html__(
1645
-                    'You do not have access to apply payments or refunds to a registration.',
1646
-                    'event_espresso'
1647
-                ),
1648
-                __FILE__,
1649
-                __FUNCTION__,
1650
-                __LINE__
1651
-            );
1652
-        }
1653
-        $query_args = [
1654
-            'page'   => 'espresso_transactions',
1655
-            'action' => 'view_transaction',
1656
-            'TXN_ID' => $TXD_ID,
1657
-        ];
1658
-
1659
-        $this->_redirect_after_action(
1660
-            ! EE_Error::has_error(),
1661
-            $amount > 0
1662
-                ? esc_html__('payment', 'event_espresso')
1663
-                : esc_html__('refund', 'event_espresso'),
1664
-            esc_html__('processed', 'event_espresso'),
1665
-            $query_args
1666
-        );
1667
-    }
1668
-
1669
-
1670
-    /**
1671
-     * _validate_payment_request_data
1672
-     *
1673
-     * @return array
1674
-     * @throws EE_Error
1675
-     * @throws InvalidArgumentException
1676
-     * @throws InvalidDataTypeException
1677
-     * @throws InvalidInterfaceException
1678
-     */
1679
-    protected function _validate_payment_request_data()
1680
-    {
1681
-        if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1682
-            return [];
1683
-        }
1684
-        $payment_form = $this->_generate_payment_form_section();
1685
-        try {
1686
-            if ($payment_form->was_submitted()) {
1687
-                $payment_form->receive_form_submission();
1688
-                if (! $payment_form->is_valid()) {
1689
-                    $submission_error_messages = [];
1690
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1691
-                        if ($validation_error instanceof EE_Validation_Error) {
1692
-                            $form_input                  = $validation_error->get_form_section();
1693
-                            $submission_error_messages[] = sprintf(
1694
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1695
-                                $form_input instanceof EE_Form_Input_Base ? $form_input->html_label_text() : '',
1696
-                                $validation_error->getMessage()
1697
-                            );
1698
-                        }
1699
-                    }
1700
-                    EE_Error::add_error(
1701
-                        implode('<br />', $submission_error_messages),
1702
-                        __FILE__,
1703
-                        __FUNCTION__,
1704
-                        __LINE__
1705
-                    );
1706
-                    return [];
1707
-                }
1708
-            }
1709
-        } catch (EE_Error $e) {
1710
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1711
-            return [];
1712
-        }
1713
-
1714
-        return $payment_form->valid_data();
1715
-    }
1716
-
1717
-
1718
-    /**
1719
-     * _generate_payment_form_section
1720
-     *
1721
-     * @return EE_Form_Section_Proper
1722
-     * @throws EE_Error
1723
-     */
1724
-    protected function _generate_payment_form_section()
1725
-    {
1726
-        return new EE_Form_Section_Proper(
1727
-            [
1728
-                'name'        => 'txn_admin_payment',
1729
-                'subsections' => [
1730
-                    'PAY_ID'          => new EE_Text_Input(
1731
-                        [
1732
-                            'default'               => 0,
1733
-                            'required'              => false,
1734
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1735
-                            'validation_strategies' => [new EE_Int_Normalization()],
1736
-                        ]
1737
-                    ),
1738
-                    'TXN_ID'          => new EE_Text_Input(
1739
-                        [
1740
-                            'default'               => 0,
1741
-                            'required'              => true,
1742
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1743
-                            'validation_strategies' => [new EE_Int_Normalization()],
1744
-                        ]
1745
-                    ),
1746
-                    'type'            => new EE_Text_Input(
1747
-                        [
1748
-                            'default'               => 1,
1749
-                            'required'              => true,
1750
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1751
-                            'validation_strategies' => [new EE_Int_Normalization()],
1752
-                        ]
1753
-                    ),
1754
-                    'amount'          => new EE_Text_Input(
1755
-                        [
1756
-                            'default'               => 0,
1757
-                            'required'              => true,
1758
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1759
-                            'validation_strategies' => [new EE_Float_Normalization()],
1760
-                        ]
1761
-                    ),
1762
-                    'status'          => new EE_Text_Input(
1763
-                        [
1764
-                            'default'         => EEM_Payment::status_id_approved,
1765
-                            'required'        => true,
1766
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1767
-                        ]
1768
-                    ),
1769
-                    'PMD_ID'          => new EE_Text_Input(
1770
-                        [
1771
-                            'default'               => 2,
1772
-                            'required'              => true,
1773
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1774
-                            'validation_strategies' => [new EE_Int_Normalization()],
1775
-                        ]
1776
-                    ),
1777
-                    'date'            => new EE_Text_Input(
1778
-                        [
1779
-                            'default'         => time(),
1780
-                            'required'        => true,
1781
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1782
-                        ]
1783
-                    ),
1784
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1785
-                        [
1786
-                            'default'               => '',
1787
-                            'required'              => false,
1788
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1789
-                            'validation_strategies' => [
1790
-                                new EE_Max_Length_Validation_Strategy(
1791
-                                    esc_html__('Input too long', 'event_espresso'),
1792
-                                    100
1793
-                                ),
1794
-                            ],
1795
-                        ]
1796
-                    ),
1797
-                    'po_number'       => new EE_Text_Input(
1798
-                        [
1799
-                            'default'               => '',
1800
-                            'required'              => false,
1801
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1802
-                            'validation_strategies' => [
1803
-                                new EE_Max_Length_Validation_Strategy(
1804
-                                    esc_html__('Input too long', 'event_espresso'),
1805
-                                    100
1806
-                                ),
1807
-                            ],
1808
-                        ]
1809
-                    ),
1810
-                    'accounting'      => new EE_Text_Input(
1811
-                        [
1812
-                            'default'               => '',
1813
-                            'required'              => false,
1814
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1815
-                            'validation_strategies' => [
1816
-                                new EE_Max_Length_Validation_Strategy(
1817
-                                    esc_html__('Input too long', 'event_espresso'),
1818
-                                    100
1819
-                                ),
1820
-                            ],
1821
-                        ]
1822
-                    ),
1823
-                ],
1824
-            ]
1825
-        );
1826
-    }
1827
-
1828
-
1829
-    /**
1830
-     * _create_payment_from_request_data
1831
-     *
1832
-     * @param array $valid_data
1833
-     * @return EE_Payment
1834
-     * @throws EE_Error
1835
-     * @throws InvalidArgumentException
1836
-     * @throws InvalidDataTypeException
1837
-     * @throws InvalidInterfaceException
1838
-     * @throws ReflectionException
1839
-     */
1840
-    protected function _create_payment_from_request_data($valid_data)
1841
-    {
1842
-        $PAY_ID = $valid_data['PAY_ID'];
1843
-        // get payment amount
1844
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1845
-        // payments have a type value of 1 and refunds have a type value of -1
1846
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1847
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1848
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1849
-        $date    = $valid_data['date']
1850
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1851
-            : date('Y-m-d g:i a', current_time('timestamp'));
1852
-        $payment = EE_Payment::new_instance(
1853
-            [
1854
-                'TXN_ID'              => $valid_data['TXN_ID'],
1855
-                'STS_ID'              => $valid_data['status'],
1856
-                'PAY_timestamp'       => $date,
1857
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1858
-                'PMD_ID'              => $valid_data['PMD_ID'],
1859
-                'PAY_amount'          => $amount,
1860
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1861
-                'PAY_po_number'       => $valid_data['po_number'],
1862
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1863
-                'PAY_details'         => $valid_data,
1864
-                'PAY_ID'              => $PAY_ID,
1865
-            ],
1866
-            '',
1867
-            ['Y-m-d', 'g:i a']
1868
-        );
1869
-
1870
-        if (! $payment->save()) {
1871
-            EE_Error::add_error(
1872
-                sprintf(
1873
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1874
-                    $payment->ID()
1875
-                ),
1876
-                __FILE__,
1877
-                __FUNCTION__,
1878
-                __LINE__
1879
-            );
1880
-        }
1881
-
1882
-        return $payment;
1883
-    }
1884
-
1885
-
1886
-    /**
1887
-     * _process_transaction_payments
1888
-     *
1889
-     * @param EE_Transaction $transaction
1890
-     * @return void
1891
-     * @throws EE_Error
1892
-     * @throws InvalidArgumentException
1893
-     * @throws ReflectionException
1894
-     * @throws InvalidDataTypeException
1895
-     * @throws InvalidInterfaceException
1896
-     */
1897
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1898
-    {
1899
-        /** @type EE_Transaction_Payments $transaction_payments */
1900
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1901
-        // update the transaction with this payment
1902
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1903
-            EE_Error::add_success(
1904
-                esc_html__(
1905
-                    'The payment has been processed successfully.',
1906
-                    'event_espresso'
1907
-                ),
1908
-                __FILE__,
1909
-                __FUNCTION__,
1910
-                __LINE__
1911
-            );
1912
-        } else {
1913
-            EE_Error::add_error(
1914
-                esc_html__(
1915
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1916
-                    'event_espresso'
1917
-                ),
1918
-                __FILE__,
1919
-                __FUNCTION__,
1920
-                __LINE__
1921
-            );
1922
-        }
1923
-    }
1924
-
1925
-
1926
-    /**
1927
-     * _get_REG_IDs_to_apply_payment_to
1928
-     * returns a list of registration IDs that the payment will apply to
1929
-     *
1930
-     * @param EE_Payment $payment
1931
-     * @return array
1932
-     * @throws EE_Error
1933
-     * @throws InvalidArgumentException
1934
-     * @throws InvalidDataTypeException
1935
-     * @throws InvalidInterfaceException
1936
-     * @throws ReflectionException
1937
-     */
1938
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1939
-    {
1940
-        // grab array of IDs for specific registrations to apply changes to
1941
-        $apply_to_all = $this->request->getRequestParam(
1942
-            'txn_admin_payment[apply_to_all_registrations]',
1943
-            false,
1944
-            DataType::BOOL
1945
-        );
1946
-        $REG_IDs      = ! $apply_to_all
1947
-            ? $this->request->getRequestParam(
1948
-                'txn_admin_payment[registrations]',
1949
-                [],
1950
-                DataType::INT,
1951
-                true
1952
-            )
1953
-            : [];
1954
-        // nothing specified ? then get all reg IDs
1955
-        if ($apply_to_all || empty($REG_IDs)) {
1956
-            $registrations = $payment->transaction()->registrations();
1957
-            $REG_IDs       = ! empty($registrations)
1958
-                ? array_keys($registrations)
1959
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1960
-        }
1961
-        // ensure that REG_IDs are integers and NOT strings
1962
-        return array_map('absint', $REG_IDs);
1963
-    }
1964
-
1965
-
1966
-    /**
1967
-     * @return array
1968
-     */
1969
-    public function existing_reg_payment_REG_IDs()
1970
-    {
1971
-        return $this->_existing_reg_payment_REG_IDs;
1972
-    }
1973
-
1974
-
1975
-    /**
1976
-     * @param array $existing_reg_payment_REG_IDs
1977
-     */
1978
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1979
-    {
1980
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1981
-    }
1982
-
1983
-
1984
-    /**
1985
-     * _get_existing_reg_payment_REG_IDs
1986
-     * returns a list of registration IDs that the payment is currently related to
1987
-     * as recorded in the database
1988
-     *
1989
-     * @param EE_Payment $payment
1990
-     * @return array
1991
-     * @throws EE_Error
1992
-     * @throws InvalidArgumentException
1993
-     * @throws InvalidDataTypeException
1994
-     * @throws InvalidInterfaceException
1995
-     * @throws ReflectionException
1996
-     */
1997
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1998
-    {
1999
-        if ($this->existing_reg_payment_REG_IDs() === null) {
2000
-            // let's get any existing reg payment records for this payment
2001
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2002
-            // but we only want the REG IDs, so grab the array keys
2003
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2004
-                ? array_keys($existing_reg_payment_REG_IDs)
2005
-                : [];
2006
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2007
-        }
2008
-
2009
-        return $this->existing_reg_payment_REG_IDs();
2010
-    }
2011
-
2012
-
2013
-    /**
2014
-     * _remove_existing_registration_payments
2015
-     * this calculates the difference between existing relations
2016
-     * to the supplied payment and the new list registration IDs,
2017
-     * removes any related registrations that no longer apply,
2018
-     * and then updates the registration paid fields
2019
-     *
2020
-     * @param EE_Payment $payment
2021
-     * @param int        $PAY_ID
2022
-     * @return bool;
2023
-     * @throws EE_Error
2024
-     * @throws InvalidArgumentException
2025
-     * @throws ReflectionException
2026
-     * @throws InvalidDataTypeException
2027
-     * @throws InvalidInterfaceException
2028
-     */
2029
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2030
-    {
2031
-        // newly created payments will have nothing recorded for $PAY_ID
2032
-        if (absint($PAY_ID) === 0) {
2033
-            return false;
2034
-        }
2035
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2036
-        if (empty($existing_reg_payment_REG_IDs)) {
2037
-            return false;
2038
-        }
2039
-        /** @type EE_Transaction_Payments $transaction_payments */
2040
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2041
-
2042
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2043
-            $payment,
2044
-            [
2045
-                [
2046
-                    'PAY_ID' => $payment->ID(),
2047
-                    'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2048
-                ],
2049
-            ]
2050
-        );
2051
-    }
2052
-
2053
-
2054
-    /**
2055
-     * _update_registration_payments
2056
-     * this applies the payments to the selected registrations
2057
-     * but only if they have not already been paid for
2058
-     *
2059
-     * @param EE_Transaction $transaction
2060
-     * @param EE_Payment     $payment
2061
-     * @param array          $REG_IDs
2062
-     * @return void
2063
-     * @throws EE_Error
2064
-     * @throws InvalidArgumentException
2065
-     * @throws ReflectionException
2066
-     * @throws RuntimeException
2067
-     * @throws InvalidDataTypeException
2068
-     * @throws InvalidInterfaceException
2069
-     */
2070
-    protected function _update_registration_payments(
2071
-        EE_Transaction $transaction,
2072
-        EE_Payment $payment,
2073
-        $REG_IDs = []
2074
-    ) {
2075
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2076
-        // so let's do that using our set of REG_IDs from the form
2077
-        $registration_query_where_params = [
2078
-            'REG_ID' => ['IN', $REG_IDs],
2079
-        ];
2080
-        // but add in some conditions regarding payment,
2081
-        // so that we don't apply payments to registrations that are free or have already been paid for
2082
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2083
-        if (! $payment->is_a_refund()) {
2084
-            $registration_query_where_params['REG_final_price']  = ['!=', 0];
2085
-            $registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2086
-        }
2087
-        $registrations = $transaction->registrations([$registration_query_where_params]);
2088
-        if (! empty($registrations)) {
2089
-            /** @type EE_Payment_Processor $payment_processor */
2090
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2091
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2092
-        }
2093
-    }
2094
-
2095
-
2096
-    /**
2097
-     * _process_registration_status_change
2098
-     * This processes requested registration status changes for all the registrations
2099
-     * on a given transaction and (optionally) sends out notifications for the changes.
2100
-     *
2101
-     * @param EE_Transaction $transaction
2102
-     * @param array          $REG_IDs
2103
-     * @return bool
2104
-     * @throws EE_Error
2105
-     * @throws InvalidArgumentException
2106
-     * @throws ReflectionException
2107
-     * @throws InvalidDataTypeException
2108
-     * @throws InvalidInterfaceException
2109
-     */
2110
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2111
-    {
2112
-        // first if there is no change in status then we get out.
2113
-        $reg_status = $reg_status ?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2114
-        if ($reg_status === 'NAN') {
2115
-            // no error message, no change requested, just nothing to do man.
2116
-            return false;
2117
-        }
2118
-        /** @type EE_Transaction_Processor $transaction_processor */
2119
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2120
-
2121
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2122
-        return $transaction_processor->manually_update_registration_statuses(
2123
-            $transaction,
2124
-            $reg_status,
2125
-            [['REG_ID' => ['IN', $REG_IDs]]]
2126
-        );
2127
-    }
2128
-
2129
-
2130
-    /**
2131
-     * _build_payment_json_response
2132
-     *
2133
-     * @access public
2134
-     * @param EE_Payment  $payment
2135
-     * @param array       $REG_IDs
2136
-     * @param bool | null $delete_txn_reg_status_change
2137
-     * @return array
2138
-     * @throws EE_Error
2139
-     * @throws InvalidArgumentException
2140
-     * @throws InvalidDataTypeException
2141
-     * @throws InvalidInterfaceException
2142
-     * @throws ReflectionException
2143
-     */
2144
-    protected function _build_payment_json_response(
2145
-        EE_Payment $payment,
2146
-        $REG_IDs = [],
2147
-        $delete_txn_reg_status_change = null
2148
-    ) {
2149
-        // was the payment deleted ?
2150
-        if (is_bool($delete_txn_reg_status_change)) {
2151
-            return [
2152
-                'PAY_ID'                       => $payment->ID(),
2153
-                'amount'                       => $payment->amount(),
2154
-                'total_paid'                   => $payment->transaction()->paid(),
2155
-                'txn_status'                   => $payment->transaction()->status_ID(),
2156
-                'pay_status'                   => $payment->STS_ID(),
2157
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2158
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2159
-            ];
2160
-        }
2161
-
2162
-        $this->_get_payment_status_array();
2163
-        return [
2164
-            'amount'           => $payment->amount(),
2165
-            'total_paid'       => $payment->transaction()->paid(),
2166
-            'txn_status'       => $payment->transaction()->status_ID(),
2167
-            'pay_status'       => $payment->STS_ID(),
2168
-            'PAY_ID'           => $payment->ID(),
2169
-            'STS_ID'           => $payment->STS_ID(),
2170
-            'status'           => self::$_pay_status[ $payment->STS_ID() ],
2171
-            'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2172
-            'method'           => strtoupper($payment->source()),
2173
-            'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2174
-            'gateway'          => $payment->payment_method()
2175
-                ? $payment->payment_method()->admin_name()
2176
-                : esc_html__('Unknown', 'event_espresso'),
2177
-            'gateway_response' => $payment->gateway_response(),
2178
-            'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2179
-            'po_number'        => $payment->po_number(),
2180
-            'extra_accntng'    => $payment->extra_accntng(),
2181
-            'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2182
-        ];
2183
-    }
2184
-
2185
-
2186
-    /**
2187
-     * delete_payment
2188
-     *    delete a payment or refund made towards a transaction
2189
-     *
2190
-     * @access public
2191
-     * @return void
2192
-     * @throws EE_Error
2193
-     * @throws InvalidArgumentException
2194
-     * @throws ReflectionException
2195
-     * @throws InvalidDataTypeException
2196
-     * @throws InvalidInterfaceException
2197
-     */
2198
-    public function delete_payment()
2199
-    {
2200
-        $TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2201
-        // $json_response_data = ['return_data' => false];
2202
-        $PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2203
-        $amount     = 0;
2204
-        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2205
-            'ee_delete_payments',
2206
-            'delete_payment_from_registration_details'
2207
-        );
2208
-        if ($PAY_ID && $can_delete) {
2209
-            $delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2210
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2211
-            if ($payment instanceof EE_Payment) {
2212
-                $amount  = $payment->amount();
2213
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2214
-                /** @type EE_Transaction_Payments $transaction_payments */
2215
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2216
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2217
-                    if ($delete_txn_reg_status_change) {
2218
-                        $this->_maybe_send_notifications();
2219
-                        $this->_process_registration_status_change(
2220
-                            $payment->transaction(),
2221
-                            $REG_IDs,
2222
-                            $delete_txn_reg_status_change
2223
-                        );
2224
-                    }
2225
-                }
2226
-            } else {
2227
-                EE_Error::add_error(
2228
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2229
-                    __FILE__,
2230
-                    __FUNCTION__,
2231
-                    __LINE__
2232
-                );
2233
-            }
2234
-        } elseif ($can_delete) {
2235
-            EE_Error::add_error(
2236
-                esc_html__(
2237
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2238
-                    'event_espresso'
2239
-                ),
2240
-                __FILE__,
2241
-                __FUNCTION__,
2242
-                __LINE__
2243
-            );
2244
-        } else {
2245
-            EE_Error::add_error(
2246
-                esc_html__(
2247
-                    'You do not have access to delete a payment.',
2248
-                    'event_espresso'
2249
-                ),
2250
-                __FILE__,
2251
-                __FUNCTION__,
2252
-                __LINE__
2253
-            );
2254
-        }
2255
-        $query_args = [
2256
-            'page'   => 'espresso_transactions',
2257
-            'action' => 'view_transaction',
2258
-            'TXN_ID' => $TXD_ID,
2259
-        ];
2260
-        $this->_redirect_after_action(
2261
-            ! EE_Error::has_error(),
2262
-            $amount > 0
2263
-                ? esc_html__('payment', 'event_espresso')
2264
-                : esc_html__('refund', 'event_espresso'),
2265
-            esc_html__('deleted', 'event_espresso'),
2266
-            $query_args
2267
-        );
2268
-    }
2269
-
2270
-
2271
-    /**
2272
-     * _registration_payment_data_array
2273
-     * adds info for 'owing' and 'paid' for each registration to the json response
2274
-     *
2275
-     * @access protected
2276
-     * @param array $REG_IDs
2277
-     * @return array
2278
-     * @throws EE_Error
2279
-     * @throws InvalidArgumentException
2280
-     * @throws InvalidDataTypeException
2281
-     * @throws InvalidInterfaceException
2282
-     * @throws ReflectionException
2283
-     */
2284
-    protected function _registration_payment_data_array($REG_IDs)
2285
-    {
2286
-        $registration_payment_data = [];
2287
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2288
-        if (! empty($REG_IDs)) {
2289
-            $registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2290
-            foreach ($registrations as $registration) {
2291
-                if ($registration instanceof EE_Registration) {
2292
-                    $registration_payment_data[ $registration->ID() ] = [
2293
-                        'paid'  => $registration->pretty_paid(),
2294
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2295
-                    ];
2296
-                }
2297
-            }
2298
-        }
2299
-
2300
-        return $registration_payment_data;
2301
-    }
2302
-
2303
-
2304
-    /**
2305
-     * _maybe_send_notifications
2306
-     * determines whether or not the admin has indicated that notifications should be sent.
2307
-     * If so, will toggle a filter switch for delivering registration notices.
2308
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2309
-     *
2310
-     * @access protected
2311
-     * @param EE_Payment | null $payment
2312
-     */
2313
-    protected function _maybe_send_notifications($payment = null)
2314
-    {
2315
-        switch ($payment instanceof EE_Payment) {
2316
-            // payment notifications
2317
-            case true:
2318
-                if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2319
-                    $this->_process_payment_notification($payment);
2320
-                }
2321
-                break;
2322
-            // registration notifications
2323
-            case false:
2324
-                if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2325
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2326
-                }
2327
-                break;
2328
-        }
2329
-    }
2330
-
2331
-
2332
-    /**
2333
-     * _send_payment_reminder
2334
-     *    generates HTML for the View Transaction Details Admin page
2335
-     *
2336
-     * @access protected
2337
-     * @return void
2338
-     * @throws EE_Error
2339
-     * @throws InvalidArgumentException
2340
-     * @throws InvalidDataTypeException
2341
-     * @throws InvalidInterfaceException
2342
-     */
2343
-    protected function _send_payment_reminder()
2344
-    {
2345
-        $TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2346
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2347
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2348
-        $query_args  = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2349
-        do_action(
2350
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2351
-            $transaction
2352
-        );
2353
-        $this->_redirect_after_action(
2354
-            false,
2355
-            esc_html__('payment reminder', 'event_espresso'),
2356
-            esc_html__('sent', 'event_espresso'),
2357
-            $query_args,
2358
-            true
2359
-        );
2360
-    }
2361
-
2362
-
2363
-    /**
2364
-     *  get_transactions
2365
-     *    get transactions for given parameters (used by list table)
2366
-     *
2367
-     * @param int     $per_page how many transactions displayed per page
2368
-     * @param boolean $count    return the count or objects
2369
-     * @param string  $view
2370
-     * @return EE_Transaction[]|int int = count || array of transaction objects
2371
-     * @throws EE_Error
2372
-     * @throws InvalidArgumentException
2373
-     * @throws InvalidDataTypeException
2374
-     * @throws InvalidInterfaceException
2375
-     * @throws ReflectionException
2376
-     */
2377
-    public function get_transactions($per_page, $count = false, $view = '')
2378
-    {
2379
-        $start_date = wp_strip_all_tags(
2380
-            $this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2381
-        );
2382
-        $end_date   = wp_strip_all_tags(
2383
-            $this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2384
-        );
2385
-
2386
-        // make sure our timestamps start and end right at the boundaries for each day
2387
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2388
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2389
-
2390
-
2391
-        // convert to timestamps
2392
-        $start_date = strtotime($start_date);
2393
-        $end_date   = strtotime($end_date);
2394
-
2395
-        // makes sure start date is the lowest value and vice versa
2396
-        $start_date = min($start_date, $end_date);
2397
-        $end_date   = max($start_date, $end_date);
2398
-
2399
-        // convert to correct format for query
2400
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2401
-            'TXN_timestamp',
2402
-            date('Y-m-d H:i:s', $start_date),
2403
-            'Y-m-d H:i:s'
2404
-        );
2405
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2406
-            'TXN_timestamp',
2407
-            date('Y-m-d H:i:s', $end_date),
2408
-            'Y-m-d H:i:s'
2409
-        );
2410
-
2411
-
2412
-        // set orderby
2413
-        $orderby = $this->request->getRequestParam('orderby');
2414
-
2415
-        switch ($orderby) {
2416
-            case 'TXN_ID':
2417
-                break;
2418
-            case 'ATT_fname':
2419
-                $orderby = 'Registration.Attendee.ATT_fname';
2420
-                break;
2421
-            case 'event_name':
2422
-                $orderby = 'Registration.Event.EVT_name';
2423
-                break;
2424
-            default: // 'TXN_timestamp'
2425
-                $orderby = 'TXN_timestamp';
2426
-        }
2427
-
2428
-        $sort         = $this->request->getRequestParam('order', 'DESC');
2429
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
2430
-
2431
-        $per_page = absint($per_page) ? $per_page : 10;
2432
-        $per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2433
-
2434
-        $offset = ($current_page - 1) * $per_page;
2435
-        $limit  = [$offset, $per_page];
2436
-
2437
-        $_where = [
2438
-            'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2439
-            'Registration.REG_count' => 1,
2440
-        ];
2441
-
2442
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2443
-        if ($EVT_ID) {
2444
-            $_where['Registration.EVT_ID'] = $EVT_ID;
2445
-        }
2446
-
2447
-        $search_term = $this->request->getRequestParam('s');
2448
-        if ($search_term) {
2449
-            $search_term  = '%' . $search_term . '%';
2450
-            $_where['OR'] = [
2451
-                'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2452
-                'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2453
-                'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2454
-                'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2455
-                'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2456
-                'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2457
-                'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2458
-                'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2459
-                'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2460
-                'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2461
-                'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2462
-                'Registration.REG_final_price'        => ['LIKE', $search_term],
2463
-                'Registration.REG_code'               => ['LIKE', $search_term],
2464
-                'Registration.REG_count'              => ['LIKE', $search_term],
2465
-                'Registration.REG_group_size'         => ['LIKE', $search_term],
2466
-                'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2467
-                'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2468
-                'Payment.PAY_source'                  => ['LIKE', $search_term],
2469
-                'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2470
-                'TXN_session_data'                    => ['LIKE', $search_term],
2471
-                'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2472
-            ];
2473
-        }
2474
-
2475
-        $status = $this->request->getRequestParam('status');
2476
-        // failed transactions
2477
-        $failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2478
-        $abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2479
-        $incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2480
-
2481
-        if ($failed) {
2482
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2483
-        } elseif ($abandoned) {
2484
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2485
-        } elseif ($incomplete) {
2486
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2487
-        } else {
2488
-            $_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2489
-            $_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2490
-        }
2491
-
2492
-        $query_params = apply_filters(
2493
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2494
-            [
2495
-                $_where,
2496
-                'order_by'                 => [$orderby => $sort],
2497
-                'limit'                    => $limit,
2498
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2499
-            ],
2500
-            $this->request->requestParams(),
2501
-            $view,
2502
-            $count
2503
-        );
2504
-
2505
-        return $count
2506
-            ? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2507
-            : EEM_Transaction::instance()->get_all($query_params);
2508
-    }
2509
-
2510
-
2511
-    /**
2512
-     * @throws EE_Error
2513
-     * @throws InvalidArgumentException
2514
-     * @throws InvalidDataTypeException
2515
-     * @throws InvalidInterfaceException
2516
-     * @throws ReflectionException
2517
-     * @throws RuntimeException
2518
-     * @since 4.9.79.p
2519
-     */
2520
-    public function recalculateLineItems()
2521
-    {
2522
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2523
-        /** @var EE_Transaction $transaction */
2524
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2525
-        $success     = $transaction->recalculateLineItems();
2526
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2527
-        $query_args  = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2528
-        $this->_redirect_after_action(
2529
-            $success,
2530
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2531
-            esc_html__('recalculated', 'event_espresso'),
2532
-            $query_args,
2533
-            true
2534
-        );
2535
-    }
16
+	/**
17
+	 * @var EE_Transaction
18
+	 */
19
+	private $_transaction;
20
+
21
+	/**
22
+	 * @var EE_Session
23
+	 */
24
+	private $_session;
25
+
26
+	/**
27
+	 * @var array $_txn_status
28
+	 */
29
+	private static $_txn_status;
30
+
31
+	/**
32
+	 * @var array $_pay_status
33
+	 */
34
+	private static $_pay_status;
35
+
36
+	/**
37
+	 * @var array $_existing_reg_payment_REG_IDs
38
+	 */
39
+	protected $_existing_reg_payment_REG_IDs;
40
+
41
+
42
+	/**
43
+	 *    _init_page_props
44
+	 *
45
+	 * @return void
46
+	 */
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug        = TXN_PG_SLUG;
50
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
51
+		$this->_admin_base_url  = TXN_ADMIN_URL;
52
+		$this->_admin_base_path = TXN_ADMIN;
53
+	}
54
+
55
+
56
+	/**
57
+	 *    _ajax_hooks
58
+	 *
59
+	 * @return void
60
+	 */
61
+	protected function _ajax_hooks()
62
+	{
63
+		// add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
64
+		// add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
65
+		// add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
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'       => 'apply_payments_or_refunds',
124
+				'noheader'   => true,
125
+				'capability' => 'ee_edit_payments',
126
+			],
127
+
128
+			'espresso_apply_refund' => [
129
+				'func'       => '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
+		EE_Registry::instance()->CAP->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
+			&& EE_Registry::instance()->CAP->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
+			EE_Registry::instance()->CAP->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
+			&& EE_Registry::instance()->CAP->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
+		EE_Registry::instance()->CAP->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']   = EE_Registry::instance()->CAP->current_user_can(
1004
+			'ee_edit_payments',
1005
+			'apply_payment_or_refund_from_registration_details'
1006
+		);
1007
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->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) ? $taxes : false;
1028
+
1029
+		$this->_template_args['grand_total']     = EEH_Template::format_currency(
1030
+			$this->_transaction->total(),
1031
+			false,
1032
+			false
1033
+		);
1034
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1035
+		$this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1036
+
1037
+		// process payment details
1038
+		$payments = $this->_transaction->payments();
1039
+		if (! empty($payments)) {
1040
+			$this->_template_args['payments']              = $payments;
1041
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1042
+		} else {
1043
+			$this->_template_args['payments']              = false;
1044
+			$this->_template_args['existing_reg_payments'] = [];
1045
+		}
1046
+
1047
+		$this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1048
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1049
+			['action' => 'espresso_delete_payment'],
1050
+			TXN_ADMIN_URL
1051
+		);
1052
+
1053
+		if (isset($txn_details['invoice_number'])) {
1054
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1055
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1056
+				'Invoice Number',
1057
+				'event_espresso'
1058
+			);
1059
+		}
1060
+
1061
+		$this->_template_args['txn_details']['registration_session']['value'] =
1062
+			$this->_transaction->primary_registration() instanceof EE_Registration
1063
+				? $this->_transaction->primary_registration()->session_ID()
1064
+				: null;
1065
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1066
+			'Registration Session',
1067
+			'event_espresso'
1068
+		);
1069
+
1070
+		$this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1071
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1072
+			'Transaction placed from IP',
1073
+			'event_espresso'
1074
+		);
1075
+
1076
+		$this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1077
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1078
+			'Registrant User Agent',
1079
+			'event_espresso'
1080
+		);
1081
+
1082
+		$reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1083
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1084
+			if ($reg_step_status === true) {
1085
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1086
+							  . sprintf(
1087
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1088
+								  ucwords(str_replace('_', ' ', $reg_step))
1089
+							  )
1090
+							  . '</div>';
1091
+			} elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1092
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1093
+							  . sprintf(
1094
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1095
+								  ucwords(str_replace('_', ' ', $reg_step)),
1096
+								  date(
1097
+									  get_option('date_format') . ' ' . get_option('time_format'),
1098
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1099
+								  )
1100
+							  )
1101
+							  . '</div>';
1102
+			} else {
1103
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1104
+							  . sprintf(
1105
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1106
+								  ucwords(str_replace('_', ' ', $reg_step))
1107
+							  )
1108
+							  . '</div>';
1109
+			}
1110
+		}
1111
+		$reg_steps                                                 .= '</ul>';
1112
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1113
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1114
+			'Registration Step Progress',
1115
+			'event_espresso'
1116
+		);
1117
+
1118
+
1119
+		$this->_get_registrations_to_apply_payment_to();
1120
+		$this->_get_payment_methods($payments);
1121
+		$this->_get_payment_status_array();
1122
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1123
+
1124
+		$this->_template_args['transaction_form_url']    = add_query_arg(
1125
+			[
1126
+				'action'  => 'edit_transaction',
1127
+				'process' => 'transaction',
1128
+			],
1129
+			TXN_ADMIN_URL
1130
+		);
1131
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(
1132
+			[
1133
+				'page'   => 'espresso_transactions',
1134
+				'action' => 'espresso_apply_payment',
1135
+			],
1136
+			TXN_ADMIN_URL
1137
+		);
1138
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1139
+			[
1140
+				'page'   => 'espresso_transactions',
1141
+				'action' => 'espresso_delete_payment',
1142
+			],
1143
+			TXN_ADMIN_URL
1144
+		);
1145
+
1146
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1147
+
1148
+		// 'espresso_delete_payment_nonce'
1149
+
1150
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1151
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1152
+	}
1153
+
1154
+
1155
+	/**
1156
+	 * _get_registration_payment_IDs
1157
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1158
+	 *
1159
+	 * @access protected
1160
+	 * @param EE_Payment[] $payments
1161
+	 * @return array
1162
+	 * @throws EE_Error
1163
+	 * @throws InvalidArgumentException
1164
+	 * @throws InvalidDataTypeException
1165
+	 * @throws InvalidInterfaceException
1166
+	 * @throws ReflectionException
1167
+	 */
1168
+	protected function _get_registration_payment_IDs($payments = [])
1169
+	{
1170
+		$existing_reg_payments = [];
1171
+		// get all reg payments for these payments
1172
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1173
+			[
1174
+				[
1175
+					'PAY_ID' => [
1176
+						'IN',
1177
+						array_keys($payments),
1178
+					],
1179
+				],
1180
+			]
1181
+		);
1182
+		if (! empty($reg_payments)) {
1183
+			foreach ($payments as $payment) {
1184
+				if (! $payment instanceof EE_Payment) {
1185
+					continue;
1186
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1187
+					$existing_reg_payments[ $payment->ID() ] = [];
1188
+				}
1189
+				foreach ($reg_payments as $reg_payment) {
1190
+					if (
1191
+						$reg_payment instanceof EE_Registration_Payment
1192
+						&& $reg_payment->payment_ID() === $payment->ID()
1193
+					) {
1194
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1195
+					}
1196
+				}
1197
+			}
1198
+		}
1199
+
1200
+		return $existing_reg_payments;
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 * _get_registrations_to_apply_payment_to
1206
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1207
+	 * which allows the admin to only apply the payment to the specific registrations
1208
+	 *
1209
+	 * @access protected
1210
+	 * @return void
1211
+	 * @throws EE_Error
1212
+	 * @throws InvalidArgumentException
1213
+	 * @throws InvalidDataTypeException
1214
+	 * @throws InvalidInterfaceException
1215
+	 * @throws ReflectionException
1216
+	 */
1217
+	protected function _get_registrations_to_apply_payment_to()
1218
+	{
1219
+		// we want any registration with an active status (ie: not deleted or cancelled)
1220
+		$query_params                      = [
1221
+			[
1222
+				'STS_ID' => [
1223
+					'IN',
1224
+					[
1225
+						EEM_Registration::status_id_approved,
1226
+						EEM_Registration::status_id_pending_payment,
1227
+						EEM_Registration::status_id_not_approved,
1228
+					],
1229
+				],
1230
+			],
1231
+		];
1232
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1233
+				'',
1234
+				'txn-admin-apply-payment-to-registrations-dv',
1235
+				'',
1236
+				'clear: both; margin: 1.5em 0 0; display: none;'
1237
+			);
1238
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1239
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1240
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1241
+			EEH_HTML::tr(
1242
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1243
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1244
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1245
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1246
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1247
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1248
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1249
+			)
1250
+		);
1251
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1252
+		// get registrations for TXN
1253
+		$registrations         = $this->_transaction->registrations($query_params);
1254
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1255
+		foreach ($registrations as $registration) {
1256
+			if ($registration instanceof EE_Registration) {
1257
+				$attendee_name                     = $registration->attendee() instanceof EE_Attendee
1258
+					? $registration->attendee()->full_name()
1259
+					: esc_html__('Unknown Attendee', 'event_espresso');
1260
+				$owing                             = $registration->final_price() - $registration->paid();
1261
+				$taxable                           = $registration->ticket()->taxable()
1262
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1263
+					: '';
1264
+				$checked                           = empty($existing_reg_payments)
1265
+													 || in_array($registration->ID(), $existing_reg_payments, true)
1266
+					? ' checked'
1267
+					: '';
1268
+				$disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1269
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1270
+					EEH_HTML::td($registration->ID()) .
1271
+					EEH_HTML::td($attendee_name) .
1272
+					EEH_HTML::td(
1273
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1274
+					) .
1275
+					EEH_HTML::td($registration->event_name()) .
1276
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1277
+					EEH_HTML::td(
1278
+						EEH_Template::format_currency($owing),
1279
+						'',
1280
+						'txn-admin-payment-owing-td jst-cntr'
1281
+					) .
1282
+					EEH_HTML::td(
1283
+						'<input type="checkbox" value="' . $registration->ID()
1284
+						. '" name="txn_admin_payment[registrations]"'
1285
+						. $checked . $disabled . '>',
1286
+						'',
1287
+						'jst-cntr'
1288
+					),
1289
+					'apply-payment-registration-row-' . $registration->ID()
1290
+				);
1291
+			}
1292
+		}
1293
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1294
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1295
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1296
+		$registrations_to_apply_payment_to                         .= EEH_HTML::p(
1297
+			esc_html__(
1298
+				'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.',
1299
+				'event_espresso'
1300
+			),
1301
+			'',
1302
+			'clear description'
1303
+		);
1304
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1305
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1306
+	}
1307
+
1308
+
1309
+	/**
1310
+	 * _get_reg_status_selection
1311
+	 *
1312
+	 * @return void
1313
+	 * @throws EE_Error
1314
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1315
+	 *         instead of events.
1316
+	 * @access protected
1317
+	 */
1318
+	protected function _get_reg_status_selection()
1319
+	{
1320
+		// first get all possible statuses
1321
+		$statuses = EEM_Registration::reg_status_array([], true);
1322
+		// let's add a "don't change" option.
1323
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1324
+		$status_array                                        = array_merge($status_array, $statuses);
1325
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1326
+			'txn_reg_status_change[reg_status]',
1327
+			$status_array,
1328
+			'NAN',
1329
+			'id="txn-admin-payment-reg-status-inp"',
1330
+			'txn-reg-status-change-reg-status'
1331
+		);
1332
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1333
+			'delete_txn_reg_status_change[reg_status]',
1334
+			$status_array,
1335
+			'NAN',
1336
+			'delete-txn-admin-payment-reg-status-inp',
1337
+			'delete-txn-reg-status-change-reg-status'
1338
+		);
1339
+	}
1340
+
1341
+
1342
+	/**
1343
+	 *    _get_payment_methods
1344
+	 * Gets all the payment methods available generally, or the ones that are already
1345
+	 * selected on these payments (in case their payment methods are no longer active).
1346
+	 * Has the side-effect of updating the template args' payment_methods item
1347
+	 *
1348
+	 * @access private
1349
+	 * @param EE_Payment[] to show on this page
1350
+	 * @return void
1351
+	 * @throws EE_Error
1352
+	 * @throws InvalidArgumentException
1353
+	 * @throws InvalidDataTypeException
1354
+	 * @throws InvalidInterfaceException
1355
+	 * @throws ReflectionException
1356
+	 */
1357
+	private function _get_payment_methods($payments = [])
1358
+	{
1359
+		$payment_methods_of_payments = [];
1360
+		foreach ($payments as $payment) {
1361
+			if ($payment instanceof EE_Payment) {
1362
+				$payment_methods_of_payments[] = $payment->ID();
1363
+			}
1364
+		}
1365
+		if ($payment_methods_of_payments) {
1366
+			$query_args = [
1367
+				[
1368
+					'OR*payment_method_for_payment' => [
1369
+						'PMD_ID'    => ['IN', $payment_methods_of_payments],
1370
+						'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1371
+					],
1372
+				],
1373
+			];
1374
+		} else {
1375
+			$query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1376
+		}
1377
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1378
+	}
1379
+
1380
+
1381
+	/**
1382
+	 * txn_attendees_meta_box
1383
+	 *    generates HTML for the Attendees Transaction main meta box
1384
+	 *
1385
+	 * @access public
1386
+	 * @param WP_Post $post
1387
+	 * @param array   $metabox
1388
+	 * @return void
1389
+	 * @throws DomainException
1390
+	 * @throws EE_Error
1391
+	 * @throws InvalidArgumentException
1392
+	 * @throws InvalidDataTypeException
1393
+	 * @throws InvalidInterfaceException
1394
+	 * @throws ReflectionException
1395
+	 */
1396
+	public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1397
+	{
1398
+		/** @noinspection NonSecureExtractUsageInspection */
1399
+		extract($metabox['args']);
1400
+		$this->_template_args['post']            = $post;
1401
+		$this->_template_args['event_attendees'] = [];
1402
+		// process items in cart
1403
+		$line_items = $this->_transaction->get_many_related(
1404
+			'Line_Item',
1405
+			[['LIN_type' => 'line-item']]
1406
+		);
1407
+		if (! empty($line_items)) {
1408
+			foreach ($line_items as $item) {
1409
+				if ($item instanceof EE_Line_Item) {
1410
+					switch ($item->OBJ_type()) {
1411
+						case 'Event':
1412
+							break;
1413
+						case 'Ticket':
1414
+							$ticket = $item->ticket();
1415
+							// right now we're only handling tickets here.
1416
+							// Cause its expected that only tickets will have attendees right?
1417
+							if (! $ticket instanceof EE_Ticket) {
1418
+								break;
1419
+							}
1420
+							try {
1421
+								$event_name = $ticket->get_event_name();
1422
+							} catch (Exception $e) {
1423
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1424
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1425
+							}
1426
+							$event_name   .= ' - ' . $item->name();
1427
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1428
+							// now get all of the registrations for this transaction that use this ticket
1429
+							$registrations = $ticket->registrations(
1430
+								[['TXN_ID' => $this->_transaction->ID()]]
1431
+							);
1432
+							foreach ($registrations as $registration) {
1433
+								if (! $registration instanceof EE_Registration) {
1434
+									break;
1435
+								}
1436
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1437
+									= $registration->status_ID();
1438
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1439
+									= $registration->count();
1440
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1441
+									= $event_name;
1442
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1443
+									= $ticket_price;
1444
+								// attendee info
1445
+								$attendee = $registration->get_first_related('Attendee');
1446
+								if ($attendee instanceof EE_Attendee) {
1447
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1448
+										= $attendee->ID();
1449
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1450
+										= $attendee->full_name();
1451
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1452
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1453
+										  . esc_html__(
1454
+											  ' Event',
1455
+											  'event_espresso'
1456
+										  )
1457
+										  . '">' . $attendee->email() . '</a>';
1458
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1459
+										= EEH_Address::format($attendee, 'inline', false, false);
1460
+								} else {
1461
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1462
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1463
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1464
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1465
+								}
1466
+							}
1467
+							break;
1468
+					}
1469
+				}
1470
+			}
1471
+
1472
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1473
+				[
1474
+					'action'  => 'edit_transaction',
1475
+					'process' => 'attendees',
1476
+				],
1477
+				TXN_ADMIN_URL
1478
+			);
1479
+			echo EEH_Template::display_template(
1480
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1481
+				$this->_template_args,
1482
+				true
1483
+			);
1484
+		} else {
1485
+			printf(
1486
+				esc_html__(
1487
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1488
+					'event_espresso'
1489
+				),
1490
+				'<p class="important-notice">',
1491
+				'</p>'
1492
+			);
1493
+		}
1494
+	}
1495
+
1496
+
1497
+	/**
1498
+	 * txn_registrant_side_meta_box
1499
+	 * generates HTML for the Edit Transaction side meta box
1500
+	 *
1501
+	 * @access public
1502
+	 * @return void
1503
+	 * @throws DomainException
1504
+	 * @throws EE_Error
1505
+	 * @throws InvalidArgumentException
1506
+	 * @throws InvalidDataTypeException
1507
+	 * @throws InvalidInterfaceException
1508
+	 * @throws ReflectionException
1509
+	 */
1510
+	public function txn_registrant_side_meta_box()
1511
+	{
1512
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1513
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1514
+			: null;
1515
+		if (! $primary_att instanceof EE_Attendee) {
1516
+			$this->_template_args['no_attendee_message'] = esc_html__(
1517
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1518
+				'event_espresso'
1519
+			);
1520
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1521
+		}
1522
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1523
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1524
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1525
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1526
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1527
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1528
+			[
1529
+				'action' => 'edit_attendee',
1530
+				'post'   => $primary_att->ID(),
1531
+			],
1532
+			REG_ADMIN_URL
1533
+		);
1534
+		// get formatted address for registrant
1535
+		$formatted_address                         = EEH_Address::format($primary_att);
1536
+		$formatted_address                         =
1537
+			$formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1538
+				? $formatted_address
1539
+				: '';
1540
+		$this->_template_args['formatted_address'] = $formatted_address;
1541
+		echo EEH_Template::display_template(
1542
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1543
+			$this->_template_args,
1544
+			true
1545
+		);
1546
+	}
1547
+
1548
+
1549
+	/**
1550
+	 * txn_billing_info_side_meta_box
1551
+	 *    generates HTML for the Edit Transaction side meta box
1552
+	 *
1553
+	 * @access public
1554
+	 * @return void
1555
+	 * @throws DomainException
1556
+	 * @throws EE_Error
1557
+	 * @throws ReflectionException
1558
+	 */
1559
+	public function txn_billing_info_side_meta_box()
1560
+	{
1561
+		$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1562
+		$this->_template_args['billing_form_url'] = add_query_arg(
1563
+			['action' => 'edit_transaction', 'process' => 'billing'],
1564
+			TXN_ADMIN_URL
1565
+		);
1566
+
1567
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1568
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1569
+	}
1570
+
1571
+
1572
+	/**
1573
+	 * apply_payments_or_refunds
1574
+	 *    registers a payment or refund made towards a transaction
1575
+	 *
1576
+	 * @access public
1577
+	 * @return void
1578
+	 * @throws EE_Error
1579
+	 * @throws InvalidArgumentException
1580
+	 * @throws ReflectionException
1581
+	 * @throws RuntimeException
1582
+	 * @throws InvalidDataTypeException
1583
+	 * @throws InvalidInterfaceException
1584
+	 */
1585
+	public function apply_payments_or_refunds()
1586
+	{
1587
+		$valid_data = $this->_validate_payment_request_data();
1588
+		$has_access = EE_Registry::instance()->CAP->current_user_can(
1589
+			'ee_edit_payments',
1590
+			'apply_payment_or_refund_from_registration_details'
1591
+		);
1592
+		$TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1593
+		$amount     = 0;
1594
+		if (! empty($valid_data) && $has_access) {
1595
+			$PAY_ID = $valid_data['PAY_ID'];
1596
+			// save  the new payment
1597
+			$payment = $this->_create_payment_from_request_data($valid_data);
1598
+			$amount  = $payment->amount();
1599
+			// get the TXN for this payment
1600
+			$transaction = $payment->transaction();
1601
+			// verify transaction
1602
+			if ($transaction instanceof EE_Transaction) {
1603
+				// calculate_total_payments_and_update_status
1604
+				$this->_process_transaction_payments($transaction);
1605
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1606
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1607
+				// apply payment to registrations (if applicable)
1608
+				if (! empty($REG_IDs)) {
1609
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1610
+					$this->_maybe_send_notifications();
1611
+					// now process status changes for the same registrations
1612
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1613
+				}
1614
+				$this->_maybe_send_notifications($payment);
1615
+				// prepare to render page
1616
+				do_action(
1617
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1618
+					$transaction,
1619
+					$payment
1620
+				);
1621
+			} else {
1622
+				EE_Error::add_error(
1623
+					esc_html__(
1624
+						'A valid Transaction for this payment could not be retrieved.',
1625
+						'event_espresso'
1626
+					),
1627
+					__FILE__,
1628
+					__FUNCTION__,
1629
+					__LINE__
1630
+				);
1631
+			}
1632
+		} elseif ($has_access) {
1633
+			EE_Error::add_error(
1634
+				esc_html__(
1635
+					'The payment form data could not be processed. Please try again.',
1636
+					'event_espresso'
1637
+				),
1638
+				__FILE__,
1639
+				__FUNCTION__,
1640
+				__LINE__
1641
+			);
1642
+		} else {
1643
+			EE_Error::add_error(
1644
+				esc_html__(
1645
+					'You do not have access to apply payments or refunds to a registration.',
1646
+					'event_espresso'
1647
+				),
1648
+				__FILE__,
1649
+				__FUNCTION__,
1650
+				__LINE__
1651
+			);
1652
+		}
1653
+		$query_args = [
1654
+			'page'   => 'espresso_transactions',
1655
+			'action' => 'view_transaction',
1656
+			'TXN_ID' => $TXD_ID,
1657
+		];
1658
+
1659
+		$this->_redirect_after_action(
1660
+			! EE_Error::has_error(),
1661
+			$amount > 0
1662
+				? esc_html__('payment', 'event_espresso')
1663
+				: esc_html__('refund', 'event_espresso'),
1664
+			esc_html__('processed', 'event_espresso'),
1665
+			$query_args
1666
+		);
1667
+	}
1668
+
1669
+
1670
+	/**
1671
+	 * _validate_payment_request_data
1672
+	 *
1673
+	 * @return array
1674
+	 * @throws EE_Error
1675
+	 * @throws InvalidArgumentException
1676
+	 * @throws InvalidDataTypeException
1677
+	 * @throws InvalidInterfaceException
1678
+	 */
1679
+	protected function _validate_payment_request_data()
1680
+	{
1681
+		if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1682
+			return [];
1683
+		}
1684
+		$payment_form = $this->_generate_payment_form_section();
1685
+		try {
1686
+			if ($payment_form->was_submitted()) {
1687
+				$payment_form->receive_form_submission();
1688
+				if (! $payment_form->is_valid()) {
1689
+					$submission_error_messages = [];
1690
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1691
+						if ($validation_error instanceof EE_Validation_Error) {
1692
+							$form_input                  = $validation_error->get_form_section();
1693
+							$submission_error_messages[] = sprintf(
1694
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1695
+								$form_input instanceof EE_Form_Input_Base ? $form_input->html_label_text() : '',
1696
+								$validation_error->getMessage()
1697
+							);
1698
+						}
1699
+					}
1700
+					EE_Error::add_error(
1701
+						implode('<br />', $submission_error_messages),
1702
+						__FILE__,
1703
+						__FUNCTION__,
1704
+						__LINE__
1705
+					);
1706
+					return [];
1707
+				}
1708
+			}
1709
+		} catch (EE_Error $e) {
1710
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1711
+			return [];
1712
+		}
1713
+
1714
+		return $payment_form->valid_data();
1715
+	}
1716
+
1717
+
1718
+	/**
1719
+	 * _generate_payment_form_section
1720
+	 *
1721
+	 * @return EE_Form_Section_Proper
1722
+	 * @throws EE_Error
1723
+	 */
1724
+	protected function _generate_payment_form_section()
1725
+	{
1726
+		return new EE_Form_Section_Proper(
1727
+			[
1728
+				'name'        => 'txn_admin_payment',
1729
+				'subsections' => [
1730
+					'PAY_ID'          => new EE_Text_Input(
1731
+						[
1732
+							'default'               => 0,
1733
+							'required'              => false,
1734
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1735
+							'validation_strategies' => [new EE_Int_Normalization()],
1736
+						]
1737
+					),
1738
+					'TXN_ID'          => new EE_Text_Input(
1739
+						[
1740
+							'default'               => 0,
1741
+							'required'              => true,
1742
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1743
+							'validation_strategies' => [new EE_Int_Normalization()],
1744
+						]
1745
+					),
1746
+					'type'            => new EE_Text_Input(
1747
+						[
1748
+							'default'               => 1,
1749
+							'required'              => true,
1750
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1751
+							'validation_strategies' => [new EE_Int_Normalization()],
1752
+						]
1753
+					),
1754
+					'amount'          => new EE_Text_Input(
1755
+						[
1756
+							'default'               => 0,
1757
+							'required'              => true,
1758
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1759
+							'validation_strategies' => [new EE_Float_Normalization()],
1760
+						]
1761
+					),
1762
+					'status'          => new EE_Text_Input(
1763
+						[
1764
+							'default'         => EEM_Payment::status_id_approved,
1765
+							'required'        => true,
1766
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1767
+						]
1768
+					),
1769
+					'PMD_ID'          => new EE_Text_Input(
1770
+						[
1771
+							'default'               => 2,
1772
+							'required'              => true,
1773
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1774
+							'validation_strategies' => [new EE_Int_Normalization()],
1775
+						]
1776
+					),
1777
+					'date'            => new EE_Text_Input(
1778
+						[
1779
+							'default'         => time(),
1780
+							'required'        => true,
1781
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1782
+						]
1783
+					),
1784
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1785
+						[
1786
+							'default'               => '',
1787
+							'required'              => false,
1788
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1789
+							'validation_strategies' => [
1790
+								new EE_Max_Length_Validation_Strategy(
1791
+									esc_html__('Input too long', 'event_espresso'),
1792
+									100
1793
+								),
1794
+							],
1795
+						]
1796
+					),
1797
+					'po_number'       => new EE_Text_Input(
1798
+						[
1799
+							'default'               => '',
1800
+							'required'              => false,
1801
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1802
+							'validation_strategies' => [
1803
+								new EE_Max_Length_Validation_Strategy(
1804
+									esc_html__('Input too long', 'event_espresso'),
1805
+									100
1806
+								),
1807
+							],
1808
+						]
1809
+					),
1810
+					'accounting'      => new EE_Text_Input(
1811
+						[
1812
+							'default'               => '',
1813
+							'required'              => false,
1814
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1815
+							'validation_strategies' => [
1816
+								new EE_Max_Length_Validation_Strategy(
1817
+									esc_html__('Input too long', 'event_espresso'),
1818
+									100
1819
+								),
1820
+							],
1821
+						]
1822
+					),
1823
+				],
1824
+			]
1825
+		);
1826
+	}
1827
+
1828
+
1829
+	/**
1830
+	 * _create_payment_from_request_data
1831
+	 *
1832
+	 * @param array $valid_data
1833
+	 * @return EE_Payment
1834
+	 * @throws EE_Error
1835
+	 * @throws InvalidArgumentException
1836
+	 * @throws InvalidDataTypeException
1837
+	 * @throws InvalidInterfaceException
1838
+	 * @throws ReflectionException
1839
+	 */
1840
+	protected function _create_payment_from_request_data($valid_data)
1841
+	{
1842
+		$PAY_ID = $valid_data['PAY_ID'];
1843
+		// get payment amount
1844
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1845
+		// payments have a type value of 1 and refunds have a type value of -1
1846
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1847
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1848
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1849
+		$date    = $valid_data['date']
1850
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1851
+			: date('Y-m-d g:i a', current_time('timestamp'));
1852
+		$payment = EE_Payment::new_instance(
1853
+			[
1854
+				'TXN_ID'              => $valid_data['TXN_ID'],
1855
+				'STS_ID'              => $valid_data['status'],
1856
+				'PAY_timestamp'       => $date,
1857
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1858
+				'PMD_ID'              => $valid_data['PMD_ID'],
1859
+				'PAY_amount'          => $amount,
1860
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1861
+				'PAY_po_number'       => $valid_data['po_number'],
1862
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1863
+				'PAY_details'         => $valid_data,
1864
+				'PAY_ID'              => $PAY_ID,
1865
+			],
1866
+			'',
1867
+			['Y-m-d', 'g:i a']
1868
+		);
1869
+
1870
+		if (! $payment->save()) {
1871
+			EE_Error::add_error(
1872
+				sprintf(
1873
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1874
+					$payment->ID()
1875
+				),
1876
+				__FILE__,
1877
+				__FUNCTION__,
1878
+				__LINE__
1879
+			);
1880
+		}
1881
+
1882
+		return $payment;
1883
+	}
1884
+
1885
+
1886
+	/**
1887
+	 * _process_transaction_payments
1888
+	 *
1889
+	 * @param EE_Transaction $transaction
1890
+	 * @return void
1891
+	 * @throws EE_Error
1892
+	 * @throws InvalidArgumentException
1893
+	 * @throws ReflectionException
1894
+	 * @throws InvalidDataTypeException
1895
+	 * @throws InvalidInterfaceException
1896
+	 */
1897
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1898
+	{
1899
+		/** @type EE_Transaction_Payments $transaction_payments */
1900
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1901
+		// update the transaction with this payment
1902
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1903
+			EE_Error::add_success(
1904
+				esc_html__(
1905
+					'The payment has been processed successfully.',
1906
+					'event_espresso'
1907
+				),
1908
+				__FILE__,
1909
+				__FUNCTION__,
1910
+				__LINE__
1911
+			);
1912
+		} else {
1913
+			EE_Error::add_error(
1914
+				esc_html__(
1915
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1916
+					'event_espresso'
1917
+				),
1918
+				__FILE__,
1919
+				__FUNCTION__,
1920
+				__LINE__
1921
+			);
1922
+		}
1923
+	}
1924
+
1925
+
1926
+	/**
1927
+	 * _get_REG_IDs_to_apply_payment_to
1928
+	 * returns a list of registration IDs that the payment will apply to
1929
+	 *
1930
+	 * @param EE_Payment $payment
1931
+	 * @return array
1932
+	 * @throws EE_Error
1933
+	 * @throws InvalidArgumentException
1934
+	 * @throws InvalidDataTypeException
1935
+	 * @throws InvalidInterfaceException
1936
+	 * @throws ReflectionException
1937
+	 */
1938
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1939
+	{
1940
+		// grab array of IDs for specific registrations to apply changes to
1941
+		$apply_to_all = $this->request->getRequestParam(
1942
+			'txn_admin_payment[apply_to_all_registrations]',
1943
+			false,
1944
+			DataType::BOOL
1945
+		);
1946
+		$REG_IDs      = ! $apply_to_all
1947
+			? $this->request->getRequestParam(
1948
+				'txn_admin_payment[registrations]',
1949
+				[],
1950
+				DataType::INT,
1951
+				true
1952
+			)
1953
+			: [];
1954
+		// nothing specified ? then get all reg IDs
1955
+		if ($apply_to_all || empty($REG_IDs)) {
1956
+			$registrations = $payment->transaction()->registrations();
1957
+			$REG_IDs       = ! empty($registrations)
1958
+				? array_keys($registrations)
1959
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1960
+		}
1961
+		// ensure that REG_IDs are integers and NOT strings
1962
+		return array_map('absint', $REG_IDs);
1963
+	}
1964
+
1965
+
1966
+	/**
1967
+	 * @return array
1968
+	 */
1969
+	public function existing_reg_payment_REG_IDs()
1970
+	{
1971
+		return $this->_existing_reg_payment_REG_IDs;
1972
+	}
1973
+
1974
+
1975
+	/**
1976
+	 * @param array $existing_reg_payment_REG_IDs
1977
+	 */
1978
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1979
+	{
1980
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1981
+	}
1982
+
1983
+
1984
+	/**
1985
+	 * _get_existing_reg_payment_REG_IDs
1986
+	 * returns a list of registration IDs that the payment is currently related to
1987
+	 * as recorded in the database
1988
+	 *
1989
+	 * @param EE_Payment $payment
1990
+	 * @return array
1991
+	 * @throws EE_Error
1992
+	 * @throws InvalidArgumentException
1993
+	 * @throws InvalidDataTypeException
1994
+	 * @throws InvalidInterfaceException
1995
+	 * @throws ReflectionException
1996
+	 */
1997
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1998
+	{
1999
+		if ($this->existing_reg_payment_REG_IDs() === null) {
2000
+			// let's get any existing reg payment records for this payment
2001
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2002
+			// but we only want the REG IDs, so grab the array keys
2003
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2004
+				? array_keys($existing_reg_payment_REG_IDs)
2005
+				: [];
2006
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2007
+		}
2008
+
2009
+		return $this->existing_reg_payment_REG_IDs();
2010
+	}
2011
+
2012
+
2013
+	/**
2014
+	 * _remove_existing_registration_payments
2015
+	 * this calculates the difference between existing relations
2016
+	 * to the supplied payment and the new list registration IDs,
2017
+	 * removes any related registrations that no longer apply,
2018
+	 * and then updates the registration paid fields
2019
+	 *
2020
+	 * @param EE_Payment $payment
2021
+	 * @param int        $PAY_ID
2022
+	 * @return bool;
2023
+	 * @throws EE_Error
2024
+	 * @throws InvalidArgumentException
2025
+	 * @throws ReflectionException
2026
+	 * @throws InvalidDataTypeException
2027
+	 * @throws InvalidInterfaceException
2028
+	 */
2029
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2030
+	{
2031
+		// newly created payments will have nothing recorded for $PAY_ID
2032
+		if (absint($PAY_ID) === 0) {
2033
+			return false;
2034
+		}
2035
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2036
+		if (empty($existing_reg_payment_REG_IDs)) {
2037
+			return false;
2038
+		}
2039
+		/** @type EE_Transaction_Payments $transaction_payments */
2040
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2041
+
2042
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2043
+			$payment,
2044
+			[
2045
+				[
2046
+					'PAY_ID' => $payment->ID(),
2047
+					'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2048
+				],
2049
+			]
2050
+		);
2051
+	}
2052
+
2053
+
2054
+	/**
2055
+	 * _update_registration_payments
2056
+	 * this applies the payments to the selected registrations
2057
+	 * but only if they have not already been paid for
2058
+	 *
2059
+	 * @param EE_Transaction $transaction
2060
+	 * @param EE_Payment     $payment
2061
+	 * @param array          $REG_IDs
2062
+	 * @return void
2063
+	 * @throws EE_Error
2064
+	 * @throws InvalidArgumentException
2065
+	 * @throws ReflectionException
2066
+	 * @throws RuntimeException
2067
+	 * @throws InvalidDataTypeException
2068
+	 * @throws InvalidInterfaceException
2069
+	 */
2070
+	protected function _update_registration_payments(
2071
+		EE_Transaction $transaction,
2072
+		EE_Payment $payment,
2073
+		$REG_IDs = []
2074
+	) {
2075
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2076
+		// so let's do that using our set of REG_IDs from the form
2077
+		$registration_query_where_params = [
2078
+			'REG_ID' => ['IN', $REG_IDs],
2079
+		];
2080
+		// but add in some conditions regarding payment,
2081
+		// so that we don't apply payments to registrations that are free or have already been paid for
2082
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2083
+		if (! $payment->is_a_refund()) {
2084
+			$registration_query_where_params['REG_final_price']  = ['!=', 0];
2085
+			$registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2086
+		}
2087
+		$registrations = $transaction->registrations([$registration_query_where_params]);
2088
+		if (! empty($registrations)) {
2089
+			/** @type EE_Payment_Processor $payment_processor */
2090
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2091
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2092
+		}
2093
+	}
2094
+
2095
+
2096
+	/**
2097
+	 * _process_registration_status_change
2098
+	 * This processes requested registration status changes for all the registrations
2099
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2100
+	 *
2101
+	 * @param EE_Transaction $transaction
2102
+	 * @param array          $REG_IDs
2103
+	 * @return bool
2104
+	 * @throws EE_Error
2105
+	 * @throws InvalidArgumentException
2106
+	 * @throws ReflectionException
2107
+	 * @throws InvalidDataTypeException
2108
+	 * @throws InvalidInterfaceException
2109
+	 */
2110
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2111
+	{
2112
+		// first if there is no change in status then we get out.
2113
+		$reg_status = $reg_status ?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2114
+		if ($reg_status === 'NAN') {
2115
+			// no error message, no change requested, just nothing to do man.
2116
+			return false;
2117
+		}
2118
+		/** @type EE_Transaction_Processor $transaction_processor */
2119
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2120
+
2121
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2122
+		return $transaction_processor->manually_update_registration_statuses(
2123
+			$transaction,
2124
+			$reg_status,
2125
+			[['REG_ID' => ['IN', $REG_IDs]]]
2126
+		);
2127
+	}
2128
+
2129
+
2130
+	/**
2131
+	 * _build_payment_json_response
2132
+	 *
2133
+	 * @access public
2134
+	 * @param EE_Payment  $payment
2135
+	 * @param array       $REG_IDs
2136
+	 * @param bool | null $delete_txn_reg_status_change
2137
+	 * @return array
2138
+	 * @throws EE_Error
2139
+	 * @throws InvalidArgumentException
2140
+	 * @throws InvalidDataTypeException
2141
+	 * @throws InvalidInterfaceException
2142
+	 * @throws ReflectionException
2143
+	 */
2144
+	protected function _build_payment_json_response(
2145
+		EE_Payment $payment,
2146
+		$REG_IDs = [],
2147
+		$delete_txn_reg_status_change = null
2148
+	) {
2149
+		// was the payment deleted ?
2150
+		if (is_bool($delete_txn_reg_status_change)) {
2151
+			return [
2152
+				'PAY_ID'                       => $payment->ID(),
2153
+				'amount'                       => $payment->amount(),
2154
+				'total_paid'                   => $payment->transaction()->paid(),
2155
+				'txn_status'                   => $payment->transaction()->status_ID(),
2156
+				'pay_status'                   => $payment->STS_ID(),
2157
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2158
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2159
+			];
2160
+		}
2161
+
2162
+		$this->_get_payment_status_array();
2163
+		return [
2164
+			'amount'           => $payment->amount(),
2165
+			'total_paid'       => $payment->transaction()->paid(),
2166
+			'txn_status'       => $payment->transaction()->status_ID(),
2167
+			'pay_status'       => $payment->STS_ID(),
2168
+			'PAY_ID'           => $payment->ID(),
2169
+			'STS_ID'           => $payment->STS_ID(),
2170
+			'status'           => self::$_pay_status[ $payment->STS_ID() ],
2171
+			'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2172
+			'method'           => strtoupper($payment->source()),
2173
+			'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2174
+			'gateway'          => $payment->payment_method()
2175
+				? $payment->payment_method()->admin_name()
2176
+				: esc_html__('Unknown', 'event_espresso'),
2177
+			'gateway_response' => $payment->gateway_response(),
2178
+			'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2179
+			'po_number'        => $payment->po_number(),
2180
+			'extra_accntng'    => $payment->extra_accntng(),
2181
+			'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2182
+		];
2183
+	}
2184
+
2185
+
2186
+	/**
2187
+	 * delete_payment
2188
+	 *    delete a payment or refund made towards a transaction
2189
+	 *
2190
+	 * @access public
2191
+	 * @return void
2192
+	 * @throws EE_Error
2193
+	 * @throws InvalidArgumentException
2194
+	 * @throws ReflectionException
2195
+	 * @throws InvalidDataTypeException
2196
+	 * @throws InvalidInterfaceException
2197
+	 */
2198
+	public function delete_payment()
2199
+	{
2200
+		$TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2201
+		// $json_response_data = ['return_data' => false];
2202
+		$PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2203
+		$amount     = 0;
2204
+		$can_delete = EE_Registry::instance()->CAP->current_user_can(
2205
+			'ee_delete_payments',
2206
+			'delete_payment_from_registration_details'
2207
+		);
2208
+		if ($PAY_ID && $can_delete) {
2209
+			$delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2210
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2211
+			if ($payment instanceof EE_Payment) {
2212
+				$amount  = $payment->amount();
2213
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2214
+				/** @type EE_Transaction_Payments $transaction_payments */
2215
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2216
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2217
+					if ($delete_txn_reg_status_change) {
2218
+						$this->_maybe_send_notifications();
2219
+						$this->_process_registration_status_change(
2220
+							$payment->transaction(),
2221
+							$REG_IDs,
2222
+							$delete_txn_reg_status_change
2223
+						);
2224
+					}
2225
+				}
2226
+			} else {
2227
+				EE_Error::add_error(
2228
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2229
+					__FILE__,
2230
+					__FUNCTION__,
2231
+					__LINE__
2232
+				);
2233
+			}
2234
+		} elseif ($can_delete) {
2235
+			EE_Error::add_error(
2236
+				esc_html__(
2237
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2238
+					'event_espresso'
2239
+				),
2240
+				__FILE__,
2241
+				__FUNCTION__,
2242
+				__LINE__
2243
+			);
2244
+		} else {
2245
+			EE_Error::add_error(
2246
+				esc_html__(
2247
+					'You do not have access to delete a payment.',
2248
+					'event_espresso'
2249
+				),
2250
+				__FILE__,
2251
+				__FUNCTION__,
2252
+				__LINE__
2253
+			);
2254
+		}
2255
+		$query_args = [
2256
+			'page'   => 'espresso_transactions',
2257
+			'action' => 'view_transaction',
2258
+			'TXN_ID' => $TXD_ID,
2259
+		];
2260
+		$this->_redirect_after_action(
2261
+			! EE_Error::has_error(),
2262
+			$amount > 0
2263
+				? esc_html__('payment', 'event_espresso')
2264
+				: esc_html__('refund', 'event_espresso'),
2265
+			esc_html__('deleted', 'event_espresso'),
2266
+			$query_args
2267
+		);
2268
+	}
2269
+
2270
+
2271
+	/**
2272
+	 * _registration_payment_data_array
2273
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2274
+	 *
2275
+	 * @access protected
2276
+	 * @param array $REG_IDs
2277
+	 * @return array
2278
+	 * @throws EE_Error
2279
+	 * @throws InvalidArgumentException
2280
+	 * @throws InvalidDataTypeException
2281
+	 * @throws InvalidInterfaceException
2282
+	 * @throws ReflectionException
2283
+	 */
2284
+	protected function _registration_payment_data_array($REG_IDs)
2285
+	{
2286
+		$registration_payment_data = [];
2287
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2288
+		if (! empty($REG_IDs)) {
2289
+			$registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2290
+			foreach ($registrations as $registration) {
2291
+				if ($registration instanceof EE_Registration) {
2292
+					$registration_payment_data[ $registration->ID() ] = [
2293
+						'paid'  => $registration->pretty_paid(),
2294
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2295
+					];
2296
+				}
2297
+			}
2298
+		}
2299
+
2300
+		return $registration_payment_data;
2301
+	}
2302
+
2303
+
2304
+	/**
2305
+	 * _maybe_send_notifications
2306
+	 * determines whether or not the admin has indicated that notifications should be sent.
2307
+	 * If so, will toggle a filter switch for delivering registration notices.
2308
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2309
+	 *
2310
+	 * @access protected
2311
+	 * @param EE_Payment | null $payment
2312
+	 */
2313
+	protected function _maybe_send_notifications($payment = null)
2314
+	{
2315
+		switch ($payment instanceof EE_Payment) {
2316
+			// payment notifications
2317
+			case true:
2318
+				if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2319
+					$this->_process_payment_notification($payment);
2320
+				}
2321
+				break;
2322
+			// registration notifications
2323
+			case false:
2324
+				if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2325
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2326
+				}
2327
+				break;
2328
+		}
2329
+	}
2330
+
2331
+
2332
+	/**
2333
+	 * _send_payment_reminder
2334
+	 *    generates HTML for the View Transaction Details Admin page
2335
+	 *
2336
+	 * @access protected
2337
+	 * @return void
2338
+	 * @throws EE_Error
2339
+	 * @throws InvalidArgumentException
2340
+	 * @throws InvalidDataTypeException
2341
+	 * @throws InvalidInterfaceException
2342
+	 */
2343
+	protected function _send_payment_reminder()
2344
+	{
2345
+		$TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2346
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2347
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2348
+		$query_args  = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2349
+		do_action(
2350
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2351
+			$transaction
2352
+		);
2353
+		$this->_redirect_after_action(
2354
+			false,
2355
+			esc_html__('payment reminder', 'event_espresso'),
2356
+			esc_html__('sent', 'event_espresso'),
2357
+			$query_args,
2358
+			true
2359
+		);
2360
+	}
2361
+
2362
+
2363
+	/**
2364
+	 *  get_transactions
2365
+	 *    get transactions for given parameters (used by list table)
2366
+	 *
2367
+	 * @param int     $per_page how many transactions displayed per page
2368
+	 * @param boolean $count    return the count or objects
2369
+	 * @param string  $view
2370
+	 * @return EE_Transaction[]|int int = count || array of transaction objects
2371
+	 * @throws EE_Error
2372
+	 * @throws InvalidArgumentException
2373
+	 * @throws InvalidDataTypeException
2374
+	 * @throws InvalidInterfaceException
2375
+	 * @throws ReflectionException
2376
+	 */
2377
+	public function get_transactions($per_page, $count = false, $view = '')
2378
+	{
2379
+		$start_date = wp_strip_all_tags(
2380
+			$this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2381
+		);
2382
+		$end_date   = wp_strip_all_tags(
2383
+			$this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2384
+		);
2385
+
2386
+		// make sure our timestamps start and end right at the boundaries for each day
2387
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2388
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2389
+
2390
+
2391
+		// convert to timestamps
2392
+		$start_date = strtotime($start_date);
2393
+		$end_date   = strtotime($end_date);
2394
+
2395
+		// makes sure start date is the lowest value and vice versa
2396
+		$start_date = min($start_date, $end_date);
2397
+		$end_date   = max($start_date, $end_date);
2398
+
2399
+		// convert to correct format for query
2400
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2401
+			'TXN_timestamp',
2402
+			date('Y-m-d H:i:s', $start_date),
2403
+			'Y-m-d H:i:s'
2404
+		);
2405
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2406
+			'TXN_timestamp',
2407
+			date('Y-m-d H:i:s', $end_date),
2408
+			'Y-m-d H:i:s'
2409
+		);
2410
+
2411
+
2412
+		// set orderby
2413
+		$orderby = $this->request->getRequestParam('orderby');
2414
+
2415
+		switch ($orderby) {
2416
+			case 'TXN_ID':
2417
+				break;
2418
+			case 'ATT_fname':
2419
+				$orderby = 'Registration.Attendee.ATT_fname';
2420
+				break;
2421
+			case 'event_name':
2422
+				$orderby = 'Registration.Event.EVT_name';
2423
+				break;
2424
+			default: // 'TXN_timestamp'
2425
+				$orderby = 'TXN_timestamp';
2426
+		}
2427
+
2428
+		$sort         = $this->request->getRequestParam('order', 'DESC');
2429
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
2430
+
2431
+		$per_page = absint($per_page) ? $per_page : 10;
2432
+		$per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2433
+
2434
+		$offset = ($current_page - 1) * $per_page;
2435
+		$limit  = [$offset, $per_page];
2436
+
2437
+		$_where = [
2438
+			'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2439
+			'Registration.REG_count' => 1,
2440
+		];
2441
+
2442
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2443
+		if ($EVT_ID) {
2444
+			$_where['Registration.EVT_ID'] = $EVT_ID;
2445
+		}
2446
+
2447
+		$search_term = $this->request->getRequestParam('s');
2448
+		if ($search_term) {
2449
+			$search_term  = '%' . $search_term . '%';
2450
+			$_where['OR'] = [
2451
+				'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2452
+				'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2453
+				'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2454
+				'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2455
+				'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2456
+				'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2457
+				'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2458
+				'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2459
+				'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2460
+				'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2461
+				'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2462
+				'Registration.REG_final_price'        => ['LIKE', $search_term],
2463
+				'Registration.REG_code'               => ['LIKE', $search_term],
2464
+				'Registration.REG_count'              => ['LIKE', $search_term],
2465
+				'Registration.REG_group_size'         => ['LIKE', $search_term],
2466
+				'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2467
+				'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2468
+				'Payment.PAY_source'                  => ['LIKE', $search_term],
2469
+				'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2470
+				'TXN_session_data'                    => ['LIKE', $search_term],
2471
+				'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2472
+			];
2473
+		}
2474
+
2475
+		$status = $this->request->getRequestParam('status');
2476
+		// failed transactions
2477
+		$failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2478
+		$abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2479
+		$incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2480
+
2481
+		if ($failed) {
2482
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2483
+		} elseif ($abandoned) {
2484
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2485
+		} elseif ($incomplete) {
2486
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2487
+		} else {
2488
+			$_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2489
+			$_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2490
+		}
2491
+
2492
+		$query_params = apply_filters(
2493
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2494
+			[
2495
+				$_where,
2496
+				'order_by'                 => [$orderby => $sort],
2497
+				'limit'                    => $limit,
2498
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2499
+			],
2500
+			$this->request->requestParams(),
2501
+			$view,
2502
+			$count
2503
+		);
2504
+
2505
+		return $count
2506
+			? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2507
+			: EEM_Transaction::instance()->get_all($query_params);
2508
+	}
2509
+
2510
+
2511
+	/**
2512
+	 * @throws EE_Error
2513
+	 * @throws InvalidArgumentException
2514
+	 * @throws InvalidDataTypeException
2515
+	 * @throws InvalidInterfaceException
2516
+	 * @throws ReflectionException
2517
+	 * @throws RuntimeException
2518
+	 * @since 4.9.79.p
2519
+	 */
2520
+	public function recalculateLineItems()
2521
+	{
2522
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2523
+		/** @var EE_Transaction $transaction */
2524
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2525
+		$success     = $transaction->recalculateLineItems();
2526
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2527
+		$query_args  = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2528
+		$this->_redirect_after_action(
2529
+			$success,
2530
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2531
+			esc_html__('recalculated', 'event_espresso'),
2532
+			$query_args,
2533
+			true
2534
+		);
2535
+	}
2536 2536
 }
Please login to merge, or discard this patch.
admin_pages/about/About_Admin_Page.core.php 2 patches
Indentation   +286 added lines, -286 removed lines patch added patch discarded remove patch
@@ -15,140 +15,140 @@  discard block
 block discarded – undo
15 15
  */
16 16
 class About_Admin_Page extends EE_Admin_Page
17 17
 {
18
-    protected function _init_page_props()
19
-    {
20
-        $this->page_slug = EE_ABOUT_PG_SLUG;
21
-        $this->page_label = esc_html__('About Event Espresso', 'event_espresso');
22
-        $this->_admin_base_url = EE_ABOUT_ADMIN_URL;
23
-        $this->_admin_base_path = EE_ABOUT_ADMIN;
24
-    }
25
-
26
-
27
-    protected function _ajax_hooks()
28
-    {
29
-        // todo: all hooks for ajax goes here.
30
-    }
31
-
32
-
33
-    protected function _define_page_props()
34
-    {
35
-        $this->_labels = array();
36
-        $this->_admin_page_title = $this->page_label;
37
-    }
38
-
39
-
40
-    protected function _set_page_routes()
41
-    {
42
-        $this->_page_routes = array(
43
-            'default' => array(
44
-                'func'       => '_overview',
45
-                'capability' => 'manage_options',
46
-            ),
47
-            // 'overview' => '_overview',
48
-            // 'func' => '_overview',
49
-            // 'capability' => 'ee_read_ee'
50
-            // ),
51
-            'credits' => array(
52
-                'func'       => '_credits',
53
-                'capability' => 'manage_options',
54
-            ),
55
-
56
-            'decafvpro' => array(
57
-                'func'       => '_decafvpro',
58
-                'capability' => 'manage_options',
59
-            ),
60
-            'reviews'   => array(
61
-                'func'       => '_reviews',
62
-                'capability' => 'manage_options',
63
-            ),
64
-        );
65
-    }
66
-
67
-
68
-    protected function _set_page_config()
69
-    {
70
-        $this->_page_config = array(
71
-            /*'default' => array(
18
+	protected function _init_page_props()
19
+	{
20
+		$this->page_slug = EE_ABOUT_PG_SLUG;
21
+		$this->page_label = esc_html__('About Event Espresso', 'event_espresso');
22
+		$this->_admin_base_url = EE_ABOUT_ADMIN_URL;
23
+		$this->_admin_base_path = EE_ABOUT_ADMIN;
24
+	}
25
+
26
+
27
+	protected function _ajax_hooks()
28
+	{
29
+		// todo: all hooks for ajax goes here.
30
+	}
31
+
32
+
33
+	protected function _define_page_props()
34
+	{
35
+		$this->_labels = array();
36
+		$this->_admin_page_title = $this->page_label;
37
+	}
38
+
39
+
40
+	protected function _set_page_routes()
41
+	{
42
+		$this->_page_routes = array(
43
+			'default' => array(
44
+				'func'       => '_overview',
45
+				'capability' => 'manage_options',
46
+			),
47
+			// 'overview' => '_overview',
48
+			// 'func' => '_overview',
49
+			// 'capability' => 'ee_read_ee'
50
+			// ),
51
+			'credits' => array(
52
+				'func'       => '_credits',
53
+				'capability' => 'manage_options',
54
+			),
55
+
56
+			'decafvpro' => array(
57
+				'func'       => '_decafvpro',
58
+				'capability' => 'manage_options',
59
+			),
60
+			'reviews'   => array(
61
+				'func'       => '_reviews',
62
+				'capability' => 'manage_options',
63
+			),
64
+		);
65
+	}
66
+
67
+
68
+	protected function _set_page_config()
69
+	{
70
+		$this->_page_config = array(
71
+			/*'default' => array(
72 72
                 'nav' => array(
73 73
                     'label' => esc_html__('What\'s New', 'event_espresso'),
74 74
                     'order' => 10),
75 75
                 'require_nonce' => FALSE
76 76
                 ),*/
77
-            // 'overview' => array(
78
-            'default' => array(
79
-                'nav'           => array(
80
-                    'label' => esc_html__('About', 'event_espresso'),
81
-                    'icon' => 'dashicons-welcome-learn-more',
82
-                    'order' => 20,
83
-                ),
84
-                'require_nonce' => false,
85
-            ),
86
-            'credits' => array(
87
-                'nav'           => array(
88
-                    'label' => esc_html__('Credits', 'event_espresso'),
89
-                    'icon' => 'dashicons-thumbs-up',
90
-                    'order' => 30,
91
-                ),
92
-                'require_nonce' => false,
93
-            ),
94
-
95
-            'decafvpro' => array(
96
-                'nav'           => array(
97
-                    'label' => esc_html__('Decaf vs Regular', 'event_espresso'),
98
-                    'icon' => 'dashicons-editor-code',
99
-                    'order' => 40,
100
-                ),
101
-                'require_nonce' => false,
102
-            ),
103
-            'reviews'   => array(
104
-                'nav'           => array(
105
-                    'label' => esc_html__('Reviews', 'event_espresso'),
106
-                    'icon' => 'dashicons-star-filled',
107
-                    'order' => 50,
108
-                ),
109
-                'require_nonce' => false,
110
-            ),
111
-        );
112
-    }
113
-
114
-
115
-    // none of the below group are currently used for Support pages
116
-    protected function _add_screen_options()
117
-    {
118
-    }
119
-
120
-    protected function _add_feature_pointers()
121
-    {
122
-    }
123
-
124
-    public function admin_init()
125
-    {
126
-    }
127
-
128
-    public function admin_notices()
129
-    {
130
-    }
131
-
132
-    public function admin_footer_scripts()
133
-    {
134
-    }
135
-
136
-    public function load_scripts_styles()
137
-    {
138
-        // enqueue style
139
-        wp_register_style(
140
-            'espresso_about_admin',
141
-            EE_ABOUT_ASSETS_URL . 'espresso_about_admin.css',
142
-            [],
143
-            EVENT_ESPRESSO_VERSION
144
-        );
145
-        wp_enqueue_style('espresso_about_admin');
146
-    }
147
-
148
-
149
-    protected function _whats_new()
150
-    {
151
-        /*$steps = EE_Maintenance_Mode::instance()->level() != EE_Maintenance_Mode::level_2_complete_maintenance ? $this->_get_started_steps() : FALSE;
77
+			// 'overview' => array(
78
+			'default' => array(
79
+				'nav'           => array(
80
+					'label' => esc_html__('About', 'event_espresso'),
81
+					'icon' => 'dashicons-welcome-learn-more',
82
+					'order' => 20,
83
+				),
84
+				'require_nonce' => false,
85
+			),
86
+			'credits' => array(
87
+				'nav'           => array(
88
+					'label' => esc_html__('Credits', 'event_espresso'),
89
+					'icon' => 'dashicons-thumbs-up',
90
+					'order' => 30,
91
+				),
92
+				'require_nonce' => false,
93
+			),
94
+
95
+			'decafvpro' => array(
96
+				'nav'           => array(
97
+					'label' => esc_html__('Decaf vs Regular', 'event_espresso'),
98
+					'icon' => 'dashicons-editor-code',
99
+					'order' => 40,
100
+				),
101
+				'require_nonce' => false,
102
+			),
103
+			'reviews'   => array(
104
+				'nav'           => array(
105
+					'label' => esc_html__('Reviews', 'event_espresso'),
106
+					'icon' => 'dashicons-star-filled',
107
+					'order' => 50,
108
+				),
109
+				'require_nonce' => false,
110
+			),
111
+		);
112
+	}
113
+
114
+
115
+	// none of the below group are currently used for Support pages
116
+	protected function _add_screen_options()
117
+	{
118
+	}
119
+
120
+	protected function _add_feature_pointers()
121
+	{
122
+	}
123
+
124
+	public function admin_init()
125
+	{
126
+	}
127
+
128
+	public function admin_notices()
129
+	{
130
+	}
131
+
132
+	public function admin_footer_scripts()
133
+	{
134
+	}
135
+
136
+	public function load_scripts_styles()
137
+	{
138
+		// enqueue style
139
+		wp_register_style(
140
+			'espresso_about_admin',
141
+			EE_ABOUT_ASSETS_URL . 'espresso_about_admin.css',
142
+			[],
143
+			EVENT_ESPRESSO_VERSION
144
+		);
145
+		wp_enqueue_style('espresso_about_admin');
146
+	}
147
+
148
+
149
+	protected function _whats_new()
150
+	{
151
+		/*$steps = EE_Maintenance_Mode::instance()->level() != EE_Maintenance_Mode::level_2_complete_maintenance ? $this->_get_started_steps() : FALSE;
152 152
         $steps = $steps !== FALSE ? $steps : '';
153 153
         $this->_admin_page_title = sprintf( esc_html__('Welcome to Event Espresso %s', 'event_espresso'), EVENT_ESPRESSO_VERSION );
154 154
         $settings_message = $steps;
@@ -156,168 +156,168 @@  discard block
 block discarded – undo
156 156
         $template = EE_ABOUT_TEMPLATE_PATH . 'whats_new.template.php';
157 157
         $this->_template_args['about_admin_page_content'] = EEH_Template::display_template( $template, $this->_template_args, TRUE );
158 158
         $this->display_about_admin_page();*/
159
-    }
159
+	}
160 160
 
161 161
 
162
-    protected function _overview()
163
-    {
164
-        /*$this->_template_args['admin_page_title'] = esc_html__('About Event Espresso', 'event_espresso');
162
+	protected function _overview()
163
+	{
164
+		/*$this->_template_args['admin_page_title'] = esc_html__('About Event Espresso', 'event_espresso');
165 165
         $this->_template_args['admin_page_subtitle'] = esc_html__('Thank you for choosing Event Espresso Decaf, the most powerful, and free, Event Management plugin for WordPress.', 'event_espresso');
166 166
         $template = EE_ABOUT_TEMPLATE_PATH . 'ee4-overview.template.php';
167 167
         $this->_template_args['about_admin_page_content'] = EEH_Template::display_template( $template, $this->_template_args, TRUE );
168 168
         $this->display_about_admin_page();*/
169 169
 
170
-        // Copied from _whats_new()
171
-        $steps = EE_Maintenance_Mode::instance()->level() != EE_Maintenance_Mode::level_2_complete_maintenance
172
-            ? $this->_get_started_steps() : false;
173
-        $steps = $steps !== false ? $steps : '';
174
-        $this->_admin_page_title = sprintf(
175
-            esc_html__('Welcome to Event Espresso %s', 'event_espresso'),
176
-            EVENT_ESPRESSO_VERSION
177
-        );
178
-        $settings_message = $steps;
179
-        $this->_template_args['admin_page_subtitle'] = esc_html__(
180
-            'Thank you for choosing Event Espresso, the most powerful, and free, Event Management plugin for WordPress.',
181
-            'event_espresso'
182
-        ) . $settings_message;
183
-        $template = EE_ABOUT_TEMPLATE_PATH . 'ee4-overview.template.php';
184
-        $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
185
-            $template,
186
-            $this->_template_args,
187
-            true
188
-        );
189
-        $this->display_about_admin_page();
190
-    }
191
-
192
-
193
-    protected function _get_started_steps()
194
-    {
195
-        $steps = '<h2>' . esc_html__('Getting Started', 'event_espresso') . '</h2>';
196
-        $step_one = '<p>'
197
-                    . sprintf(
198
-                        esc_html__(
199
-                            '%sStep 1%s: Visit your %sOrganization Settings%s and add/update your details.',
200
-                            'event_espresso'
201
-                        ),
202
-                        '<strong>',
203
-                        '</strong>',
204
-                        '<a href="admin.php?page=espresso_general_settings">',
205
-                        '</a>'
206
-                    ) . '</strong></p>';
207
-        $step_two = '<p>'
208
-                    . sprintf(
209
-                        esc_html__('%sStep 2%s: Setup your %sPayment Methods%s.', 'event_espresso'),
210
-                        '<strong>',
211
-                        '</strong>',
212
-                        '<a href="admin.php?page=espresso_payment_settings">',
213
-                        '</a>'
214
-                    ) . '</strong></p>';
215
-        $step_three = '<p>'
216
-                      . sprintf(
217
-                          esc_html__('%sStep 3%s: Create your %sFirst Event%s.', 'event_espresso'),
218
-                          '<strong>',
219
-                          '</strong>',
220
-                          '<a href="admin.php?page=espresso_events&action=create_new">',
221
-                          '</a>'
222
-                      ) . '</strong></p>';
223
-
224
-        // done?
225
-        $done_step_one = EE_Registry::instance()->CFG->organization->address_1 == '123 Onna Road' ? false : true;
226
-        $active_invoice_pm = EEM_Payment_Method::instance()->get_one_active(
227
-            EEM_Payment_Method::scope_cart,
228
-            array(array('PMD_type' => 'Invoice'))
229
-        );
230
-        $active_pms_count = EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart);
231
-        // done step two if a non-invoice paymetn method is active; or there is more than one PM active, or
232
-        // if only the invoice is active but it's clearly been updated
233
-        $done_step_two = $active_pms_count > 1 ||
234
-                         ($active_pms_count === 1 && ! $active_invoice_pm) ||
235
-                         ($active_invoice_pm instanceof EE_Payment_Method && (
236
-                                 $active_invoice_pm->get_extra_meta('pdf_payee_name', true, '') ||
237
-                                 $active_invoice_pm->get_extra_meta('pdf_payee_email', true, '') ||
238
-                                 $active_invoice_pm->get_extra_meta('pdf_payee_tax_number', true, '') ||
239
-                                 $active_invoice_pm->get_extra_meta('pdf_payee_address', true, '') ||
240
-                                 $active_invoice_pm->get_extra_meta('page_extra_info', true, '')
241
-                             )
242
-                         );
243
-        $done_step_three = EE_Registry::instance()->load_model('Event')->count() > 0 ? true : false;
244
-
245
-        // if ALL steps are done, let's just return FALSE so we don't display anything
246
-        if ($done_step_one && $done_step_two && $done_step_three) {
247
-            return false;
248
-        }
249
-
250
-        // now let's put it together
251
-        $steps .= sprintf('%s' . $step_one . '%s', $done_step_one ? '<strike>' : '', $done_step_one ? '</strike>' : '');
252
-        $steps .= sprintf('%s' . $step_two . '%s', $done_step_two ? '<strike>' : '', $done_step_two ? '</strike>' : '');
253
-        $steps .= sprintf(
254
-            '%s' . $step_three . '%s',
255
-            $done_step_three ? '<strike>' : '',
256
-            $done_step_three ? '</strike>' : ''
257
-        );
258
-
259
-        return $steps;
260
-    }
261
-
262
-
263
-    protected function _credits()
264
-    {
265
-        $this->_template_args['admin_page_title'] = sprintf(
266
-            esc_html__('Welcome to Event Espresso %s', 'event_espresso'),
267
-            EVENT_ESPRESSO_VERSION
268
-        );
269
-        $this->_template_args['admin_page_subtitle'] = esc_html__(
270
-            'Thank you for choosing Event Espresso Decaf, the most powerful, and free, Event Management plugin for WordPress.',
271
-            'event_espresso'
272
-        );
273
-        $template = EE_ABOUT_TEMPLATE_PATH . 'credits.template.php';
274
-        $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
275
-            $template,
276
-            $this->_template_args,
277
-            true
278
-        );
279
-        $this->display_about_admin_page();
280
-    }
281
-
282
-
283
-    protected function _decafvpro()
284
-    {
285
-        $this->_template_args['admin_page_title'] = sprintf(
286
-            esc_html__('Welcome to Event Espresso %s', 'event_espresso'),
287
-            EVENT_ESPRESSO_VERSION
288
-        );
289
-        $this->_template_args['admin_page_subtitle'] = sprintf(
290
-            esc_html__(
291
-                'Event Espresso lets you focus on doing %swhat you love%s — %sorganizing your events%s',
292
-                'event_espresso'
293
-            ),
294
-            '<em>',
295
-            '</em>',
296
-            '<strong>',
297
-            '</strong>'
298
-        );
299
-        $template = EE_ABOUT_TEMPLATE_PATH . 'decafvpro.template.php';
300
-        $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
301
-            $template,
302
-            $this->_template_args,
303
-            true
304
-        );
305
-        $this->display_about_admin_page();
306
-    }
307
-
308
-    protected function _reviews()
309
-    {
310
-        $this->_template_args['admin_page_title'] = esc_html__('Rave Reviews About Event Espresso 4', 'event_espresso');
311
-        $this->_template_args['admin_page_subtitle'] = esc_html__(
312
-            'At Event Espresso, customer satisfaction is our ultimate goal.',
313
-            'event_espresso'
314
-        );
315
-        $template = EE_ABOUT_TEMPLATE_PATH . 'reviews.template.php';
316
-        $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
317
-            $template,
318
-            $this->_template_args,
319
-            true
320
-        );
321
-        $this->display_about_admin_page();
322
-    }
170
+		// Copied from _whats_new()
171
+		$steps = EE_Maintenance_Mode::instance()->level() != EE_Maintenance_Mode::level_2_complete_maintenance
172
+			? $this->_get_started_steps() : false;
173
+		$steps = $steps !== false ? $steps : '';
174
+		$this->_admin_page_title = sprintf(
175
+			esc_html__('Welcome to Event Espresso %s', 'event_espresso'),
176
+			EVENT_ESPRESSO_VERSION
177
+		);
178
+		$settings_message = $steps;
179
+		$this->_template_args['admin_page_subtitle'] = esc_html__(
180
+			'Thank you for choosing Event Espresso, the most powerful, and free, Event Management plugin for WordPress.',
181
+			'event_espresso'
182
+		) . $settings_message;
183
+		$template = EE_ABOUT_TEMPLATE_PATH . 'ee4-overview.template.php';
184
+		$this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
185
+			$template,
186
+			$this->_template_args,
187
+			true
188
+		);
189
+		$this->display_about_admin_page();
190
+	}
191
+
192
+
193
+	protected function _get_started_steps()
194
+	{
195
+		$steps = '<h2>' . esc_html__('Getting Started', 'event_espresso') . '</h2>';
196
+		$step_one = '<p>'
197
+					. sprintf(
198
+						esc_html__(
199
+							'%sStep 1%s: Visit your %sOrganization Settings%s and add/update your details.',
200
+							'event_espresso'
201
+						),
202
+						'<strong>',
203
+						'</strong>',
204
+						'<a href="admin.php?page=espresso_general_settings">',
205
+						'</a>'
206
+					) . '</strong></p>';
207
+		$step_two = '<p>'
208
+					. sprintf(
209
+						esc_html__('%sStep 2%s: Setup your %sPayment Methods%s.', 'event_espresso'),
210
+						'<strong>',
211
+						'</strong>',
212
+						'<a href="admin.php?page=espresso_payment_settings">',
213
+						'</a>'
214
+					) . '</strong></p>';
215
+		$step_three = '<p>'
216
+					  . sprintf(
217
+						  esc_html__('%sStep 3%s: Create your %sFirst Event%s.', 'event_espresso'),
218
+						  '<strong>',
219
+						  '</strong>',
220
+						  '<a href="admin.php?page=espresso_events&action=create_new">',
221
+						  '</a>'
222
+					  ) . '</strong></p>';
223
+
224
+		// done?
225
+		$done_step_one = EE_Registry::instance()->CFG->organization->address_1 == '123 Onna Road' ? false : true;
226
+		$active_invoice_pm = EEM_Payment_Method::instance()->get_one_active(
227
+			EEM_Payment_Method::scope_cart,
228
+			array(array('PMD_type' => 'Invoice'))
229
+		);
230
+		$active_pms_count = EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart);
231
+		// done step two if a non-invoice paymetn method is active; or there is more than one PM active, or
232
+		// if only the invoice is active but it's clearly been updated
233
+		$done_step_two = $active_pms_count > 1 ||
234
+						 ($active_pms_count === 1 && ! $active_invoice_pm) ||
235
+						 ($active_invoice_pm instanceof EE_Payment_Method && (
236
+								 $active_invoice_pm->get_extra_meta('pdf_payee_name', true, '') ||
237
+								 $active_invoice_pm->get_extra_meta('pdf_payee_email', true, '') ||
238
+								 $active_invoice_pm->get_extra_meta('pdf_payee_tax_number', true, '') ||
239
+								 $active_invoice_pm->get_extra_meta('pdf_payee_address', true, '') ||
240
+								 $active_invoice_pm->get_extra_meta('page_extra_info', true, '')
241
+							 )
242
+						 );
243
+		$done_step_three = EE_Registry::instance()->load_model('Event')->count() > 0 ? true : false;
244
+
245
+		// if ALL steps are done, let's just return FALSE so we don't display anything
246
+		if ($done_step_one && $done_step_two && $done_step_three) {
247
+			return false;
248
+		}
249
+
250
+		// now let's put it together
251
+		$steps .= sprintf('%s' . $step_one . '%s', $done_step_one ? '<strike>' : '', $done_step_one ? '</strike>' : '');
252
+		$steps .= sprintf('%s' . $step_two . '%s', $done_step_two ? '<strike>' : '', $done_step_two ? '</strike>' : '');
253
+		$steps .= sprintf(
254
+			'%s' . $step_three . '%s',
255
+			$done_step_three ? '<strike>' : '',
256
+			$done_step_three ? '</strike>' : ''
257
+		);
258
+
259
+		return $steps;
260
+	}
261
+
262
+
263
+	protected function _credits()
264
+	{
265
+		$this->_template_args['admin_page_title'] = sprintf(
266
+			esc_html__('Welcome to Event Espresso %s', 'event_espresso'),
267
+			EVENT_ESPRESSO_VERSION
268
+		);
269
+		$this->_template_args['admin_page_subtitle'] = esc_html__(
270
+			'Thank you for choosing Event Espresso Decaf, the most powerful, and free, Event Management plugin for WordPress.',
271
+			'event_espresso'
272
+		);
273
+		$template = EE_ABOUT_TEMPLATE_PATH . 'credits.template.php';
274
+		$this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
275
+			$template,
276
+			$this->_template_args,
277
+			true
278
+		);
279
+		$this->display_about_admin_page();
280
+	}
281
+
282
+
283
+	protected function _decafvpro()
284
+	{
285
+		$this->_template_args['admin_page_title'] = sprintf(
286
+			esc_html__('Welcome to Event Espresso %s', 'event_espresso'),
287
+			EVENT_ESPRESSO_VERSION
288
+		);
289
+		$this->_template_args['admin_page_subtitle'] = sprintf(
290
+			esc_html__(
291
+				'Event Espresso lets you focus on doing %swhat you love%s — %sorganizing your events%s',
292
+				'event_espresso'
293
+			),
294
+			'<em>',
295
+			'</em>',
296
+			'<strong>',
297
+			'</strong>'
298
+		);
299
+		$template = EE_ABOUT_TEMPLATE_PATH . 'decafvpro.template.php';
300
+		$this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
301
+			$template,
302
+			$this->_template_args,
303
+			true
304
+		);
305
+		$this->display_about_admin_page();
306
+	}
307
+
308
+	protected function _reviews()
309
+	{
310
+		$this->_template_args['admin_page_title'] = esc_html__('Rave Reviews About Event Espresso 4', 'event_espresso');
311
+		$this->_template_args['admin_page_subtitle'] = esc_html__(
312
+			'At Event Espresso, customer satisfaction is our ultimate goal.',
313
+			'event_espresso'
314
+		);
315
+		$template = EE_ABOUT_TEMPLATE_PATH . 'reviews.template.php';
316
+		$this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
317
+			$template,
318
+			$this->_template_args,
319
+			true
320
+		);
321
+		$this->display_about_admin_page();
322
+	}
323 323
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
         // enqueue style
139 139
         wp_register_style(
140 140
             'espresso_about_admin',
141
-            EE_ABOUT_ASSETS_URL . 'espresso_about_admin.css',
141
+            EE_ABOUT_ASSETS_URL.'espresso_about_admin.css',
142 142
             [],
143 143
             EVENT_ESPRESSO_VERSION
144 144
         );
@@ -179,8 +179,8 @@  discard block
 block discarded – undo
179 179
         $this->_template_args['admin_page_subtitle'] = esc_html__(
180 180
             'Thank you for choosing Event Espresso, the most powerful, and free, Event Management plugin for WordPress.',
181 181
             'event_espresso'
182
-        ) . $settings_message;
183
-        $template = EE_ABOUT_TEMPLATE_PATH . 'ee4-overview.template.php';
182
+        ).$settings_message;
183
+        $template = EE_ABOUT_TEMPLATE_PATH.'ee4-overview.template.php';
184 184
         $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
185 185
             $template,
186 186
             $this->_template_args,
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
 
193 193
     protected function _get_started_steps()
194 194
     {
195
-        $steps = '<h2>' . esc_html__('Getting Started', 'event_espresso') . '</h2>';
195
+        $steps = '<h2>'.esc_html__('Getting Started', 'event_espresso').'</h2>';
196 196
         $step_one = '<p>'
197 197
                     . sprintf(
198 198
                         esc_html__(
@@ -203,7 +203,7 @@  discard block
 block discarded – undo
203 203
                         '</strong>',
204 204
                         '<a href="admin.php?page=espresso_general_settings">',
205 205
                         '</a>'
206
-                    ) . '</strong></p>';
206
+                    ).'</strong></p>';
207 207
         $step_two = '<p>'
208 208
                     . sprintf(
209 209
                         esc_html__('%sStep 2%s: Setup your %sPayment Methods%s.', 'event_espresso'),
@@ -211,7 +211,7 @@  discard block
 block discarded – undo
211 211
                         '</strong>',
212 212
                         '<a href="admin.php?page=espresso_payment_settings">',
213 213
                         '</a>'
214
-                    ) . '</strong></p>';
214
+                    ).'</strong></p>';
215 215
         $step_three = '<p>'
216 216
                       . sprintf(
217 217
                           esc_html__('%sStep 3%s: Create your %sFirst Event%s.', 'event_espresso'),
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
                           '</strong>',
220 220
                           '<a href="admin.php?page=espresso_events&action=create_new">',
221 221
                           '</a>'
222
-                      ) . '</strong></p>';
222
+                      ).'</strong></p>';
223 223
 
224 224
         // done?
225 225
         $done_step_one = EE_Registry::instance()->CFG->organization->address_1 == '123 Onna Road' ? false : true;
@@ -248,10 +248,10 @@  discard block
 block discarded – undo
248 248
         }
249 249
 
250 250
         // now let's put it together
251
-        $steps .= sprintf('%s' . $step_one . '%s', $done_step_one ? '<strike>' : '', $done_step_one ? '</strike>' : '');
252
-        $steps .= sprintf('%s' . $step_two . '%s', $done_step_two ? '<strike>' : '', $done_step_two ? '</strike>' : '');
251
+        $steps .= sprintf('%s'.$step_one.'%s', $done_step_one ? '<strike>' : '', $done_step_one ? '</strike>' : '');
252
+        $steps .= sprintf('%s'.$step_two.'%s', $done_step_two ? '<strike>' : '', $done_step_two ? '</strike>' : '');
253 253
         $steps .= sprintf(
254
-            '%s' . $step_three . '%s',
254
+            '%s'.$step_three.'%s',
255 255
             $done_step_three ? '<strike>' : '',
256 256
             $done_step_three ? '</strike>' : ''
257 257
         );
@@ -270,7 +270,7 @@  discard block
 block discarded – undo
270 270
             'Thank you for choosing Event Espresso Decaf, the most powerful, and free, Event Management plugin for WordPress.',
271 271
             'event_espresso'
272 272
         );
273
-        $template = EE_ABOUT_TEMPLATE_PATH . 'credits.template.php';
273
+        $template = EE_ABOUT_TEMPLATE_PATH.'credits.template.php';
274 274
         $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
275 275
             $template,
276 276
             $this->_template_args,
@@ -296,7 +296,7 @@  discard block
 block discarded – undo
296 296
             '<strong>',
297 297
             '</strong>'
298 298
         );
299
-        $template = EE_ABOUT_TEMPLATE_PATH . 'decafvpro.template.php';
299
+        $template = EE_ABOUT_TEMPLATE_PATH.'decafvpro.template.php';
300 300
         $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
301 301
             $template,
302 302
             $this->_template_args,
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
             'At Event Espresso, customer satisfaction is our ultimate goal.',
313 313
             'event_espresso'
314 314
         );
315
-        $template = EE_ABOUT_TEMPLATE_PATH . 'reviews.template.php';
315
+        $template = EE_ABOUT_TEMPLATE_PATH.'reviews.template.php';
316 316
         $this->_template_args['about_admin_page_content'] = EEH_Template::display_template(
317 317
             $template,
318 318
             $this->_template_args,
Please login to merge, or discard this patch.
admin_pages/events/templates/event_registration_options.template.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -19,9 +19,9 @@
 block discarded – undo
19 19
 <p>
20 20
     <label for="max-registrants">
21 21
         <?php esc_html_e(
22
-            'Maximum number of tickets allowed per order for this event: ',
23
-            'event_espresso'
24
-        ); ?>
22
+			'Maximum number of tickets allowed per order for this event: ',
23
+			'event_espresso'
24
+		); ?>
25 25
     </label>
26 26
     <input class="ee-numeric ee-input-width--small"
27 27
            id="max-registrants"
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2957 added lines, -2957 removed lines patch added patch discarded remove patch
@@ -18,2964 +18,2964 @@
 block discarded – undo
18 18
  */
19 19
 class Events_Admin_Page extends EE_Admin_Page_CPT
20 20
 {
21
-    /**
22
-     * This will hold the event object for event_details screen.
21
+	/**
22
+	 * This will hold the event object for event_details screen.
23
+	 *
24
+	 * @var EE_Event $_event
25
+	 */
26
+	protected $_event;
27
+
28
+
29
+	/**
30
+	 * This will hold the category object for category_details screen.
31
+	 *
32
+	 * @var stdClass $_category
33
+	 */
34
+	protected $_category;
35
+
36
+
37
+	/**
38
+	 * This will hold the event model instance
39
+	 *
40
+	 * @var EEM_Event $_event_model
41
+	 */
42
+	protected $_event_model;
43
+
44
+
45
+	/**
46
+	 * @var EE_Event
47
+	 */
48
+	protected $_cpt_model_obj = null;
49
+
50
+
51
+	/**
52
+	 * @var NodeGroupDao
53
+	 */
54
+	protected $model_obj_node_group_persister;
55
+
56
+	/**
57
+	 * @var AdvancedEditorAdminFormSection
58
+	 */
59
+	protected $advanced_editor_admin_form;
60
+
61
+
62
+	/**
63
+	 * Initialize page props for this admin page group.
64
+	 */
65
+	protected function _init_page_props()
66
+	{
67
+		$this->page_slug        = EVENTS_PG_SLUG;
68
+		$this->page_label       = EVENTS_LABEL;
69
+		$this->_admin_base_url  = EVENTS_ADMIN_URL;
70
+		$this->_admin_base_path = EVENTS_ADMIN;
71
+		$this->_cpt_model_names = [
72
+			'create_new' => 'EEM_Event',
73
+			'edit'       => 'EEM_Event',
74
+		];
75
+		$this->_cpt_edit_routes = [
76
+			'espresso_events' => 'edit',
77
+		];
78
+		add_action(
79
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
80
+			[$this, 'verify_event_edit'],
81
+			10,
82
+			2
83
+		);
84
+	}
85
+
86
+
87
+	/**
88
+	 * Sets the ajax hooks used for this admin page group.
89
+	 */
90
+	protected function _ajax_hooks()
91
+	{
92
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
93
+	}
94
+
95
+
96
+	/**
97
+	 * Sets the page properties for this admin page group.
98
+	 */
99
+	protected function _define_page_props()
100
+	{
101
+		$event_id = $this->request->getRequestParam('post', 0, DataType::INT);
102
+		if ($event_id) {
103
+			$event_post = get_post($event_id);
104
+		}
105
+
106
+		$this->_admin_page_title = EVENTS_LABEL;
107
+		$this->_labels           = [
108
+			'buttons'      => [
109
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
110
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
111
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
112
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
113
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
114
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
115
+			],
116
+			'editor_title' => [
117
+				'espresso_events' => isset($event_post) && $event_post instanceof WP_Post
118
+					? $event_post->post_title
119
+					: esc_html__('Edit Event', 'event_espresso'),
120
+			],
121
+			'publishbox'   => [
122
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
123
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
124
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
125
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
126
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
127
+			],
128
+		];
129
+	}
130
+
131
+
132
+	/**
133
+	 * Sets the page routes property for this admin page group.
134
+	 */
135
+	protected function _set_page_routes()
136
+	{
137
+		// load formatter helper
138
+		// load field generator helper
139
+		// is there a evt_id in the request?
140
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
141
+		$EVT_ID = $this->request->getRequestParam('post', $EVT_ID, DataType::INT);
142
+
143
+		$this->_page_routes = [
144
+			'default'                       => [
145
+				'func'       => [$this, '_events_overview_list_table'],
146
+				'capability' => 'ee_read_events',
147
+			],
148
+			'create_new'                    => [
149
+				'func'       => [$this, '_create_new_cpt_item'],
150
+				'capability' => 'ee_edit_events',
151
+			],
152
+			'edit'                          => [
153
+				'func'       => [$this, '_edit_cpt_item'],
154
+				'capability' => 'ee_edit_event',
155
+				'obj_id'     => $EVT_ID,
156
+			],
157
+			'copy_event'                    => [
158
+				'func'       => [$this, '_copy_events'],
159
+				'capability' => 'ee_edit_event',
160
+				'obj_id'     => $EVT_ID,
161
+				'noheader'   => true,
162
+			],
163
+			'trash_event'                   => [
164
+				'func'       => [$this, '_trash_or_restore_event'],
165
+				'args'       => ['event_status' => 'trash'],
166
+				'capability' => 'ee_delete_event',
167
+				'obj_id'     => $EVT_ID,
168
+				'noheader'   => true,
169
+			],
170
+			'trash_events'                  => [
171
+				'func'       => [$this, '_trash_or_restore_events'],
172
+				'args'       => ['event_status' => 'trash'],
173
+				'capability' => 'ee_delete_events',
174
+				'noheader'   => true,
175
+			],
176
+			'restore_event'                 => [
177
+				'func'       => [$this, '_trash_or_restore_event'],
178
+				'args'       => ['event_status' => 'draft'],
179
+				'capability' => 'ee_delete_event',
180
+				'obj_id'     => $EVT_ID,
181
+				'noheader'   => true,
182
+			],
183
+			'restore_events'                => [
184
+				'func'       => [$this, '_trash_or_restore_events'],
185
+				'args'       => ['event_status' => 'draft'],
186
+				'capability' => 'ee_delete_events',
187
+				'noheader'   => true,
188
+			],
189
+			'delete_event'                  => [
190
+				'func'       => [$this, '_delete_event'],
191
+				'capability' => 'ee_delete_event',
192
+				'obj_id'     => $EVT_ID,
193
+				'noheader'   => true,
194
+			],
195
+			'delete_events'                 => [
196
+				'func'       => [$this, '_delete_events'],
197
+				'capability' => 'ee_delete_events',
198
+				'noheader'   => true,
199
+			],
200
+			'view_report'                   => [
201
+				'func'       => [$this, '_view_report'],
202
+				'capability' => 'ee_edit_events',
203
+			],
204
+			'default_event_settings'        => [
205
+				'func'       => [$this, '_default_event_settings'],
206
+				'capability' => 'manage_options',
207
+			],
208
+			'update_default_event_settings' => [
209
+				'func'       => [$this, '_update_default_event_settings'],
210
+				'capability' => 'manage_options',
211
+				'noheader'   => true,
212
+			],
213
+			'template_settings'             => [
214
+				'func'       => [$this, '_template_settings'],
215
+				'capability' => 'manage_options',
216
+			],
217
+			// event category tab related
218
+			'add_category'                  => [
219
+				'func'       => [$this, '_category_details'],
220
+				'capability' => 'ee_edit_event_category',
221
+				'args'       => ['view' => 'add'],
222
+			],
223
+			'edit_category'                 => [
224
+				'func'       => [$this, '_category_details'],
225
+				'capability' => 'ee_edit_event_category',
226
+				'args'       => ['view' => 'edit'],
227
+			],
228
+			'delete_categories'             => [
229
+				'func'       => [$this, '_delete_categories'],
230
+				'capability' => 'ee_delete_event_category',
231
+				'noheader'   => true,
232
+			],
233
+			'delete_category'               => [
234
+				'func'       => [$this, '_delete_categories'],
235
+				'capability' => 'ee_delete_event_category',
236
+				'noheader'   => true,
237
+			],
238
+			'insert_category'               => [
239
+				'func'       => [$this, '_insert_or_update_category'],
240
+				'args'       => ['new_category' => true],
241
+				'capability' => 'ee_edit_event_category',
242
+				'noheader'   => true,
243
+			],
244
+			'update_category'               => [
245
+				'func'       => [$this, '_insert_or_update_category'],
246
+				'args'       => ['new_category' => false],
247
+				'capability' => 'ee_edit_event_category',
248
+				'noheader'   => true,
249
+			],
250
+			'category_list'                 => [
251
+				'func'       => [$this, '_category_list_table'],
252
+				'capability' => 'ee_manage_event_categories',
253
+			],
254
+			'preview_deletion'              => [
255
+				'func'       => [$this, 'previewDeletion'],
256
+				'capability' => 'ee_delete_events',
257
+			],
258
+			'confirm_deletion'              => [
259
+				'func'       => [$this, 'confirmDeletion'],
260
+				'capability' => 'ee_delete_events',
261
+				'noheader'   => true,
262
+			],
263
+		];
264
+	}
265
+
266
+
267
+	/**
268
+	 * Set the _page_config property for this admin page group.
269
+	 */
270
+	protected function _set_page_config()
271
+	{
272
+		$post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
273
+		$EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
274
+		$this->_page_config = [
275
+			'default'                => [
276
+				'nav'           => [
277
+					'label' => esc_html__('Overview', 'event_espresso'),
278
+					'icon'  => 'dashicons-list-view',
279
+					'order' => 10,
280
+				],
281
+				'list_table'    => 'Events_Admin_List_Table',
282
+				'help_tabs'     => [
283
+					'events_overview_help_tab'                       => [
284
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
285
+						'filename' => 'events_overview',
286
+					],
287
+					'events_overview_table_column_headings_help_tab' => [
288
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
289
+						'filename' => 'events_overview_table_column_headings',
290
+					],
291
+					'events_overview_filters_help_tab'               => [
292
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
293
+						'filename' => 'events_overview_filters',
294
+					],
295
+					'events_overview_view_help_tab'                  => [
296
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
297
+						'filename' => 'events_overview_views',
298
+					],
299
+					'events_overview_other_help_tab'                 => [
300
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
301
+						'filename' => 'events_overview_other',
302
+					],
303
+				],
304
+				'require_nonce' => false,
305
+			],
306
+			'create_new'             => [
307
+				'nav'           => [
308
+					'label'      => esc_html__('Add New Event', 'event_espresso'),
309
+					'icon'       => 'dashicons-plus-alt',
310
+					'order'      => 15,
311
+					'persistent' => false,
312
+				],
313
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
314
+				'help_tabs'     => [
315
+					'event_editor_help_tab'                            => [
316
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
317
+						'filename' => 'event_editor',
318
+					],
319
+					'event_editor_title_richtexteditor_help_tab'       => [
320
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
321
+						'filename' => 'event_editor_title_richtexteditor',
322
+					],
323
+					'event_editor_venue_details_help_tab'              => [
324
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
325
+						'filename' => 'event_editor_venue_details',
326
+					],
327
+					'event_editor_event_datetimes_help_tab'            => [
328
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
329
+						'filename' => 'event_editor_event_datetimes',
330
+					],
331
+					'event_editor_event_tickets_help_tab'              => [
332
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
333
+						'filename' => 'event_editor_event_tickets',
334
+					],
335
+					'event_editor_event_registration_options_help_tab' => [
336
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
337
+						'filename' => 'event_editor_event_registration_options',
338
+					],
339
+					'event_editor_tags_categories_help_tab'            => [
340
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
341
+						'filename' => 'event_editor_tags_categories',
342
+					],
343
+					'event_editor_questions_registrants_help_tab'      => [
344
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
345
+						'filename' => 'event_editor_questions_registrants',
346
+					],
347
+					'event_editor_save_new_event_help_tab'             => [
348
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
349
+						'filename' => 'event_editor_save_new_event',
350
+					],
351
+					'event_editor_other_help_tab'                      => [
352
+						'title'    => esc_html__('Event Other', 'event_espresso'),
353
+						'filename' => 'event_editor_other',
354
+					],
355
+				],
356
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
357
+				'require_nonce' => false,
358
+			],
359
+			'edit'                   => [
360
+				'nav'           => [
361
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
362
+					'icon'       => 'dashicons-edit',
363
+					'order'      => 15,
364
+					'persistent' => false,
365
+					'url'        => $post_id
366
+						? EE_Admin_Page::add_query_args_and_nonce(
367
+							['post' => $post_id, 'action' => 'edit'],
368
+							$this->_current_page_view_url
369
+						)
370
+						: $this->_admin_base_url,
371
+				],
372
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
373
+				'help_tabs'     => [
374
+					'event_editor_help_tab'                            => [
375
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
376
+						'filename' => 'event_editor',
377
+					],
378
+					'event_editor_title_richtexteditor_help_tab'       => [
379
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
380
+						'filename' => 'event_editor_title_richtexteditor',
381
+					],
382
+					'event_editor_venue_details_help_tab'              => [
383
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
384
+						'filename' => 'event_editor_venue_details',
385
+					],
386
+					'event_editor_event_datetimes_help_tab'            => [
387
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
388
+						'filename' => 'event_editor_event_datetimes',
389
+					],
390
+					'event_editor_event_tickets_help_tab'              => [
391
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
392
+						'filename' => 'event_editor_event_tickets',
393
+					],
394
+					'event_editor_event_registration_options_help_tab' => [
395
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
396
+						'filename' => 'event_editor_event_registration_options',
397
+					],
398
+					'event_editor_tags_categories_help_tab'            => [
399
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
400
+						'filename' => 'event_editor_tags_categories',
401
+					],
402
+					'event_editor_questions_registrants_help_tab'      => [
403
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
404
+						'filename' => 'event_editor_questions_registrants',
405
+					],
406
+					'event_editor_save_new_event_help_tab'             => [
407
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
408
+						'filename' => 'event_editor_save_new_event',
409
+					],
410
+					'event_editor_other_help_tab'                      => [
411
+						'title'    => esc_html__('Event Other', 'event_espresso'),
412
+						'filename' => 'event_editor_other',
413
+					],
414
+				],
415
+				'require_nonce' => false,
416
+			],
417
+			'default_event_settings' => [
418
+				'nav'           => [
419
+					'label' => esc_html__('Default Settings', 'event_espresso'),
420
+					'icon'  => 'dashicons-admin-generic',
421
+					'order' => 40,
422
+				],
423
+				'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
424
+				'labels'        => [
425
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
426
+				],
427
+				'help_tabs'     => [
428
+					'default_settings_help_tab'        => [
429
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
430
+						'filename' => 'events_default_settings',
431
+					],
432
+					'default_settings_status_help_tab' => [
433
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
434
+						'filename' => 'events_default_settings_status',
435
+					],
436
+					'default_maximum_tickets_help_tab' => [
437
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
438
+						'filename' => 'events_default_settings_max_tickets',
439
+					],
440
+				],
441
+				'require_nonce' => false,
442
+			],
443
+			// template settings
444
+			'template_settings'      => [
445
+				'nav'           => [
446
+					'label' => esc_html__('Templates', 'event_espresso'),
447
+					'icon'  => 'dashicons-layout',
448
+					'order' => 30,
449
+				],
450
+				'metaboxes'     => $this->_default_espresso_metaboxes,
451
+				'help_tabs'     => [
452
+					'general_settings_templates_help_tab' => [
453
+						'title'    => esc_html__('Templates', 'event_espresso'),
454
+						'filename' => 'general_settings_templates',
455
+					],
456
+				],
457
+				'require_nonce' => false,
458
+			],
459
+			// event category stuff
460
+			'add_category'           => [
461
+				'nav'           => [
462
+					'label'      => esc_html__('Add Category', 'event_espresso'),
463
+					'icon'       => 'dashicons-plus-alt',
464
+					'order'      => 25,
465
+					'persistent' => false,
466
+				],
467
+				'help_tabs'     => [
468
+					'add_category_help_tab' => [
469
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
470
+						'filename' => 'events_add_category',
471
+					],
472
+				],
473
+				'metaboxes'     => ['_publish_post_box'],
474
+				'require_nonce' => false,
475
+			],
476
+			'edit_category'          => [
477
+				'nav'           => [
478
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
479
+					'icon'       => 'dashicons-edit',
480
+					'order'      => 25,
481
+					'persistent' => false,
482
+					'url'        => $EVT_CAT_ID
483
+						? add_query_arg(
484
+							['EVT_CAT_ID' => $EVT_CAT_ID],
485
+							$this->_current_page_view_url
486
+						)
487
+						: $this->_admin_base_url,
488
+				],
489
+				'help_tabs'     => [
490
+					'edit_category_help_tab' => [
491
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
492
+						'filename' => 'events_edit_category',
493
+					],
494
+				],
495
+				'metaboxes'     => ['_publish_post_box'],
496
+				'require_nonce' => false,
497
+			],
498
+			'category_list'          => [
499
+				'nav'           => [
500
+					'label' => esc_html__('Categories', 'event_espresso'),
501
+					'icon'  => 'dashicons-networking',
502
+					'order' => 20,
503
+				],
504
+				'list_table'    => 'Event_Categories_Admin_List_Table',
505
+				'help_tabs'     => [
506
+					'events_categories_help_tab'                       => [
507
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
508
+						'filename' => 'events_categories',
509
+					],
510
+					'events_categories_table_column_headings_help_tab' => [
511
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
512
+						'filename' => 'events_categories_table_column_headings',
513
+					],
514
+					'events_categories_view_help_tab'                  => [
515
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
516
+						'filename' => 'events_categories_views',
517
+					],
518
+					'events_categories_other_help_tab'                 => [
519
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
520
+						'filename' => 'events_categories_other',
521
+					],
522
+				],
523
+				'metaboxes'     => $this->_default_espresso_metaboxes,
524
+				'require_nonce' => false,
525
+			],
526
+			'preview_deletion'       => [
527
+				'nav'           => [
528
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
529
+					'icon'       => 'dashicons-remove',
530
+					'order'      => 15,
531
+					'persistent' => false,
532
+					'url'        => '',
533
+				],
534
+				'require_nonce' => false,
535
+			],
536
+		];
537
+	}
538
+
539
+
540
+	/**
541
+	 * Used to register any global screen options if necessary for every route in this admin page group.
542
+	 */
543
+	protected function _add_screen_options()
544
+	{
545
+	}
546
+
547
+
548
+	/**
549
+	 * Implementing the screen options for the 'default' route.
550
+	 *
551
+	 * @throws InvalidArgumentException
552
+	 * @throws InvalidDataTypeException
553
+	 * @throws InvalidInterfaceException
554
+	 */
555
+	protected function _add_screen_options_default()
556
+	{
557
+		$this->_per_page_screen_option();
558
+	}
559
+
560
+
561
+	/**
562
+	 * Implementing screen options for the category list route.
563
+	 *
564
+	 * @throws InvalidArgumentException
565
+	 * @throws InvalidDataTypeException
566
+	 * @throws InvalidInterfaceException
567
+	 */
568
+	protected function _add_screen_options_category_list()
569
+	{
570
+		$page_title              = $this->_admin_page_title;
571
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
572
+		$this->_per_page_screen_option();
573
+		$this->_admin_page_title = $page_title;
574
+	}
575
+
576
+
577
+	/**
578
+	 * Used to register any global feature pointers for the admin page group.
579
+	 */
580
+	protected function _add_feature_pointers()
581
+	{
582
+	}
583
+
584
+
585
+	/**
586
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
587
+	 */
588
+	public function load_scripts_styles()
589
+	{
590
+		wp_register_style(
591
+			'events-admin-css',
592
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
593
+			[],
594
+			EVENT_ESPRESSO_VERSION
595
+		);
596
+		wp_register_style(
597
+			'ee-cat-admin',
598
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
599
+			[],
600
+			EVENT_ESPRESSO_VERSION
601
+		);
602
+		wp_enqueue_style('events-admin-css');
603
+		wp_enqueue_style('ee-cat-admin');
604
+		// scripts
605
+		wp_register_script(
606
+			'event_editor_js',
607
+			EVENTS_ASSETS_URL . 'event_editor.js',
608
+			['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
609
+			EVENT_ESPRESSO_VERSION,
610
+			true
611
+		);
612
+	}
613
+
614
+
615
+	/**
616
+	 * Enqueuing scripts and styles specific to this view
617
+	 */
618
+	public function load_scripts_styles_create_new()
619
+	{
620
+		$this->load_scripts_styles_edit();
621
+	}
622
+
623
+
624
+	/**
625
+	 * Enqueuing scripts and styles specific to this view
626
+	 */
627
+	public function load_scripts_styles_edit()
628
+	{
629
+		// styles
630
+		wp_enqueue_style('espresso-ui-theme');
631
+		wp_register_style(
632
+			'event-editor-css',
633
+			EVENTS_ASSETS_URL . 'event-editor.css',
634
+			['ee-admin-css'],
635
+			EVENT_ESPRESSO_VERSION
636
+		);
637
+		wp_enqueue_style('event-editor-css');
638
+		// scripts
639
+		if (! $this->admin_config->useAdvancedEditor()) {
640
+			wp_register_script(
641
+				'event-datetime-metabox',
642
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
643
+				['event_editor_js', 'ee-datepicker'],
644
+				EVENT_ESPRESSO_VERSION
645
+			);
646
+			wp_enqueue_script('event-datetime-metabox');
647
+		}
648
+	}
649
+
650
+
651
+	/**
652
+	 * Populating the _views property for the category list table view.
653
+	 */
654
+	protected function _set_list_table_views_category_list()
655
+	{
656
+		$this->_views = [
657
+			'all' => [
658
+				'slug'        => 'all',
659
+				'label'       => esc_html__('All', 'event_espresso'),
660
+				'count'       => 0,
661
+				'bulk_action' => [
662
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
663
+				],
664
+			],
665
+		];
666
+	}
667
+
668
+
669
+	/**
670
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
671
+	 */
672
+	public function admin_init()
673
+	{
674
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
675
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
676
+			'event_espresso'
677
+		);
678
+	}
679
+
680
+
681
+	/**
682
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
683
+	 * group.
684
+	 */
685
+	public function admin_notices()
686
+	{
687
+	}
688
+
689
+
690
+	/**
691
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
692
+	 * this admin page group.
693
+	 */
694
+	public function admin_footer_scripts()
695
+	{
696
+	}
697
+
698
+
699
+	/**
700
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
701
+	 * warning (via EE_Error::add_error());
702
+	 *
703
+	 * @param EE_Event|null $event Event object
704
+	 * @param string        $req_type
705
+	 * @return void
706
+	 * @throws EE_Error
707
+	 * @throws ReflectionException
708
+	 */
709
+	public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
710
+	{
711
+		// don't need to do this when processing
712
+		if (! empty($req_type)) {
713
+			return;
714
+		}
715
+		// no event?
716
+		if (! $event instanceof EE_Event) {
717
+			$event = $this->_cpt_model_obj;
718
+		}
719
+		// STILL no event?
720
+		if (! $event instanceof EE_Event) {
721
+			return;
722
+		}
723
+		// don't need to keep calling this
724
+		remove_action(
725
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
726
+			[$this, 'verify_event_edit']
727
+		);
728
+		$orig_status = $event->status();
729
+		// first check if event is active.
730
+		if (
731
+			$orig_status === EEM_Event::cancelled
732
+			|| $orig_status === EEM_Event::postponed
733
+			|| $event->is_expired()
734
+			|| $event->is_inactive()
735
+		) {
736
+			return;
737
+		}
738
+		// made it here so it IS active... next check that any of the tickets are sold.
739
+		if ($event->is_sold_out(true)) {
740
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
741
+				EE_Error::add_attention(
742
+					sprintf(
743
+						esc_html__(
744
+							'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.',
745
+							'event_espresso'
746
+						),
747
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
748
+					)
749
+				);
750
+			}
751
+			return;
752
+		}
753
+		if ($orig_status === EEM_Event::sold_out) {
754
+			EE_Error::add_attention(
755
+				sprintf(
756
+					esc_html__(
757
+						'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.',
758
+						'event_espresso'
759
+					),
760
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
761
+				)
762
+			);
763
+		}
764
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
765
+		if (! $event->tickets_on_sale()) {
766
+			return;
767
+		}
768
+		// made it here so show warning
769
+		$this->_edit_event_warning();
770
+	}
771
+
772
+
773
+	/**
774
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
775
+	 * When needed, hook this into a EE_Error::add_error() notice.
776
+	 *
777
+	 * @access protected
778
+	 * @return void
779
+	 */
780
+	protected function _edit_event_warning()
781
+	{
782
+		// we don't want to add warnings during these requests
783
+		if ($this->request->getRequestParam('action') === 'editpost') {
784
+			return;
785
+		}
786
+		EE_Error::add_attention(
787
+			sprintf(
788
+				esc_html__(
789
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
790
+					'event_espresso'
791
+				),
792
+				'<a class="espresso-help-tab-lnk ee-help-tab-link">',
793
+				'</a>'
794
+			)
795
+		);
796
+	}
797
+
798
+
799
+	/**
800
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
801
+	 * Otherwise, do the normal logic
802
+	 *
803
+	 * @return void
804
+	 * @throws EE_Error
805
+	 * @throws InvalidArgumentException
806
+	 * @throws InvalidDataTypeException
807
+	 * @throws InvalidInterfaceException
808
+	 * @throws ReflectionException
809
+	 */
810
+	protected function _create_new_cpt_item()
811
+	{
812
+		$has_timezone_string = get_option('timezone_string');
813
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
814
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
815
+			EE_Error::add_attention(
816
+				sprintf(
817
+					esc_html__(
818
+						'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',
819
+						'event_espresso'
820
+					),
821
+					'<br>',
822
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
823
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
824
+					. '</select>',
825
+					'<button class="button button--secondary timezone-submit">',
826
+					'</button><span class="spinner"></span>'
827
+				),
828
+				__FILE__,
829
+				__FUNCTION__,
830
+				__LINE__
831
+			);
832
+		}
833
+		parent::_create_new_cpt_item();
834
+	}
835
+
836
+
837
+	/**
838
+	 * Sets the _views property for the default route in this admin page group.
839
+	 */
840
+	protected function _set_list_table_views_default()
841
+	{
842
+		$this->_views = [
843
+			'all'   => [
844
+				'slug'        => 'all',
845
+				'label'       => esc_html__('View All Events', 'event_espresso'),
846
+				'count'       => 0,
847
+				'bulk_action' => [
848
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
+				],
850
+			],
851
+			'draft' => [
852
+				'slug'        => 'draft',
853
+				'label'       => esc_html__('Draft', 'event_espresso'),
854
+				'count'       => 0,
855
+				'bulk_action' => [
856
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
857
+				],
858
+			],
859
+		];
860
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
861
+			$this->_views['trash'] = [
862
+				'slug'        => 'trash',
863
+				'label'       => esc_html__('Trash', 'event_espresso'),
864
+				'count'       => 0,
865
+				'bulk_action' => [
866
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
867
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
868
+				],
869
+			];
870
+		}
871
+	}
872
+
873
+
874
+	/**
875
+	 * Provides the legend item array for the default list table view.
876
+	 *
877
+	 * @return array
878
+	 * @throws EE_Error
879
+	 * @throws EE_Error
880
+	 */
881
+	protected function _event_legend_items(): array
882
+	{
883
+		$items    = [
884
+			'view_details'   => [
885
+				'class' => 'dashicons dashicons-visibility',
886
+				'desc'  => esc_html__('View Event', 'event_espresso'),
887
+			],
888
+			'edit_event'     => [
889
+				'class' => 'dashicons dashicons-calendar-alt',
890
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
891
+			],
892
+			'view_attendees' => [
893
+				'class' => 'dashicons dashicons-groups',
894
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
895
+			],
896
+		];
897
+		$items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
898
+		$statuses = [
899
+			'sold_out_status'  => [
900
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
901
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
902
+			],
903
+			'active_status'    => [
904
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
905
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
906
+			],
907
+			'upcoming_status'  => [
908
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
909
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
910
+			],
911
+			'postponed_status' => [
912
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
913
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
914
+			],
915
+			'cancelled_status' => [
916
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
917
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
918
+			],
919
+			'expired_status'   => [
920
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
921
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
922
+			],
923
+			'inactive_status'  => [
924
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
925
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
926
+			],
927
+		];
928
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
929
+		return array_merge($items, $statuses);
930
+	}
931
+
932
+
933
+	/**
934
+	 * @return EEM_Event
935
+	 * @throws EE_Error
936
+	 * @throws InvalidArgumentException
937
+	 * @throws InvalidDataTypeException
938
+	 * @throws InvalidInterfaceException
939
+	 * @throws ReflectionException
940
+	 */
941
+	private function _event_model(): EEM_Event
942
+	{
943
+		if (! $this->_event_model instanceof EEM_Event) {
944
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
945
+		}
946
+		return $this->_event_model;
947
+	}
948
+
949
+
950
+	/**
951
+	 * Adds extra buttons to the WP CPT permalink field row.
952
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
953
+	 *
954
+	 * @param string      $return    the current html
955
+	 * @param int         $id        the post id for the page
956
+	 * @param string|null $new_title What the title is
957
+	 * @param string|null $new_slug  what the slug is
958
+	 * @return string            The new html string for the permalink area
959
+	 * @deprecated 5.0.0.p
960
+	 * @see TicketSelectorShortcodeButton::addButton
961
+	 */
962
+	public function extra_permalink_field_buttons(
963
+		string $return,
964
+		int $id,
965
+		?string $new_title,
966
+		?string $new_slug
967
+	): string {
968
+		return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
969
+	}
970
+
971
+
972
+	/**
973
+	 * _events_overview_list_table
974
+	 * This contains the logic for showing the events_overview list
975
+	 *
976
+	 * @access protected
977
+	 * @return void
978
+	 * @throws DomainException
979
+	 * @throws EE_Error
980
+	 * @throws InvalidArgumentException
981
+	 * @throws InvalidDataTypeException
982
+	 * @throws InvalidInterfaceException
983
+	 */
984
+	protected function _events_overview_list_table()
985
+	{
986
+		$after_list_table = [];
987
+		$links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
988
+		$links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
989
+		$links_html       .= EEH_HTML::div(
990
+			EEH_Template::get_button_or_link(
991
+				get_post_type_archive_link('espresso_events'),
992
+				esc_html__('View Event Archive Page', 'event_espresso'),
993
+				'button button--small button--secondary'
994
+			),
995
+			'',
996
+			'ee-admin-button-row ee-admin-button-row--align-start'
997
+		);
998
+		$links_html       .= EEH_HTML::divx();
999
+
1000
+		$after_list_table['view_event_list_button'] = $links_html;
1001
+
1002
+		$after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
1003
+		$this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
1004
+			'create_new',
1005
+			'add',
1006
+			[],
1007
+			'add-new-h2'
1008
+		);
1009
+
1010
+		$this->_template_args['after_list_table'] = array_merge(
1011
+			(array) $this->_template_args['after_list_table'],
1012
+			$after_list_table
1013
+		);
1014
+		$this->display_admin_list_table_page_with_no_sidebar();
1015
+	}
1016
+
1017
+
1018
+	/**
1019
+	 * this allows for extra misc actions in the default WP publish box
1020
+	 *
1021
+	 * @return void
1022
+	 * @throws DomainException
1023
+	 * @throws EE_Error
1024
+	 * @throws InvalidArgumentException
1025
+	 * @throws InvalidDataTypeException
1026
+	 * @throws InvalidInterfaceException
1027
+	 * @throws ReflectionException
1028
+	 */
1029
+	public function extra_misc_actions_publish_box()
1030
+	{
1031
+		$this->_generate_publish_box_extra_content();
1032
+	}
1033
+
1034
+
1035
+	/**
1036
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1037
+	 * saved.
1038
+	 * Typically you would use this to save any additional data.
1039
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1040
+	 * ALSO very important.  When a post transitions from scheduled to published,
1041
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1042
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1043
+	 *
1044
+	 * @access protected
1045
+	 * @abstract
1046
+	 * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1047
+	 * @param WP_Post $post    The post object of the cpt that was saved.
1048
+	 * @return void
1049
+	 * @throws EE_Error
1050
+	 * @throws InvalidArgumentException
1051
+	 * @throws InvalidDataTypeException
1052
+	 * @throws InvalidInterfaceException
1053
+	 * @throws ReflectionException
1054
+	 */
1055
+	protected function _insert_update_cpt_item($post_id, $post)
1056
+	{
1057
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1058
+			// get out we're not processing an event save.
1059
+			return;
1060
+		}
1061
+		$event_values = [
1062
+			'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1063
+			'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1064
+			'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1065
+		];
1066
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1067
+		if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1068
+			$event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1069
+				'display_ticket_selector',
1070
+				false,
1071
+				'bool'
1072
+			);
1073
+			$event_values['EVT_additional_limit']            = min(
1074
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1075
+				$this->request->getRequestParam(
1076
+					'additional_limit',
1077
+					EEM_Event::get_default_additional_limit(),
1078
+					'int'
1079
+				)
1080
+			);
1081
+			$event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1082
+				'EVT_default_registration_status',
1083
+				EE_Registry::instance()->CFG->registration->default_STS_ID
1084
+			);
1085
+
1086
+			$event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1087
+			$event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1088
+			$event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1089
+		} elseif ($post instanceof WP_Post) {
1090
+			$event_values['EVT_name'] = $post->post_title;
1091
+			$event_values['EVT_desc'] = $post->post_content;
1092
+		}
1093
+		// update event
1094
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1095
+		// get event_object for other metaboxes...
1096
+		// though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1097
+		// i have to setup where conditions to override the filters in the model
1098
+		// that filter out auto-draft and inherit statuses so we GET the inherit id!
1099
+		/** @var EE_Event $event */
1100
+		$event = $this->_event_model()->get_one(
1101
+			[
1102
+				[
1103
+					$this->_event_model()->primary_key_name() => $post_id,
1104
+					'OR'                                      => [
1105
+						'status'   => $post->post_status,
1106
+						// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1107
+						// but the returned object here has a status of "publish", so use the original post status as well
1108
+						'status*1' => $this->request->getRequestParam('original_post_status'),
1109
+					],
1110
+				],
1111
+			]
1112
+		);
1113
+
1114
+		// the following are default callbacks for event attachment updates
1115
+		// that can be overridden by caffeinated functionality and/or addons.
1116
+		$event_update_callbacks = [];
1117
+		if (! $this->admin_config->useAdvancedEditor()) {
1118
+			$event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1119
+			$event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1120
+		}
1121
+		$event_update_callbacks = apply_filters(
1122
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1123
+			$event_update_callbacks
1124
+		);
1125
+
1126
+		$att_success = true;
1127
+		foreach ($event_update_callbacks as $e_callback) {
1128
+			$_success = is_callable($e_callback)
1129
+				? $e_callback($event, $this->request->requestParams())
1130
+				: false;
1131
+			// if ANY of these updates fail then we want the appropriate global error message
1132
+			$att_success = $_success !== false ? $att_success : false;
1133
+		}
1134
+		// any errors?
1135
+		if ($success && $att_success === false) {
1136
+			EE_Error::add_error(
1137
+				esc_html__(
1138
+					'Event Details saved successfully but something went wrong with saving attachments.',
1139
+					'event_espresso'
1140
+				),
1141
+				__FILE__,
1142
+				__FUNCTION__,
1143
+				__LINE__
1144
+			);
1145
+		} elseif ($success === false) {
1146
+			EE_Error::add_error(
1147
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1148
+				__FILE__,
1149
+				__FUNCTION__,
1150
+				__LINE__
1151
+			);
1152
+		}
1153
+	}
1154
+
1155
+
1156
+	/**
1157
+	 * @param int $post_id
1158
+	 * @param int $revision_id
1159
+	 * @throws EE_Error
1160
+	 * @throws EE_Error
1161
+	 * @throws ReflectionException
1162
+	 * @see parent::restore_item()
1163
+	 */
1164
+	protected function _restore_cpt_item(int $post_id, int $revision_id)
1165
+	{
1166
+		// copy existing event meta to new post
1167
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1168
+		if ($post_evt instanceof EE_Event) {
1169
+			// meta revision restore
1170
+			$post_evt->restore_revision($revision_id);
1171
+			// related objs restore
1172
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1173
+		}
1174
+	}
1175
+
1176
+
1177
+	/**
1178
+	 * Attach the venue to the Event
1179
+	 *
1180
+	 * @param EE_Event $event Event Object to add the venue to
1181
+	 * @param array    $data  The request data from the form
1182
+	 * @return bool           Success or fail.
1183
+	 * @throws EE_Error
1184
+	 * @throws ReflectionException
1185
+	 */
1186
+	protected function _default_venue_update(EE_Event $event, array $data): bool
1187
+	{
1188
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1189
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1190
+		$venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1191
+		// very important.  If we don't have a venue name...
1192
+		// then we'll get out because not necessary to create empty venue
1193
+		if (empty($data['venue_title'])) {
1194
+			return false;
1195
+		}
1196
+		$venue_array = [
1197
+			'VNU_wp_user'         => $event->get('EVT_wp_user'),
1198
+			'VNU_name'            => $data['venue_title'],
1199
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1200
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1201
+			'VNU_short_desc'      => ! empty($data['venue_short_description'])
1202
+				? $data['venue_short_description']
1203
+				: null,
1204
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1205
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1206
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1207
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1208
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1209
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1210
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1211
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1212
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1213
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1214
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1215
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1216
+			'status'              => 'publish',
1217
+		];
1218
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1219
+		if (! empty($venue_id)) {
1220
+			$update_where  = [$venue_model->primary_key_name() => $venue_id];
1221
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1222
+			// we've gotta make sure that the venue is always attached to a revision..
1223
+			// add_relation_to should take care of making sure that the relation is already present.
1224
+			$event->_add_relation_to($venue_id, 'Venue');
1225
+			return $rows_affected > 0;
1226
+		}
1227
+		// we insert the venue
1228
+		$venue_id = $venue_model->insert($venue_array);
1229
+		$event->_add_relation_to($venue_id, 'Venue');
1230
+		return ! empty($venue_id);
1231
+		// when we have the ancestor come in it's already been handled by the revision save.
1232
+	}
1233
+
1234
+
1235
+	/**
1236
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1237
+	 *
1238
+	 * @param EE_Event $event The Event object we're attaching data to
1239
+	 * @param array    $data  The request data from the form
1240
+	 * @return array
1241
+	 * @throws EE_Error
1242
+	 * @throws ReflectionException
1243
+	 * @throws Exception
1244
+	 */
1245
+	protected function _default_tickets_update(EE_Event $event, array $data): array
1246
+	{
1247
+		if ($this->admin_config->useAdvancedEditor()) {
1248
+			return [];
1249
+		}
1250
+		$datetime       = null;
1251
+		$saved_tickets  = [];
1252
+		$event_timezone = $event->get_timezone();
1253
+		$date_formats   = ['Y-m-d', 'h:i a'];
1254
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1255
+			// trim all values to ensure any excess whitespace is removed.
1256
+			$datetime_data                = array_map('trim', $datetime_data);
1257
+			$datetime_data['DTT_EVT_end'] =
1258
+				isset($datetime_data['DTT_EVT_end']) && ! empty($datetime_data['DTT_EVT_end'])
1259
+					? $datetime_data['DTT_EVT_end']
1260
+					: $datetime_data['DTT_EVT_start'];
1261
+			$datetime_values              = [
1262
+				'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1263
+				'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1264
+				'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1265
+				'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1266
+				'DTT_order'     => $row,
1267
+			];
1268
+			// if we have an id then let's get existing object first and then set the new values.
1269
+			//  Otherwise we instantiate a new object for save.
1270
+			if (! empty($datetime_data['DTT_ID'])) {
1271
+				$datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1272
+				if (! $datetime instanceof EE_Datetime) {
1273
+					throw new RuntimeException(
1274
+						sprintf(
1275
+							esc_html__(
1276
+								'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1277
+								'event_espresso'
1278
+							),
1279
+							$datetime_data['DTT_ID']
1280
+						)
1281
+					);
1282
+				}
1283
+				$datetime->set_date_format($date_formats[0]);
1284
+				$datetime->set_time_format($date_formats[1]);
1285
+				foreach ($datetime_values as $field => $value) {
1286
+					$datetime->set($field, $value);
1287
+				}
1288
+			} else {
1289
+				$datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1290
+			}
1291
+			if (! $datetime instanceof EE_Datetime) {
1292
+				throw new RuntimeException(
1293
+					sprintf(
1294
+						esc_html__(
1295
+							'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1296
+							'event_espresso'
1297
+						),
1298
+						print_r($datetime_values, true)
1299
+					)
1300
+				);
1301
+			}
1302
+			// before going any further make sure our dates are setup correctly
1303
+			// so that the end date is always equal or greater than the start date.
1304
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1305
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1306
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1307
+			}
1308
+			$datetime->save();
1309
+			$event->_add_relation_to($datetime, 'Datetime');
1310
+		}
1311
+		// no datetimes get deleted so we don't do any of that logic here.
1312
+		// update tickets next
1313
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1314
+
1315
+		// set up some default start and end dates in case those are not present in the incoming data
1316
+		$default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1317
+		$default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1318
+		// use the start date of the first datetime for the end date
1319
+		$first_datetime   = $event->first_datetime();
1320
+		$default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1321
+
1322
+		// now process the incoming data
1323
+		foreach ($data['edit_tickets'] as $row => $ticket_data) {
1324
+			$update_prices = false;
1325
+			$ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1326
+			// trim inputs to ensure any excess whitespace is removed.
1327
+			$ticket_data   = array_map('trim', $ticket_data);
1328
+			$ticket_values = [
1329
+				'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1330
+				'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1331
+				'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1332
+				'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1333
+				'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1334
+					? $ticket_data['TKT_start_date']
1335
+					: $default_start_date,
1336
+				'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1337
+					? $ticket_data['TKT_end_date']
1338
+					: $default_end_date,
1339
+				'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1340
+									 || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1341
+					? $ticket_data['TKT_qty']
1342
+					: EE_INF,
1343
+				'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1344
+									 || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1345
+					? $ticket_data['TKT_uses']
1346
+					: EE_INF,
1347
+				'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1348
+				'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1349
+				'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1350
+				'TKT_price'       => $ticket_price,
1351
+				'TKT_row'         => $row,
1352
+			];
1353
+			// if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1354
+			// which means in turn that the prices will become new prices as well.
1355
+			if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1356
+				$ticket_values['TKT_ID']         = 0;
1357
+				$ticket_values['TKT_is_default'] = 0;
1358
+				$update_prices                   = true;
1359
+			}
1360
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1361
+			// we actually do our saves ahead of adding any relations because its entirely possible that this
1362
+			// ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1363
+			// keep in mind that if the ticket has been sold (and we have changed pricing information),
1364
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1365
+			if (! empty($ticket_data['TKT_ID'])) {
1366
+				$existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1367
+				if (! $existing_ticket instanceof EE_Ticket) {
1368
+					throw new RuntimeException(
1369
+						sprintf(
1370
+							esc_html__(
1371
+								'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1372
+								'event_espresso'
1373
+							),
1374
+							$ticket_data['TKT_ID']
1375
+						)
1376
+					);
1377
+				}
1378
+				$ticket_sold = $existing_ticket->count_related(
1379
+					'Registration',
1380
+					[
1381
+							[
1382
+								'STS_ID' => [
1383
+									'NOT IN',
1384
+									[EEM_Registration::status_id_incomplete],
1385
+								],
1386
+							],
1387
+						]
1388
+				) > 0;
1389
+				// let's just check the total price for the existing ticket and determine if it matches the new total price.
1390
+				// if they are different then we create a new ticket (if $ticket_sold)
1391
+				// if they aren't different then we go ahead and modify existing ticket.
1392
+				$create_new_ticket = $ticket_sold
1393
+									 && $ticket_price !== $existing_ticket->price()
1394
+									 && ! $existing_ticket->deleted();
1395
+				$existing_ticket->set_date_format($date_formats[0]);
1396
+				$existing_ticket->set_time_format($date_formats[1]);
1397
+				// set new values
1398
+				foreach ($ticket_values as $field => $value) {
1399
+					if ($field == 'TKT_qty') {
1400
+						$existing_ticket->set_qty($value);
1401
+					} elseif ($field == 'TKT_price') {
1402
+						$existing_ticket->set('TKT_price', $ticket_price);
1403
+					} else {
1404
+						$existing_ticket->set($field, $value);
1405
+					}
1406
+				}
1407
+				$ticket = $existing_ticket;
1408
+				// if $create_new_ticket is false then we can safely update the existing ticket.
1409
+				//  Otherwise we have to create a new ticket.
1410
+				if ($create_new_ticket) {
1411
+					// archive the old ticket first
1412
+					$existing_ticket->set('TKT_deleted', 1);
1413
+					$existing_ticket->save();
1414
+					// make sure this ticket is still recorded in our $saved_tickets
1415
+					// so we don't run it through the regular trash routine.
1416
+					$saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1417
+					// create new ticket that's a copy of the existing except,
1418
+					// (a new id of course and not archived) AND has the new TKT_price associated with it.
1419
+					$new_ticket = clone $existing_ticket;
1420
+					$new_ticket->set('TKT_ID', 0);
1421
+					$new_ticket->set('TKT_deleted', 0);
1422
+					$new_ticket->set('TKT_sold', 0);
1423
+					// now we need to make sure that $new prices are created as well and attached to new ticket.
1424
+					$update_prices = true;
1425
+					$ticket        = $new_ticket;
1426
+				}
1427
+			} else {
1428
+				// no TKT_id so a new ticket
1429
+				$ticket_values['TKT_price'] = $ticket_price;
1430
+				$ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1431
+				$update_prices              = true;
1432
+			}
1433
+			if (! $ticket instanceof EE_Ticket) {
1434
+				throw new RuntimeException(
1435
+					sprintf(
1436
+						esc_html__(
1437
+							'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1438
+							'event_espresso'
1439
+						),
1440
+						print_r($ticket_values, true)
1441
+					)
1442
+				);
1443
+			}
1444
+			// cap ticket qty by datetime reg limits
1445
+			$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1446
+			// update ticket.
1447
+			$ticket->save();
1448
+			// before going any further make sure our dates are setup correctly
1449
+			// so that the end date is always equal or greater than the start date.
1450
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1451
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1452
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1453
+				$ticket->save();
1454
+			}
1455
+			// initially let's add the ticket to the datetime
1456
+			$datetime->_add_relation_to($ticket, 'Ticket');
1457
+			$saved_tickets[ $ticket->ID() ] = $ticket;
1458
+			// add prices to ticket
1459
+			$prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1460
+				? $data['edit_prices'][ $row ]
1461
+				: [];
1462
+			$this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1463
+		}
1464
+		// however now we need to handle permanently deleting tickets via the ui.
1465
+		// Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1466
+		// However, it does allow for deleting tickets that have no tickets sold,
1467
+		// in which case we want to get rid of permanently because there is no need to save in db.
1468
+		$old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1469
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1470
+		foreach ($tickets_removed as $id) {
1471
+			$id = absint($id);
1472
+			// get the ticket for this id
1473
+			$ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1474
+			if (! $ticket_to_remove instanceof EE_Ticket) {
1475
+				continue;
1476
+			}
1477
+			// need to get all the related datetimes on this ticket and remove from every single one of them
1478
+			// (remember this process can ONLY kick off if there are NO tickets sold)
1479
+			$related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1480
+			foreach ($related_datetimes as $related_datetime) {
1481
+				$ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1482
+			}
1483
+			// need to do the same for prices (except these prices can also be deleted because again,
1484
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1485
+			$ticket_to_remove->delete_related_permanently('Price');
1486
+			// finally let's delete this ticket
1487
+			// (which should not be blocked at this point b/c we've removed all our relationships)
1488
+			$ticket_to_remove->delete_permanently();
1489
+		}
1490
+		return [$datetime, $saved_tickets];
1491
+	}
1492
+
1493
+
1494
+	/**
1495
+	 * This attaches a list of given prices to a ticket.
1496
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices)
1497
+	 * because if there is a change in price information on a ticket, a new ticket is created anyways
1498
+	 * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1499
+	 *
1500
+	 * @access  private
1501
+	 * @param array     $prices_data Array of prices from the form.
1502
+	 * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1503
+	 * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1504
+	 * @return  void
1505
+	 * @throws EE_Error
1506
+	 * @throws ReflectionException
1507
+	 */
1508
+	private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1509
+	{
1510
+		$timezone = $ticket->get_timezone();
1511
+		foreach ($prices_data as $row => $price_data) {
1512
+			$price_values = [
1513
+				'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1514
+				'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1515
+				'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1516
+				'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1517
+				'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1518
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1519
+				'PRC_order'      => $row,
1520
+			];
1521
+			if ($new_prices || empty($price_values['PRC_ID'])) {
1522
+				$price_values['PRC_ID'] = 0;
1523
+				$price                  = EE_Price::new_instance($price_values, $timezone);
1524
+			} else {
1525
+				$price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1526
+				// update this price with new values
1527
+				foreach ($price_values as $field => $new_price) {
1528
+					$price->set($field, $new_price);
1529
+				}
1530
+			}
1531
+			if (! $price instanceof EE_Price) {
1532
+				throw new RuntimeException(
1533
+					sprintf(
1534
+						esc_html__(
1535
+							'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1536
+							'event_espresso'
1537
+						),
1538
+						print_r($price_values, true)
1539
+					)
1540
+				);
1541
+			}
1542
+			$price->save();
1543
+			$ticket->_add_relation_to($price, 'Price');
1544
+		}
1545
+	}
1546
+
1547
+
1548
+	/**
1549
+	 * Add in our autosave ajax handlers
1550
+	 *
1551
+	 */
1552
+	protected function _ee_autosave_create_new()
1553
+	{
1554
+	}
1555
+
1556
+
1557
+	/**
1558
+	 * More autosave handlers.
1559
+	 */
1560
+	protected function _ee_autosave_edit()
1561
+	{
1562
+	}
1563
+
1564
+
1565
+	/**
1566
+	 * @throws EE_Error
1567
+	 * @throws ReflectionException
1568
+	 */
1569
+	private function _generate_publish_box_extra_content()
1570
+	{
1571
+		// load formatter helper
1572
+		// args for getting related registrations
1573
+		$approved_query_args        = [
1574
+			[
1575
+				'REG_deleted' => 0,
1576
+				'STS_ID'      => EEM_Registration::status_id_approved,
1577
+			],
1578
+		];
1579
+		$not_approved_query_args    = [
1580
+			[
1581
+				'REG_deleted' => 0,
1582
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1583
+			],
1584
+		];
1585
+		$pending_payment_query_args = [
1586
+			[
1587
+				'REG_deleted' => 0,
1588
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1589
+			],
1590
+		];
1591
+		// publish box
1592
+		$publish_box_extra_args = [
1593
+			'view_approved_reg_url'        => add_query_arg(
1594
+				[
1595
+					'action'      => 'default',
1596
+					'event_id'    => $this->_cpt_model_obj->ID(),
1597
+					'_reg_status' => EEM_Registration::status_id_approved,
1598
+					'use_filters' => true,
1599
+				],
1600
+				REG_ADMIN_URL
1601
+			),
1602
+			'view_not_approved_reg_url'    => add_query_arg(
1603
+				[
1604
+					'action'      => 'default',
1605
+					'event_id'    => $this->_cpt_model_obj->ID(),
1606
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1607
+					'use_filters' => true,
1608
+				],
1609
+				REG_ADMIN_URL
1610
+			),
1611
+			'view_pending_payment_reg_url' => add_query_arg(
1612
+				[
1613
+					'action'      => 'default',
1614
+					'event_id'    => $this->_cpt_model_obj->ID(),
1615
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1616
+					'use_filters' => true,
1617
+				],
1618
+				REG_ADMIN_URL
1619
+			),
1620
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1621
+				'Registration',
1622
+				$approved_query_args
1623
+			),
1624
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1625
+				'Registration',
1626
+				$not_approved_query_args
1627
+			),
1628
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1629
+				'Registration',
1630
+				$pending_payment_query_args
1631
+			),
1632
+			'misc_pub_section_class'       => apply_filters(
1633
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1634
+				'misc-pub-section'
1635
+			),
1636
+		];
1637
+		ob_start();
1638
+		do_action(
1639
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1640
+			$this->_cpt_model_obj
1641
+		);
1642
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1643
+		// load template
1644
+		EEH_Template::display_template(
1645
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1646
+			$publish_box_extra_args
1647
+		);
1648
+	}
1649
+
1650
+
1651
+	/**
1652
+	 * @return EE_Event
1653
+	 */
1654
+	public function get_event_object()
1655
+	{
1656
+		return $this->_cpt_model_obj;
1657
+	}
1658
+
1659
+
1660
+
1661
+
1662
+	/** METABOXES * */
1663
+	/**
1664
+	 * _register_event_editor_meta_boxes
1665
+	 * add all metaboxes related to the event_editor
1666
+	 *
1667
+	 * @return void
1668
+	 * @throws EE_Error
1669
+	 * @throws ReflectionException
1670
+	 */
1671
+	protected function _register_event_editor_meta_boxes()
1672
+	{
1673
+		$this->verify_cpt_object();
1674
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1675
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1676
+		if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1677
+			$this->addMetaBox(
1678
+				'espresso_event_editor_event_options',
1679
+				esc_html__('Event Registration Options', 'event_espresso'),
1680
+				[$this, 'registration_options_meta_box'],
1681
+				$this->page_slug,
1682
+				'side'
1683
+			);
1684
+		}
1685
+		if (! $use_advanced_editor) {
1686
+			$this->addMetaBox(
1687
+				'espresso_event_editor_tickets',
1688
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1689
+				[$this, 'ticket_metabox'],
1690
+				$this->page_slug,
1691
+				'normal',
1692
+				'high'
1693
+			);
1694
+		} elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1695
+			add_action(
1696
+				'add_meta_boxes_espresso_events',
1697
+				function () {
1698
+					global $current_screen;
1699
+					remove_meta_box('authordiv', $current_screen, 'normal');
1700
+				},
1701
+				99
1702
+			);
1703
+		}
1704
+		// NOTE: if you're looking for other metaboxes in here,
1705
+		// where a metabox has a related management page in the admin
1706
+		// you will find it setup in the related management page's "_Hooks" file.
1707
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1708
+	}
1709
+
1710
+
1711
+	/**
1712
+	 * @throws DomainException
1713
+	 * @throws EE_Error
1714
+	 * @throws ReflectionException
1715
+	 */
1716
+	public function ticket_metabox()
1717
+	{
1718
+		$existing_datetime_ids = $existing_ticket_ids = [];
1719
+		// defaults for template args
1720
+		$template_args = [
1721
+			'ticket_rows'       => '',
1722
+			'total_ticket_rows' => 1,
1723
+			'trash_icon'        => 'dashicons dashicons-lock',
1724
+			'disabled'          => '',
1725
+		];
1726
+		$event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1727
+		/**
1728
+		 * 1. Start with retrieving Datetimes
1729
+		 * 2. Fore each datetime get related tickets
1730
+		 * 3. For each ticket get related prices
1731
+		 */
1732
+		/** @var EEM_Datetime $datetime_model */
1733
+		$datetime_model = EE_Registry::instance()->load_model('Datetime');
1734
+		/** @var EEM_Ticket $datetime_model */
1735
+		$ticket_model = EE_Registry::instance()->load_model('Ticket');
1736
+		$times        = $datetime_model->get_all_event_dates($event_id);
1737
+		/** @type EE_Datetime $first_datetime */
1738
+		$first_datetime = reset($times);
1739
+		// do we get related tickets?
1740
+		if (
1741
+			$first_datetime instanceof EE_Datetime
1742
+			&& $first_datetime->ID() !== 0
1743
+		) {
1744
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1745
+			$template_args['time']   = $first_datetime;
1746
+			$related_tickets         = $first_datetime->tickets(
1747
+				[
1748
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1749
+					'default_where_conditions' => 'none',
1750
+				]
1751
+			);
1752
+			if (! empty($related_tickets)) {
1753
+				$template_args['total_ticket_rows'] = count($related_tickets);
1754
+				$row                                = 0;
1755
+				foreach ($related_tickets as $ticket) {
1756
+					$existing_ticket_ids[]        = $ticket->get('TKT_ID');
1757
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1758
+					$row++;
1759
+				}
1760
+			} else {
1761
+				$template_args['total_ticket_rows'] = 1;
1762
+				/** @type EE_Ticket $ticket */
1763
+				$ticket                       = $ticket_model->create_default_object();
1764
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1765
+			}
1766
+		} else {
1767
+			$template_args['time'] = $times[0];
1768
+			/** @type EE_Ticket[] $tickets */
1769
+			$tickets                      = $ticket_model->get_all_default_tickets();
1770
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1771
+			// NOTE: we're just sending the first default row
1772
+			// (decaf can't manage default tickets so this should be sufficient);
1773
+		}
1774
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1775
+			'event_editor_event_datetimes_help_tab'
1776
+		);
1777
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1778
+		$template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1779
+		$template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1780
+		$template_args['ticket_js_structure']      = $this->_get_ticket_row(
1781
+			$ticket_model->create_default_object(),
1782
+			true
1783
+		);
1784
+		$template                                  = apply_filters(
1785
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1786
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1787
+		);
1788
+		EEH_Template::display_template($template, $template_args);
1789
+	}
1790
+
1791
+
1792
+	/**
1793
+	 * Setup an individual ticket form for the decaf event editor page
1794
+	 *
1795
+	 * @access private
1796
+	 * @param EE_Ticket $ticket   the ticket object
1797
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1798
+	 * @param int       $row
1799
+	 * @return string generated html for the ticket row.
1800
+	 * @throws EE_Error
1801
+	 * @throws ReflectionException
1802
+	 */
1803
+	private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1804
+	{
1805
+		$template_args = [
1806
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1807
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1808
+				: '',
1809
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1810
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1811
+			'TKT_name'            => $ticket->get('TKT_name'),
1812
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1813
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1814
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1815
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1816
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1817
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1818
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1819
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1820
+				? 'dashicons dashicons-post-trash clickable'
1821
+				: 'dashicons dashicons-lock',
1822
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1823
+				: ' disabled=disabled',
1824
+		];
1825
+		$price         = $ticket->ID() !== 0
1826
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1827
+			: null;
1828
+		$price         = $price instanceof EE_Price
1829
+			? $price
1830
+			: EEM_Price::instance()->create_default_object();
1831
+		$price_args    = [
1832
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1833
+			'PRC_amount'            => $price->get('PRC_amount'),
1834
+			'PRT_ID'                => $price->get('PRT_ID'),
1835
+			'PRC_ID'                => $price->get('PRC_ID'),
1836
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1837
+		];
1838
+		// make sure we have default start and end dates if skeleton
1839
+		// handle rows that should NOT be empty
1840
+		if (empty($template_args['TKT_start_date'])) {
1841
+			// if empty then the start date will be now.
1842
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1843
+		}
1844
+		if (empty($template_args['TKT_end_date'])) {
1845
+			// get the earliest datetime (if present);
1846
+			$earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1847
+				? $this->_cpt_model_obj->get_first_related(
1848
+					'Datetime',
1849
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1850
+				)
1851
+				: null;
1852
+			$template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1853
+				? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1854
+				: date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1855
+		}
1856
+		$template_args = array_merge($template_args, $price_args);
1857
+		$template      = apply_filters(
1858
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1859
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1860
+			$ticket
1861
+		);
1862
+		return EEH_Template::display_template($template, $template_args, true);
1863
+	}
1864
+
1865
+
1866
+	/**
1867
+	 * @throws EE_Error
1868
+	 * @throws ReflectionException
1869
+	 */
1870
+	public function registration_options_meta_box()
1871
+	{
1872
+		$yes_no_values             = [
1873
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1874
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1875
+		];
1876
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1877
+			[
1878
+				EEM_Registration::status_id_cancelled,
1879
+				EEM_Registration::status_id_declined,
1880
+				EEM_Registration::status_id_incomplete,
1881
+			],
1882
+			true
1883
+		);
1884
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1885
+		$template_args['_event']                          = $this->_cpt_model_obj;
1886
+		$template_args['event']                           = $this->_cpt_model_obj;
1887
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1888
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1889
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1890
+			'default_reg_status',
1891
+			$default_reg_status_values,
1892
+			$this->_cpt_model_obj->default_registration_status()
1893
+		);
1894
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
1895
+			'display_desc',
1896
+			$yes_no_values,
1897
+			$this->_cpt_model_obj->display_description()
1898
+		);
1899
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1900
+			'display_ticket_selector',
1901
+			$yes_no_values,
1902
+			$this->_cpt_model_obj->display_ticket_selector(),
1903
+			'',
1904
+			'',
1905
+			false
1906
+		);
1907
+		$template_args['additional_registration_options'] = apply_filters(
1908
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1909
+			'',
1910
+			$template_args,
1911
+			$yes_no_values,
1912
+			$default_reg_status_values
1913
+		);
1914
+		EEH_Template::display_template(
1915
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1916
+			$template_args
1917
+		);
1918
+	}
1919
+
1920
+
1921
+	/**
1922
+	 * _get_events()
1923
+	 * This method simply returns all the events (for the given _view and paging)
1924
+	 *
1925
+	 * @access public
1926
+	 * @param int  $per_page     count of items per page (20 default);
1927
+	 * @param int  $current_page what is the current page being viewed.
1928
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1929
+	 *                           If FALSE then we return an array of event objects
1930
+	 *                           that match the given _view and paging parameters.
1931
+	 * @return array|int         an array of event objects or a count of them.
1932
+	 * @throws Exception
1933
+	 */
1934
+	public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1935
+	{
1936
+		$EEM_Event   = $this->_event_model();
1937
+		$offset      = ($current_page - 1) * $per_page;
1938
+		$limit       = $count ? null : $offset . ',' . $per_page;
1939
+		$orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1940
+		$order       = $this->request->getRequestParam('order', 'DESC');
1941
+		$month_range = $this->request->getRequestParam('month_range');
1942
+		if ($month_range) {
1943
+			$pieces = explode(' ', $month_range, 3);
1944
+			// simulate the FIRST day of the month, that fixes issues for months like February
1945
+			// where PHP doesn't know what to assume for date.
1946
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1947
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1948
+			$year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
1949
+		}
1950
+		$where  = [];
1951
+		$status = $this->request->getRequestParam('status');
1952
+		// determine what post_status our condition will have for the query.
1953
+		switch ($status) {
1954
+			case 'month':
1955
+			case 'today':
1956
+			case null:
1957
+			case 'all':
1958
+				break;
1959
+			case 'draft':
1960
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1961
+				break;
1962
+			default:
1963
+				$where['status'] = $status;
1964
+		}
1965
+		// categories? The default for all categories is -1
1966
+		$category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1967
+		if ($category !== -1) {
1968
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1969
+			$where['Term_Taxonomy.term_id']  = $category;
1970
+		}
1971
+		// date where conditions
1972
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1973
+		if ($month_range) {
1974
+			$DateTime = new DateTime(
1975
+				$year_r . '-' . $month_r . '-01 00:00:00',
1976
+				new DateTimeZone('UTC')
1977
+			);
1978
+			$start    = $DateTime->getTimestamp();
1979
+			// set the datetime to be the end of the month
1980
+			$DateTime->setDate(
1981
+				$year_r,
1982
+				$month_r,
1983
+				$DateTime->format('t')
1984
+			)->setTime(23, 59, 59);
1985
+			$end                             = $DateTime->getTimestamp();
1986
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1987
+		} elseif ($status === 'today') {
1988
+			$DateTime                        =
1989
+				new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1990
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1991
+			$end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1992
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1993
+		} elseif ($status === 'month') {
1994
+			$now                             = date('Y-m-01');
1995
+			$DateTime                        =
1996
+				new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1997
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1998
+			$end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1999
+														->setTime(23, 59, 59)
2000
+														->format(implode(' ', $start_formats));
2001
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
2002
+		}
2003
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2004
+			$where['EVT_wp_user'] = get_current_user_id();
2005
+		} else {
2006
+			if (! isset($where['status'])) {
2007
+				if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
2008
+					$where['OR'] = [
2009
+						'status*restrict_private' => ['!=', 'private'],
2010
+						'AND'                     => [
2011
+							'status*inclusive' => ['=', 'private'],
2012
+							'EVT_wp_user'      => get_current_user_id(),
2013
+						],
2014
+					];
2015
+				}
2016
+			}
2017
+		}
2018
+		$wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2019
+		if (
2020
+			$wp_user
2021
+			&& $wp_user !== get_current_user_id()
2022
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2023
+		) {
2024
+			$where['EVT_wp_user'] = $wp_user;
2025
+		}
2026
+		// search query handling
2027
+		$search_term = $this->request->getRequestParam('s');
2028
+		if ($search_term) {
2029
+			$search_term = '%' . $search_term . '%';
2030
+			$where['OR'] = [
2031
+				'EVT_name'       => ['LIKE', $search_term],
2032
+				'EVT_desc'       => ['LIKE', $search_term],
2033
+				'EVT_short_desc' => ['LIKE', $search_term],
2034
+			];
2035
+		}
2036
+		// filter events by venue.
2037
+		$venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2038
+		if ($venue) {
2039
+			$where['Venue.VNU_ID'] = $venue;
2040
+		}
2041
+		$request_params = $this->request->requestParams();
2042
+		$where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2043
+		$query_params   = apply_filters(
2044
+			'FHEE__Events_Admin_Page__get_events__query_params',
2045
+			[
2046
+				$where,
2047
+				'limit'    => $limit,
2048
+				'order_by' => $orderby,
2049
+				'order'    => $order,
2050
+				'group_by' => 'EVT_ID',
2051
+			],
2052
+			$request_params
2053
+		);
2054
+
2055
+		// let's first check if we have special requests coming in.
2056
+		$active_status = $this->request->getRequestParam('active_status');
2057
+		if ($active_status) {
2058
+			switch ($active_status) {
2059
+				case 'upcoming':
2060
+					return $EEM_Event->get_upcoming_events($query_params, $count);
2061
+				case 'expired':
2062
+					return $EEM_Event->get_expired_events($query_params, $count);
2063
+				case 'active':
2064
+					return $EEM_Event->get_active_events($query_params, $count);
2065
+				case 'inactive':
2066
+					return $EEM_Event->get_inactive_events($query_params, $count);
2067
+			}
2068
+		}
2069
+
2070
+		return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2071
+	}
2072
+
2073
+
2074
+	/**
2075
+	 * handling for WordPress CPT actions (trash, restore, delete)
2076
+	 *
2077
+	 * @param string $post_id
2078
+	 * @throws EE_Error
2079
+	 * @throws ReflectionException
2080
+	 */
2081
+	public function trash_cpt_item($post_id)
2082
+	{
2083
+		$this->request->setRequestParam('EVT_ID', $post_id);
2084
+		$this->_trash_or_restore_event('trash', false);
2085
+	}
2086
+
2087
+
2088
+	/**
2089
+	 * @param string $post_id
2090
+	 * @throws EE_Error
2091
+	 * @throws ReflectionException
2092
+	 */
2093
+	public function restore_cpt_item($post_id)
2094
+	{
2095
+		$this->request->setRequestParam('EVT_ID', $post_id);
2096
+		$this->_trash_or_restore_event('draft', false);
2097
+	}
2098
+
2099
+
2100
+	/**
2101
+	 * @param string $post_id
2102
+	 * @throws EE_Error
2103
+	 * @throws EE_Error
2104
+	 */
2105
+	public function delete_cpt_item($post_id)
2106
+	{
2107
+		throw new EE_Error(
2108
+			esc_html__(
2109
+				'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2110
+				'event_espresso'
2111
+			)
2112
+		);
2113
+		// $this->request->setRequestParam('EVT_ID', $post_id);
2114
+		// $this->_delete_event();
2115
+	}
2116
+
2117
+
2118
+	/**
2119
+	 * _trash_or_restore_event
2120
+	 *
2121
+	 * @access protected
2122
+	 * @param string $event_status
2123
+	 * @param bool   $redirect_after
2124
+	 * @throws EE_Error
2125
+	 * @throws EE_Error
2126
+	 * @throws ReflectionException
2127
+	 */
2128
+	protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2129
+	{
2130
+		// determine the event id and set to array.
2131
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
2132
+		// loop thru events
2133
+		if ($EVT_ID) {
2134
+			// clean status
2135
+			$event_status = sanitize_key($event_status);
2136
+			// grab status
2137
+			if (! empty($event_status)) {
2138
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2139
+			} else {
2140
+				$success = false;
2141
+				$msg     = esc_html__(
2142
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2143
+					'event_espresso'
2144
+				);
2145
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2146
+			}
2147
+		} else {
2148
+			$success = false;
2149
+			$msg     = esc_html__(
2150
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2151
+				'event_espresso'
2152
+			);
2153
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2154
+		}
2155
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2156
+		if ($redirect_after) {
2157
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2158
+		}
2159
+	}
2160
+
2161
+
2162
+	/**
2163
+	 * _trash_or_restore_events
2164
+	 *
2165
+	 * @access protected
2166
+	 * @param string $event_status
2167
+	 * @return void
2168
+	 * @throws EE_Error
2169
+	 * @throws EE_Error
2170
+	 * @throws ReflectionException
2171
+	 */
2172
+	protected function _trash_or_restore_events(string $event_status = 'trash')
2173
+	{
2174
+		// clean status
2175
+		$event_status = sanitize_key($event_status);
2176
+		// grab status
2177
+		if (! empty($event_status)) {
2178
+			$success = true;
2179
+			// determine the event id and set to array.
2180
+			$EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2181
+			// loop thru events
2182
+			foreach ($EVT_IDs as $EVT_ID) {
2183
+				if ($EVT_ID = absint($EVT_ID)) {
2184
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2185
+					$success = $results !== false ? $success : false;
2186
+				} else {
2187
+					$msg = sprintf(
2188
+						esc_html__(
2189
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2190
+							'event_espresso'
2191
+						),
2192
+						$EVT_ID
2193
+					);
2194
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2195
+					$success = false;
2196
+				}
2197
+			}
2198
+		} else {
2199
+			$success = false;
2200
+			$msg     = esc_html__(
2201
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2202
+				'event_espresso'
2203
+			);
2204
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2205
+		}
2206
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2207
+		$success = $success ? 2 : false;
2208
+		$action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2209
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2210
+	}
2211
+
2212
+
2213
+	/**
2214
+	 * @param int    $EVT_ID
2215
+	 * @param string $event_status
2216
+	 * @return bool
2217
+	 * @throws EE_Error
2218
+	 * @throws ReflectionException
2219
+	 */
2220
+	private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2221
+	{
2222
+		// grab event id
2223
+		if (! $EVT_ID) {
2224
+			$msg = esc_html__(
2225
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2226
+				'event_espresso'
2227
+			);
2228
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2229
+			return false;
2230
+		}
2231
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2232
+		// clean status
2233
+		$event_status = sanitize_key($event_status);
2234
+		// grab status
2235
+		if (empty($event_status)) {
2236
+			$msg = esc_html__(
2237
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2238
+				'event_espresso'
2239
+			);
2240
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2241
+			return false;
2242
+		}
2243
+		// was event trashed or restored ?
2244
+		switch ($event_status) {
2245
+			case 'draft':
2246
+				$action = 'restored from the trash';
2247
+				$hook   = 'AHEE_event_restored_from_trash';
2248
+				break;
2249
+			case 'trash':
2250
+				$action = 'moved to the trash';
2251
+				$hook   = 'AHEE_event_moved_to_trash';
2252
+				break;
2253
+			default:
2254
+				$action = 'updated';
2255
+				$hook   = false;
2256
+		}
2257
+		// use class to change status
2258
+		$this->_cpt_model_obj->set_status($event_status);
2259
+		$success = $this->_cpt_model_obj->save();
2260
+		if (! $success) {
2261
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2262
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2263
+			return false;
2264
+		}
2265
+		if ($hook) {
2266
+			do_action($hook);
2267
+			// fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2268
+			// because events side step that and it otherwise won't get called
2269
+			do_action(
2270
+				'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2271
+				$this->_cpt_model_obj,
2272
+				$hook === 'AHEE_event_moved_to_trash',
2273
+				$success
2274
+			);
2275
+		}
2276
+		return true;
2277
+	}
2278
+
2279
+
2280
+	/**
2281
+	 * @param array $event_ids
2282
+	 * @return array
2283
+	 * @since   4.10.23.p
2284
+	 */
2285
+	private function cleanEventIds(array $event_ids): array
2286
+	{
2287
+		return array_map('absint', $event_ids);
2288
+	}
2289
+
2290
+
2291
+	/**
2292
+	 * @return array
2293
+	 * @since   4.10.23.p
2294
+	 */
2295
+	private function getEventIdsFromRequest(): array
2296
+	{
2297
+		if ($this->request->requestParamIsSet('EVT_IDs')) {
2298
+			return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2299
+		} else {
2300
+			return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2301
+		}
2302
+	}
2303
+
2304
+
2305
+	/**
2306
+	 * @param bool $preview_delete
2307
+	 * @throws EE_Error
2308
+	 * @throws ReflectionException
2309
+	 */
2310
+	protected function _delete_event(bool $preview_delete = true)
2311
+	{
2312
+		$this->_delete_events($preview_delete);
2313
+	}
2314
+
2315
+
2316
+	/**
2317
+	 * Gets the tree traversal batch persister.
2318
+	 *
2319
+	 * @return NodeGroupDao
2320
+	 * @throws InvalidArgumentException
2321
+	 * @throws InvalidDataTypeException
2322
+	 * @throws InvalidInterfaceException
2323
+	 * @since 4.10.12.p
2324
+	 */
2325
+	protected function getModelObjNodeGroupPersister(): NodeGroupDao
2326
+	{
2327
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2328
+			$this->model_obj_node_group_persister =
2329
+				$this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2330
+		}
2331
+		return $this->model_obj_node_group_persister;
2332
+	}
2333
+
2334
+
2335
+	/**
2336
+	 * @param bool $preview_delete
2337
+	 * @return void
2338
+	 * @throws EE_Error
2339
+	 * @throws ReflectionException
2340
+	 */
2341
+	protected function _delete_events(bool $preview_delete = true)
2342
+	{
2343
+		$event_ids = $this->getEventIdsFromRequest();
2344
+		if ($preview_delete) {
2345
+			$this->generateDeletionPreview($event_ids);
2346
+		} else {
2347
+			foreach ($event_ids as $event_id) {
2348
+				$event = EEM_Event::instance()->get_one_by_ID($event_id);
2349
+				if ($event instanceof EE_Event) {
2350
+					$event->delete_permanently();
2351
+				}
2352
+			}
2353
+		}
2354
+	}
2355
+
2356
+
2357
+	/**
2358
+	 * @param array $event_ids
2359
+	 */
2360
+	protected function generateDeletionPreview(array $event_ids)
2361
+	{
2362
+		$event_ids = $this->cleanEventIds($event_ids);
2363
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2364
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2365
+		$return_url        = EE_Admin_Page::add_query_args_and_nonce(
2366
+			[
2367
+				'action'            => 'preview_deletion',
2368
+				'deletion_job_code' => $deletion_job_code,
2369
+			],
2370
+			$this->_admin_base_url
2371
+		);
2372
+		EEH_URL::safeRedirectAndExit(
2373
+			EE_Admin_Page::add_query_args_and_nonce(
2374
+				[
2375
+					'page'              => EED_Batch::PAGE_SLUG,
2376
+					'batch'             => EED_Batch::batch_job,
2377
+					'EVT_IDs'           => $event_ids,
2378
+					'deletion_job_code' => $deletion_job_code,
2379
+					'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2380
+					'return_url'        => urlencode($return_url),
2381
+				],
2382
+				admin_url()
2383
+			)
2384
+		);
2385
+	}
2386
+
2387
+
2388
+	/**
2389
+	 * Checks for a POST submission
2390
+	 *
2391
+	 * @since 4.10.12.p
2392
+	 */
2393
+	protected function confirmDeletion()
2394
+	{
2395
+		$deletion_redirect_logic = $this->getLoader()->getShared(
2396
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2397
+		);
2398
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2399
+	}
2400
+
2401
+
2402
+	/**
2403
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2404
+	 *
2405
+	 * @throws EE_Error
2406
+	 * @since 4.10.12.p
2407
+	 */
2408
+	protected function previewDeletion()
2409
+	{
2410
+		$preview_deletion_logic = $this->getLoader()->getShared(
2411
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2412
+		);
2413
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2414
+		$this->display_admin_page_with_no_sidebar();
2415
+	}
2416
+
2417
+
2418
+	/**
2419
+	 * get total number of events
2420
+	 *
2421
+	 * @access public
2422
+	 * @return int
2423
+	 * @throws EE_Error
2424
+	 * @throws EE_Error
2425
+	 * @throws ReflectionException
2426
+	 */
2427
+	public function total_events(): int
2428
+	{
2429
+		return EEM_Event::instance()->count(
2430
+			['caps' => 'read_admin'],
2431
+			'EVT_ID',
2432
+			true
2433
+		);
2434
+	}
2435
+
2436
+
2437
+	/**
2438
+	 * get total number of draft events
2439
+	 *
2440
+	 * @access public
2441
+	 * @return int
2442
+	 * @throws EE_Error
2443
+	 * @throws EE_Error
2444
+	 * @throws ReflectionException
2445
+	 */
2446
+	public function total_events_draft(): int
2447
+	{
2448
+		return EEM_Event::instance()->count(
2449
+			[
2450
+				['status' => ['IN', ['draft', 'auto-draft']]],
2451
+				'caps' => 'read_admin',
2452
+			],
2453
+			'EVT_ID',
2454
+			true
2455
+		);
2456
+	}
2457
+
2458
+
2459
+	/**
2460
+	 * get total number of trashed events
2461
+	 *
2462
+	 * @access public
2463
+	 * @return int
2464
+	 * @throws EE_Error
2465
+	 * @throws EE_Error
2466
+	 * @throws ReflectionException
2467
+	 */
2468
+	public function total_trashed_events(): int
2469
+	{
2470
+		return EEM_Event::instance()->count(
2471
+			[
2472
+				['status' => 'trash'],
2473
+				'caps' => 'read_admin',
2474
+			],
2475
+			'EVT_ID',
2476
+			true
2477
+		);
2478
+	}
2479
+
2480
+
2481
+	/**
2482
+	 *    _default_event_settings
2483
+	 *    This generates the Default Settings Tab
2484
+	 *
2485
+	 * @return void
2486
+	 * @throws DomainException
2487
+	 * @throws EE_Error
2488
+	 * @throws InvalidArgumentException
2489
+	 * @throws InvalidDataTypeException
2490
+	 * @throws InvalidInterfaceException
2491
+	 */
2492
+	protected function _default_event_settings()
2493
+	{
2494
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2495
+		$this->_set_publish_post_box_vars();
2496
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
2497
+			$this->_default_event_settings_form()->get_html(),
2498
+			'',
2499
+			'padding'
2500
+		);
2501
+		$this->display_admin_page_with_sidebar();
2502
+	}
2503
+
2504
+
2505
+	/**
2506
+	 * Return the form for event settings.
2507
+	 *
2508
+	 * @return EE_Form_Section_Proper
2509
+	 * @throws EE_Error
2510
+	 */
2511
+	protected function _default_event_settings_form(): EE_Form_Section_Proper
2512
+	{
2513
+		$registration_config              = EE_Registry::instance()->CFG->registration;
2514
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2515
+		// exclude
2516
+			[
2517
+				EEM_Registration::status_id_cancelled,
2518
+				EEM_Registration::status_id_declined,
2519
+				EEM_Registration::status_id_incomplete,
2520
+				EEM_Registration::status_id_wait_list,
2521
+			],
2522
+			true
2523
+		);
2524
+		// setup Advanced Editor ???
2525
+		if (
2526
+			$this->raw_req_action === 'default_event_settings'
2527
+			|| $this->raw_req_action === 'update_default_event_settings'
2528
+		) {
2529
+			$this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2530
+		}
2531
+		return new EE_Form_Section_Proper(
2532
+			[
2533
+				'name'            => 'update_default_event_settings',
2534
+				'html_id'         => 'update_default_event_settings',
2535
+				'html_class'      => 'form-table',
2536
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2537
+				'subsections'     => apply_filters(
2538
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2539
+					[
2540
+						'defaults_section_header' => new EE_Form_Section_HTML(
2541
+							EEH_HTML::h2(
2542
+								esc_html__('Default Settings', 'event_espresso'),
2543
+								'',
2544
+								'ee-admin-settings-hdr'
2545
+							)
2546
+						),
2547
+						'default_reg_status'      => new EE_Select_Input(
2548
+							$registration_stati_for_selection,
2549
+							[
2550
+								'default'         => isset($registration_config->default_STS_ID)
2551
+													 && array_key_exists(
2552
+														 $registration_config->default_STS_ID,
2553
+														 $registration_stati_for_selection
2554
+													 )
2555
+									? sanitize_text_field($registration_config->default_STS_ID)
2556
+									: EEM_Registration::status_id_pending_payment,
2557
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2558
+													 . EEH_Template::get_help_tab_link(
2559
+														 'default_settings_status_help_tab'
2560
+													 ),
2561
+								'html_help_text'  => esc_html__(
2562
+									'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.',
2563
+									'event_espresso'
2564
+								),
2565
+							]
2566
+						),
2567
+						'default_max_tickets'     => new EE_Integer_Input(
2568
+							[
2569
+								'default'         => $registration_config->default_maximum_number_of_tickets
2570
+													 ?? EEM_Event::get_default_additional_limit(),
2571
+								'html_label_text' => esc_html__(
2572
+									'Default Maximum Tickets Allowed Per Order:',
2573
+									'event_espresso'
2574
+								)
2575
+													 . EEH_Template::get_help_tab_link(
2576
+														 'default_maximum_tickets_help_tab"'
2577
+													 ),
2578
+								'html_help_text'  => esc_html__(
2579
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2580
+									'event_espresso'
2581
+								),
2582
+							]
2583
+						),
2584
+					]
2585
+				),
2586
+			]
2587
+		);
2588
+	}
2589
+
2590
+
2591
+	/**
2592
+	 * @return void
2593
+	 * @throws EE_Error
2594
+	 * @throws InvalidArgumentException
2595
+	 * @throws InvalidDataTypeException
2596
+	 * @throws InvalidInterfaceException
2597
+	 */
2598
+	protected function _update_default_event_settings()
2599
+	{
2600
+		$form = $this->_default_event_settings_form();
2601
+		if ($form->was_submitted()) {
2602
+			$form->receive_form_submission();
2603
+			if ($form->is_valid()) {
2604
+				$registration_config = EE_Registry::instance()->CFG->registration;
2605
+				$valid_data          = $form->valid_data();
2606
+				if (isset($valid_data['default_reg_status'])) {
2607
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2608
+				}
2609
+				if (isset($valid_data['default_max_tickets'])) {
2610
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2611
+				}
2612
+				do_action(
2613
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2614
+					$valid_data,
2615
+					EE_Registry::instance()->CFG,
2616
+					$this
2617
+				);
2618
+				// update because data was valid!
2619
+				EE_Registry::instance()->CFG->update_espresso_config();
2620
+				EE_Error::overwrite_success();
2621
+				EE_Error::add_success(
2622
+					esc_html__('Default Event Settings were updated', 'event_espresso')
2623
+				);
2624
+			}
2625
+		}
2626
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2627
+	}
2628
+
2629
+
2630
+	/*************        Templates        *************
23 2631
      *
24
-     * @var EE_Event $_event
25
-     */
26
-    protected $_event;
27
-
28
-
29
-    /**
30
-     * This will hold the category object for category_details screen.
31
-     *
32
-     * @var stdClass $_category
33
-     */
34
-    protected $_category;
35
-
36
-
37
-    /**
38
-     * This will hold the event model instance
39
-     *
40
-     * @var EEM_Event $_event_model
41
-     */
42
-    protected $_event_model;
43
-
44
-
45
-    /**
46
-     * @var EE_Event
47
-     */
48
-    protected $_cpt_model_obj = null;
49
-
50
-
51
-    /**
52
-     * @var NodeGroupDao
53
-     */
54
-    protected $model_obj_node_group_persister;
55
-
56
-    /**
57
-     * @var AdvancedEditorAdminFormSection
58
-     */
59
-    protected $advanced_editor_admin_form;
60
-
61
-
62
-    /**
63
-     * Initialize page props for this admin page group.
64
-     */
65
-    protected function _init_page_props()
66
-    {
67
-        $this->page_slug        = EVENTS_PG_SLUG;
68
-        $this->page_label       = EVENTS_LABEL;
69
-        $this->_admin_base_url  = EVENTS_ADMIN_URL;
70
-        $this->_admin_base_path = EVENTS_ADMIN;
71
-        $this->_cpt_model_names = [
72
-            'create_new' => 'EEM_Event',
73
-            'edit'       => 'EEM_Event',
74
-        ];
75
-        $this->_cpt_edit_routes = [
76
-            'espresso_events' => 'edit',
77
-        ];
78
-        add_action(
79
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
80
-            [$this, 'verify_event_edit'],
81
-            10,
82
-            2
83
-        );
84
-    }
85
-
86
-
87
-    /**
88
-     * Sets the ajax hooks used for this admin page group.
89
-     */
90
-    protected function _ajax_hooks()
91
-    {
92
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
93
-    }
94
-
95
-
96
-    /**
97
-     * Sets the page properties for this admin page group.
98
-     */
99
-    protected function _define_page_props()
100
-    {
101
-        $event_id = $this->request->getRequestParam('post', 0, DataType::INT);
102
-        if ($event_id) {
103
-            $event_post = get_post($event_id);
104
-        }
105
-
106
-        $this->_admin_page_title = EVENTS_LABEL;
107
-        $this->_labels           = [
108
-            'buttons'      => [
109
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
110
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
111
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
112
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
113
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
114
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
115
-            ],
116
-            'editor_title' => [
117
-                'espresso_events' => isset($event_post) && $event_post instanceof WP_Post
118
-                    ? $event_post->post_title
119
-                    : esc_html__('Edit Event', 'event_espresso'),
120
-            ],
121
-            'publishbox'   => [
122
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
123
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
124
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
125
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
126
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
127
-            ],
128
-        ];
129
-    }
130
-
131
-
132
-    /**
133
-     * Sets the page routes property for this admin page group.
134
-     */
135
-    protected function _set_page_routes()
136
-    {
137
-        // load formatter helper
138
-        // load field generator helper
139
-        // is there a evt_id in the request?
140
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
141
-        $EVT_ID = $this->request->getRequestParam('post', $EVT_ID, DataType::INT);
142
-
143
-        $this->_page_routes = [
144
-            'default'                       => [
145
-                'func'       => [$this, '_events_overview_list_table'],
146
-                'capability' => 'ee_read_events',
147
-            ],
148
-            'create_new'                    => [
149
-                'func'       => [$this, '_create_new_cpt_item'],
150
-                'capability' => 'ee_edit_events',
151
-            ],
152
-            'edit'                          => [
153
-                'func'       => [$this, '_edit_cpt_item'],
154
-                'capability' => 'ee_edit_event',
155
-                'obj_id'     => $EVT_ID,
156
-            ],
157
-            'copy_event'                    => [
158
-                'func'       => [$this, '_copy_events'],
159
-                'capability' => 'ee_edit_event',
160
-                'obj_id'     => $EVT_ID,
161
-                'noheader'   => true,
162
-            ],
163
-            'trash_event'                   => [
164
-                'func'       => [$this, '_trash_or_restore_event'],
165
-                'args'       => ['event_status' => 'trash'],
166
-                'capability' => 'ee_delete_event',
167
-                'obj_id'     => $EVT_ID,
168
-                'noheader'   => true,
169
-            ],
170
-            'trash_events'                  => [
171
-                'func'       => [$this, '_trash_or_restore_events'],
172
-                'args'       => ['event_status' => 'trash'],
173
-                'capability' => 'ee_delete_events',
174
-                'noheader'   => true,
175
-            ],
176
-            'restore_event'                 => [
177
-                'func'       => [$this, '_trash_or_restore_event'],
178
-                'args'       => ['event_status' => 'draft'],
179
-                'capability' => 'ee_delete_event',
180
-                'obj_id'     => $EVT_ID,
181
-                'noheader'   => true,
182
-            ],
183
-            'restore_events'                => [
184
-                'func'       => [$this, '_trash_or_restore_events'],
185
-                'args'       => ['event_status' => 'draft'],
186
-                'capability' => 'ee_delete_events',
187
-                'noheader'   => true,
188
-            ],
189
-            'delete_event'                  => [
190
-                'func'       => [$this, '_delete_event'],
191
-                'capability' => 'ee_delete_event',
192
-                'obj_id'     => $EVT_ID,
193
-                'noheader'   => true,
194
-            ],
195
-            'delete_events'                 => [
196
-                'func'       => [$this, '_delete_events'],
197
-                'capability' => 'ee_delete_events',
198
-                'noheader'   => true,
199
-            ],
200
-            'view_report'                   => [
201
-                'func'       => [$this, '_view_report'],
202
-                'capability' => 'ee_edit_events',
203
-            ],
204
-            'default_event_settings'        => [
205
-                'func'       => [$this, '_default_event_settings'],
206
-                'capability' => 'manage_options',
207
-            ],
208
-            'update_default_event_settings' => [
209
-                'func'       => [$this, '_update_default_event_settings'],
210
-                'capability' => 'manage_options',
211
-                'noheader'   => true,
212
-            ],
213
-            'template_settings'             => [
214
-                'func'       => [$this, '_template_settings'],
215
-                'capability' => 'manage_options',
216
-            ],
217
-            // event category tab related
218
-            'add_category'                  => [
219
-                'func'       => [$this, '_category_details'],
220
-                'capability' => 'ee_edit_event_category',
221
-                'args'       => ['view' => 'add'],
222
-            ],
223
-            'edit_category'                 => [
224
-                'func'       => [$this, '_category_details'],
225
-                'capability' => 'ee_edit_event_category',
226
-                'args'       => ['view' => 'edit'],
227
-            ],
228
-            'delete_categories'             => [
229
-                'func'       => [$this, '_delete_categories'],
230
-                'capability' => 'ee_delete_event_category',
231
-                'noheader'   => true,
232
-            ],
233
-            'delete_category'               => [
234
-                'func'       => [$this, '_delete_categories'],
235
-                'capability' => 'ee_delete_event_category',
236
-                'noheader'   => true,
237
-            ],
238
-            'insert_category'               => [
239
-                'func'       => [$this, '_insert_or_update_category'],
240
-                'args'       => ['new_category' => true],
241
-                'capability' => 'ee_edit_event_category',
242
-                'noheader'   => true,
243
-            ],
244
-            'update_category'               => [
245
-                'func'       => [$this, '_insert_or_update_category'],
246
-                'args'       => ['new_category' => false],
247
-                'capability' => 'ee_edit_event_category',
248
-                'noheader'   => true,
249
-            ],
250
-            'category_list'                 => [
251
-                'func'       => [$this, '_category_list_table'],
252
-                'capability' => 'ee_manage_event_categories',
253
-            ],
254
-            'preview_deletion'              => [
255
-                'func'       => [$this, 'previewDeletion'],
256
-                'capability' => 'ee_delete_events',
257
-            ],
258
-            'confirm_deletion'              => [
259
-                'func'       => [$this, 'confirmDeletion'],
260
-                'capability' => 'ee_delete_events',
261
-                'noheader'   => true,
262
-            ],
263
-        ];
264
-    }
265
-
266
-
267
-    /**
268
-     * Set the _page_config property for this admin page group.
269
-     */
270
-    protected function _set_page_config()
271
-    {
272
-        $post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
273
-        $EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
274
-        $this->_page_config = [
275
-            'default'                => [
276
-                'nav'           => [
277
-                    'label' => esc_html__('Overview', 'event_espresso'),
278
-                    'icon'  => 'dashicons-list-view',
279
-                    'order' => 10,
280
-                ],
281
-                'list_table'    => 'Events_Admin_List_Table',
282
-                'help_tabs'     => [
283
-                    'events_overview_help_tab'                       => [
284
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
285
-                        'filename' => 'events_overview',
286
-                    ],
287
-                    'events_overview_table_column_headings_help_tab' => [
288
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
289
-                        'filename' => 'events_overview_table_column_headings',
290
-                    ],
291
-                    'events_overview_filters_help_tab'               => [
292
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
293
-                        'filename' => 'events_overview_filters',
294
-                    ],
295
-                    'events_overview_view_help_tab'                  => [
296
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
297
-                        'filename' => 'events_overview_views',
298
-                    ],
299
-                    'events_overview_other_help_tab'                 => [
300
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
301
-                        'filename' => 'events_overview_other',
302
-                    ],
303
-                ],
304
-                'require_nonce' => false,
305
-            ],
306
-            'create_new'             => [
307
-                'nav'           => [
308
-                    'label'      => esc_html__('Add New Event', 'event_espresso'),
309
-                    'icon'       => 'dashicons-plus-alt',
310
-                    'order'      => 15,
311
-                    'persistent' => false,
312
-                ],
313
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
314
-                'help_tabs'     => [
315
-                    'event_editor_help_tab'                            => [
316
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
317
-                        'filename' => 'event_editor',
318
-                    ],
319
-                    'event_editor_title_richtexteditor_help_tab'       => [
320
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
321
-                        'filename' => 'event_editor_title_richtexteditor',
322
-                    ],
323
-                    'event_editor_venue_details_help_tab'              => [
324
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
325
-                        'filename' => 'event_editor_venue_details',
326
-                    ],
327
-                    'event_editor_event_datetimes_help_tab'            => [
328
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
329
-                        'filename' => 'event_editor_event_datetimes',
330
-                    ],
331
-                    'event_editor_event_tickets_help_tab'              => [
332
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
333
-                        'filename' => 'event_editor_event_tickets',
334
-                    ],
335
-                    'event_editor_event_registration_options_help_tab' => [
336
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
337
-                        'filename' => 'event_editor_event_registration_options',
338
-                    ],
339
-                    'event_editor_tags_categories_help_tab'            => [
340
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
341
-                        'filename' => 'event_editor_tags_categories',
342
-                    ],
343
-                    'event_editor_questions_registrants_help_tab'      => [
344
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
345
-                        'filename' => 'event_editor_questions_registrants',
346
-                    ],
347
-                    'event_editor_save_new_event_help_tab'             => [
348
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
349
-                        'filename' => 'event_editor_save_new_event',
350
-                    ],
351
-                    'event_editor_other_help_tab'                      => [
352
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
353
-                        'filename' => 'event_editor_other',
354
-                    ],
355
-                ],
356
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
357
-                'require_nonce' => false,
358
-            ],
359
-            'edit'                   => [
360
-                'nav'           => [
361
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
362
-                    'icon'       => 'dashicons-edit',
363
-                    'order'      => 15,
364
-                    'persistent' => false,
365
-                    'url'        => $post_id
366
-                        ? EE_Admin_Page::add_query_args_and_nonce(
367
-                            ['post' => $post_id, 'action' => 'edit'],
368
-                            $this->_current_page_view_url
369
-                        )
370
-                        : $this->_admin_base_url,
371
-                ],
372
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
373
-                'help_tabs'     => [
374
-                    'event_editor_help_tab'                            => [
375
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
376
-                        'filename' => 'event_editor',
377
-                    ],
378
-                    'event_editor_title_richtexteditor_help_tab'       => [
379
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
380
-                        'filename' => 'event_editor_title_richtexteditor',
381
-                    ],
382
-                    'event_editor_venue_details_help_tab'              => [
383
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
384
-                        'filename' => 'event_editor_venue_details',
385
-                    ],
386
-                    'event_editor_event_datetimes_help_tab'            => [
387
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
388
-                        'filename' => 'event_editor_event_datetimes',
389
-                    ],
390
-                    'event_editor_event_tickets_help_tab'              => [
391
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
392
-                        'filename' => 'event_editor_event_tickets',
393
-                    ],
394
-                    'event_editor_event_registration_options_help_tab' => [
395
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
396
-                        'filename' => 'event_editor_event_registration_options',
397
-                    ],
398
-                    'event_editor_tags_categories_help_tab'            => [
399
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
400
-                        'filename' => 'event_editor_tags_categories',
401
-                    ],
402
-                    'event_editor_questions_registrants_help_tab'      => [
403
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
404
-                        'filename' => 'event_editor_questions_registrants',
405
-                    ],
406
-                    'event_editor_save_new_event_help_tab'             => [
407
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
408
-                        'filename' => 'event_editor_save_new_event',
409
-                    ],
410
-                    'event_editor_other_help_tab'                      => [
411
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
412
-                        'filename' => 'event_editor_other',
413
-                    ],
414
-                ],
415
-                'require_nonce' => false,
416
-            ],
417
-            'default_event_settings' => [
418
-                'nav'           => [
419
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
420
-                    'icon'  => 'dashicons-admin-generic',
421
-                    'order' => 40,
422
-                ],
423
-                'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
424
-                'labels'        => [
425
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
426
-                ],
427
-                'help_tabs'     => [
428
-                    'default_settings_help_tab'        => [
429
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
430
-                        'filename' => 'events_default_settings',
431
-                    ],
432
-                    'default_settings_status_help_tab' => [
433
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
434
-                        'filename' => 'events_default_settings_status',
435
-                    ],
436
-                    'default_maximum_tickets_help_tab' => [
437
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
438
-                        'filename' => 'events_default_settings_max_tickets',
439
-                    ],
440
-                ],
441
-                'require_nonce' => false,
442
-            ],
443
-            // template settings
444
-            'template_settings'      => [
445
-                'nav'           => [
446
-                    'label' => esc_html__('Templates', 'event_espresso'),
447
-                    'icon'  => 'dashicons-layout',
448
-                    'order' => 30,
449
-                ],
450
-                'metaboxes'     => $this->_default_espresso_metaboxes,
451
-                'help_tabs'     => [
452
-                    'general_settings_templates_help_tab' => [
453
-                        'title'    => esc_html__('Templates', 'event_espresso'),
454
-                        'filename' => 'general_settings_templates',
455
-                    ],
456
-                ],
457
-                'require_nonce' => false,
458
-            ],
459
-            // event category stuff
460
-            'add_category'           => [
461
-                'nav'           => [
462
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
463
-                    'icon'       => 'dashicons-plus-alt',
464
-                    'order'      => 25,
465
-                    'persistent' => false,
466
-                ],
467
-                'help_tabs'     => [
468
-                    'add_category_help_tab' => [
469
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
470
-                        'filename' => 'events_add_category',
471
-                    ],
472
-                ],
473
-                'metaboxes'     => ['_publish_post_box'],
474
-                'require_nonce' => false,
475
-            ],
476
-            'edit_category'          => [
477
-                'nav'           => [
478
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
479
-                    'icon'       => 'dashicons-edit',
480
-                    'order'      => 25,
481
-                    'persistent' => false,
482
-                    'url'        => $EVT_CAT_ID
483
-                        ? add_query_arg(
484
-                            ['EVT_CAT_ID' => $EVT_CAT_ID],
485
-                            $this->_current_page_view_url
486
-                        )
487
-                        : $this->_admin_base_url,
488
-                ],
489
-                'help_tabs'     => [
490
-                    'edit_category_help_tab' => [
491
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
492
-                        'filename' => 'events_edit_category',
493
-                    ],
494
-                ],
495
-                'metaboxes'     => ['_publish_post_box'],
496
-                'require_nonce' => false,
497
-            ],
498
-            'category_list'          => [
499
-                'nav'           => [
500
-                    'label' => esc_html__('Categories', 'event_espresso'),
501
-                    'icon'  => 'dashicons-networking',
502
-                    'order' => 20,
503
-                ],
504
-                'list_table'    => 'Event_Categories_Admin_List_Table',
505
-                'help_tabs'     => [
506
-                    'events_categories_help_tab'                       => [
507
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
508
-                        'filename' => 'events_categories',
509
-                    ],
510
-                    'events_categories_table_column_headings_help_tab' => [
511
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
512
-                        'filename' => 'events_categories_table_column_headings',
513
-                    ],
514
-                    'events_categories_view_help_tab'                  => [
515
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
516
-                        'filename' => 'events_categories_views',
517
-                    ],
518
-                    'events_categories_other_help_tab'                 => [
519
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
520
-                        'filename' => 'events_categories_other',
521
-                    ],
522
-                ],
523
-                'metaboxes'     => $this->_default_espresso_metaboxes,
524
-                'require_nonce' => false,
525
-            ],
526
-            'preview_deletion'       => [
527
-                'nav'           => [
528
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
529
-                    'icon'       => 'dashicons-remove',
530
-                    'order'      => 15,
531
-                    'persistent' => false,
532
-                    'url'        => '',
533
-                ],
534
-                'require_nonce' => false,
535
-            ],
536
-        ];
537
-    }
538
-
539
-
540
-    /**
541
-     * Used to register any global screen options if necessary for every route in this admin page group.
542
-     */
543
-    protected function _add_screen_options()
544
-    {
545
-    }
546
-
547
-
548
-    /**
549
-     * Implementing the screen options for the 'default' route.
550
-     *
551
-     * @throws InvalidArgumentException
552
-     * @throws InvalidDataTypeException
553
-     * @throws InvalidInterfaceException
554
-     */
555
-    protected function _add_screen_options_default()
556
-    {
557
-        $this->_per_page_screen_option();
558
-    }
559
-
560
-
561
-    /**
562
-     * Implementing screen options for the category list route.
563
-     *
564
-     * @throws InvalidArgumentException
565
-     * @throws InvalidDataTypeException
566
-     * @throws InvalidInterfaceException
567
-     */
568
-    protected function _add_screen_options_category_list()
569
-    {
570
-        $page_title              = $this->_admin_page_title;
571
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
572
-        $this->_per_page_screen_option();
573
-        $this->_admin_page_title = $page_title;
574
-    }
575
-
576
-
577
-    /**
578
-     * Used to register any global feature pointers for the admin page group.
579
-     */
580
-    protected function _add_feature_pointers()
581
-    {
582
-    }
583
-
584
-
585
-    /**
586
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
587
-     */
588
-    public function load_scripts_styles()
589
-    {
590
-        wp_register_style(
591
-            'events-admin-css',
592
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
593
-            [],
594
-            EVENT_ESPRESSO_VERSION
595
-        );
596
-        wp_register_style(
597
-            'ee-cat-admin',
598
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
599
-            [],
600
-            EVENT_ESPRESSO_VERSION
601
-        );
602
-        wp_enqueue_style('events-admin-css');
603
-        wp_enqueue_style('ee-cat-admin');
604
-        // scripts
605
-        wp_register_script(
606
-            'event_editor_js',
607
-            EVENTS_ASSETS_URL . 'event_editor.js',
608
-            ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
609
-            EVENT_ESPRESSO_VERSION,
610
-            true
611
-        );
612
-    }
613
-
614
-
615
-    /**
616
-     * Enqueuing scripts and styles specific to this view
617
-     */
618
-    public function load_scripts_styles_create_new()
619
-    {
620
-        $this->load_scripts_styles_edit();
621
-    }
622
-
623
-
624
-    /**
625
-     * Enqueuing scripts and styles specific to this view
626
-     */
627
-    public function load_scripts_styles_edit()
628
-    {
629
-        // styles
630
-        wp_enqueue_style('espresso-ui-theme');
631
-        wp_register_style(
632
-            'event-editor-css',
633
-            EVENTS_ASSETS_URL . 'event-editor.css',
634
-            ['ee-admin-css'],
635
-            EVENT_ESPRESSO_VERSION
636
-        );
637
-        wp_enqueue_style('event-editor-css');
638
-        // scripts
639
-        if (! $this->admin_config->useAdvancedEditor()) {
640
-            wp_register_script(
641
-                'event-datetime-metabox',
642
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
643
-                ['event_editor_js', 'ee-datepicker'],
644
-                EVENT_ESPRESSO_VERSION
645
-            );
646
-            wp_enqueue_script('event-datetime-metabox');
647
-        }
648
-    }
649
-
650
-
651
-    /**
652
-     * Populating the _views property for the category list table view.
653
-     */
654
-    protected function _set_list_table_views_category_list()
655
-    {
656
-        $this->_views = [
657
-            'all' => [
658
-                'slug'        => 'all',
659
-                'label'       => esc_html__('All', 'event_espresso'),
660
-                'count'       => 0,
661
-                'bulk_action' => [
662
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
663
-                ],
664
-            ],
665
-        ];
666
-    }
667
-
668
-
669
-    /**
670
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
671
-     */
672
-    public function admin_init()
673
-    {
674
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
675
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
676
-            'event_espresso'
677
-        );
678
-    }
679
-
680
-
681
-    /**
682
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
683
-     * group.
684
-     */
685
-    public function admin_notices()
686
-    {
687
-    }
688
-
689
-
690
-    /**
691
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
692
-     * this admin page group.
693
-     */
694
-    public function admin_footer_scripts()
695
-    {
696
-    }
697
-
698
-
699
-    /**
700
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
701
-     * warning (via EE_Error::add_error());
702
-     *
703
-     * @param EE_Event|null $event Event object
704
-     * @param string        $req_type
705
-     * @return void
706
-     * @throws EE_Error
707
-     * @throws ReflectionException
708
-     */
709
-    public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
710
-    {
711
-        // don't need to do this when processing
712
-        if (! empty($req_type)) {
713
-            return;
714
-        }
715
-        // no event?
716
-        if (! $event instanceof EE_Event) {
717
-            $event = $this->_cpt_model_obj;
718
-        }
719
-        // STILL no event?
720
-        if (! $event instanceof EE_Event) {
721
-            return;
722
-        }
723
-        // don't need to keep calling this
724
-        remove_action(
725
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
726
-            [$this, 'verify_event_edit']
727
-        );
728
-        $orig_status = $event->status();
729
-        // first check if event is active.
730
-        if (
731
-            $orig_status === EEM_Event::cancelled
732
-            || $orig_status === EEM_Event::postponed
733
-            || $event->is_expired()
734
-            || $event->is_inactive()
735
-        ) {
736
-            return;
737
-        }
738
-        // made it here so it IS active... next check that any of the tickets are sold.
739
-        if ($event->is_sold_out(true)) {
740
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
741
-                EE_Error::add_attention(
742
-                    sprintf(
743
-                        esc_html__(
744
-                            '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.',
745
-                            'event_espresso'
746
-                        ),
747
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
748
-                    )
749
-                );
750
-            }
751
-            return;
752
-        }
753
-        if ($orig_status === EEM_Event::sold_out) {
754
-            EE_Error::add_attention(
755
-                sprintf(
756
-                    esc_html__(
757
-                        '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.',
758
-                        'event_espresso'
759
-                    ),
760
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
761
-                )
762
-            );
763
-        }
764
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
765
-        if (! $event->tickets_on_sale()) {
766
-            return;
767
-        }
768
-        // made it here so show warning
769
-        $this->_edit_event_warning();
770
-    }
771
-
772
-
773
-    /**
774
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
775
-     * When needed, hook this into a EE_Error::add_error() notice.
776
-     *
777
-     * @access protected
778
-     * @return void
779
-     */
780
-    protected function _edit_event_warning()
781
-    {
782
-        // we don't want to add warnings during these requests
783
-        if ($this->request->getRequestParam('action') === 'editpost') {
784
-            return;
785
-        }
786
-        EE_Error::add_attention(
787
-            sprintf(
788
-                esc_html__(
789
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
790
-                    'event_espresso'
791
-                ),
792
-                '<a class="espresso-help-tab-lnk ee-help-tab-link">',
793
-                '</a>'
794
-            )
795
-        );
796
-    }
797
-
798
-
799
-    /**
800
-     * When a user is creating a new event, notify them if they haven't set their timezone.
801
-     * Otherwise, do the normal logic
802
-     *
803
-     * @return void
804
-     * @throws EE_Error
805
-     * @throws InvalidArgumentException
806
-     * @throws InvalidDataTypeException
807
-     * @throws InvalidInterfaceException
808
-     * @throws ReflectionException
809
-     */
810
-    protected function _create_new_cpt_item()
811
-    {
812
-        $has_timezone_string = get_option('timezone_string');
813
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
814
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
815
-            EE_Error::add_attention(
816
-                sprintf(
817
-                    esc_html__(
818
-                        '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',
819
-                        'event_espresso'
820
-                    ),
821
-                    '<br>',
822
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
823
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
824
-                    . '</select>',
825
-                    '<button class="button button--secondary timezone-submit">',
826
-                    '</button><span class="spinner"></span>'
827
-                ),
828
-                __FILE__,
829
-                __FUNCTION__,
830
-                __LINE__
831
-            );
832
-        }
833
-        parent::_create_new_cpt_item();
834
-    }
835
-
836
-
837
-    /**
838
-     * Sets the _views property for the default route in this admin page group.
839
-     */
840
-    protected function _set_list_table_views_default()
841
-    {
842
-        $this->_views = [
843
-            'all'   => [
844
-                'slug'        => 'all',
845
-                'label'       => esc_html__('View All Events', 'event_espresso'),
846
-                'count'       => 0,
847
-                'bulk_action' => [
848
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
-                ],
850
-            ],
851
-            'draft' => [
852
-                'slug'        => 'draft',
853
-                'label'       => esc_html__('Draft', 'event_espresso'),
854
-                'count'       => 0,
855
-                'bulk_action' => [
856
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
857
-                ],
858
-            ],
859
-        ];
860
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
861
-            $this->_views['trash'] = [
862
-                'slug'        => 'trash',
863
-                'label'       => esc_html__('Trash', 'event_espresso'),
864
-                'count'       => 0,
865
-                'bulk_action' => [
866
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
867
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
868
-                ],
869
-            ];
870
-        }
871
-    }
872
-
873
-
874
-    /**
875
-     * Provides the legend item array for the default list table view.
876
-     *
877
-     * @return array
878
-     * @throws EE_Error
879
-     * @throws EE_Error
880
-     */
881
-    protected function _event_legend_items(): array
882
-    {
883
-        $items    = [
884
-            'view_details'   => [
885
-                'class' => 'dashicons dashicons-visibility',
886
-                'desc'  => esc_html__('View Event', 'event_espresso'),
887
-            ],
888
-            'edit_event'     => [
889
-                'class' => 'dashicons dashicons-calendar-alt',
890
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
891
-            ],
892
-            'view_attendees' => [
893
-                'class' => 'dashicons dashicons-groups',
894
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
895
-            ],
896
-        ];
897
-        $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
898
-        $statuses = [
899
-            'sold_out_status'  => [
900
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
901
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
902
-            ],
903
-            'active_status'    => [
904
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
905
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
906
-            ],
907
-            'upcoming_status'  => [
908
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
909
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
910
-            ],
911
-            'postponed_status' => [
912
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
913
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
914
-            ],
915
-            'cancelled_status' => [
916
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
917
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
918
-            ],
919
-            'expired_status'   => [
920
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
921
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
922
-            ],
923
-            'inactive_status'  => [
924
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
925
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
926
-            ],
927
-        ];
928
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
929
-        return array_merge($items, $statuses);
930
-    }
931
-
932
-
933
-    /**
934
-     * @return EEM_Event
935
-     * @throws EE_Error
936
-     * @throws InvalidArgumentException
937
-     * @throws InvalidDataTypeException
938
-     * @throws InvalidInterfaceException
939
-     * @throws ReflectionException
940
-     */
941
-    private function _event_model(): EEM_Event
942
-    {
943
-        if (! $this->_event_model instanceof EEM_Event) {
944
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
945
-        }
946
-        return $this->_event_model;
947
-    }
948
-
949
-
950
-    /**
951
-     * Adds extra buttons to the WP CPT permalink field row.
952
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
953
-     *
954
-     * @param string      $return    the current html
955
-     * @param int         $id        the post id for the page
956
-     * @param string|null $new_title What the title is
957
-     * @param string|null $new_slug  what the slug is
958
-     * @return string            The new html string for the permalink area
959
-     * @deprecated 5.0.0.p
960
-     * @see TicketSelectorShortcodeButton::addButton
961
-     */
962
-    public function extra_permalink_field_buttons(
963
-        string $return,
964
-        int $id,
965
-        ?string $new_title,
966
-        ?string $new_slug
967
-    ): string {
968
-        return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
969
-    }
970
-
971
-
972
-    /**
973
-     * _events_overview_list_table
974
-     * This contains the logic for showing the events_overview list
975
-     *
976
-     * @access protected
977
-     * @return void
978
-     * @throws DomainException
979
-     * @throws EE_Error
980
-     * @throws InvalidArgumentException
981
-     * @throws InvalidDataTypeException
982
-     * @throws InvalidInterfaceException
983
-     */
984
-    protected function _events_overview_list_table()
985
-    {
986
-        $after_list_table = [];
987
-        $links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
988
-        $links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
989
-        $links_html       .= EEH_HTML::div(
990
-            EEH_Template::get_button_or_link(
991
-                get_post_type_archive_link('espresso_events'),
992
-                esc_html__('View Event Archive Page', 'event_espresso'),
993
-                'button button--small button--secondary'
994
-            ),
995
-            '',
996
-            'ee-admin-button-row ee-admin-button-row--align-start'
997
-        );
998
-        $links_html       .= EEH_HTML::divx();
999
-
1000
-        $after_list_table['view_event_list_button'] = $links_html;
1001
-
1002
-        $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
1003
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
1004
-            'create_new',
1005
-            'add',
1006
-            [],
1007
-            'add-new-h2'
1008
-        );
1009
-
1010
-        $this->_template_args['after_list_table'] = array_merge(
1011
-            (array) $this->_template_args['after_list_table'],
1012
-            $after_list_table
1013
-        );
1014
-        $this->display_admin_list_table_page_with_no_sidebar();
1015
-    }
1016
-
1017
-
1018
-    /**
1019
-     * this allows for extra misc actions in the default WP publish box
1020
-     *
1021
-     * @return void
1022
-     * @throws DomainException
1023
-     * @throws EE_Error
1024
-     * @throws InvalidArgumentException
1025
-     * @throws InvalidDataTypeException
1026
-     * @throws InvalidInterfaceException
1027
-     * @throws ReflectionException
1028
-     */
1029
-    public function extra_misc_actions_publish_box()
1030
-    {
1031
-        $this->_generate_publish_box_extra_content();
1032
-    }
1033
-
1034
-
1035
-    /**
1036
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1037
-     * saved.
1038
-     * Typically you would use this to save any additional data.
1039
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1040
-     * ALSO very important.  When a post transitions from scheduled to published,
1041
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1042
-     * other meta saves. So MAKE sure that you handle this accordingly.
1043
-     *
1044
-     * @access protected
1045
-     * @abstract
1046
-     * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1047
-     * @param WP_Post $post    The post object of the cpt that was saved.
1048
-     * @return void
1049
-     * @throws EE_Error
1050
-     * @throws InvalidArgumentException
1051
-     * @throws InvalidDataTypeException
1052
-     * @throws InvalidInterfaceException
1053
-     * @throws ReflectionException
1054
-     */
1055
-    protected function _insert_update_cpt_item($post_id, $post)
1056
-    {
1057
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1058
-            // get out we're not processing an event save.
1059
-            return;
1060
-        }
1061
-        $event_values = [
1062
-            'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1063
-            'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1064
-            'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1065
-        ];
1066
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1067
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1068
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1069
-                'display_ticket_selector',
1070
-                false,
1071
-                'bool'
1072
-            );
1073
-            $event_values['EVT_additional_limit']            = min(
1074
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1075
-                $this->request->getRequestParam(
1076
-                    'additional_limit',
1077
-                    EEM_Event::get_default_additional_limit(),
1078
-                    'int'
1079
-                )
1080
-            );
1081
-            $event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1082
-                'EVT_default_registration_status',
1083
-                EE_Registry::instance()->CFG->registration->default_STS_ID
1084
-            );
1085
-
1086
-            $event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1087
-            $event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1088
-            $event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1089
-        } elseif ($post instanceof WP_Post) {
1090
-            $event_values['EVT_name'] = $post->post_title;
1091
-            $event_values['EVT_desc'] = $post->post_content;
1092
-        }
1093
-        // update event
1094
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1095
-        // get event_object for other metaboxes...
1096
-        // though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1097
-        // i have to setup where conditions to override the filters in the model
1098
-        // that filter out auto-draft and inherit statuses so we GET the inherit id!
1099
-        /** @var EE_Event $event */
1100
-        $event = $this->_event_model()->get_one(
1101
-            [
1102
-                [
1103
-                    $this->_event_model()->primary_key_name() => $post_id,
1104
-                    'OR'                                      => [
1105
-                        'status'   => $post->post_status,
1106
-                        // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1107
-                        // but the returned object here has a status of "publish", so use the original post status as well
1108
-                        'status*1' => $this->request->getRequestParam('original_post_status'),
1109
-                    ],
1110
-                ],
1111
-            ]
1112
-        );
1113
-
1114
-        // the following are default callbacks for event attachment updates
1115
-        // that can be overridden by caffeinated functionality and/or addons.
1116
-        $event_update_callbacks = [];
1117
-        if (! $this->admin_config->useAdvancedEditor()) {
1118
-            $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1119
-            $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1120
-        }
1121
-        $event_update_callbacks = apply_filters(
1122
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1123
-            $event_update_callbacks
1124
-        );
1125
-
1126
-        $att_success = true;
1127
-        foreach ($event_update_callbacks as $e_callback) {
1128
-            $_success = is_callable($e_callback)
1129
-                ? $e_callback($event, $this->request->requestParams())
1130
-                : false;
1131
-            // if ANY of these updates fail then we want the appropriate global error message
1132
-            $att_success = $_success !== false ? $att_success : false;
1133
-        }
1134
-        // any errors?
1135
-        if ($success && $att_success === false) {
1136
-            EE_Error::add_error(
1137
-                esc_html__(
1138
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1139
-                    'event_espresso'
1140
-                ),
1141
-                __FILE__,
1142
-                __FUNCTION__,
1143
-                __LINE__
1144
-            );
1145
-        } elseif ($success === false) {
1146
-            EE_Error::add_error(
1147
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1148
-                __FILE__,
1149
-                __FUNCTION__,
1150
-                __LINE__
1151
-            );
1152
-        }
1153
-    }
1154
-
1155
-
1156
-    /**
1157
-     * @param int $post_id
1158
-     * @param int $revision_id
1159
-     * @throws EE_Error
1160
-     * @throws EE_Error
1161
-     * @throws ReflectionException
1162
-     * @see parent::restore_item()
1163
-     */
1164
-    protected function _restore_cpt_item(int $post_id, int $revision_id)
1165
-    {
1166
-        // copy existing event meta to new post
1167
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1168
-        if ($post_evt instanceof EE_Event) {
1169
-            // meta revision restore
1170
-            $post_evt->restore_revision($revision_id);
1171
-            // related objs restore
1172
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1173
-        }
1174
-    }
1175
-
1176
-
1177
-    /**
1178
-     * Attach the venue to the Event
1179
-     *
1180
-     * @param EE_Event $event Event Object to add the venue to
1181
-     * @param array    $data  The request data from the form
1182
-     * @return bool           Success or fail.
1183
-     * @throws EE_Error
1184
-     * @throws ReflectionException
1185
-     */
1186
-    protected function _default_venue_update(EE_Event $event, array $data): bool
1187
-    {
1188
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1189
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1190
-        $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1191
-        // very important.  If we don't have a venue name...
1192
-        // then we'll get out because not necessary to create empty venue
1193
-        if (empty($data['venue_title'])) {
1194
-            return false;
1195
-        }
1196
-        $venue_array = [
1197
-            'VNU_wp_user'         => $event->get('EVT_wp_user'),
1198
-            'VNU_name'            => $data['venue_title'],
1199
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1200
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1201
-            'VNU_short_desc'      => ! empty($data['venue_short_description'])
1202
-                ? $data['venue_short_description']
1203
-                : null,
1204
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1205
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1206
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1207
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1208
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1209
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1210
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1211
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1212
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1213
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1214
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1215
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1216
-            'status'              => 'publish',
1217
-        ];
1218
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1219
-        if (! empty($venue_id)) {
1220
-            $update_where  = [$venue_model->primary_key_name() => $venue_id];
1221
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1222
-            // we've gotta make sure that the venue is always attached to a revision..
1223
-            // add_relation_to should take care of making sure that the relation is already present.
1224
-            $event->_add_relation_to($venue_id, 'Venue');
1225
-            return $rows_affected > 0;
1226
-        }
1227
-        // we insert the venue
1228
-        $venue_id = $venue_model->insert($venue_array);
1229
-        $event->_add_relation_to($venue_id, 'Venue');
1230
-        return ! empty($venue_id);
1231
-        // when we have the ancestor come in it's already been handled by the revision save.
1232
-    }
1233
-
1234
-
1235
-    /**
1236
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1237
-     *
1238
-     * @param EE_Event $event The Event object we're attaching data to
1239
-     * @param array    $data  The request data from the form
1240
-     * @return array
1241
-     * @throws EE_Error
1242
-     * @throws ReflectionException
1243
-     * @throws Exception
1244
-     */
1245
-    protected function _default_tickets_update(EE_Event $event, array $data): array
1246
-    {
1247
-        if ($this->admin_config->useAdvancedEditor()) {
1248
-            return [];
1249
-        }
1250
-        $datetime       = null;
1251
-        $saved_tickets  = [];
1252
-        $event_timezone = $event->get_timezone();
1253
-        $date_formats   = ['Y-m-d', 'h:i a'];
1254
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1255
-            // trim all values to ensure any excess whitespace is removed.
1256
-            $datetime_data                = array_map('trim', $datetime_data);
1257
-            $datetime_data['DTT_EVT_end'] =
1258
-                isset($datetime_data['DTT_EVT_end']) && ! empty($datetime_data['DTT_EVT_end'])
1259
-                    ? $datetime_data['DTT_EVT_end']
1260
-                    : $datetime_data['DTT_EVT_start'];
1261
-            $datetime_values              = [
1262
-                'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1263
-                'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1264
-                'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1265
-                'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1266
-                'DTT_order'     => $row,
1267
-            ];
1268
-            // if we have an id then let's get existing object first and then set the new values.
1269
-            //  Otherwise we instantiate a new object for save.
1270
-            if (! empty($datetime_data['DTT_ID'])) {
1271
-                $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1272
-                if (! $datetime instanceof EE_Datetime) {
1273
-                    throw new RuntimeException(
1274
-                        sprintf(
1275
-                            esc_html__(
1276
-                                'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1277
-                                'event_espresso'
1278
-                            ),
1279
-                            $datetime_data['DTT_ID']
1280
-                        )
1281
-                    );
1282
-                }
1283
-                $datetime->set_date_format($date_formats[0]);
1284
-                $datetime->set_time_format($date_formats[1]);
1285
-                foreach ($datetime_values as $field => $value) {
1286
-                    $datetime->set($field, $value);
1287
-                }
1288
-            } else {
1289
-                $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1290
-            }
1291
-            if (! $datetime instanceof EE_Datetime) {
1292
-                throw new RuntimeException(
1293
-                    sprintf(
1294
-                        esc_html__(
1295
-                            'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1296
-                            'event_espresso'
1297
-                        ),
1298
-                        print_r($datetime_values, true)
1299
-                    )
1300
-                );
1301
-            }
1302
-            // before going any further make sure our dates are setup correctly
1303
-            // so that the end date is always equal or greater than the start date.
1304
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1305
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1306
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1307
-            }
1308
-            $datetime->save();
1309
-            $event->_add_relation_to($datetime, 'Datetime');
1310
-        }
1311
-        // no datetimes get deleted so we don't do any of that logic here.
1312
-        // update tickets next
1313
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1314
-
1315
-        // set up some default start and end dates in case those are not present in the incoming data
1316
-        $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1317
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1318
-        // use the start date of the first datetime for the end date
1319
-        $first_datetime   = $event->first_datetime();
1320
-        $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1321
-
1322
-        // now process the incoming data
1323
-        foreach ($data['edit_tickets'] as $row => $ticket_data) {
1324
-            $update_prices = false;
1325
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1326
-            // trim inputs to ensure any excess whitespace is removed.
1327
-            $ticket_data   = array_map('trim', $ticket_data);
1328
-            $ticket_values = [
1329
-                'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1330
-                'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1331
-                'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1332
-                'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1333
-                'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1334
-                    ? $ticket_data['TKT_start_date']
1335
-                    : $default_start_date,
1336
-                'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1337
-                    ? $ticket_data['TKT_end_date']
1338
-                    : $default_end_date,
1339
-                'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1340
-                                     || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1341
-                    ? $ticket_data['TKT_qty']
1342
-                    : EE_INF,
1343
-                'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1344
-                                     || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1345
-                    ? $ticket_data['TKT_uses']
1346
-                    : EE_INF,
1347
-                'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1348
-                'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1349
-                'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1350
-                'TKT_price'       => $ticket_price,
1351
-                'TKT_row'         => $row,
1352
-            ];
1353
-            // if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1354
-            // which means in turn that the prices will become new prices as well.
1355
-            if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1356
-                $ticket_values['TKT_ID']         = 0;
1357
-                $ticket_values['TKT_is_default'] = 0;
1358
-                $update_prices                   = true;
1359
-            }
1360
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1361
-            // we actually do our saves ahead of adding any relations because its entirely possible that this
1362
-            // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1363
-            // keep in mind that if the ticket has been sold (and we have changed pricing information),
1364
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1365
-            if (! empty($ticket_data['TKT_ID'])) {
1366
-                $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1367
-                if (! $existing_ticket instanceof EE_Ticket) {
1368
-                    throw new RuntimeException(
1369
-                        sprintf(
1370
-                            esc_html__(
1371
-                                'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1372
-                                'event_espresso'
1373
-                            ),
1374
-                            $ticket_data['TKT_ID']
1375
-                        )
1376
-                    );
1377
-                }
1378
-                $ticket_sold = $existing_ticket->count_related(
1379
-                    'Registration',
1380
-                    [
1381
-                            [
1382
-                                'STS_ID' => [
1383
-                                    'NOT IN',
1384
-                                    [EEM_Registration::status_id_incomplete],
1385
-                                ],
1386
-                            ],
1387
-                        ]
1388
-                ) > 0;
1389
-                // let's just check the total price for the existing ticket and determine if it matches the new total price.
1390
-                // if they are different then we create a new ticket (if $ticket_sold)
1391
-                // if they aren't different then we go ahead and modify existing ticket.
1392
-                $create_new_ticket = $ticket_sold
1393
-                                     && $ticket_price !== $existing_ticket->price()
1394
-                                     && ! $existing_ticket->deleted();
1395
-                $existing_ticket->set_date_format($date_formats[0]);
1396
-                $existing_ticket->set_time_format($date_formats[1]);
1397
-                // set new values
1398
-                foreach ($ticket_values as $field => $value) {
1399
-                    if ($field == 'TKT_qty') {
1400
-                        $existing_ticket->set_qty($value);
1401
-                    } elseif ($field == 'TKT_price') {
1402
-                        $existing_ticket->set('TKT_price', $ticket_price);
1403
-                    } else {
1404
-                        $existing_ticket->set($field, $value);
1405
-                    }
1406
-                }
1407
-                $ticket = $existing_ticket;
1408
-                // if $create_new_ticket is false then we can safely update the existing ticket.
1409
-                //  Otherwise we have to create a new ticket.
1410
-                if ($create_new_ticket) {
1411
-                    // archive the old ticket first
1412
-                    $existing_ticket->set('TKT_deleted', 1);
1413
-                    $existing_ticket->save();
1414
-                    // make sure this ticket is still recorded in our $saved_tickets
1415
-                    // so we don't run it through the regular trash routine.
1416
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1417
-                    // create new ticket that's a copy of the existing except,
1418
-                    // (a new id of course and not archived) AND has the new TKT_price associated with it.
1419
-                    $new_ticket = clone $existing_ticket;
1420
-                    $new_ticket->set('TKT_ID', 0);
1421
-                    $new_ticket->set('TKT_deleted', 0);
1422
-                    $new_ticket->set('TKT_sold', 0);
1423
-                    // now we need to make sure that $new prices are created as well and attached to new ticket.
1424
-                    $update_prices = true;
1425
-                    $ticket        = $new_ticket;
1426
-                }
1427
-            } else {
1428
-                // no TKT_id so a new ticket
1429
-                $ticket_values['TKT_price'] = $ticket_price;
1430
-                $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1431
-                $update_prices              = true;
1432
-            }
1433
-            if (! $ticket instanceof EE_Ticket) {
1434
-                throw new RuntimeException(
1435
-                    sprintf(
1436
-                        esc_html__(
1437
-                            'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1438
-                            'event_espresso'
1439
-                        ),
1440
-                        print_r($ticket_values, true)
1441
-                    )
1442
-                );
1443
-            }
1444
-            // cap ticket qty by datetime reg limits
1445
-            $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1446
-            // update ticket.
1447
-            $ticket->save();
1448
-            // before going any further make sure our dates are setup correctly
1449
-            // so that the end date is always equal or greater than the start date.
1450
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1451
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1452
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1453
-                $ticket->save();
1454
-            }
1455
-            // initially let's add the ticket to the datetime
1456
-            $datetime->_add_relation_to($ticket, 'Ticket');
1457
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1458
-            // add prices to ticket
1459
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1460
-                ? $data['edit_prices'][ $row ]
1461
-                : [];
1462
-            $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1463
-        }
1464
-        // however now we need to handle permanently deleting tickets via the ui.
1465
-        // Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1466
-        // However, it does allow for deleting tickets that have no tickets sold,
1467
-        // in which case we want to get rid of permanently because there is no need to save in db.
1468
-        $old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1469
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1470
-        foreach ($tickets_removed as $id) {
1471
-            $id = absint($id);
1472
-            // get the ticket for this id
1473
-            $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1474
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1475
-                continue;
1476
-            }
1477
-            // need to get all the related datetimes on this ticket and remove from every single one of them
1478
-            // (remember this process can ONLY kick off if there are NO tickets sold)
1479
-            $related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1480
-            foreach ($related_datetimes as $related_datetime) {
1481
-                $ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1482
-            }
1483
-            // need to do the same for prices (except these prices can also be deleted because again,
1484
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1485
-            $ticket_to_remove->delete_related_permanently('Price');
1486
-            // finally let's delete this ticket
1487
-            // (which should not be blocked at this point b/c we've removed all our relationships)
1488
-            $ticket_to_remove->delete_permanently();
1489
-        }
1490
-        return [$datetime, $saved_tickets];
1491
-    }
1492
-
1493
-
1494
-    /**
1495
-     * This attaches a list of given prices to a ticket.
1496
-     * Note we dont' have to worry about ever removing relationships (or archiving prices)
1497
-     * because if there is a change in price information on a ticket, a new ticket is created anyways
1498
-     * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1499
-     *
1500
-     * @access  private
1501
-     * @param array     $prices_data Array of prices from the form.
1502
-     * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1503
-     * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1504
-     * @return  void
1505
-     * @throws EE_Error
1506
-     * @throws ReflectionException
1507
-     */
1508
-    private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1509
-    {
1510
-        $timezone = $ticket->get_timezone();
1511
-        foreach ($prices_data as $row => $price_data) {
1512
-            $price_values = [
1513
-                'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1514
-                'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1515
-                'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1516
-                'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1517
-                'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1518
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1519
-                'PRC_order'      => $row,
1520
-            ];
1521
-            if ($new_prices || empty($price_values['PRC_ID'])) {
1522
-                $price_values['PRC_ID'] = 0;
1523
-                $price                  = EE_Price::new_instance($price_values, $timezone);
1524
-            } else {
1525
-                $price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1526
-                // update this price with new values
1527
-                foreach ($price_values as $field => $new_price) {
1528
-                    $price->set($field, $new_price);
1529
-                }
1530
-            }
1531
-            if (! $price instanceof EE_Price) {
1532
-                throw new RuntimeException(
1533
-                    sprintf(
1534
-                        esc_html__(
1535
-                            'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1536
-                            'event_espresso'
1537
-                        ),
1538
-                        print_r($price_values, true)
1539
-                    )
1540
-                );
1541
-            }
1542
-            $price->save();
1543
-            $ticket->_add_relation_to($price, 'Price');
1544
-        }
1545
-    }
1546
-
1547
-
1548
-    /**
1549
-     * Add in our autosave ajax handlers
1550
-     *
1551
-     */
1552
-    protected function _ee_autosave_create_new()
1553
-    {
1554
-    }
1555
-
1556
-
1557
-    /**
1558
-     * More autosave handlers.
1559
-     */
1560
-    protected function _ee_autosave_edit()
1561
-    {
1562
-    }
1563
-
1564
-
1565
-    /**
1566
-     * @throws EE_Error
1567
-     * @throws ReflectionException
1568
-     */
1569
-    private function _generate_publish_box_extra_content()
1570
-    {
1571
-        // load formatter helper
1572
-        // args for getting related registrations
1573
-        $approved_query_args        = [
1574
-            [
1575
-                'REG_deleted' => 0,
1576
-                'STS_ID'      => EEM_Registration::status_id_approved,
1577
-            ],
1578
-        ];
1579
-        $not_approved_query_args    = [
1580
-            [
1581
-                'REG_deleted' => 0,
1582
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1583
-            ],
1584
-        ];
1585
-        $pending_payment_query_args = [
1586
-            [
1587
-                'REG_deleted' => 0,
1588
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1589
-            ],
1590
-        ];
1591
-        // publish box
1592
-        $publish_box_extra_args = [
1593
-            'view_approved_reg_url'        => add_query_arg(
1594
-                [
1595
-                    'action'      => 'default',
1596
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1597
-                    '_reg_status' => EEM_Registration::status_id_approved,
1598
-                    'use_filters' => true,
1599
-                ],
1600
-                REG_ADMIN_URL
1601
-            ),
1602
-            'view_not_approved_reg_url'    => add_query_arg(
1603
-                [
1604
-                    'action'      => 'default',
1605
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1606
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1607
-                    'use_filters' => true,
1608
-                ],
1609
-                REG_ADMIN_URL
1610
-            ),
1611
-            'view_pending_payment_reg_url' => add_query_arg(
1612
-                [
1613
-                    'action'      => 'default',
1614
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1615
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1616
-                    'use_filters' => true,
1617
-                ],
1618
-                REG_ADMIN_URL
1619
-            ),
1620
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1621
-                'Registration',
1622
-                $approved_query_args
1623
-            ),
1624
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1625
-                'Registration',
1626
-                $not_approved_query_args
1627
-            ),
1628
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1629
-                'Registration',
1630
-                $pending_payment_query_args
1631
-            ),
1632
-            'misc_pub_section_class'       => apply_filters(
1633
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1634
-                'misc-pub-section'
1635
-            ),
1636
-        ];
1637
-        ob_start();
1638
-        do_action(
1639
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1640
-            $this->_cpt_model_obj
1641
-        );
1642
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1643
-        // load template
1644
-        EEH_Template::display_template(
1645
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1646
-            $publish_box_extra_args
1647
-        );
1648
-    }
1649
-
1650
-
1651
-    /**
1652
-     * @return EE_Event
1653
-     */
1654
-    public function get_event_object()
1655
-    {
1656
-        return $this->_cpt_model_obj;
1657
-    }
1658
-
1659
-
1660
-
1661
-
1662
-    /** METABOXES * */
1663
-    /**
1664
-     * _register_event_editor_meta_boxes
1665
-     * add all metaboxes related to the event_editor
1666
-     *
1667
-     * @return void
1668
-     * @throws EE_Error
1669
-     * @throws ReflectionException
1670
-     */
1671
-    protected function _register_event_editor_meta_boxes()
1672
-    {
1673
-        $this->verify_cpt_object();
1674
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1675
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1676
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1677
-            $this->addMetaBox(
1678
-                'espresso_event_editor_event_options',
1679
-                esc_html__('Event Registration Options', 'event_espresso'),
1680
-                [$this, 'registration_options_meta_box'],
1681
-                $this->page_slug,
1682
-                'side'
1683
-            );
1684
-        }
1685
-        if (! $use_advanced_editor) {
1686
-            $this->addMetaBox(
1687
-                'espresso_event_editor_tickets',
1688
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1689
-                [$this, 'ticket_metabox'],
1690
-                $this->page_slug,
1691
-                'normal',
1692
-                'high'
1693
-            );
1694
-        } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1695
-            add_action(
1696
-                'add_meta_boxes_espresso_events',
1697
-                function () {
1698
-                    global $current_screen;
1699
-                    remove_meta_box('authordiv', $current_screen, 'normal');
1700
-                },
1701
-                99
1702
-            );
1703
-        }
1704
-        // NOTE: if you're looking for other metaboxes in here,
1705
-        // where a metabox has a related management page in the admin
1706
-        // you will find it setup in the related management page's "_Hooks" file.
1707
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1708
-    }
1709
-
1710
-
1711
-    /**
1712
-     * @throws DomainException
1713
-     * @throws EE_Error
1714
-     * @throws ReflectionException
1715
-     */
1716
-    public function ticket_metabox()
1717
-    {
1718
-        $existing_datetime_ids = $existing_ticket_ids = [];
1719
-        // defaults for template args
1720
-        $template_args = [
1721
-            'ticket_rows'       => '',
1722
-            'total_ticket_rows' => 1,
1723
-            'trash_icon'        => 'dashicons dashicons-lock',
1724
-            'disabled'          => '',
1725
-        ];
1726
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1727
-        /**
1728
-         * 1. Start with retrieving Datetimes
1729
-         * 2. Fore each datetime get related tickets
1730
-         * 3. For each ticket get related prices
1731
-         */
1732
-        /** @var EEM_Datetime $datetime_model */
1733
-        $datetime_model = EE_Registry::instance()->load_model('Datetime');
1734
-        /** @var EEM_Ticket $datetime_model */
1735
-        $ticket_model = EE_Registry::instance()->load_model('Ticket');
1736
-        $times        = $datetime_model->get_all_event_dates($event_id);
1737
-        /** @type EE_Datetime $first_datetime */
1738
-        $first_datetime = reset($times);
1739
-        // do we get related tickets?
1740
-        if (
1741
-            $first_datetime instanceof EE_Datetime
1742
-            && $first_datetime->ID() !== 0
1743
-        ) {
1744
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1745
-            $template_args['time']   = $first_datetime;
1746
-            $related_tickets         = $first_datetime->tickets(
1747
-                [
1748
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1749
-                    'default_where_conditions' => 'none',
1750
-                ]
1751
-            );
1752
-            if (! empty($related_tickets)) {
1753
-                $template_args['total_ticket_rows'] = count($related_tickets);
1754
-                $row                                = 0;
1755
-                foreach ($related_tickets as $ticket) {
1756
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1757
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1758
-                    $row++;
1759
-                }
1760
-            } else {
1761
-                $template_args['total_ticket_rows'] = 1;
1762
-                /** @type EE_Ticket $ticket */
1763
-                $ticket                       = $ticket_model->create_default_object();
1764
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1765
-            }
1766
-        } else {
1767
-            $template_args['time'] = $times[0];
1768
-            /** @type EE_Ticket[] $tickets */
1769
-            $tickets                      = $ticket_model->get_all_default_tickets();
1770
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1771
-            // NOTE: we're just sending the first default row
1772
-            // (decaf can't manage default tickets so this should be sufficient);
1773
-        }
1774
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1775
-            'event_editor_event_datetimes_help_tab'
1776
-        );
1777
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1778
-        $template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1779
-        $template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1780
-        $template_args['ticket_js_structure']      = $this->_get_ticket_row(
1781
-            $ticket_model->create_default_object(),
1782
-            true
1783
-        );
1784
-        $template                                  = apply_filters(
1785
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1786
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1787
-        );
1788
-        EEH_Template::display_template($template, $template_args);
1789
-    }
1790
-
1791
-
1792
-    /**
1793
-     * Setup an individual ticket form for the decaf event editor page
1794
-     *
1795
-     * @access private
1796
-     * @param EE_Ticket $ticket   the ticket object
1797
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1798
-     * @param int       $row
1799
-     * @return string generated html for the ticket row.
1800
-     * @throws EE_Error
1801
-     * @throws ReflectionException
1802
-     */
1803
-    private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1804
-    {
1805
-        $template_args = [
1806
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1807
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1808
-                : '',
1809
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1810
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1811
-            'TKT_name'            => $ticket->get('TKT_name'),
1812
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1813
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1814
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1815
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1816
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1817
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1818
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1819
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1820
-                ? 'dashicons dashicons-post-trash clickable'
1821
-                : 'dashicons dashicons-lock',
1822
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1823
-                : ' disabled=disabled',
1824
-        ];
1825
-        $price         = $ticket->ID() !== 0
1826
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1827
-            : null;
1828
-        $price         = $price instanceof EE_Price
1829
-            ? $price
1830
-            : EEM_Price::instance()->create_default_object();
1831
-        $price_args    = [
1832
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1833
-            'PRC_amount'            => $price->get('PRC_amount'),
1834
-            'PRT_ID'                => $price->get('PRT_ID'),
1835
-            'PRC_ID'                => $price->get('PRC_ID'),
1836
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1837
-        ];
1838
-        // make sure we have default start and end dates if skeleton
1839
-        // handle rows that should NOT be empty
1840
-        if (empty($template_args['TKT_start_date'])) {
1841
-            // if empty then the start date will be now.
1842
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1843
-        }
1844
-        if (empty($template_args['TKT_end_date'])) {
1845
-            // get the earliest datetime (if present);
1846
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1847
-                ? $this->_cpt_model_obj->get_first_related(
1848
-                    'Datetime',
1849
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1850
-                )
1851
-                : null;
1852
-            $template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1853
-                ? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1854
-                : date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1855
-        }
1856
-        $template_args = array_merge($template_args, $price_args);
1857
-        $template      = apply_filters(
1858
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1859
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1860
-            $ticket
1861
-        );
1862
-        return EEH_Template::display_template($template, $template_args, true);
1863
-    }
1864
-
1865
-
1866
-    /**
1867
-     * @throws EE_Error
1868
-     * @throws ReflectionException
1869
-     */
1870
-    public function registration_options_meta_box()
1871
-    {
1872
-        $yes_no_values             = [
1873
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1874
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1875
-        ];
1876
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1877
-            [
1878
-                EEM_Registration::status_id_cancelled,
1879
-                EEM_Registration::status_id_declined,
1880
-                EEM_Registration::status_id_incomplete,
1881
-            ],
1882
-            true
1883
-        );
1884
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1885
-        $template_args['_event']                          = $this->_cpt_model_obj;
1886
-        $template_args['event']                           = $this->_cpt_model_obj;
1887
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1888
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1889
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1890
-            'default_reg_status',
1891
-            $default_reg_status_values,
1892
-            $this->_cpt_model_obj->default_registration_status()
1893
-        );
1894
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1895
-            'display_desc',
1896
-            $yes_no_values,
1897
-            $this->_cpt_model_obj->display_description()
1898
-        );
1899
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1900
-            'display_ticket_selector',
1901
-            $yes_no_values,
1902
-            $this->_cpt_model_obj->display_ticket_selector(),
1903
-            '',
1904
-            '',
1905
-            false
1906
-        );
1907
-        $template_args['additional_registration_options'] = apply_filters(
1908
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1909
-            '',
1910
-            $template_args,
1911
-            $yes_no_values,
1912
-            $default_reg_status_values
1913
-        );
1914
-        EEH_Template::display_template(
1915
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1916
-            $template_args
1917
-        );
1918
-    }
1919
-
1920
-
1921
-    /**
1922
-     * _get_events()
1923
-     * This method simply returns all the events (for the given _view and paging)
1924
-     *
1925
-     * @access public
1926
-     * @param int  $per_page     count of items per page (20 default);
1927
-     * @param int  $current_page what is the current page being viewed.
1928
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1929
-     *                           If FALSE then we return an array of event objects
1930
-     *                           that match the given _view and paging parameters.
1931
-     * @return array|int         an array of event objects or a count of them.
1932
-     * @throws Exception
1933
-     */
1934
-    public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1935
-    {
1936
-        $EEM_Event   = $this->_event_model();
1937
-        $offset      = ($current_page - 1) * $per_page;
1938
-        $limit       = $count ? null : $offset . ',' . $per_page;
1939
-        $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1940
-        $order       = $this->request->getRequestParam('order', 'DESC');
1941
-        $month_range = $this->request->getRequestParam('month_range');
1942
-        if ($month_range) {
1943
-            $pieces = explode(' ', $month_range, 3);
1944
-            // simulate the FIRST day of the month, that fixes issues for months like February
1945
-            // where PHP doesn't know what to assume for date.
1946
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1947
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1948
-            $year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
1949
-        }
1950
-        $where  = [];
1951
-        $status = $this->request->getRequestParam('status');
1952
-        // determine what post_status our condition will have for the query.
1953
-        switch ($status) {
1954
-            case 'month':
1955
-            case 'today':
1956
-            case null:
1957
-            case 'all':
1958
-                break;
1959
-            case 'draft':
1960
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1961
-                break;
1962
-            default:
1963
-                $where['status'] = $status;
1964
-        }
1965
-        // categories? The default for all categories is -1
1966
-        $category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1967
-        if ($category !== -1) {
1968
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1969
-            $where['Term_Taxonomy.term_id']  = $category;
1970
-        }
1971
-        // date where conditions
1972
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1973
-        if ($month_range) {
1974
-            $DateTime = new DateTime(
1975
-                $year_r . '-' . $month_r . '-01 00:00:00',
1976
-                new DateTimeZone('UTC')
1977
-            );
1978
-            $start    = $DateTime->getTimestamp();
1979
-            // set the datetime to be the end of the month
1980
-            $DateTime->setDate(
1981
-                $year_r,
1982
-                $month_r,
1983
-                $DateTime->format('t')
1984
-            )->setTime(23, 59, 59);
1985
-            $end                             = $DateTime->getTimestamp();
1986
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1987
-        } elseif ($status === 'today') {
1988
-            $DateTime                        =
1989
-                new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1990
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1991
-            $end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1992
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1993
-        } elseif ($status === 'month') {
1994
-            $now                             = date('Y-m-01');
1995
-            $DateTime                        =
1996
-                new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1997
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1998
-            $end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1999
-                                                        ->setTime(23, 59, 59)
2000
-                                                        ->format(implode(' ', $start_formats));
2001
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
2002
-        }
2003
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2004
-            $where['EVT_wp_user'] = get_current_user_id();
2005
-        } else {
2006
-            if (! isset($where['status'])) {
2007
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
2008
-                    $where['OR'] = [
2009
-                        'status*restrict_private' => ['!=', 'private'],
2010
-                        'AND'                     => [
2011
-                            'status*inclusive' => ['=', 'private'],
2012
-                            'EVT_wp_user'      => get_current_user_id(),
2013
-                        ],
2014
-                    ];
2015
-                }
2016
-            }
2017
-        }
2018
-        $wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2019
-        if (
2020
-            $wp_user
2021
-            && $wp_user !== get_current_user_id()
2022
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2023
-        ) {
2024
-            $where['EVT_wp_user'] = $wp_user;
2025
-        }
2026
-        // search query handling
2027
-        $search_term = $this->request->getRequestParam('s');
2028
-        if ($search_term) {
2029
-            $search_term = '%' . $search_term . '%';
2030
-            $where['OR'] = [
2031
-                'EVT_name'       => ['LIKE', $search_term],
2032
-                'EVT_desc'       => ['LIKE', $search_term],
2033
-                'EVT_short_desc' => ['LIKE', $search_term],
2034
-            ];
2035
-        }
2036
-        // filter events by venue.
2037
-        $venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2038
-        if ($venue) {
2039
-            $where['Venue.VNU_ID'] = $venue;
2040
-        }
2041
-        $request_params = $this->request->requestParams();
2042
-        $where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2043
-        $query_params   = apply_filters(
2044
-            'FHEE__Events_Admin_Page__get_events__query_params',
2045
-            [
2046
-                $where,
2047
-                'limit'    => $limit,
2048
-                'order_by' => $orderby,
2049
-                'order'    => $order,
2050
-                'group_by' => 'EVT_ID',
2051
-            ],
2052
-            $request_params
2053
-        );
2054
-
2055
-        // let's first check if we have special requests coming in.
2056
-        $active_status = $this->request->getRequestParam('active_status');
2057
-        if ($active_status) {
2058
-            switch ($active_status) {
2059
-                case 'upcoming':
2060
-                    return $EEM_Event->get_upcoming_events($query_params, $count);
2061
-                case 'expired':
2062
-                    return $EEM_Event->get_expired_events($query_params, $count);
2063
-                case 'active':
2064
-                    return $EEM_Event->get_active_events($query_params, $count);
2065
-                case 'inactive':
2066
-                    return $EEM_Event->get_inactive_events($query_params, $count);
2067
-            }
2068
-        }
2069
-
2070
-        return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2071
-    }
2072
-
2073
-
2074
-    /**
2075
-     * handling for WordPress CPT actions (trash, restore, delete)
2076
-     *
2077
-     * @param string $post_id
2078
-     * @throws EE_Error
2079
-     * @throws ReflectionException
2080
-     */
2081
-    public function trash_cpt_item($post_id)
2082
-    {
2083
-        $this->request->setRequestParam('EVT_ID', $post_id);
2084
-        $this->_trash_or_restore_event('trash', false);
2085
-    }
2086
-
2087
-
2088
-    /**
2089
-     * @param string $post_id
2090
-     * @throws EE_Error
2091
-     * @throws ReflectionException
2092
-     */
2093
-    public function restore_cpt_item($post_id)
2094
-    {
2095
-        $this->request->setRequestParam('EVT_ID', $post_id);
2096
-        $this->_trash_or_restore_event('draft', false);
2097
-    }
2098
-
2099
-
2100
-    /**
2101
-     * @param string $post_id
2102
-     * @throws EE_Error
2103
-     * @throws EE_Error
2104
-     */
2105
-    public function delete_cpt_item($post_id)
2106
-    {
2107
-        throw new EE_Error(
2108
-            esc_html__(
2109
-                'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2110
-                'event_espresso'
2111
-            )
2112
-        );
2113
-        // $this->request->setRequestParam('EVT_ID', $post_id);
2114
-        // $this->_delete_event();
2115
-    }
2116
-
2117
-
2118
-    /**
2119
-     * _trash_or_restore_event
2120
-     *
2121
-     * @access protected
2122
-     * @param string $event_status
2123
-     * @param bool   $redirect_after
2124
-     * @throws EE_Error
2125
-     * @throws EE_Error
2126
-     * @throws ReflectionException
2127
-     */
2128
-    protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2129
-    {
2130
-        // determine the event id and set to array.
2131
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
2132
-        // loop thru events
2133
-        if ($EVT_ID) {
2134
-            // clean status
2135
-            $event_status = sanitize_key($event_status);
2136
-            // grab status
2137
-            if (! empty($event_status)) {
2138
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2139
-            } else {
2140
-                $success = false;
2141
-                $msg     = esc_html__(
2142
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2143
-                    'event_espresso'
2144
-                );
2145
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2146
-            }
2147
-        } else {
2148
-            $success = false;
2149
-            $msg     = esc_html__(
2150
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2151
-                'event_espresso'
2152
-            );
2153
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2154
-        }
2155
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2156
-        if ($redirect_after) {
2157
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2158
-        }
2159
-    }
2160
-
2161
-
2162
-    /**
2163
-     * _trash_or_restore_events
2164
-     *
2165
-     * @access protected
2166
-     * @param string $event_status
2167
-     * @return void
2168
-     * @throws EE_Error
2169
-     * @throws EE_Error
2170
-     * @throws ReflectionException
2171
-     */
2172
-    protected function _trash_or_restore_events(string $event_status = 'trash')
2173
-    {
2174
-        // clean status
2175
-        $event_status = sanitize_key($event_status);
2176
-        // grab status
2177
-        if (! empty($event_status)) {
2178
-            $success = true;
2179
-            // determine the event id and set to array.
2180
-            $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2181
-            // loop thru events
2182
-            foreach ($EVT_IDs as $EVT_ID) {
2183
-                if ($EVT_ID = absint($EVT_ID)) {
2184
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2185
-                    $success = $results !== false ? $success : false;
2186
-                } else {
2187
-                    $msg = sprintf(
2188
-                        esc_html__(
2189
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2190
-                            'event_espresso'
2191
-                        ),
2192
-                        $EVT_ID
2193
-                    );
2194
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2195
-                    $success = false;
2196
-                }
2197
-            }
2198
-        } else {
2199
-            $success = false;
2200
-            $msg     = esc_html__(
2201
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2202
-                'event_espresso'
2203
-            );
2204
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2205
-        }
2206
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2207
-        $success = $success ? 2 : false;
2208
-        $action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2209
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2210
-    }
2211
-
2212
-
2213
-    /**
2214
-     * @param int    $EVT_ID
2215
-     * @param string $event_status
2216
-     * @return bool
2217
-     * @throws EE_Error
2218
-     * @throws ReflectionException
2219
-     */
2220
-    private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2221
-    {
2222
-        // grab event id
2223
-        if (! $EVT_ID) {
2224
-            $msg = esc_html__(
2225
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2226
-                'event_espresso'
2227
-            );
2228
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2229
-            return false;
2230
-        }
2231
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2232
-        // clean status
2233
-        $event_status = sanitize_key($event_status);
2234
-        // grab status
2235
-        if (empty($event_status)) {
2236
-            $msg = esc_html__(
2237
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2238
-                'event_espresso'
2239
-            );
2240
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2241
-            return false;
2242
-        }
2243
-        // was event trashed or restored ?
2244
-        switch ($event_status) {
2245
-            case 'draft':
2246
-                $action = 'restored from the trash';
2247
-                $hook   = 'AHEE_event_restored_from_trash';
2248
-                break;
2249
-            case 'trash':
2250
-                $action = 'moved to the trash';
2251
-                $hook   = 'AHEE_event_moved_to_trash';
2252
-                break;
2253
-            default:
2254
-                $action = 'updated';
2255
-                $hook   = false;
2256
-        }
2257
-        // use class to change status
2258
-        $this->_cpt_model_obj->set_status($event_status);
2259
-        $success = $this->_cpt_model_obj->save();
2260
-        if (! $success) {
2261
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2262
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2263
-            return false;
2264
-        }
2265
-        if ($hook) {
2266
-            do_action($hook);
2267
-            // fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2268
-            // because events side step that and it otherwise won't get called
2269
-            do_action(
2270
-                'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2271
-                $this->_cpt_model_obj,
2272
-                $hook === 'AHEE_event_moved_to_trash',
2273
-                $success
2274
-            );
2275
-        }
2276
-        return true;
2277
-    }
2278
-
2279
-
2280
-    /**
2281
-     * @param array $event_ids
2282
-     * @return array
2283
-     * @since   4.10.23.p
2284
-     */
2285
-    private function cleanEventIds(array $event_ids): array
2286
-    {
2287
-        return array_map('absint', $event_ids);
2288
-    }
2289
-
2290
-
2291
-    /**
2292
-     * @return array
2293
-     * @since   4.10.23.p
2294
-     */
2295
-    private function getEventIdsFromRequest(): array
2296
-    {
2297
-        if ($this->request->requestParamIsSet('EVT_IDs')) {
2298
-            return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2299
-        } else {
2300
-            return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2301
-        }
2302
-    }
2303
-
2304
-
2305
-    /**
2306
-     * @param bool $preview_delete
2307
-     * @throws EE_Error
2308
-     * @throws ReflectionException
2309
-     */
2310
-    protected function _delete_event(bool $preview_delete = true)
2311
-    {
2312
-        $this->_delete_events($preview_delete);
2313
-    }
2314
-
2315
-
2316
-    /**
2317
-     * Gets the tree traversal batch persister.
2318
-     *
2319
-     * @return NodeGroupDao
2320
-     * @throws InvalidArgumentException
2321
-     * @throws InvalidDataTypeException
2322
-     * @throws InvalidInterfaceException
2323
-     * @since 4.10.12.p
2324
-     */
2325
-    protected function getModelObjNodeGroupPersister(): NodeGroupDao
2326
-    {
2327
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2328
-            $this->model_obj_node_group_persister =
2329
-                $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2330
-        }
2331
-        return $this->model_obj_node_group_persister;
2332
-    }
2333
-
2334
-
2335
-    /**
2336
-     * @param bool $preview_delete
2337
-     * @return void
2338
-     * @throws EE_Error
2339
-     * @throws ReflectionException
2340
-     */
2341
-    protected function _delete_events(bool $preview_delete = true)
2342
-    {
2343
-        $event_ids = $this->getEventIdsFromRequest();
2344
-        if ($preview_delete) {
2345
-            $this->generateDeletionPreview($event_ids);
2346
-        } else {
2347
-            foreach ($event_ids as $event_id) {
2348
-                $event = EEM_Event::instance()->get_one_by_ID($event_id);
2349
-                if ($event instanceof EE_Event) {
2350
-                    $event->delete_permanently();
2351
-                }
2352
-            }
2353
-        }
2354
-    }
2355
-
2356
-
2357
-    /**
2358
-     * @param array $event_ids
2359
-     */
2360
-    protected function generateDeletionPreview(array $event_ids)
2361
-    {
2362
-        $event_ids = $this->cleanEventIds($event_ids);
2363
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2364
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2365
-        $return_url        = EE_Admin_Page::add_query_args_and_nonce(
2366
-            [
2367
-                'action'            => 'preview_deletion',
2368
-                'deletion_job_code' => $deletion_job_code,
2369
-            ],
2370
-            $this->_admin_base_url
2371
-        );
2372
-        EEH_URL::safeRedirectAndExit(
2373
-            EE_Admin_Page::add_query_args_and_nonce(
2374
-                [
2375
-                    'page'              => EED_Batch::PAGE_SLUG,
2376
-                    'batch'             => EED_Batch::batch_job,
2377
-                    'EVT_IDs'           => $event_ids,
2378
-                    'deletion_job_code' => $deletion_job_code,
2379
-                    'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2380
-                    'return_url'        => urlencode($return_url),
2381
-                ],
2382
-                admin_url()
2383
-            )
2384
-        );
2385
-    }
2386
-
2387
-
2388
-    /**
2389
-     * Checks for a POST submission
2390
-     *
2391
-     * @since 4.10.12.p
2392
-     */
2393
-    protected function confirmDeletion()
2394
-    {
2395
-        $deletion_redirect_logic = $this->getLoader()->getShared(
2396
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2397
-        );
2398
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2399
-    }
2400
-
2401
-
2402
-    /**
2403
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2404
-     *
2405
-     * @throws EE_Error
2406
-     * @since 4.10.12.p
2407
-     */
2408
-    protected function previewDeletion()
2409
-    {
2410
-        $preview_deletion_logic = $this->getLoader()->getShared(
2411
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2412
-        );
2413
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2414
-        $this->display_admin_page_with_no_sidebar();
2415
-    }
2416
-
2417
-
2418
-    /**
2419
-     * get total number of events
2420
-     *
2421
-     * @access public
2422
-     * @return int
2423
-     * @throws EE_Error
2424
-     * @throws EE_Error
2425
-     * @throws ReflectionException
2426
-     */
2427
-    public function total_events(): int
2428
-    {
2429
-        return EEM_Event::instance()->count(
2430
-            ['caps' => 'read_admin'],
2431
-            'EVT_ID',
2432
-            true
2433
-        );
2434
-    }
2435
-
2436
-
2437
-    /**
2438
-     * get total number of draft events
2439
-     *
2440
-     * @access public
2441
-     * @return int
2442
-     * @throws EE_Error
2443
-     * @throws EE_Error
2444
-     * @throws ReflectionException
2445
-     */
2446
-    public function total_events_draft(): int
2447
-    {
2448
-        return EEM_Event::instance()->count(
2449
-            [
2450
-                ['status' => ['IN', ['draft', 'auto-draft']]],
2451
-                'caps' => 'read_admin',
2452
-            ],
2453
-            'EVT_ID',
2454
-            true
2455
-        );
2456
-    }
2457
-
2458
-
2459
-    /**
2460
-     * get total number of trashed events
2461
-     *
2462
-     * @access public
2463
-     * @return int
2464
-     * @throws EE_Error
2465
-     * @throws EE_Error
2466
-     * @throws ReflectionException
2467
-     */
2468
-    public function total_trashed_events(): int
2469
-    {
2470
-        return EEM_Event::instance()->count(
2471
-            [
2472
-                ['status' => 'trash'],
2473
-                'caps' => 'read_admin',
2474
-            ],
2475
-            'EVT_ID',
2476
-            true
2477
-        );
2478
-    }
2479
-
2480
-
2481
-    /**
2482
-     *    _default_event_settings
2483
-     *    This generates the Default Settings Tab
2484
-     *
2485
-     * @return void
2486
-     * @throws DomainException
2487
-     * @throws EE_Error
2488
-     * @throws InvalidArgumentException
2489
-     * @throws InvalidDataTypeException
2490
-     * @throws InvalidInterfaceException
2491
-     */
2492
-    protected function _default_event_settings()
2493
-    {
2494
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2495
-        $this->_set_publish_post_box_vars();
2496
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
2497
-            $this->_default_event_settings_form()->get_html(),
2498
-            '',
2499
-            'padding'
2500
-        );
2501
-        $this->display_admin_page_with_sidebar();
2502
-    }
2503
-
2504
-
2505
-    /**
2506
-     * Return the form for event settings.
2507
-     *
2508
-     * @return EE_Form_Section_Proper
2509
-     * @throws EE_Error
2510
-     */
2511
-    protected function _default_event_settings_form(): EE_Form_Section_Proper
2512
-    {
2513
-        $registration_config              = EE_Registry::instance()->CFG->registration;
2514
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2515
-        // exclude
2516
-            [
2517
-                EEM_Registration::status_id_cancelled,
2518
-                EEM_Registration::status_id_declined,
2519
-                EEM_Registration::status_id_incomplete,
2520
-                EEM_Registration::status_id_wait_list,
2521
-            ],
2522
-            true
2523
-        );
2524
-        // setup Advanced Editor ???
2525
-        if (
2526
-            $this->raw_req_action === 'default_event_settings'
2527
-            || $this->raw_req_action === 'update_default_event_settings'
2528
-        ) {
2529
-            $this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2530
-        }
2531
-        return new EE_Form_Section_Proper(
2532
-            [
2533
-                'name'            => 'update_default_event_settings',
2534
-                'html_id'         => 'update_default_event_settings',
2535
-                'html_class'      => 'form-table',
2536
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2537
-                'subsections'     => apply_filters(
2538
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2539
-                    [
2540
-                        'defaults_section_header' => new EE_Form_Section_HTML(
2541
-                            EEH_HTML::h2(
2542
-                                esc_html__('Default Settings', 'event_espresso'),
2543
-                                '',
2544
-                                'ee-admin-settings-hdr'
2545
-                            )
2546
-                        ),
2547
-                        'default_reg_status'      => new EE_Select_Input(
2548
-                            $registration_stati_for_selection,
2549
-                            [
2550
-                                'default'         => isset($registration_config->default_STS_ID)
2551
-                                                     && array_key_exists(
2552
-                                                         $registration_config->default_STS_ID,
2553
-                                                         $registration_stati_for_selection
2554
-                                                     )
2555
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2556
-                                    : EEM_Registration::status_id_pending_payment,
2557
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2558
-                                                     . EEH_Template::get_help_tab_link(
2559
-                                                         'default_settings_status_help_tab'
2560
-                                                     ),
2561
-                                'html_help_text'  => esc_html__(
2562
-                                    '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.',
2563
-                                    'event_espresso'
2564
-                                ),
2565
-                            ]
2566
-                        ),
2567
-                        'default_max_tickets'     => new EE_Integer_Input(
2568
-                            [
2569
-                                'default'         => $registration_config->default_maximum_number_of_tickets
2570
-                                                     ?? EEM_Event::get_default_additional_limit(),
2571
-                                'html_label_text' => esc_html__(
2572
-                                    'Default Maximum Tickets Allowed Per Order:',
2573
-                                    'event_espresso'
2574
-                                )
2575
-                                                     . EEH_Template::get_help_tab_link(
2576
-                                                         'default_maximum_tickets_help_tab"'
2577
-                                                     ),
2578
-                                'html_help_text'  => esc_html__(
2579
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2580
-                                    'event_espresso'
2581
-                                ),
2582
-                            ]
2583
-                        ),
2584
-                    ]
2585
-                ),
2586
-            ]
2587
-        );
2588
-    }
2589
-
2590
-
2591
-    /**
2592
-     * @return void
2593
-     * @throws EE_Error
2594
-     * @throws InvalidArgumentException
2595
-     * @throws InvalidDataTypeException
2596
-     * @throws InvalidInterfaceException
2597
-     */
2598
-    protected function _update_default_event_settings()
2599
-    {
2600
-        $form = $this->_default_event_settings_form();
2601
-        if ($form->was_submitted()) {
2602
-            $form->receive_form_submission();
2603
-            if ($form->is_valid()) {
2604
-                $registration_config = EE_Registry::instance()->CFG->registration;
2605
-                $valid_data          = $form->valid_data();
2606
-                if (isset($valid_data['default_reg_status'])) {
2607
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2608
-                }
2609
-                if (isset($valid_data['default_max_tickets'])) {
2610
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2611
-                }
2612
-                do_action(
2613
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2614
-                    $valid_data,
2615
-                    EE_Registry::instance()->CFG,
2616
-                    $this
2617
-                );
2618
-                // update because data was valid!
2619
-                EE_Registry::instance()->CFG->update_espresso_config();
2620
-                EE_Error::overwrite_success();
2621
-                EE_Error::add_success(
2622
-                    esc_html__('Default Event Settings were updated', 'event_espresso')
2623
-                );
2624
-            }
2625
-        }
2626
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2627
-    }
2628
-
2629
-
2630
-    /*************        Templates        *************
2631
-     *
2632
-     * @throws EE_Error
2633
-     */
2634
-    protected function _template_settings()
2635
-    {
2636
-        $this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2637
-        $this->_template_args['preview_img']  = '<img src="'
2638
-                                                . EVENTS_ASSETS_URL
2639
-                                                . '/images/'
2640
-                                                . 'caffeinated_template_features.jpg" alt="'
2641
-                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2642
-                                                . '" />';
2643
-        $this->_template_args['preview_text'] = '<strong>'
2644
-                                                . esc_html__(
2645
-                                                    '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.',
2646
-                                                    'event_espresso'
2647
-                                                ) . '</strong>';
2648
-        $this->display_admin_caf_preview_page('template_settings_tab');
2649
-    }
2650
-
2651
-
2652
-    /** Event Category Stuff **/
2653
-    /**
2654
-     * set the _category property with the category object for the loaded page.
2655
-     *
2656
-     * @access private
2657
-     * @return void
2658
-     */
2659
-    private function _set_category_object()
2660
-    {
2661
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2662
-            return;
2663
-        } //already have the category object so get out.
2664
-        // set default category object
2665
-        $this->_set_empty_category_object();
2666
-        // only set if we've got an id
2667
-        $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2668
-        if (! $category_ID) {
2669
-            return;
2670
-        }
2671
-        $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2672
-        if (! empty($term)) {
2673
-            $this->_category->category_name       = $term->name;
2674
-            $this->_category->category_identifier = $term->slug;
2675
-            $this->_category->category_desc       = $term->description;
2676
-            $this->_category->id                  = $term->term_id;
2677
-            $this->_category->parent              = $term->parent;
2678
-        }
2679
-    }
2680
-
2681
-
2682
-    /**
2683
-     * Clears out category properties.
2684
-     */
2685
-    private function _set_empty_category_object()
2686
-    {
2687
-        $this->_category                = new stdClass();
2688
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2689
-        $this->_category->id            = $this->_category->parent = 0;
2690
-    }
2691
-
2692
-
2693
-    /**
2694
-     * @throws DomainException
2695
-     * @throws EE_Error
2696
-     * @throws InvalidArgumentException
2697
-     * @throws InvalidDataTypeException
2698
-     * @throws InvalidInterfaceException
2699
-     */
2700
-    protected function _category_list_table()
2701
-    {
2702
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2703
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2704
-        $this->_admin_page_title .= ' ';
2705
-        $this->_admin_page_title .= $this->get_action_link_or_button(
2706
-            'add_category',
2707
-            'add_category',
2708
-            [],
2709
-            'add-new-h2'
2710
-        );
2711
-        $this->display_admin_list_table_page_with_sidebar();
2712
-    }
2713
-
2714
-
2715
-    /**
2716
-     * Output category details view.
2717
-     *
2718
-     * @throws EE_Error
2719
-     * @throws EE_Error
2720
-     */
2721
-    protected function _category_details($view)
2722
-    {
2723
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2724
-        $this->_set_add_edit_form_tags($route);
2725
-        $this->_set_category_object();
2726
-        $id            = ! empty($this->_category->id) ? $this->_category->id : '';
2727
-        $delete_action = 'delete_category';
2728
-        // custom redirect
2729
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2730
-            ['action' => 'category_list'],
2731
-            $this->_admin_base_url
2732
-        );
2733
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect, true);
2734
-        // take care of contents
2735
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2736
-        $this->display_admin_page_with_sidebar();
2737
-    }
2738
-
2739
-
2740
-    /**
2741
-     * Output category details content.
2742
-     *
2743
-     * @throws DomainException
2744
-     */
2745
-    protected function _category_details_content(): string
2746
-    {
2747
-        $editor_args['category_desc'] = [
2748
-            'type'          => 'wp_editor',
2749
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2750
-            'class'         => 'my_editor_custom',
2751
-            'wpeditor_args' => ['media_buttons' => false],
2752
-        ];
2753
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2754
-        $all_terms                    = get_terms(
2755
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2756
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2757
-        );
2758
-        // setup category select for term parents.
2759
-        $category_select_values[] = [
2760
-            'text' => esc_html__('No Parent', 'event_espresso'),
2761
-            'id'   => 0,
2762
-        ];
2763
-        foreach ($all_terms as $term) {
2764
-            $category_select_values[] = [
2765
-                'text' => $term->name,
2766
-                'id'   => $term->term_id,
2767
-            ];
2768
-        }
2769
-        $category_select = EEH_Form_Fields::select_input(
2770
-            'category_parent',
2771
-            $category_select_values,
2772
-            $this->_category->parent
2773
-        );
2774
-        $template_args   = [
2775
-            'category'                 => $this->_category,
2776
-            'category_select'          => $category_select,
2777
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2778
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2779
-            'disable'                  => '',
2780
-            'disabled_message'         => false,
2781
-        ];
2782
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2783
-        return EEH_Template::display_template($template, $template_args, true);
2784
-    }
2785
-
2786
-
2787
-    /**
2788
-     * Handles deleting categories.
2789
-     *
2790
-     * @throws EE_Error
2791
-     */
2792
-    protected function _delete_categories()
2793
-    {
2794
-        $category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2795
-        foreach ($category_IDs as $category_ID) {
2796
-            $this->_delete_category($category_ID);
2797
-        }
2798
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2799
-        $query_args = [
2800
-            'action' => 'category_list',
2801
-        ];
2802
-        $this->_redirect_after_action(0, '', '', $query_args);
2803
-    }
2804
-
2805
-
2806
-    /**
2807
-     * Handles deleting specific category.
2808
-     *
2809
-     * @param int $cat_id
2810
-     */
2811
-    protected function _delete_category(int $cat_id)
2812
-    {
2813
-        $cat_id = absint($cat_id);
2814
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2815
-    }
2816
-
2817
-
2818
-    /**
2819
-     * Handles triggering the update or insertion of a new category.
2820
-     *
2821
-     * @param bool $new_category true means we're triggering the insert of a new category.
2822
-     * @throws EE_Error
2823
-     * @throws EE_Error
2824
-     */
2825
-    protected function _insert_or_update_category(bool $new_category)
2826
-    {
2827
-        $cat_id  = $this->_insert_category($new_category);
2828
-        $success = 0; // we already have a success message so lets not send another.
2829
-        if ($cat_id) {
2830
-            $query_args = [
2831
-                'action'     => 'edit_category',
2832
-                'EVT_CAT_ID' => $cat_id,
2833
-            ];
2834
-        } else {
2835
-            $query_args = ['action' => 'add_category'];
2836
-        }
2837
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2838
-    }
2839
-
2840
-
2841
-    /**
2842
-     * Inserts or updates category
2843
-     *
2844
-     * @param bool $new_category (true indicates we're updating a category).
2845
-     * @return bool|mixed|string
2846
-     */
2847
-    private function _insert_category(bool $new_category)
2848
-    {
2849
-        $category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2850
-        $category_name       = $this->request->getRequestParam('category_name', '');
2851
-        $category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2852
-        $category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2853
-        $category_identifier = $this->request->getRequestParam('category_identifier', '');
2854
-
2855
-        if (empty($category_name)) {
2856
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2857
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2858
-            return 0;
2859
-        }
2860
-        $term_args = [
2861
-            'name'        => $category_name,
2862
-            'description' => $category_desc,
2863
-            'parent'      => $category_parent,
2864
-        ];
2865
-        // was the category_identifier input disabled?
2866
-        if ($category_identifier) {
2867
-            $term_args['slug'] = $category_identifier;
2868
-        }
2869
-        $insert_ids = $new_category
2870
-            ? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2871
-            : wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2872
-
2873
-        if ($insert_ids instanceof WP_Error) {
2874
-            EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2875
-            return 0;
2876
-        }
2877
-        $category_ID = $insert_ids['term_id'] ?? 0;
2878
-        if (! $category_ID) {
2879
-            EE_Error::add_error(
2880
-                esc_html__(
2881
-                    'An error occurred and the category has not been saved to the database.',
2882
-                    'event_espresso'
2883
-                ),
2884
-                __FILE__,
2885
-                __FUNCTION__,
2886
-                __LINE__
2887
-            );
2888
-            return 0;
2889
-        }
2890
-        EE_Error::add_success(
2891
-            sprintf(
2892
-                esc_html__('The category %s was successfully saved', 'event_espresso'),
2893
-                $category_name
2894
-            )
2895
-        );
2896
-        return $category_ID;
2897
-    }
2898
-
2899
-
2900
-    /**
2901
-     * Gets categories or count of categories matching the arguments in the request.
2902
-     *
2903
-     * @param int  $per_page
2904
-     * @param int  $current_page
2905
-     * @param bool $count
2906
-     * @return EE_Term_Taxonomy[]|int
2907
-     * @throws EE_Error
2908
-     * @throws ReflectionException
2909
-     */
2910
-    public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2911
-    {
2912
-        // testing term stuff
2913
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2914
-        $order       = $this->request->getRequestParam('order', 'DESC');
2915
-        $limit       = ($current_page - 1) * $per_page;
2916
-        $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2917
-        $search_term = $this->request->getRequestParam('s');
2918
-        if ($search_term) {
2919
-            $search_term = '%' . $search_term . '%';
2920
-            $where['OR'] = [
2921
-                'Term.name'   => ['LIKE', $search_term],
2922
-                'description' => ['LIKE', $search_term],
2923
-            ];
2924
-        }
2925
-        $query_params = [
2926
-            $where,
2927
-            'order_by'   => [$orderby => $order],
2928
-            'limit'      => $limit . ',' . $per_page,
2929
-            'force_join' => ['Term'],
2930
-        ];
2931
-        return $count
2932
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2933
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2934
-    }
2935
-
2936
-    /* end category stuff */
2937
-
2938
-
2939
-    /**************/
2940
-
2941
-
2942
-    /**
2943
-     * Callback for the `ee_save_timezone_setting` ajax action.
2944
-     *
2945
-     * @throws EE_Error
2946
-     * @throws InvalidArgumentException
2947
-     * @throws InvalidDataTypeException
2948
-     * @throws InvalidInterfaceException
2949
-     */
2950
-    public function saveTimezoneString()
2951
-    {
2952
-        $timezone_string = $this->request->getRequestParam('timezone_selected');
2953
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2954
-            EE_Error::add_error(
2955
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2956
-                __FILE__,
2957
-                __FUNCTION__,
2958
-                __LINE__
2959
-            );
2960
-            $this->_template_args['error'] = true;
2961
-            $this->_return_json();
2962
-        }
2963
-
2964
-        update_option('timezone_string', $timezone_string);
2965
-        EE_Error::add_success(
2966
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2967
-        );
2968
-        $this->_template_args['success'] = true;
2969
-        $this->_return_json(true, ['action' => 'create_new']);
2970
-    }
2971
-
2972
-
2973
-    /**
2974 2632
      * @throws EE_Error
2975
-     * @deprecated 4.10.25.p
2976 2633
      */
2977
-    public function save_timezonestring_setting()
2978
-    {
2979
-        $this->saveTimezoneString();
2980
-    }
2634
+	protected function _template_settings()
2635
+	{
2636
+		$this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2637
+		$this->_template_args['preview_img']  = '<img src="'
2638
+												. EVENTS_ASSETS_URL
2639
+												. '/images/'
2640
+												. 'caffeinated_template_features.jpg" alt="'
2641
+												. esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2642
+												. '" />';
2643
+		$this->_template_args['preview_text'] = '<strong>'
2644
+												. esc_html__(
2645
+													'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.',
2646
+													'event_espresso'
2647
+												) . '</strong>';
2648
+		$this->display_admin_caf_preview_page('template_settings_tab');
2649
+	}
2650
+
2651
+
2652
+	/** Event Category Stuff **/
2653
+	/**
2654
+	 * set the _category property with the category object for the loaded page.
2655
+	 *
2656
+	 * @access private
2657
+	 * @return void
2658
+	 */
2659
+	private function _set_category_object()
2660
+	{
2661
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2662
+			return;
2663
+		} //already have the category object so get out.
2664
+		// set default category object
2665
+		$this->_set_empty_category_object();
2666
+		// only set if we've got an id
2667
+		$category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2668
+		if (! $category_ID) {
2669
+			return;
2670
+		}
2671
+		$term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2672
+		if (! empty($term)) {
2673
+			$this->_category->category_name       = $term->name;
2674
+			$this->_category->category_identifier = $term->slug;
2675
+			$this->_category->category_desc       = $term->description;
2676
+			$this->_category->id                  = $term->term_id;
2677
+			$this->_category->parent              = $term->parent;
2678
+		}
2679
+	}
2680
+
2681
+
2682
+	/**
2683
+	 * Clears out category properties.
2684
+	 */
2685
+	private function _set_empty_category_object()
2686
+	{
2687
+		$this->_category                = new stdClass();
2688
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2689
+		$this->_category->id            = $this->_category->parent = 0;
2690
+	}
2691
+
2692
+
2693
+	/**
2694
+	 * @throws DomainException
2695
+	 * @throws EE_Error
2696
+	 * @throws InvalidArgumentException
2697
+	 * @throws InvalidDataTypeException
2698
+	 * @throws InvalidInterfaceException
2699
+	 */
2700
+	protected function _category_list_table()
2701
+	{
2702
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2703
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2704
+		$this->_admin_page_title .= ' ';
2705
+		$this->_admin_page_title .= $this->get_action_link_or_button(
2706
+			'add_category',
2707
+			'add_category',
2708
+			[],
2709
+			'add-new-h2'
2710
+		);
2711
+		$this->display_admin_list_table_page_with_sidebar();
2712
+	}
2713
+
2714
+
2715
+	/**
2716
+	 * Output category details view.
2717
+	 *
2718
+	 * @throws EE_Error
2719
+	 * @throws EE_Error
2720
+	 */
2721
+	protected function _category_details($view)
2722
+	{
2723
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2724
+		$this->_set_add_edit_form_tags($route);
2725
+		$this->_set_category_object();
2726
+		$id            = ! empty($this->_category->id) ? $this->_category->id : '';
2727
+		$delete_action = 'delete_category';
2728
+		// custom redirect
2729
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2730
+			['action' => 'category_list'],
2731
+			$this->_admin_base_url
2732
+		);
2733
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect, true);
2734
+		// take care of contents
2735
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2736
+		$this->display_admin_page_with_sidebar();
2737
+	}
2738
+
2739
+
2740
+	/**
2741
+	 * Output category details content.
2742
+	 *
2743
+	 * @throws DomainException
2744
+	 */
2745
+	protected function _category_details_content(): string
2746
+	{
2747
+		$editor_args['category_desc'] = [
2748
+			'type'          => 'wp_editor',
2749
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2750
+			'class'         => 'my_editor_custom',
2751
+			'wpeditor_args' => ['media_buttons' => false],
2752
+		];
2753
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2754
+		$all_terms                    = get_terms(
2755
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2756
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2757
+		);
2758
+		// setup category select for term parents.
2759
+		$category_select_values[] = [
2760
+			'text' => esc_html__('No Parent', 'event_espresso'),
2761
+			'id'   => 0,
2762
+		];
2763
+		foreach ($all_terms as $term) {
2764
+			$category_select_values[] = [
2765
+				'text' => $term->name,
2766
+				'id'   => $term->term_id,
2767
+			];
2768
+		}
2769
+		$category_select = EEH_Form_Fields::select_input(
2770
+			'category_parent',
2771
+			$category_select_values,
2772
+			$this->_category->parent
2773
+		);
2774
+		$template_args   = [
2775
+			'category'                 => $this->_category,
2776
+			'category_select'          => $category_select,
2777
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2778
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2779
+			'disable'                  => '',
2780
+			'disabled_message'         => false,
2781
+		];
2782
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2783
+		return EEH_Template::display_template($template, $template_args, true);
2784
+	}
2785
+
2786
+
2787
+	/**
2788
+	 * Handles deleting categories.
2789
+	 *
2790
+	 * @throws EE_Error
2791
+	 */
2792
+	protected function _delete_categories()
2793
+	{
2794
+		$category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2795
+		foreach ($category_IDs as $category_ID) {
2796
+			$this->_delete_category($category_ID);
2797
+		}
2798
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2799
+		$query_args = [
2800
+			'action' => 'category_list',
2801
+		];
2802
+		$this->_redirect_after_action(0, '', '', $query_args);
2803
+	}
2804
+
2805
+
2806
+	/**
2807
+	 * Handles deleting specific category.
2808
+	 *
2809
+	 * @param int $cat_id
2810
+	 */
2811
+	protected function _delete_category(int $cat_id)
2812
+	{
2813
+		$cat_id = absint($cat_id);
2814
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2815
+	}
2816
+
2817
+
2818
+	/**
2819
+	 * Handles triggering the update or insertion of a new category.
2820
+	 *
2821
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2822
+	 * @throws EE_Error
2823
+	 * @throws EE_Error
2824
+	 */
2825
+	protected function _insert_or_update_category(bool $new_category)
2826
+	{
2827
+		$cat_id  = $this->_insert_category($new_category);
2828
+		$success = 0; // we already have a success message so lets not send another.
2829
+		if ($cat_id) {
2830
+			$query_args = [
2831
+				'action'     => 'edit_category',
2832
+				'EVT_CAT_ID' => $cat_id,
2833
+			];
2834
+		} else {
2835
+			$query_args = ['action' => 'add_category'];
2836
+		}
2837
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2838
+	}
2839
+
2840
+
2841
+	/**
2842
+	 * Inserts or updates category
2843
+	 *
2844
+	 * @param bool $new_category (true indicates we're updating a category).
2845
+	 * @return bool|mixed|string
2846
+	 */
2847
+	private function _insert_category(bool $new_category)
2848
+	{
2849
+		$category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2850
+		$category_name       = $this->request->getRequestParam('category_name', '');
2851
+		$category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2852
+		$category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2853
+		$category_identifier = $this->request->getRequestParam('category_identifier', '');
2854
+
2855
+		if (empty($category_name)) {
2856
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2857
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2858
+			return 0;
2859
+		}
2860
+		$term_args = [
2861
+			'name'        => $category_name,
2862
+			'description' => $category_desc,
2863
+			'parent'      => $category_parent,
2864
+		];
2865
+		// was the category_identifier input disabled?
2866
+		if ($category_identifier) {
2867
+			$term_args['slug'] = $category_identifier;
2868
+		}
2869
+		$insert_ids = $new_category
2870
+			? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2871
+			: wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2872
+
2873
+		if ($insert_ids instanceof WP_Error) {
2874
+			EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2875
+			return 0;
2876
+		}
2877
+		$category_ID = $insert_ids['term_id'] ?? 0;
2878
+		if (! $category_ID) {
2879
+			EE_Error::add_error(
2880
+				esc_html__(
2881
+					'An error occurred and the category has not been saved to the database.',
2882
+					'event_espresso'
2883
+				),
2884
+				__FILE__,
2885
+				__FUNCTION__,
2886
+				__LINE__
2887
+			);
2888
+			return 0;
2889
+		}
2890
+		EE_Error::add_success(
2891
+			sprintf(
2892
+				esc_html__('The category %s was successfully saved', 'event_espresso'),
2893
+				$category_name
2894
+			)
2895
+		);
2896
+		return $category_ID;
2897
+	}
2898
+
2899
+
2900
+	/**
2901
+	 * Gets categories or count of categories matching the arguments in the request.
2902
+	 *
2903
+	 * @param int  $per_page
2904
+	 * @param int  $current_page
2905
+	 * @param bool $count
2906
+	 * @return EE_Term_Taxonomy[]|int
2907
+	 * @throws EE_Error
2908
+	 * @throws ReflectionException
2909
+	 */
2910
+	public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2911
+	{
2912
+		// testing term stuff
2913
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2914
+		$order       = $this->request->getRequestParam('order', 'DESC');
2915
+		$limit       = ($current_page - 1) * $per_page;
2916
+		$where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2917
+		$search_term = $this->request->getRequestParam('s');
2918
+		if ($search_term) {
2919
+			$search_term = '%' . $search_term . '%';
2920
+			$where['OR'] = [
2921
+				'Term.name'   => ['LIKE', $search_term],
2922
+				'description' => ['LIKE', $search_term],
2923
+			];
2924
+		}
2925
+		$query_params = [
2926
+			$where,
2927
+			'order_by'   => [$orderby => $order],
2928
+			'limit'      => $limit . ',' . $per_page,
2929
+			'force_join' => ['Term'],
2930
+		];
2931
+		return $count
2932
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2933
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2934
+	}
2935
+
2936
+	/* end category stuff */
2937
+
2938
+
2939
+	/**************/
2940
+
2941
+
2942
+	/**
2943
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2944
+	 *
2945
+	 * @throws EE_Error
2946
+	 * @throws InvalidArgumentException
2947
+	 * @throws InvalidDataTypeException
2948
+	 * @throws InvalidInterfaceException
2949
+	 */
2950
+	public function saveTimezoneString()
2951
+	{
2952
+		$timezone_string = $this->request->getRequestParam('timezone_selected');
2953
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2954
+			EE_Error::add_error(
2955
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2956
+				__FILE__,
2957
+				__FUNCTION__,
2958
+				__LINE__
2959
+			);
2960
+			$this->_template_args['error'] = true;
2961
+			$this->_return_json();
2962
+		}
2963
+
2964
+		update_option('timezone_string', $timezone_string);
2965
+		EE_Error::add_success(
2966
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2967
+		);
2968
+		$this->_template_args['success'] = true;
2969
+		$this->_return_json(true, ['action' => 'create_new']);
2970
+	}
2971
+
2972
+
2973
+	/**
2974
+	 * @throws EE_Error
2975
+	 * @deprecated 4.10.25.p
2976
+	 */
2977
+	public function save_timezonestring_setting()
2978
+	{
2979
+		$this->saveTimezoneString();
2980
+	}
2981 2981
 }
Please login to merge, or discard this patch.
Spacing   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -589,13 +589,13 @@  discard block
 block discarded – undo
589 589
     {
590 590
         wp_register_style(
591 591
             'events-admin-css',
592
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
592
+            EVENTS_ASSETS_URL.'events-admin-page.css',
593 593
             [],
594 594
             EVENT_ESPRESSO_VERSION
595 595
         );
596 596
         wp_register_style(
597 597
             'ee-cat-admin',
598
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
598
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
599 599
             [],
600 600
             EVENT_ESPRESSO_VERSION
601 601
         );
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
         // scripts
605 605
         wp_register_script(
606 606
             'event_editor_js',
607
-            EVENTS_ASSETS_URL . 'event_editor.js',
607
+            EVENTS_ASSETS_URL.'event_editor.js',
608 608
             ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
609 609
             EVENT_ESPRESSO_VERSION,
610 610
             true
@@ -630,16 +630,16 @@  discard block
 block discarded – undo
630 630
         wp_enqueue_style('espresso-ui-theme');
631 631
         wp_register_style(
632 632
             'event-editor-css',
633
-            EVENTS_ASSETS_URL . 'event-editor.css',
633
+            EVENTS_ASSETS_URL.'event-editor.css',
634 634
             ['ee-admin-css'],
635 635
             EVENT_ESPRESSO_VERSION
636 636
         );
637 637
         wp_enqueue_style('event-editor-css');
638 638
         // scripts
639
-        if (! $this->admin_config->useAdvancedEditor()) {
639
+        if ( ! $this->admin_config->useAdvancedEditor()) {
640 640
             wp_register_script(
641 641
                 'event-datetime-metabox',
642
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
642
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
643 643
                 ['event_editor_js', 'ee-datepicker'],
644 644
                 EVENT_ESPRESSO_VERSION
645 645
             );
@@ -709,15 +709,15 @@  discard block
 block discarded – undo
709 709
     public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
710 710
     {
711 711
         // don't need to do this when processing
712
-        if (! empty($req_type)) {
712
+        if ( ! empty($req_type)) {
713 713
             return;
714 714
         }
715 715
         // no event?
716
-        if (! $event instanceof EE_Event) {
716
+        if ( ! $event instanceof EE_Event) {
717 717
             $event = $this->_cpt_model_obj;
718 718
         }
719 719
         // STILL no event?
720
-        if (! $event instanceof EE_Event) {
720
+        if ( ! $event instanceof EE_Event) {
721 721
             return;
722 722
         }
723 723
         // don't need to keep calling this
@@ -762,7 +762,7 @@  discard block
 block discarded – undo
762 762
             );
763 763
         }
764 764
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
765
-        if (! $event->tickets_on_sale()) {
765
+        if ( ! $event->tickets_on_sale()) {
766 766
             return;
767 767
         }
768 768
         // made it here so show warning
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
     {
812 812
         $has_timezone_string = get_option('timezone_string');
813 813
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
814
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
814
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
815 815
             EE_Error::add_attention(
816 816
                 sprintf(
817 817
                     esc_html__(
@@ -880,7 +880,7 @@  discard block
 block discarded – undo
880 880
      */
881 881
     protected function _event_legend_items(): array
882 882
     {
883
-        $items    = [
883
+        $items = [
884 884
             'view_details'   => [
885 885
                 'class' => 'dashicons dashicons-visibility',
886 886
                 'desc'  => esc_html__('View Event', 'event_espresso'),
@@ -897,31 +897,31 @@  discard block
 block discarded – undo
897 897
         $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
898 898
         $statuses = [
899 899
             'sold_out_status'  => [
900
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
900
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::sold_out,
901 901
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
902 902
             ],
903 903
             'active_status'    => [
904
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
904
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::active,
905 905
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
906 906
             ],
907 907
             'upcoming_status'  => [
908
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
908
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::upcoming,
909 909
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
910 910
             ],
911 911
             'postponed_status' => [
912
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
912
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::postponed,
913 913
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
914 914
             ],
915 915
             'cancelled_status' => [
916
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
916
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::cancelled,
917 917
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
918 918
             ],
919 919
             'expired_status'   => [
920
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
920
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::expired,
921 921
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
922 922
             ],
923 923
             'inactive_status'  => [
924
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
924
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::inactive,
925 925
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
926 926
             ],
927 927
         ];
@@ -940,7 +940,7 @@  discard block
 block discarded – undo
940 940
      */
941 941
     private function _event_model(): EEM_Event
942 942
     {
943
-        if (! $this->_event_model instanceof EEM_Event) {
943
+        if ( ! $this->_event_model instanceof EEM_Event) {
944 944
             $this->_event_model = EE_Registry::instance()->load_model('Event');
945 945
         }
946 946
         return $this->_event_model;
@@ -995,12 +995,12 @@  discard block
 block discarded – undo
995 995
             '',
996 996
             'ee-admin-button-row ee-admin-button-row--align-start'
997 997
         );
998
-        $links_html       .= EEH_HTML::divx();
998
+        $links_html .= EEH_HTML::divx();
999 999
 
1000 1000
         $after_list_table['view_event_list_button'] = $links_html;
1001 1001
 
1002 1002
         $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
1003
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
1003
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1004 1004
             'create_new',
1005 1005
             'add',
1006 1006
             [],
@@ -1064,13 +1064,13 @@  discard block
 block discarded – undo
1064 1064
             'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1065 1065
         ];
1066 1066
         // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1067
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1068
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1067
+        if ( ! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1068
+            $event_values['EVT_display_ticket_selector'] = $this->request->getRequestParam(
1069 1069
                 'display_ticket_selector',
1070 1070
                 false,
1071 1071
                 'bool'
1072 1072
             );
1073
-            $event_values['EVT_additional_limit']            = min(
1073
+            $event_values['EVT_additional_limit'] = min(
1074 1074
                 apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1075 1075
                 $this->request->getRequestParam(
1076 1076
                     'additional_limit',
@@ -1114,7 +1114,7 @@  discard block
 block discarded – undo
1114 1114
         // the following are default callbacks for event attachment updates
1115 1115
         // that can be overridden by caffeinated functionality and/or addons.
1116 1116
         $event_update_callbacks = [];
1117
-        if (! $this->admin_config->useAdvancedEditor()) {
1117
+        if ( ! $this->admin_config->useAdvancedEditor()) {
1118 1118
             $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1119 1119
             $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1120 1120
         }
@@ -1185,7 +1185,7 @@  discard block
 block discarded – undo
1185 1185
      */
1186 1186
     protected function _default_venue_update(EE_Event $event, array $data): bool
1187 1187
     {
1188
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1188
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1189 1189
         $venue_model = EE_Registry::instance()->load_model('Venue');
1190 1190
         $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1191 1191
         // very important.  If we don't have a venue name...
@@ -1216,7 +1216,7 @@  discard block
 block discarded – undo
1216 1216
             'status'              => 'publish',
1217 1217
         ];
1218 1218
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1219
-        if (! empty($venue_id)) {
1219
+        if ( ! empty($venue_id)) {
1220 1220
             $update_where  = [$venue_model->primary_key_name() => $venue_id];
1221 1221
             $rows_affected = $venue_model->update($venue_array, [$update_where]);
1222 1222
             // we've gotta make sure that the venue is always attached to a revision..
@@ -1258,7 +1258,7 @@  discard block
 block discarded – undo
1258 1258
                 isset($datetime_data['DTT_EVT_end']) && ! empty($datetime_data['DTT_EVT_end'])
1259 1259
                     ? $datetime_data['DTT_EVT_end']
1260 1260
                     : $datetime_data['DTT_EVT_start'];
1261
-            $datetime_values              = [
1261
+            $datetime_values = [
1262 1262
                 'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1263 1263
                 'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1264 1264
                 'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
@@ -1267,9 +1267,9 @@  discard block
 block discarded – undo
1267 1267
             ];
1268 1268
             // if we have an id then let's get existing object first and then set the new values.
1269 1269
             //  Otherwise we instantiate a new object for save.
1270
-            if (! empty($datetime_data['DTT_ID'])) {
1270
+            if ( ! empty($datetime_data['DTT_ID'])) {
1271 1271
                 $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1272
-                if (! $datetime instanceof EE_Datetime) {
1272
+                if ( ! $datetime instanceof EE_Datetime) {
1273 1273
                     throw new RuntimeException(
1274 1274
                         sprintf(
1275 1275
                             esc_html__(
@@ -1288,7 +1288,7 @@  discard block
 block discarded – undo
1288 1288
             } else {
1289 1289
                 $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1290 1290
             }
1291
-            if (! $datetime instanceof EE_Datetime) {
1291
+            if ( ! $datetime instanceof EE_Datetime) {
1292 1292
                 throw new RuntimeException(
1293 1293
                     sprintf(
1294 1294
                         esc_html__(
@@ -1314,7 +1314,7 @@  discard block
 block discarded – undo
1314 1314
 
1315 1315
         // set up some default start and end dates in case those are not present in the incoming data
1316 1316
         $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1317
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1317
+        $default_start_date = $default_start_date->format($date_formats[0].' '.$date_formats[1]);
1318 1318
         // use the start date of the first datetime for the end date
1319 1319
         $first_datetime   = $event->first_datetime();
1320 1320
         $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
@@ -1322,7 +1322,7 @@  discard block
 block discarded – undo
1322 1322
         // now process the incoming data
1323 1323
         foreach ($data['edit_tickets'] as $row => $ticket_data) {
1324 1324
             $update_prices = false;
1325
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1325
+            $ticket_price  = $data['edit_prices'][$row][1]['PRC_amount'] ?? 0;
1326 1326
             // trim inputs to ensure any excess whitespace is removed.
1327 1327
             $ticket_data   = array_map('trim', $ticket_data);
1328 1328
             $ticket_values = [
@@ -1362,9 +1362,9 @@  discard block
 block discarded – undo
1362 1362
             // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1363 1363
             // keep in mind that if the ticket has been sold (and we have changed pricing information),
1364 1364
             // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1365
-            if (! empty($ticket_data['TKT_ID'])) {
1365
+            if ( ! empty($ticket_data['TKT_ID'])) {
1366 1366
                 $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1367
-                if (! $existing_ticket instanceof EE_Ticket) {
1367
+                if ( ! $existing_ticket instanceof EE_Ticket) {
1368 1368
                     throw new RuntimeException(
1369 1369
                         sprintf(
1370 1370
                             esc_html__(
@@ -1413,7 +1413,7 @@  discard block
 block discarded – undo
1413 1413
                     $existing_ticket->save();
1414 1414
                     // make sure this ticket is still recorded in our $saved_tickets
1415 1415
                     // so we don't run it through the regular trash routine.
1416
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1416
+                    $saved_tickets[$existing_ticket->ID()] = $existing_ticket;
1417 1417
                     // create new ticket that's a copy of the existing except,
1418 1418
                     // (a new id of course and not archived) AND has the new TKT_price associated with it.
1419 1419
                     $new_ticket = clone $existing_ticket;
@@ -1430,7 +1430,7 @@  discard block
 block discarded – undo
1430 1430
                 $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1431 1431
                 $update_prices              = true;
1432 1432
             }
1433
-            if (! $ticket instanceof EE_Ticket) {
1433
+            if ( ! $ticket instanceof EE_Ticket) {
1434 1434
                 throw new RuntimeException(
1435 1435
                     sprintf(
1436 1436
                         esc_html__(
@@ -1454,10 +1454,10 @@  discard block
 block discarded – undo
1454 1454
             }
1455 1455
             // initially let's add the ticket to the datetime
1456 1456
             $datetime->_add_relation_to($ticket, 'Ticket');
1457
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1457
+            $saved_tickets[$ticket->ID()] = $ticket;
1458 1458
             // add prices to ticket
1459
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1460
-                ? $data['edit_prices'][ $row ]
1459
+            $prices_data = isset($data['edit_prices'][$row]) && is_array($data['edit_prices'][$row])
1460
+                ? $data['edit_prices'][$row]
1461 1461
                 : [];
1462 1462
             $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1463 1463
         }
@@ -1471,7 +1471,7 @@  discard block
 block discarded – undo
1471 1471
             $id = absint($id);
1472 1472
             // get the ticket for this id
1473 1473
             $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1474
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1474
+            if ( ! $ticket_to_remove instanceof EE_Ticket) {
1475 1475
                 continue;
1476 1476
             }
1477 1477
             // need to get all the related datetimes on this ticket and remove from every single one of them
@@ -1528,7 +1528,7 @@  discard block
 block discarded – undo
1528 1528
                     $price->set($field, $new_price);
1529 1529
                 }
1530 1530
             }
1531
-            if (! $price instanceof EE_Price) {
1531
+            if ( ! $price instanceof EE_Price) {
1532 1532
                 throw new RuntimeException(
1533 1533
                     sprintf(
1534 1534
                         esc_html__(
@@ -1570,13 +1570,13 @@  discard block
 block discarded – undo
1570 1570
     {
1571 1571
         // load formatter helper
1572 1572
         // args for getting related registrations
1573
-        $approved_query_args        = [
1573
+        $approved_query_args = [
1574 1574
             [
1575 1575
                 'REG_deleted' => 0,
1576 1576
                 'STS_ID'      => EEM_Registration::status_id_approved,
1577 1577
             ],
1578 1578
         ];
1579
-        $not_approved_query_args    = [
1579
+        $not_approved_query_args = [
1580 1580
             [
1581 1581
                 'REG_deleted' => 0,
1582 1582
                 'STS_ID'      => EEM_Registration::status_id_not_approved,
@@ -1642,7 +1642,7 @@  discard block
 block discarded – undo
1642 1642
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1643 1643
         // load template
1644 1644
         EEH_Template::display_template(
1645
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1645
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1646 1646
             $publish_box_extra_args
1647 1647
         );
1648 1648
     }
@@ -1673,7 +1673,7 @@  discard block
 block discarded – undo
1673 1673
         $this->verify_cpt_object();
1674 1674
         $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1675 1675
         // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1676
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1676
+        if ( ! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1677 1677
             $this->addMetaBox(
1678 1678
                 'espresso_event_editor_event_options',
1679 1679
                 esc_html__('Event Registration Options', 'event_espresso'),
@@ -1682,7 +1682,7 @@  discard block
 block discarded – undo
1682 1682
                 'side'
1683 1683
             );
1684 1684
         }
1685
-        if (! $use_advanced_editor) {
1685
+        if ( ! $use_advanced_editor) {
1686 1686
             $this->addMetaBox(
1687 1687
                 'espresso_event_editor_tickets',
1688 1688
                 esc_html__('Event Datetime & Ticket', 'event_espresso'),
@@ -1694,7 +1694,7 @@  discard block
 block discarded – undo
1694 1694
         } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1695 1695
             add_action(
1696 1696
                 'add_meta_boxes_espresso_events',
1697
-                function () {
1697
+                function() {
1698 1698
                     global $current_screen;
1699 1699
                     remove_meta_box('authordiv', $current_screen, 'normal');
1700 1700
                 },
@@ -1723,7 +1723,7 @@  discard block
 block discarded – undo
1723 1723
             'trash_icon'        => 'dashicons dashicons-lock',
1724 1724
             'disabled'          => '',
1725 1725
         ];
1726
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1726
+        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1727 1727
         /**
1728 1728
          * 1. Start with retrieving Datetimes
1729 1729
          * 2. Fore each datetime get related tickets
@@ -1749,24 +1749,24 @@  discard block
 block discarded – undo
1749 1749
                     'default_where_conditions' => 'none',
1750 1750
                 ]
1751 1751
             );
1752
-            if (! empty($related_tickets)) {
1752
+            if ( ! empty($related_tickets)) {
1753 1753
                 $template_args['total_ticket_rows'] = count($related_tickets);
1754 1754
                 $row                                = 0;
1755 1755
                 foreach ($related_tickets as $ticket) {
1756
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1756
+                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1757 1757
                     $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1758 1758
                     $row++;
1759 1759
                 }
1760 1760
             } else {
1761 1761
                 $template_args['total_ticket_rows'] = 1;
1762 1762
                 /** @type EE_Ticket $ticket */
1763
-                $ticket                       = $ticket_model->create_default_object();
1763
+                $ticket = $ticket_model->create_default_object();
1764 1764
                 $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1765 1765
             }
1766 1766
         } else {
1767 1767
             $template_args['time'] = $times[0];
1768 1768
             /** @type EE_Ticket[] $tickets */
1769
-            $tickets                      = $ticket_model->get_all_default_tickets();
1769
+            $tickets = $ticket_model->get_all_default_tickets();
1770 1770
             $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1771 1771
             // NOTE: we're just sending the first default row
1772 1772
             // (decaf can't manage default tickets so this should be sufficient);
@@ -1781,9 +1781,9 @@  discard block
 block discarded – undo
1781 1781
             $ticket_model->create_default_object(),
1782 1782
             true
1783 1783
         );
1784
-        $template                                  = apply_filters(
1784
+        $template = apply_filters(
1785 1785
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1786
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1786
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1787 1787
         );
1788 1788
         EEH_Template::display_template($template, $template_args);
1789 1789
     }
@@ -1803,7 +1803,7 @@  discard block
 block discarded – undo
1803 1803
     private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1804 1804
     {
1805 1805
         $template_args = [
1806
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1806
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1807 1807
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1808 1808
                 : '',
1809 1809
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1815,11 +1815,11 @@  discard block
 block discarded – undo
1815 1815
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1816 1816
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1817 1817
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1818
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1819
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1818
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1819
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1820 1820
                 ? 'dashicons dashicons-post-trash clickable'
1821 1821
                 : 'dashicons dashicons-lock',
1822
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1822
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1823 1823
                 : ' disabled=disabled',
1824 1824
         ];
1825 1825
         $price         = $ticket->ID() !== 0
@@ -1843,7 +1843,7 @@  discard block
 block discarded – undo
1843 1843
         }
1844 1844
         if (empty($template_args['TKT_end_date'])) {
1845 1845
             // get the earliest datetime (if present);
1846
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1846
+            $earliest_datetime = $this->_cpt_model_obj->ID() > 0
1847 1847
                 ? $this->_cpt_model_obj->get_first_related(
1848 1848
                     'Datetime',
1849 1849
                     ['order_by' => ['DTT_EVT_start' => 'ASC']]
@@ -1856,7 +1856,7 @@  discard block
 block discarded – undo
1856 1856
         $template_args = array_merge($template_args, $price_args);
1857 1857
         $template      = apply_filters(
1858 1858
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1859
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1859
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1860 1860
             $ticket
1861 1861
         );
1862 1862
         return EEH_Template::display_template($template, $template_args, true);
@@ -1869,7 +1869,7 @@  discard block
 block discarded – undo
1869 1869
      */
1870 1870
     public function registration_options_meta_box()
1871 1871
     {
1872
-        $yes_no_values             = [
1872
+        $yes_no_values = [
1873 1873
             ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1874 1874
             ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1875 1875
         ];
@@ -1891,12 +1891,12 @@  discard block
 block discarded – undo
1891 1891
             $default_reg_status_values,
1892 1892
             $this->_cpt_model_obj->default_registration_status()
1893 1893
         );
1894
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1894
+        $template_args['display_description'] = EEH_Form_Fields::select_input(
1895 1895
             'display_desc',
1896 1896
             $yes_no_values,
1897 1897
             $this->_cpt_model_obj->display_description()
1898 1898
         );
1899
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1899
+        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1900 1900
             'display_ticket_selector',
1901 1901
             $yes_no_values,
1902 1902
             $this->_cpt_model_obj->display_ticket_selector(),
@@ -1912,7 +1912,7 @@  discard block
 block discarded – undo
1912 1912
             $default_reg_status_values
1913 1913
         );
1914 1914
         EEH_Template::display_template(
1915
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1915
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1916 1916
             $template_args
1917 1917
         );
1918 1918
     }
@@ -1935,7 +1935,7 @@  discard block
 block discarded – undo
1935 1935
     {
1936 1936
         $EEM_Event   = $this->_event_model();
1937 1937
         $offset      = ($current_page - 1) * $per_page;
1938
-        $limit       = $count ? null : $offset . ',' . $per_page;
1938
+        $limit       = $count ? null : $offset.','.$per_page;
1939 1939
         $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1940 1940
         $order       = $this->request->getRequestParam('order', 'DESC');
1941 1941
         $month_range = $this->request->getRequestParam('month_range');
@@ -1972,10 +1972,10 @@  discard block
 block discarded – undo
1972 1972
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1973 1973
         if ($month_range) {
1974 1974
             $DateTime = new DateTime(
1975
-                $year_r . '-' . $month_r . '-01 00:00:00',
1975
+                $year_r.'-'.$month_r.'-01 00:00:00',
1976 1976
                 new DateTimeZone('UTC')
1977 1977
             );
1978
-            $start    = $DateTime->getTimestamp();
1978
+            $start = $DateTime->getTimestamp();
1979 1979
             // set the datetime to be the end of the month
1980 1980
             $DateTime->setDate(
1981 1981
                 $year_r,
@@ -2000,11 +2000,11 @@  discard block
 block discarded – undo
2000 2000
                                                         ->format(implode(' ', $start_formats));
2001 2001
             $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
2002 2002
         }
2003
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2003
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2004 2004
             $where['EVT_wp_user'] = get_current_user_id();
2005 2005
         } else {
2006
-            if (! isset($where['status'])) {
2007
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
2006
+            if ( ! isset($where['status'])) {
2007
+                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
2008 2008
                     $where['OR'] = [
2009 2009
                         'status*restrict_private' => ['!=', 'private'],
2010 2010
                         'AND'                     => [
@@ -2026,7 +2026,7 @@  discard block
 block discarded – undo
2026 2026
         // search query handling
2027 2027
         $search_term = $this->request->getRequestParam('s');
2028 2028
         if ($search_term) {
2029
-            $search_term = '%' . $search_term . '%';
2029
+            $search_term = '%'.$search_term.'%';
2030 2030
             $where['OR'] = [
2031 2031
                 'EVT_name'       => ['LIKE', $search_term],
2032 2032
                 'EVT_desc'       => ['LIKE', $search_term],
@@ -2134,7 +2134,7 @@  discard block
 block discarded – undo
2134 2134
             // clean status
2135 2135
             $event_status = sanitize_key($event_status);
2136 2136
             // grab status
2137
-            if (! empty($event_status)) {
2137
+            if ( ! empty($event_status)) {
2138 2138
                 $success = $this->_change_event_status($EVT_ID, $event_status);
2139 2139
             } else {
2140 2140
                 $success = false;
@@ -2174,7 +2174,7 @@  discard block
 block discarded – undo
2174 2174
         // clean status
2175 2175
         $event_status = sanitize_key($event_status);
2176 2176
         // grab status
2177
-        if (! empty($event_status)) {
2177
+        if ( ! empty($event_status)) {
2178 2178
             $success = true;
2179 2179
             // determine the event id and set to array.
2180 2180
             $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
@@ -2220,7 +2220,7 @@  discard block
 block discarded – undo
2220 2220
     private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2221 2221
     {
2222 2222
         // grab event id
2223
-        if (! $EVT_ID) {
2223
+        if ( ! $EVT_ID) {
2224 2224
             $msg = esc_html__(
2225 2225
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2226 2226
                 'event_espresso'
@@ -2257,7 +2257,7 @@  discard block
 block discarded – undo
2257 2257
         // use class to change status
2258 2258
         $this->_cpt_model_obj->set_status($event_status);
2259 2259
         $success = $this->_cpt_model_obj->save();
2260
-        if (! $success) {
2260
+        if ( ! $success) {
2261 2261
             $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2262 2262
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2263 2263
             return false;
@@ -2324,7 +2324,7 @@  discard block
 block discarded – undo
2324 2324
      */
2325 2325
     protected function getModelObjNodeGroupPersister(): NodeGroupDao
2326 2326
     {
2327
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2327
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2328 2328
             $this->model_obj_node_group_persister =
2329 2329
                 $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2330 2330
         }
@@ -2644,7 +2644,7 @@  discard block
 block discarded – undo
2644 2644
                                                 . esc_html__(
2645 2645
                                                     '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.',
2646 2646
                                                     'event_espresso'
2647
-                                                ) . '</strong>';
2647
+                                                ).'</strong>';
2648 2648
         $this->display_admin_caf_preview_page('template_settings_tab');
2649 2649
     }
2650 2650
 
@@ -2665,11 +2665,11 @@  discard block
 block discarded – undo
2665 2665
         $this->_set_empty_category_object();
2666 2666
         // only set if we've got an id
2667 2667
         $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2668
-        if (! $category_ID) {
2668
+        if ( ! $category_ID) {
2669 2669
             return;
2670 2670
         }
2671 2671
         $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2672
-        if (! empty($term)) {
2672
+        if ( ! empty($term)) {
2673 2673
             $this->_category->category_name       = $term->name;
2674 2674
             $this->_category->category_identifier = $term->slug;
2675 2675
             $this->_category->category_desc       = $term->description;
@@ -2771,7 +2771,7 @@  discard block
 block discarded – undo
2771 2771
             $category_select_values,
2772 2772
             $this->_category->parent
2773 2773
         );
2774
-        $template_args   = [
2774
+        $template_args = [
2775 2775
             'category'                 => $this->_category,
2776 2776
             'category_select'          => $category_select,
2777 2777
             'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
@@ -2779,7 +2779,7 @@  discard block
 block discarded – undo
2779 2779
             'disable'                  => '',
2780 2780
             'disabled_message'         => false,
2781 2781
         ];
2782
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2782
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2783 2783
         return EEH_Template::display_template($template, $template_args, true);
2784 2784
     }
2785 2785
 
@@ -2875,7 +2875,7 @@  discard block
 block discarded – undo
2875 2875
             return 0;
2876 2876
         }
2877 2877
         $category_ID = $insert_ids['term_id'] ?? 0;
2878
-        if (! $category_ID) {
2878
+        if ( ! $category_ID) {
2879 2879
             EE_Error::add_error(
2880 2880
                 esc_html__(
2881 2881
                     'An error occurred and the category has not been saved to the database.',
@@ -2916,7 +2916,7 @@  discard block
 block discarded – undo
2916 2916
         $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2917 2917
         $search_term = $this->request->getRequestParam('s');
2918 2918
         if ($search_term) {
2919
-            $search_term = '%' . $search_term . '%';
2919
+            $search_term = '%'.$search_term.'%';
2920 2920
             $where['OR'] = [
2921 2921
                 'Term.name'   => ['LIKE', $search_term],
2922 2922
                 'description' => ['LIKE', $search_term],
@@ -2925,7 +2925,7 @@  discard block
 block discarded – undo
2925 2925
         $query_params = [
2926 2926
             $where,
2927 2927
             'order_by'   => [$orderby => $order],
2928
-            'limit'      => $limit . ',' . $per_page,
2928
+            'limit'      => $limit.','.$per_page,
2929 2929
             'force_join' => ['Term'],
2930 2930
         ];
2931 2931
         return $count
Please login to merge, or discard this patch.