Completed
Branch dev (1f3862)
by
unknown
14:13 queued 07:26
created
admin/registrations/list_table/csv_reports/RegistrationsCsvReportParams.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -43,9 +43,9 @@  discard block
 block discarded – undo
43 43
 
44 44
         $route_details = [
45 45
             'route'         => 'registrations_report',
46
-            'extra_request' => [ 'return_url' => $return_url ],
46
+            'extra_request' => ['return_url' => $return_url],
47 47
         ];
48
-        if (! empty($EVT_ID)) {
48
+        if ( ! empty($EVT_ID)) {
49 49
             $route_details['extra_request']['EVT_ID'] = $EVT_ID;
50 50
         }
51 51
         if ($DTT_ID) {
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
     <span class="csv-report-notice__wrapper">
76 76
         <span class="dashicons dashicons-info"></span>
77 77
         <span class="csv-report-notice__text">
78
-        ' .  esc_html('All Registration CSV Reports are now triggered by the preceding button') . '
78
+        ' .  esc_html('All Registration CSV Reports are now triggered by the preceding button').'
79 79
         </span>
80 80
     </span>';
81 81
     }
Please login to merge, or discard this patch.
Indentation   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -14,69 +14,69 @@
 block discarded – undo
14 14
  */
15 15
 class RegistrationsCsvReportParams
16 16
 {
17
-    /**
18
-     * @param string $return_url
19
-     * @param array  $request_params
20
-     * @param int    $EVT_ID
21
-     * @param int    $DTT_ID
22
-     * @return array
23
-     */
24
-    public static function getRequestParams(
25
-        $return_url,
26
-        $request_params = [],
27
-        $EVT_ID = 0,
28
-        $DTT_ID = 0
29
-    ) {
30
-        if (
31
-            ! EE_Capabilities::instance()->current_user_can(
32
-                'ee_read_registrations',
33
-                'espresso_registrations_registrations_reports',
34
-                $EVT_ID
35
-            )
36
-        ) {
37
-            return [];
38
-        }
39
-        unset($request_params['_wp_http_referer']);
40
-        add_action(
41
-            'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
42
-            [RegistrationsCsvReportParams::class, 'csvReportNotice']
43
-        );
17
+	/**
18
+	 * @param string $return_url
19
+	 * @param array  $request_params
20
+	 * @param int    $EVT_ID
21
+	 * @param int    $DTT_ID
22
+	 * @return array
23
+	 */
24
+	public static function getRequestParams(
25
+		$return_url,
26
+		$request_params = [],
27
+		$EVT_ID = 0,
28
+		$DTT_ID = 0
29
+	) {
30
+		if (
31
+			! EE_Capabilities::instance()->current_user_can(
32
+				'ee_read_registrations',
33
+				'espresso_registrations_registrations_reports',
34
+				$EVT_ID
35
+			)
36
+		) {
37
+			return [];
38
+		}
39
+		unset($request_params['_wp_http_referer']);
40
+		add_action(
41
+			'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
42
+			[RegistrationsCsvReportParams::class, 'csvReportNotice']
43
+		);
44 44
 
45
-        $route_details = [
46
-            'route'         => 'registrations_report',
47
-            'extra_request' => [ 'return_url' => $return_url ],
48
-        ];
49
-        if (! empty($EVT_ID)) {
50
-            $route_details['extra_request']['EVT_ID'] = $EVT_ID;
51
-        }
52
-        if ($DTT_ID) {
53
-            $route_details['extra_request']['DTT_ID'] = $DTT_ID;
54
-        }
55
-        if (
56
-            isset($request_params['use_filters'])
57
-            && filter_var($request_params['use_filters'], FILTER_VALIDATE_BOOLEAN)
58
-        ) {
59
-            $route_details['extra_request']['filters'] = array_diff_key(
60
-                $request_params,
61
-                [
62
-                    'page'          => '',
63
-                    'action'        => '',
64
-                    'default_nonce' => '',
65
-                ]
66
-            );
67
-        }
68
-        return $route_details;
69
-    }
45
+		$route_details = [
46
+			'route'         => 'registrations_report',
47
+			'extra_request' => [ 'return_url' => $return_url ],
48
+		];
49
+		if (! empty($EVT_ID)) {
50
+			$route_details['extra_request']['EVT_ID'] = $EVT_ID;
51
+		}
52
+		if ($DTT_ID) {
53
+			$route_details['extra_request']['DTT_ID'] = $DTT_ID;
54
+		}
55
+		if (
56
+			isset($request_params['use_filters'])
57
+			&& filter_var($request_params['use_filters'], FILTER_VALIDATE_BOOLEAN)
58
+		) {
59
+			$route_details['extra_request']['filters'] = array_diff_key(
60
+				$request_params,
61
+				[
62
+					'page'          => '',
63
+					'action'        => '',
64
+					'default_nonce' => '',
65
+				]
66
+			);
67
+		}
68
+		return $route_details;
69
+	}
70 70
 
71 71
 
72
-    public static function csvReportNotice()
73
-    {
74
-        echo '
72
+	public static function csvReportNotice()
73
+	{
74
+		echo '
75 75
     <span class="csv-report-notice__wrapper">
76 76
         <span class="dashicons dashicons-info"></span>
77 77
         <span class="csv-report-notice__text">
78 78
         ' .  esc_html('All Registration CSV Reports are now triggered by the preceding button') . '
79 79
         </span>
80 80
     </span>';
81
-    }
81
+	}
82 82
 }
Please login to merge, or discard this patch.
core/domain/services/admin/registrations/list_table/QueryBuilder.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
         $this->request = $request;
59 59
         $this->registration_model = $registration_model;
60 60
         foreach ($extra_request_params as $key => $value) {
61
-            if (! $this->request->requestParamIsSet($key)) {
61
+            if ( ! $this->request->requestParamIsSet($key)) {
62 62
                 $this->request->setRequestParam($key, $value);
63 63
             }
64 64
         }
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
             'caps'                     => EEM_Base::caps_read_admin,
86 86
             'default_where_conditions' => 'this_model_only',
87 87
         ];
88
-        if (! $count_query) {
88
+        if ( ! $count_query) {
89 89
             $query_params = array_merge(
90 90
                 $query_params,
91 91
                 $this->getOrderbyClause(),
@@ -231,12 +231,12 @@  discard block
 block discarded – undo
231 231
                 [
232 232
                     $this->registration_model->convert_datetime_for_query(
233 233
                         'REG_date',
234
-                        $now . ' 00:00:00',
234
+                        $now.' 00:00:00',
235 235
                         'Y-m-d H:i:s'
236 236
                     ),
237 237
                     $this->registration_model->convert_datetime_for_query(
238 238
                         'REG_date',
239
-                        $now . ' 23:59:59',
239
+                        $now.' 23:59:59',
240 240
                         'Y-m-d H:i:s'
241 241
                     ),
242 242
                 ],
@@ -251,12 +251,12 @@  discard block
 block discarded – undo
251 251
                 [
252 252
                     $this->registration_model->convert_datetime_for_query(
253 253
                         'REG_date',
254
-                        $current_year_and_month . '-01 00:00:00',
254
+                        $current_year_and_month.'-01 00:00:00',
255 255
                         'Y-m-d H:i:s'
256 256
                     ),
257 257
                     $this->registration_model->convert_datetime_for_query(
258 258
                         'REG_date',
259
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
259
+                        $current_year_and_month.'-'.$days_this_month.' 23:59:59',
260 260
                         'Y-m-d H:i:s'
261 261
                     ),
262 262
                 ],
@@ -275,18 +275,18 @@  discard block
 block discarded – undo
275 275
                 : '';
276 276
             // if there is not a month or year then we can't go further
277 277
             if ($month_requested && $year_requested) {
278
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
278
+                $days_in_month = date('t', strtotime($year_requested.'-'.$month_requested.'-'.'01'));
279 279
                 $this->where_params['REG_date'] = [
280 280
                     'BETWEEN',
281 281
                     [
282 282
                         $this->registration_model->convert_datetime_for_query(
283 283
                             'REG_date',
284
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
284
+                            $year_requested.'-'.$month_requested.'-01 00:00:00',
285 285
                             'Y-m-d H:i:s'
286 286
                         ),
287 287
                         $this->registration_model->convert_datetime_for_query(
288 288
                             'REG_date',
289
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
289
+                            $year_requested.'-'.$month_requested.'-'.$days_in_month.' 23:59:59',
290 290
                             'Y-m-d H:i:s'
291 291
                         ),
292 292
                     ],
@@ -303,7 +303,7 @@  discard block
 block discarded – undo
303 303
     {
304 304
         $search = $this->request->getRequestParam('s');
305 305
         if ($search) {
306
-            $search_string = '%' . sanitize_text_field($search) . '%';
306
+            $search_string = '%'.sanitize_text_field($search).'%';
307 307
             $this->where_params['OR*search_conditions'] = [
308 308
                 'Event.EVT_name'                          => ['LIKE', $search_string],
309 309
                 'Event.EVT_desc'                          => ['LIKE', $search_string],
Please login to merge, or discard this patch.
Indentation   +380 added lines, -380 removed lines patch added patch discarded remove patch
@@ -21,384 +21,384 @@
 block discarded – undo
21 21
  */
22 22
 class QueryBuilder
23 23
 {
24
-    /**
25
-     * @var RequestInterface $request
26
-     */
27
-    protected $request;
28
-
29
-    /**
30
-     * @var EEM_Registration $registration_model
31
-     */
32
-    protected $registration_model;
33
-
34
-    /**
35
-     * @var string $view
36
-     */
37
-    protected $view;
38
-
39
-    /**
40
-     * @var array $where_params
41
-     */
42
-    protected $where_params;
43
-
44
-
45
-    /**
46
-     * QueryBuilder constructor.
47
-     *
48
-     * @param RequestInterface $request
49
-     * @param EEM_Registration $registration_model
50
-     * @param array            $extra_request_params
51
-     */
52
-    public function __construct(
53
-        RequestInterface $request,
54
-        EEM_Registration $registration_model,
55
-        array $extra_request_params = []
56
-    ) {
57
-        $this->request = $request;
58
-        $this->registration_model = $registration_model;
59
-        foreach ($extra_request_params as $key => $value) {
60
-            if (! $this->request->requestParamIsSet($key)) {
61
-                $this->request->setRequestParam($key, $value);
62
-            }
63
-        }
64
-        $this->view = $this->request->getRequestParam('status', '');
65
-        $this->where_params = [];
66
-    }
67
-
68
-
69
-    /**
70
-     * Sets up the where conditions for the registrations query.
71
-     *
72
-     * @param int  $per_page
73
-     * @param bool $count_query
74
-     * @return array
75
-     * @throws EE_Error
76
-     * @throws InvalidArgumentException
77
-     * @throws InvalidDataTypeException
78
-     * @throws InvalidInterfaceException
79
-     */
80
-    public function getQueryParams($per_page = 10, $count_query = false)
81
-    {
82
-        $query_params = [
83
-            0                          => $this->getWhereClause(),
84
-            'caps'                     => EEM_Base::caps_read_admin,
85
-            'default_where_conditions' => 'this_model_only',
86
-        ];
87
-        if (! $count_query) {
88
-            $query_params = array_merge(
89
-                $query_params,
90
-                $this->getOrderbyClause(),
91
-                $this->getLimitClause($per_page)
92
-            );
93
-        }
94
-
95
-        return $query_params;
96
-    }
97
-
98
-
99
-    /**
100
-     * Sets up the where conditions for the registrations query.
101
-     *
102
-     * @return array
103
-     * @throws EE_Error
104
-     * @throws InvalidArgumentException
105
-     * @throws InvalidDataTypeException
106
-     * @throws InvalidInterfaceException
107
-     */
108
-    protected function getWhereClause()
109
-    {
110
-        $this->addAttendeeIdToWhereConditions();
111
-        $this->addEventIdToWhereConditions();
112
-        $this->addCategoryIdToWhereConditions();
113
-        $this->addDatetimeIdToWhereConditions();
114
-        $this->addTicketIdToWhereConditions();
115
-        $this->addRegistrationStatusToWhereConditions();
116
-        $this->addDateToWhereConditions();
117
-        $this->addSearchToWhereConditions();
118
-        return apply_filters(
119
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
120
-            $this->where_params,
121
-            $this->request->requestParams()
122
-        );
123
-    }
124
-
125
-
126
-    /**
127
-     * This will add ATT_ID to the provided $this->where_clause array for EE model query parameters.
128
-     */
129
-    protected function addAttendeeIdToWhereConditions()
130
-    {
131
-        $ATT_ID = $this->request->getRequestParam('attendee_id');
132
-        $ATT_ID = $this->request->getRequestParam('ATT_ID', $ATT_ID, 'int');
133
-        if ($ATT_ID) {
134
-            $this->where_params['ATT_ID'] = $ATT_ID;
135
-        }
136
-    }
137
-
138
-
139
-    /**
140
-     * This will add EVT_ID to the provided $this->where_clause array for EE model query parameters.
141
-     */
142
-    protected function addEventIdToWhereConditions()
143
-    {
144
-        $EVT_ID = $this->request->getRequestParam('event_id');
145
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', $EVT_ID, 'int');
146
-        if ($EVT_ID) {
147
-            $this->where_params['EVT_ID'] = $EVT_ID;
148
-        }
149
-    }
150
-
151
-
152
-    /**
153
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
154
-     */
155
-    protected function addCategoryIdToWhereConditions()
156
-    {
157
-        $EVT_CAT = (int) $this->request->getRequestParam('EVT_CAT', 0, 'int');
158
-        if ($EVT_CAT > 0) {
159
-            $this->where_params['Event.Term_Taxonomy.term_id'] = $EVT_CAT;
160
-        }
161
-    }
162
-
163
-
164
-    /**
165
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
166
-     */
167
-    protected function addDatetimeIdToWhereConditions()
168
-    {
169
-        // first look for 'datetime_id' then 'DTT_ID' using first result as fallback default value
170
-        $DTT_ID = $this->request->getRequestParam('datetime_id');
171
-        $DTT_ID = $this->request->getRequestParam('DTT_ID', $DTT_ID, 'int');
172
-        if ($DTT_ID) {
173
-            $this->where_params['Ticket.Datetime.DTT_ID'] = $DTT_ID;
174
-        }
175
-    }
176
-
177
-
178
-    /**
179
-     * Adds the ticket ID if it exists in the request to the where conditions for the registrations query.
180
-     */
181
-    protected function addTicketIdToWhereConditions()
182
-    {
183
-        // first look for 'ticket_id' then 'TKT_ID' using first result as fallback default value
184
-        $TKT_ID = $this->request->getRequestParam('ticket_id');
185
-        $TKT_ID = $this->request->getRequestParam('TKT_ID', $TKT_ID, 'int');
186
-        if ($TKT_ID) {
187
-            $this->where_params['TKT_ID'] = $TKT_ID;
188
-        }
189
-    }
190
-
191
-
192
-    /**
193
-     * Adds the correct registration status to the where conditions for the registrations query.
194
-     * If filtering by registration status, then we show registrations matching that status.
195
-     * If not filtering by specified status, then we show all registrations excluding incomplete registrations
196
-     * UNLESS viewing trashed registrations.
197
-     */
198
-    protected function addRegistrationStatusToWhereConditions()
199
-    {
200
-        $registration_status = $this->request->getRequestParam('_reg_status');
201
-        if ($registration_status) {
202
-            $this->where_params['STS_ID'] = sanitize_text_field($registration_status);
203
-            return;
204
-        }
205
-        // make sure we exclude incomplete registrations, but only if not trashed.
206
-        if ($this->view === 'trash') {
207
-            $this->where_params['REG_deleted'] = true;
208
-            return;
209
-        }
210
-        $this->where_params['STS_ID'] = $this->view === 'incomplete'
211
-            ? EEM_Registration::status_id_incomplete
212
-            : ['!=', EEM_Registration::status_id_incomplete];
213
-    }
214
-
215
-
216
-    /**
217
-     * Adds any provided date restraints to the where conditions for the registrations query.
218
-     *
219
-     * @throws EE_Error
220
-     * @throws InvalidArgumentException
221
-     * @throws InvalidDataTypeException
222
-     * @throws InvalidInterfaceException
223
-     */
224
-    protected function addDateToWhereConditions()
225
-    {
226
-        if ($this->view === 'today') {
227
-            $now = date('Y-m-d', current_time('timestamp'));
228
-            $this->where_params['REG_date'] = [
229
-                'BETWEEN',
230
-                [
231
-                    $this->registration_model->convert_datetime_for_query(
232
-                        'REG_date',
233
-                        $now . ' 00:00:00',
234
-                        'Y-m-d H:i:s'
235
-                    ),
236
-                    $this->registration_model->convert_datetime_for_query(
237
-                        'REG_date',
238
-                        $now . ' 23:59:59',
239
-                        'Y-m-d H:i:s'
240
-                    ),
241
-                ],
242
-            ];
243
-            return;
244
-        }
245
-        if ($this->view === 'month') {
246
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
247
-            $days_this_month = date('t', current_time('timestamp'));
248
-            $this->where_params['REG_date'] = [
249
-                'BETWEEN',
250
-                [
251
-                    $this->registration_model->convert_datetime_for_query(
252
-                        'REG_date',
253
-                        $current_year_and_month . '-01 00:00:00',
254
-                        'Y-m-d H:i:s'
255
-                    ),
256
-                    $this->registration_model->convert_datetime_for_query(
257
-                        'REG_date',
258
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
259
-                        'Y-m-d H:i:s'
260
-                    ),
261
-                ],
262
-            ];
263
-            return;
264
-        }
265
-        $month_range = $this->request->getRequestParam('month_range');
266
-        if ($month_range) {
267
-            $month_range = sanitize_text_field($month_range);
268
-            $pieces = explode(' ', $month_range, 3);
269
-            $month_requested = ! empty($pieces[0])
270
-                ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
271
-                : '';
272
-            $year_requested = ! empty($pieces[1])
273
-                ? $pieces[1]
274
-                : '';
275
-            // if there is not a month or year then we can't go further
276
-            if ($month_requested && $year_requested) {
277
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
278
-                $this->where_params['REG_date'] = [
279
-                    'BETWEEN',
280
-                    [
281
-                        $this->registration_model->convert_datetime_for_query(
282
-                            'REG_date',
283
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
284
-                            'Y-m-d H:i:s'
285
-                        ),
286
-                        $this->registration_model->convert_datetime_for_query(
287
-                            'REG_date',
288
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
289
-                            'Y-m-d H:i:s'
290
-                        ),
291
-                    ],
292
-                ];
293
-            }
294
-        }
295
-    }
296
-
297
-
298
-    /**
299
-     * Adds any provided search restraints to the where conditions for the registrations query
300
-     */
301
-    protected function addSearchToWhereConditions()
302
-    {
303
-        $search = $this->request->getRequestParam('s');
304
-        if ($search) {
305
-            $search_string = '%' . sanitize_text_field($search) . '%';
306
-            $this->where_params['OR*search_conditions'] = [
307
-                'Event.EVT_name'                          => ['LIKE', $search_string],
308
-                'Event.EVT_desc'                          => ['LIKE', $search_string],
309
-                'Event.EVT_short_desc'                    => ['LIKE', $search_string],
310
-                'Attendee.ATT_full_name'                  => ['LIKE', $search_string],
311
-                'Attendee.ATT_fname'                      => ['LIKE', $search_string],
312
-                'Attendee.ATT_lname'                      => ['LIKE', $search_string],
313
-                'Attendee.ATT_short_bio'                  => ['LIKE', $search_string],
314
-                'Attendee.ATT_email'                      => ['LIKE', $search_string],
315
-                'Attendee.ATT_address'                    => ['LIKE', $search_string],
316
-                'Attendee.ATT_address2'                   => ['LIKE', $search_string],
317
-                'Attendee.ATT_city'                       => ['LIKE', $search_string],
318
-                'REG_final_price'                         => ['LIKE', $search_string],
319
-                'REG_code'                                => ['LIKE', $search_string],
320
-                'REG_count'                               => ['LIKE', $search_string],
321
-                'REG_group_size'                          => ['LIKE', $search_string],
322
-                'Ticket.TKT_name'                         => ['LIKE', $search_string],
323
-                'Ticket.TKT_description'                  => ['LIKE', $search_string],
324
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => ['LIKE', $search_string],
325
-            ];
326
-        }
327
-    }
328
-
329
-
330
-    /**
331
-     * Sets up the orderby for the registrations query.
332
-     *
333
-     * @return array
334
-     */
335
-    protected function getOrderbyClause()
336
-    {
337
-        $orderby_field = $this->request->getRequestParam('orderby');
338
-        $orderby_field = $orderby_field ? sanitize_text_field($orderby_field) : '_REG_date';
339
-        switch ($orderby_field) {
340
-            case '_REG_ID':
341
-                $orderby = ['REG_ID'];
342
-                break;
343
-            case '_Reg_status':
344
-                $orderby = ['STS_ID'];
345
-                break;
346
-            case 'ATT_fname':
347
-                $orderby = ['Attendee.ATT_fname', 'Attendee.ATT_lname'];
348
-                break;
349
-            case 'ATT_lname':
350
-                $orderby = ['Attendee.ATT_lname', 'Attendee.ATT_fname'];
351
-                break;
352
-            case 'event_name':
353
-                $orderby = ['Event.EVT_name'];
354
-                break;
355
-            case 'DTT_EVT_start':
356
-                $orderby = ['Event.Datetime.DTT_EVT_start'];
357
-                break;
358
-            case '_REG_date':
359
-                $orderby = ['REG_date'];
360
-                break;
361
-            default:
362
-                $orderby = [$orderby_field];
363
-                break;
364
-        }
365
-        $order = $this->request->getRequestParam('order');
366
-        $order = $order ? sanitize_text_field($order) : 'DESC';
367
-
368
-        $orderby = array_combine(
369
-            $orderby,
370
-            array_fill(0, count($orderby), $order)
371
-        );
372
-        // because there are many registrations with the same date, define
373
-        // a secondary way to order them, otherwise MySQL seems to be a bit random
374
-        if (empty($orderby['REG_ID'])) {
375
-            $orderby['REG_ID'] = $order;
376
-        }
377
-
378
-        $orderby = apply_filters(
379
-            'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
380
-            $orderby,
381
-            $this->request->requestParams()
382
-        );
383
-        return ['order_by' => $orderby];
384
-    }
385
-
386
-
387
-    /**
388
-     * Sets up the limit for the registrations query.
389
-     *
390
-     * @param $per_page
391
-     * @return array
392
-     */
393
-    protected function getLimitClause($per_page)
394
-    {
395
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
396
-        $per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
397
-        // -1 means return all results so get out if that's set.
398
-        if ($per_page === -1) {
399
-            return [];
400
-        }
401
-        $offset = ($current_page - 1) * $per_page;
402
-        return ['limit' => [$offset, $per_page]];
403
-    }
24
+	/**
25
+	 * @var RequestInterface $request
26
+	 */
27
+	protected $request;
28
+
29
+	/**
30
+	 * @var EEM_Registration $registration_model
31
+	 */
32
+	protected $registration_model;
33
+
34
+	/**
35
+	 * @var string $view
36
+	 */
37
+	protected $view;
38
+
39
+	/**
40
+	 * @var array $where_params
41
+	 */
42
+	protected $where_params;
43
+
44
+
45
+	/**
46
+	 * QueryBuilder constructor.
47
+	 *
48
+	 * @param RequestInterface $request
49
+	 * @param EEM_Registration $registration_model
50
+	 * @param array            $extra_request_params
51
+	 */
52
+	public function __construct(
53
+		RequestInterface $request,
54
+		EEM_Registration $registration_model,
55
+		array $extra_request_params = []
56
+	) {
57
+		$this->request = $request;
58
+		$this->registration_model = $registration_model;
59
+		foreach ($extra_request_params as $key => $value) {
60
+			if (! $this->request->requestParamIsSet($key)) {
61
+				$this->request->setRequestParam($key, $value);
62
+			}
63
+		}
64
+		$this->view = $this->request->getRequestParam('status', '');
65
+		$this->where_params = [];
66
+	}
67
+
68
+
69
+	/**
70
+	 * Sets up the where conditions for the registrations query.
71
+	 *
72
+	 * @param int  $per_page
73
+	 * @param bool $count_query
74
+	 * @return array
75
+	 * @throws EE_Error
76
+	 * @throws InvalidArgumentException
77
+	 * @throws InvalidDataTypeException
78
+	 * @throws InvalidInterfaceException
79
+	 */
80
+	public function getQueryParams($per_page = 10, $count_query = false)
81
+	{
82
+		$query_params = [
83
+			0                          => $this->getWhereClause(),
84
+			'caps'                     => EEM_Base::caps_read_admin,
85
+			'default_where_conditions' => 'this_model_only',
86
+		];
87
+		if (! $count_query) {
88
+			$query_params = array_merge(
89
+				$query_params,
90
+				$this->getOrderbyClause(),
91
+				$this->getLimitClause($per_page)
92
+			);
93
+		}
94
+
95
+		return $query_params;
96
+	}
97
+
98
+
99
+	/**
100
+	 * Sets up the where conditions for the registrations query.
101
+	 *
102
+	 * @return array
103
+	 * @throws EE_Error
104
+	 * @throws InvalidArgumentException
105
+	 * @throws InvalidDataTypeException
106
+	 * @throws InvalidInterfaceException
107
+	 */
108
+	protected function getWhereClause()
109
+	{
110
+		$this->addAttendeeIdToWhereConditions();
111
+		$this->addEventIdToWhereConditions();
112
+		$this->addCategoryIdToWhereConditions();
113
+		$this->addDatetimeIdToWhereConditions();
114
+		$this->addTicketIdToWhereConditions();
115
+		$this->addRegistrationStatusToWhereConditions();
116
+		$this->addDateToWhereConditions();
117
+		$this->addSearchToWhereConditions();
118
+		return apply_filters(
119
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
120
+			$this->where_params,
121
+			$this->request->requestParams()
122
+		);
123
+	}
124
+
125
+
126
+	/**
127
+	 * This will add ATT_ID to the provided $this->where_clause array for EE model query parameters.
128
+	 */
129
+	protected function addAttendeeIdToWhereConditions()
130
+	{
131
+		$ATT_ID = $this->request->getRequestParam('attendee_id');
132
+		$ATT_ID = $this->request->getRequestParam('ATT_ID', $ATT_ID, 'int');
133
+		if ($ATT_ID) {
134
+			$this->where_params['ATT_ID'] = $ATT_ID;
135
+		}
136
+	}
137
+
138
+
139
+	/**
140
+	 * This will add EVT_ID to the provided $this->where_clause array for EE model query parameters.
141
+	 */
142
+	protected function addEventIdToWhereConditions()
143
+	{
144
+		$EVT_ID = $this->request->getRequestParam('event_id');
145
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', $EVT_ID, 'int');
146
+		if ($EVT_ID) {
147
+			$this->where_params['EVT_ID'] = $EVT_ID;
148
+		}
149
+	}
150
+
151
+
152
+	/**
153
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
154
+	 */
155
+	protected function addCategoryIdToWhereConditions()
156
+	{
157
+		$EVT_CAT = (int) $this->request->getRequestParam('EVT_CAT', 0, 'int');
158
+		if ($EVT_CAT > 0) {
159
+			$this->where_params['Event.Term_Taxonomy.term_id'] = $EVT_CAT;
160
+		}
161
+	}
162
+
163
+
164
+	/**
165
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
166
+	 */
167
+	protected function addDatetimeIdToWhereConditions()
168
+	{
169
+		// first look for 'datetime_id' then 'DTT_ID' using first result as fallback default value
170
+		$DTT_ID = $this->request->getRequestParam('datetime_id');
171
+		$DTT_ID = $this->request->getRequestParam('DTT_ID', $DTT_ID, 'int');
172
+		if ($DTT_ID) {
173
+			$this->where_params['Ticket.Datetime.DTT_ID'] = $DTT_ID;
174
+		}
175
+	}
176
+
177
+
178
+	/**
179
+	 * Adds the ticket ID if it exists in the request to the where conditions for the registrations query.
180
+	 */
181
+	protected function addTicketIdToWhereConditions()
182
+	{
183
+		// first look for 'ticket_id' then 'TKT_ID' using first result as fallback default value
184
+		$TKT_ID = $this->request->getRequestParam('ticket_id');
185
+		$TKT_ID = $this->request->getRequestParam('TKT_ID', $TKT_ID, 'int');
186
+		if ($TKT_ID) {
187
+			$this->where_params['TKT_ID'] = $TKT_ID;
188
+		}
189
+	}
190
+
191
+
192
+	/**
193
+	 * Adds the correct registration status to the where conditions for the registrations query.
194
+	 * If filtering by registration status, then we show registrations matching that status.
195
+	 * If not filtering by specified status, then we show all registrations excluding incomplete registrations
196
+	 * UNLESS viewing trashed registrations.
197
+	 */
198
+	protected function addRegistrationStatusToWhereConditions()
199
+	{
200
+		$registration_status = $this->request->getRequestParam('_reg_status');
201
+		if ($registration_status) {
202
+			$this->where_params['STS_ID'] = sanitize_text_field($registration_status);
203
+			return;
204
+		}
205
+		// make sure we exclude incomplete registrations, but only if not trashed.
206
+		if ($this->view === 'trash') {
207
+			$this->where_params['REG_deleted'] = true;
208
+			return;
209
+		}
210
+		$this->where_params['STS_ID'] = $this->view === 'incomplete'
211
+			? EEM_Registration::status_id_incomplete
212
+			: ['!=', EEM_Registration::status_id_incomplete];
213
+	}
214
+
215
+
216
+	/**
217
+	 * Adds any provided date restraints to the where conditions for the registrations query.
218
+	 *
219
+	 * @throws EE_Error
220
+	 * @throws InvalidArgumentException
221
+	 * @throws InvalidDataTypeException
222
+	 * @throws InvalidInterfaceException
223
+	 */
224
+	protected function addDateToWhereConditions()
225
+	{
226
+		if ($this->view === 'today') {
227
+			$now = date('Y-m-d', current_time('timestamp'));
228
+			$this->where_params['REG_date'] = [
229
+				'BETWEEN',
230
+				[
231
+					$this->registration_model->convert_datetime_for_query(
232
+						'REG_date',
233
+						$now . ' 00:00:00',
234
+						'Y-m-d H:i:s'
235
+					),
236
+					$this->registration_model->convert_datetime_for_query(
237
+						'REG_date',
238
+						$now . ' 23:59:59',
239
+						'Y-m-d H:i:s'
240
+					),
241
+				],
242
+			];
243
+			return;
244
+		}
245
+		if ($this->view === 'month') {
246
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
247
+			$days_this_month = date('t', current_time('timestamp'));
248
+			$this->where_params['REG_date'] = [
249
+				'BETWEEN',
250
+				[
251
+					$this->registration_model->convert_datetime_for_query(
252
+						'REG_date',
253
+						$current_year_and_month . '-01 00:00:00',
254
+						'Y-m-d H:i:s'
255
+					),
256
+					$this->registration_model->convert_datetime_for_query(
257
+						'REG_date',
258
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
259
+						'Y-m-d H:i:s'
260
+					),
261
+				],
262
+			];
263
+			return;
264
+		}
265
+		$month_range = $this->request->getRequestParam('month_range');
266
+		if ($month_range) {
267
+			$month_range = sanitize_text_field($month_range);
268
+			$pieces = explode(' ', $month_range, 3);
269
+			$month_requested = ! empty($pieces[0])
270
+				? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
271
+				: '';
272
+			$year_requested = ! empty($pieces[1])
273
+				? $pieces[1]
274
+				: '';
275
+			// if there is not a month or year then we can't go further
276
+			if ($month_requested && $year_requested) {
277
+				$days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
278
+				$this->where_params['REG_date'] = [
279
+					'BETWEEN',
280
+					[
281
+						$this->registration_model->convert_datetime_for_query(
282
+							'REG_date',
283
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
284
+							'Y-m-d H:i:s'
285
+						),
286
+						$this->registration_model->convert_datetime_for_query(
287
+							'REG_date',
288
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
289
+							'Y-m-d H:i:s'
290
+						),
291
+					],
292
+				];
293
+			}
294
+		}
295
+	}
296
+
297
+
298
+	/**
299
+	 * Adds any provided search restraints to the where conditions for the registrations query
300
+	 */
301
+	protected function addSearchToWhereConditions()
302
+	{
303
+		$search = $this->request->getRequestParam('s');
304
+		if ($search) {
305
+			$search_string = '%' . sanitize_text_field($search) . '%';
306
+			$this->where_params['OR*search_conditions'] = [
307
+				'Event.EVT_name'                          => ['LIKE', $search_string],
308
+				'Event.EVT_desc'                          => ['LIKE', $search_string],
309
+				'Event.EVT_short_desc'                    => ['LIKE', $search_string],
310
+				'Attendee.ATT_full_name'                  => ['LIKE', $search_string],
311
+				'Attendee.ATT_fname'                      => ['LIKE', $search_string],
312
+				'Attendee.ATT_lname'                      => ['LIKE', $search_string],
313
+				'Attendee.ATT_short_bio'                  => ['LIKE', $search_string],
314
+				'Attendee.ATT_email'                      => ['LIKE', $search_string],
315
+				'Attendee.ATT_address'                    => ['LIKE', $search_string],
316
+				'Attendee.ATT_address2'                   => ['LIKE', $search_string],
317
+				'Attendee.ATT_city'                       => ['LIKE', $search_string],
318
+				'REG_final_price'                         => ['LIKE', $search_string],
319
+				'REG_code'                                => ['LIKE', $search_string],
320
+				'REG_count'                               => ['LIKE', $search_string],
321
+				'REG_group_size'                          => ['LIKE', $search_string],
322
+				'Ticket.TKT_name'                         => ['LIKE', $search_string],
323
+				'Ticket.TKT_description'                  => ['LIKE', $search_string],
324
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => ['LIKE', $search_string],
325
+			];
326
+		}
327
+	}
328
+
329
+
330
+	/**
331
+	 * Sets up the orderby for the registrations query.
332
+	 *
333
+	 * @return array
334
+	 */
335
+	protected function getOrderbyClause()
336
+	{
337
+		$orderby_field = $this->request->getRequestParam('orderby');
338
+		$orderby_field = $orderby_field ? sanitize_text_field($orderby_field) : '_REG_date';
339
+		switch ($orderby_field) {
340
+			case '_REG_ID':
341
+				$orderby = ['REG_ID'];
342
+				break;
343
+			case '_Reg_status':
344
+				$orderby = ['STS_ID'];
345
+				break;
346
+			case 'ATT_fname':
347
+				$orderby = ['Attendee.ATT_fname', 'Attendee.ATT_lname'];
348
+				break;
349
+			case 'ATT_lname':
350
+				$orderby = ['Attendee.ATT_lname', 'Attendee.ATT_fname'];
351
+				break;
352
+			case 'event_name':
353
+				$orderby = ['Event.EVT_name'];
354
+				break;
355
+			case 'DTT_EVT_start':
356
+				$orderby = ['Event.Datetime.DTT_EVT_start'];
357
+				break;
358
+			case '_REG_date':
359
+				$orderby = ['REG_date'];
360
+				break;
361
+			default:
362
+				$orderby = [$orderby_field];
363
+				break;
364
+		}
365
+		$order = $this->request->getRequestParam('order');
366
+		$order = $order ? sanitize_text_field($order) : 'DESC';
367
+
368
+		$orderby = array_combine(
369
+			$orderby,
370
+			array_fill(0, count($orderby), $order)
371
+		);
372
+		// because there are many registrations with the same date, define
373
+		// a secondary way to order them, otherwise MySQL seems to be a bit random
374
+		if (empty($orderby['REG_ID'])) {
375
+			$orderby['REG_ID'] = $order;
376
+		}
377
+
378
+		$orderby = apply_filters(
379
+			'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
380
+			$orderby,
381
+			$this->request->requestParams()
382
+		);
383
+		return ['order_by' => $orderby];
384
+	}
385
+
386
+
387
+	/**
388
+	 * Sets up the limit for the registrations query.
389
+	 *
390
+	 * @param $per_page
391
+	 * @return array
392
+	 */
393
+	protected function getLimitClause($per_page)
394
+	{
395
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
396
+		$per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
397
+		// -1 means return all results so get out if that's set.
398
+		if ($per_page === -1) {
399
+			return [];
400
+		}
401
+		$offset = ($current_page - 1) * $per_page;
402
+		return ['limit' => [$offset, $per_page]];
403
+	}
404 404
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_List_Table.core.php 1 patch
Indentation   +915 added lines, -915 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
4 4
 
5 5
 if (! class_exists('WP_List_Table')) {
6
-    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
6
+	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
7 7
 }
8 8
 
9 9
 
@@ -21,481 +21,481 @@  discard block
 block discarded – undo
21 21
  */
22 22
 abstract class EE_Admin_List_Table extends WP_List_Table
23 23
 {
24
-    const ACTION_COPY    = 'duplicate';
25
-
26
-    const ACTION_DELETE  = 'delete';
27
-
28
-    const ACTION_EDIT    = 'edit';
29
-
30
-    const ACTION_RESTORE = 'restore';
31
-
32
-    const ACTION_TRASH   = 'trash';
33
-
34
-    protected static $actions = [
35
-        self::ACTION_COPY,
36
-        self::ACTION_DELETE,
37
-        self::ACTION_EDIT,
38
-        self::ACTION_RESTORE,
39
-        self::ACTION_TRASH,
40
-    ];
41
-
42
-    /**
43
-     * holds the data that will be processed for the table
44
-     *
45
-     * @var array $_data
46
-     */
47
-    protected $_data;
48
-
49
-
50
-    /**
51
-     * This holds the value of all the data available for the given view (for all pages).
52
-     *
53
-     * @var int $_all_data_count
54
-     */
55
-    protected $_all_data_count;
56
-
57
-
58
-    /**
59
-     * Will contain the count of trashed items for the view label.
60
-     *
61
-     * @var int $_trashed_count
62
-     */
63
-    protected $_trashed_count;
64
-
65
-
66
-    /**
67
-     * This is what will be referenced as the slug for the current screen
68
-     *
69
-     * @var string $_screen
70
-     */
71
-    protected $_screen;
72
-
73
-
74
-    /**
75
-     * this is the EE_Admin_Page object
76
-     *
77
-     * @var EE_Admin_Page $_admin_page
78
-     */
79
-    protected $_admin_page;
80
-
81
-
82
-    /**
83
-     * The current view
84
-     *
85
-     * @var string $_view
86
-     */
87
-    protected $_view;
88
-
89
-
90
-    /**
91
-     * array of possible views for this table
92
-     *
93
-     * @var array $_views
94
-     */
95
-    protected $_views;
96
-
97
-
98
-    /**
99
-     * An array of key => value pairs containing information about the current table
100
-     * array(
101
-     *        'plural' => 'plural label',
102
-     *        'singular' => 'singular label',
103
-     *        'ajax' => false, //whether to use ajax or not
104
-     *        'screen' => null, //string used to reference what screen this is
105
-     *        (WP_List_table converts to screen object)
106
-     * )
107
-     *
108
-     * @var array $_wp_list_args
109
-     */
110
-    protected $_wp_list_args;
111
-
112
-    /**
113
-     * an array of column names
114
-     * array(
115
-     *    'internal-name' => 'Title'
116
-     * )
117
-     *
118
-     * @var array $_columns
119
-     */
120
-    protected $_columns;
121
-
122
-    /**
123
-     * An array of sortable columns
124
-     * array(
125
-     *    'internal-name' => 'orderby' //or
126
-     *    'internal-name' => array( 'orderby', true )
127
-     * )
128
-     *
129
-     * @var array $_sortable_columns
130
-     */
131
-    protected $_sortable_columns;
132
-
133
-    /**
134
-     * callback method used to perform AJAX row reordering
135
-     *
136
-     * @var string $_ajax_sorting_callback
137
-     */
138
-    protected $_ajax_sorting_callback;
139
-
140
-    /**
141
-     * An array of hidden columns (if needed)
142
-     * array('internal-name', 'internal-name')
143
-     *
144
-     * @var array $_hidden_columns
145
-     */
146
-    protected $_hidden_columns;
147
-
148
-    /**
149
-     * holds the per_page value
150
-     *
151
-     * @var int $_per_page
152
-     */
153
-    protected $_per_page;
154
-
155
-    /**
156
-     * holds what page number is currently being viewed
157
-     *
158
-     * @var int $_current_page
159
-     */
160
-    protected $_current_page;
161
-
162
-    /**
163
-     * the reference string for the nonce_action
164
-     *
165
-     * @var string $_nonce_action_ref
166
-     */
167
-    protected $_nonce_action_ref;
168
-
169
-    /**
170
-     * property to hold incoming request data (as set by the admin_page_core)
171
-     *
172
-     * @var array $_req_data
173
-     */
174
-    protected $_req_data;
175
-
176
-
177
-    /**
178
-     * yes / no array for admin form fields
179
-     *
180
-     * @var array $_yes_no
181
-     */
182
-    protected $_yes_no = [];
183
-
184
-    /**
185
-     * Array describing buttons that should appear at the bottom of the page
186
-     * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
187
-     * and the values are another array with the following keys
188
-     * array(
189
-     *    'route' => 'page_route',
190
-     *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
191
-     * )
192
-     *
193
-     * @var array $_bottom_buttons
194
-     */
195
-    protected $_bottom_buttons = [];
196
-
197
-
198
-    /**
199
-     * Used to indicate what should be the primary column for the list table.
200
-     * If not present then falls back to what WP calculates
201
-     * as the primary column.
202
-     *
203
-     * @type string $_primary_column
204
-     */
205
-    protected $_primary_column = '';
206
-
207
-
208
-    /**
209
-     * Used to indicate whether the table has a checkbox column or not.
210
-     *
211
-     * @type bool $_has_checkbox_column
212
-     */
213
-    protected $_has_checkbox_column = false;
214
-
215
-
216
-    /**
217
-     * @param EE_Admin_Page $admin_page we use this for obtaining everything we need in the list table
218
-     */
219
-    public function __construct(EE_Admin_Page $admin_page)
220
-    {
221
-        $this->_admin_page   = $admin_page;
222
-        $this->_req_data     = $this->_admin_page->get_request_data();
223
-        $this->_view         = $this->_admin_page->get_view();
224
-        $this->_views        = empty($this->_views) ? $this->_admin_page->get_list_table_view_RLs() : $this->_views;
225
-        $this->_current_page = $this->get_pagenum();
226
-        $this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
227
-        $this->_yes_no       = [
228
-            esc_html__('No', 'event_espresso'),
229
-            esc_html__('Yes', 'event_espresso')
230
-        ];
231
-
232
-        $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
233
-
234
-        $this->_setup_data();
235
-        $this->_add_view_counts();
236
-
237
-        $this->_nonce_action_ref = $this->_view;
238
-
239
-        $this->_set_properties();
240
-
241
-        // set primary column
242
-        add_filter('list_table_primary_column', [$this, 'set_primary_column']);
243
-
244
-        // set parent defaults
245
-        parent::__construct($this->_wp_list_args);
246
-
247
-        $this->prepare_items();
248
-    }
249
-
250
-
251
-    /**
252
-     * _setup_data
253
-     * this method is used to setup the $_data, $_all_data_count, and _per_page properties
254
-     *
255
-     * @return void
256
-     * @uses $this->_admin_page
257
-     */
258
-    abstract protected function _setup_data();
259
-
260
-
261
-    /**
262
-     * set the properties that this class needs to be able to execute wp_list_table properly
263
-     * properties set:
264
-     * _wp_list_args = what the arguments required for the parent _wp_list_table.
265
-     * _columns = set the columns in an array.
266
-     * _sortable_columns = columns that are sortable (array).
267
-     * _hidden_columns = columns that are hidden (array)
268
-     * _default_orderby = the default orderby for sorting.
269
-     *
270
-     * @abstract
271
-     * @access protected
272
-     * @return void
273
-     */
274
-    abstract protected function _set_properties();
275
-
276
-
277
-    /**
278
-     * _get_table_filters
279
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
280
-     * gets shown in the table.
281
-     *
282
-     * @abstract
283
-     * @access protected
284
-     * @return string
285
-     */
286
-    abstract protected function _get_table_filters();
287
-
288
-
289
-    /**
290
-     * this is a method that child class will do to add counts to the views array so when views are displayed the
291
-     * counts of the views is accurate.
292
-     *
293
-     * @abstract
294
-     * @access protected
295
-     * @return void
296
-     */
297
-    abstract protected function _add_view_counts();
298
-
299
-
300
-    /**
301
-     * _get_hidden_fields
302
-     * returns a html string of hidden fields so if any table filters are used the current view will be respected.
303
-     *
304
-     * @return string
305
-     */
306
-    protected function _get_hidden_fields()
307
-    {
308
-        $action = isset($this->_req_data['route']) ? $this->_req_data['route'] : '';
309
-        $action = empty($action) && isset($this->_req_data['action']) ? $this->_req_data['action'] : $action;
310
-        // if action is STILL empty, then we set it to default
311
-        $action = empty($action) ? 'default' : $action;
312
-        $field  = '<input type="hidden" name="page" value="' . esc_attr($this->_req_data['page']) . '" />' . "\n";
313
-        $field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
314
-        $field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
315
-
316
-        $bulk_actions = $this->_get_bulk_actions();
317
-        foreach ($bulk_actions as $bulk_action => $label) {
318
-            $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
319
-                      . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
320
-        }
321
-
322
-        return $field;
323
-    }
324
-
325
-
326
-    /**
327
-     * _set_column_info
328
-     * we're using this to set the column headers property.
329
-     *
330
-     * @access protected
331
-     * @return void
332
-     */
333
-    protected function _set_column_info()
334
-    {
335
-        $columns   = $this->get_columns();
336
-        $hidden    = $this->get_hidden_columns();
337
-        $_sortable = $this->get_sortable_columns();
338
-
339
-        /**
340
-         * Dynamic hook allowing for adding sortable columns in this list table.
341
-         * Note that $this->screen->id is in the format
342
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
343
-         * table it is: event-espresso_page_espresso_messages.
344
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
345
-         * hook prefix ("event-espresso") will be different.
346
-         *
347
-         * @var array
348
-         */
349
-        $_sortable = apply_filters("FHEE_manage_{$this->screen->id}_sortable_columns", $_sortable, $this->_screen);
350
-
351
-        $sortable = [];
352
-        foreach ($_sortable as $id => $data) {
353
-            if (empty($data)) {
354
-                continue;
355
-            }
356
-            // fix for offset errors with WP_List_Table default get_columninfo()
357
-            if (is_array($data)) {
358
-                $_data[0] = key($data);
359
-                $_data[1] = isset($data[1]) ? $data[1] : false;
360
-            } else {
361
-                $_data[0] = $data;
362
-            }
363
-
364
-            $data = (array) $data;
365
-
366
-            if (! isset($data[1])) {
367
-                $_data[1] = false;
368
-            }
369
-
370
-            $sortable[ $id ] = $_data;
371
-        }
372
-        $primary               = $this->get_primary_column_name();
373
-        $this->_column_headers = [$columns, $hidden, $sortable, $primary];
374
-    }
375
-
376
-
377
-    /**
378
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
379
-     *
380
-     * @return string
381
-     */
382
-    protected function get_primary_column_name()
383
-    {
384
-        foreach (class_parents($this) as $parent) {
385
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
386
-                return parent::get_primary_column_name();
387
-            }
388
-        }
389
-        return $this->_primary_column;
390
-    }
391
-
392
-
393
-    /**
394
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
395
-     *
396
-     * @param EE_Base_Class $item
397
-     * @param string        $column_name
398
-     * @param string        $primary
399
-     * @return string
400
-     */
401
-    protected function handle_row_actions($item, $column_name, $primary)
402
-    {
403
-        foreach (class_parents($this) as $parent) {
404
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
405
-                return parent::handle_row_actions($item, $column_name, $primary);
406
-            }
407
-        }
408
-        return '';
409
-    }
410
-
411
-
412
-    /**
413
-     * _get_bulk_actions
414
-     * This is a wrapper called by WP_List_Table::get_bulk_actions()
415
-     *
416
-     * @access protected
417
-     * @return array bulk_actions
418
-     */
419
-    protected function _get_bulk_actions(): array
420
-    {
421
-        $actions = [];
422
-        // the _views property should have the bulk_actions, so let's go through and extract them into a properly
423
-        // formatted array for the wp_list_table();
424
-        foreach ($this->_views as $view => $args) {
425
-            if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
426
-                // each bulk action will correspond with a admin page route, so we can check whatever the capability is
427
-                // for that page route and skip adding the bulk action if no access for the current logged in user.
428
-                foreach ($args['bulk_action'] as $route => $label) {
429
-                    if ($this->_admin_page->check_user_access($route, true)) {
430
-                        $actions[ $route ] = $label;
431
-                    }
432
-                }
433
-            }
434
-        }
435
-        return $actions;
436
-    }
437
-
438
-
439
-    /**
440
-     * Generate the table navigation above or below the table.
441
-     * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
442
-     *
443
-     * @throws EE_Error
444
-     * @since 4.9.44.rc.001
445
-     */
446
-    public function display_tablenav($which)
447
-    {
448
-        if ('top' === $which) {
449
-            wp_nonce_field('bulk-' . $this->_args['plural']);
450
-        }
451
-        ?>
24
+	const ACTION_COPY    = 'duplicate';
25
+
26
+	const ACTION_DELETE  = 'delete';
27
+
28
+	const ACTION_EDIT    = 'edit';
29
+
30
+	const ACTION_RESTORE = 'restore';
31
+
32
+	const ACTION_TRASH   = 'trash';
33
+
34
+	protected static $actions = [
35
+		self::ACTION_COPY,
36
+		self::ACTION_DELETE,
37
+		self::ACTION_EDIT,
38
+		self::ACTION_RESTORE,
39
+		self::ACTION_TRASH,
40
+	];
41
+
42
+	/**
43
+	 * holds the data that will be processed for the table
44
+	 *
45
+	 * @var array $_data
46
+	 */
47
+	protected $_data;
48
+
49
+
50
+	/**
51
+	 * This holds the value of all the data available for the given view (for all pages).
52
+	 *
53
+	 * @var int $_all_data_count
54
+	 */
55
+	protected $_all_data_count;
56
+
57
+
58
+	/**
59
+	 * Will contain the count of trashed items for the view label.
60
+	 *
61
+	 * @var int $_trashed_count
62
+	 */
63
+	protected $_trashed_count;
64
+
65
+
66
+	/**
67
+	 * This is what will be referenced as the slug for the current screen
68
+	 *
69
+	 * @var string $_screen
70
+	 */
71
+	protected $_screen;
72
+
73
+
74
+	/**
75
+	 * this is the EE_Admin_Page object
76
+	 *
77
+	 * @var EE_Admin_Page $_admin_page
78
+	 */
79
+	protected $_admin_page;
80
+
81
+
82
+	/**
83
+	 * The current view
84
+	 *
85
+	 * @var string $_view
86
+	 */
87
+	protected $_view;
88
+
89
+
90
+	/**
91
+	 * array of possible views for this table
92
+	 *
93
+	 * @var array $_views
94
+	 */
95
+	protected $_views;
96
+
97
+
98
+	/**
99
+	 * An array of key => value pairs containing information about the current table
100
+	 * array(
101
+	 *        'plural' => 'plural label',
102
+	 *        'singular' => 'singular label',
103
+	 *        'ajax' => false, //whether to use ajax or not
104
+	 *        'screen' => null, //string used to reference what screen this is
105
+	 *        (WP_List_table converts to screen object)
106
+	 * )
107
+	 *
108
+	 * @var array $_wp_list_args
109
+	 */
110
+	protected $_wp_list_args;
111
+
112
+	/**
113
+	 * an array of column names
114
+	 * array(
115
+	 *    'internal-name' => 'Title'
116
+	 * )
117
+	 *
118
+	 * @var array $_columns
119
+	 */
120
+	protected $_columns;
121
+
122
+	/**
123
+	 * An array of sortable columns
124
+	 * array(
125
+	 *    'internal-name' => 'orderby' //or
126
+	 *    'internal-name' => array( 'orderby', true )
127
+	 * )
128
+	 *
129
+	 * @var array $_sortable_columns
130
+	 */
131
+	protected $_sortable_columns;
132
+
133
+	/**
134
+	 * callback method used to perform AJAX row reordering
135
+	 *
136
+	 * @var string $_ajax_sorting_callback
137
+	 */
138
+	protected $_ajax_sorting_callback;
139
+
140
+	/**
141
+	 * An array of hidden columns (if needed)
142
+	 * array('internal-name', 'internal-name')
143
+	 *
144
+	 * @var array $_hidden_columns
145
+	 */
146
+	protected $_hidden_columns;
147
+
148
+	/**
149
+	 * holds the per_page value
150
+	 *
151
+	 * @var int $_per_page
152
+	 */
153
+	protected $_per_page;
154
+
155
+	/**
156
+	 * holds what page number is currently being viewed
157
+	 *
158
+	 * @var int $_current_page
159
+	 */
160
+	protected $_current_page;
161
+
162
+	/**
163
+	 * the reference string for the nonce_action
164
+	 *
165
+	 * @var string $_nonce_action_ref
166
+	 */
167
+	protected $_nonce_action_ref;
168
+
169
+	/**
170
+	 * property to hold incoming request data (as set by the admin_page_core)
171
+	 *
172
+	 * @var array $_req_data
173
+	 */
174
+	protected $_req_data;
175
+
176
+
177
+	/**
178
+	 * yes / no array for admin form fields
179
+	 *
180
+	 * @var array $_yes_no
181
+	 */
182
+	protected $_yes_no = [];
183
+
184
+	/**
185
+	 * Array describing buttons that should appear at the bottom of the page
186
+	 * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
187
+	 * and the values are another array with the following keys
188
+	 * array(
189
+	 *    'route' => 'page_route',
190
+	 *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
191
+	 * )
192
+	 *
193
+	 * @var array $_bottom_buttons
194
+	 */
195
+	protected $_bottom_buttons = [];
196
+
197
+
198
+	/**
199
+	 * Used to indicate what should be the primary column for the list table.
200
+	 * If not present then falls back to what WP calculates
201
+	 * as the primary column.
202
+	 *
203
+	 * @type string $_primary_column
204
+	 */
205
+	protected $_primary_column = '';
206
+
207
+
208
+	/**
209
+	 * Used to indicate whether the table has a checkbox column or not.
210
+	 *
211
+	 * @type bool $_has_checkbox_column
212
+	 */
213
+	protected $_has_checkbox_column = false;
214
+
215
+
216
+	/**
217
+	 * @param EE_Admin_Page $admin_page we use this for obtaining everything we need in the list table
218
+	 */
219
+	public function __construct(EE_Admin_Page $admin_page)
220
+	{
221
+		$this->_admin_page   = $admin_page;
222
+		$this->_req_data     = $this->_admin_page->get_request_data();
223
+		$this->_view         = $this->_admin_page->get_view();
224
+		$this->_views        = empty($this->_views) ? $this->_admin_page->get_list_table_view_RLs() : $this->_views;
225
+		$this->_current_page = $this->get_pagenum();
226
+		$this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
227
+		$this->_yes_no       = [
228
+			esc_html__('No', 'event_espresso'),
229
+			esc_html__('Yes', 'event_espresso')
230
+		];
231
+
232
+		$this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
233
+
234
+		$this->_setup_data();
235
+		$this->_add_view_counts();
236
+
237
+		$this->_nonce_action_ref = $this->_view;
238
+
239
+		$this->_set_properties();
240
+
241
+		// set primary column
242
+		add_filter('list_table_primary_column', [$this, 'set_primary_column']);
243
+
244
+		// set parent defaults
245
+		parent::__construct($this->_wp_list_args);
246
+
247
+		$this->prepare_items();
248
+	}
249
+
250
+
251
+	/**
252
+	 * _setup_data
253
+	 * this method is used to setup the $_data, $_all_data_count, and _per_page properties
254
+	 *
255
+	 * @return void
256
+	 * @uses $this->_admin_page
257
+	 */
258
+	abstract protected function _setup_data();
259
+
260
+
261
+	/**
262
+	 * set the properties that this class needs to be able to execute wp_list_table properly
263
+	 * properties set:
264
+	 * _wp_list_args = what the arguments required for the parent _wp_list_table.
265
+	 * _columns = set the columns in an array.
266
+	 * _sortable_columns = columns that are sortable (array).
267
+	 * _hidden_columns = columns that are hidden (array)
268
+	 * _default_orderby = the default orderby for sorting.
269
+	 *
270
+	 * @abstract
271
+	 * @access protected
272
+	 * @return void
273
+	 */
274
+	abstract protected function _set_properties();
275
+
276
+
277
+	/**
278
+	 * _get_table_filters
279
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
280
+	 * gets shown in the table.
281
+	 *
282
+	 * @abstract
283
+	 * @access protected
284
+	 * @return string
285
+	 */
286
+	abstract protected function _get_table_filters();
287
+
288
+
289
+	/**
290
+	 * this is a method that child class will do to add counts to the views array so when views are displayed the
291
+	 * counts of the views is accurate.
292
+	 *
293
+	 * @abstract
294
+	 * @access protected
295
+	 * @return void
296
+	 */
297
+	abstract protected function _add_view_counts();
298
+
299
+
300
+	/**
301
+	 * _get_hidden_fields
302
+	 * returns a html string of hidden fields so if any table filters are used the current view will be respected.
303
+	 *
304
+	 * @return string
305
+	 */
306
+	protected function _get_hidden_fields()
307
+	{
308
+		$action = isset($this->_req_data['route']) ? $this->_req_data['route'] : '';
309
+		$action = empty($action) && isset($this->_req_data['action']) ? $this->_req_data['action'] : $action;
310
+		// if action is STILL empty, then we set it to default
311
+		$action = empty($action) ? 'default' : $action;
312
+		$field  = '<input type="hidden" name="page" value="' . esc_attr($this->_req_data['page']) . '" />' . "\n";
313
+		$field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
314
+		$field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
315
+
316
+		$bulk_actions = $this->_get_bulk_actions();
317
+		foreach ($bulk_actions as $bulk_action => $label) {
318
+			$field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
319
+					  . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
320
+		}
321
+
322
+		return $field;
323
+	}
324
+
325
+
326
+	/**
327
+	 * _set_column_info
328
+	 * we're using this to set the column headers property.
329
+	 *
330
+	 * @access protected
331
+	 * @return void
332
+	 */
333
+	protected function _set_column_info()
334
+	{
335
+		$columns   = $this->get_columns();
336
+		$hidden    = $this->get_hidden_columns();
337
+		$_sortable = $this->get_sortable_columns();
338
+
339
+		/**
340
+		 * Dynamic hook allowing for adding sortable columns in this list table.
341
+		 * Note that $this->screen->id is in the format
342
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
343
+		 * table it is: event-espresso_page_espresso_messages.
344
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
345
+		 * hook prefix ("event-espresso") will be different.
346
+		 *
347
+		 * @var array
348
+		 */
349
+		$_sortable = apply_filters("FHEE_manage_{$this->screen->id}_sortable_columns", $_sortable, $this->_screen);
350
+
351
+		$sortable = [];
352
+		foreach ($_sortable as $id => $data) {
353
+			if (empty($data)) {
354
+				continue;
355
+			}
356
+			// fix for offset errors with WP_List_Table default get_columninfo()
357
+			if (is_array($data)) {
358
+				$_data[0] = key($data);
359
+				$_data[1] = isset($data[1]) ? $data[1] : false;
360
+			} else {
361
+				$_data[0] = $data;
362
+			}
363
+
364
+			$data = (array) $data;
365
+
366
+			if (! isset($data[1])) {
367
+				$_data[1] = false;
368
+			}
369
+
370
+			$sortable[ $id ] = $_data;
371
+		}
372
+		$primary               = $this->get_primary_column_name();
373
+		$this->_column_headers = [$columns, $hidden, $sortable, $primary];
374
+	}
375
+
376
+
377
+	/**
378
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
379
+	 *
380
+	 * @return string
381
+	 */
382
+	protected function get_primary_column_name()
383
+	{
384
+		foreach (class_parents($this) as $parent) {
385
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
386
+				return parent::get_primary_column_name();
387
+			}
388
+		}
389
+		return $this->_primary_column;
390
+	}
391
+
392
+
393
+	/**
394
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
395
+	 *
396
+	 * @param EE_Base_Class $item
397
+	 * @param string        $column_name
398
+	 * @param string        $primary
399
+	 * @return string
400
+	 */
401
+	protected function handle_row_actions($item, $column_name, $primary)
402
+	{
403
+		foreach (class_parents($this) as $parent) {
404
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
405
+				return parent::handle_row_actions($item, $column_name, $primary);
406
+			}
407
+		}
408
+		return '';
409
+	}
410
+
411
+
412
+	/**
413
+	 * _get_bulk_actions
414
+	 * This is a wrapper called by WP_List_Table::get_bulk_actions()
415
+	 *
416
+	 * @access protected
417
+	 * @return array bulk_actions
418
+	 */
419
+	protected function _get_bulk_actions(): array
420
+	{
421
+		$actions = [];
422
+		// the _views property should have the bulk_actions, so let's go through and extract them into a properly
423
+		// formatted array for the wp_list_table();
424
+		foreach ($this->_views as $view => $args) {
425
+			if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
426
+				// each bulk action will correspond with a admin page route, so we can check whatever the capability is
427
+				// for that page route and skip adding the bulk action if no access for the current logged in user.
428
+				foreach ($args['bulk_action'] as $route => $label) {
429
+					if ($this->_admin_page->check_user_access($route, true)) {
430
+						$actions[ $route ] = $label;
431
+					}
432
+				}
433
+			}
434
+		}
435
+		return $actions;
436
+	}
437
+
438
+
439
+	/**
440
+	 * Generate the table navigation above or below the table.
441
+	 * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
442
+	 *
443
+	 * @throws EE_Error
444
+	 * @since 4.9.44.rc.001
445
+	 */
446
+	public function display_tablenav($which)
447
+	{
448
+		if ('top' === $which) {
449
+			wp_nonce_field('bulk-' . $this->_args['plural']);
450
+		}
451
+		?>
452 452
         <div class="tablenav <?php echo esc_attr($which); ?>">
453 453
             <?php if ($this->_get_bulk_actions()) { ?>
454 454
                 <div class="alignleft actions bulkactions">
455 455
                     <?php $this->bulk_actions(); ?>
456 456
                 </div>
457 457
             <?php }
458
-            $this->extra_tablenav($which);
459
-            $this->pagination($which);
460
-            ?>
458
+			$this->extra_tablenav($which);
459
+			$this->pagination($which);
460
+			?>
461 461
 
462 462
             <br class="clear" />
463 463
         </div>
464 464
         <?php
465
-    }
466
-
467
-
468
-    /**
469
-     * _filters
470
-     * This receives the filters array from children _get_table_filters() and assembles the string including the filter
471
-     * button.
472
-     *
473
-     * @access private
474
-     * @return void  echos html showing filters
475
-     */
476
-    private function _filters()
477
-    {
478
-        $classname = get_class($this);
479
-        $filters   = apply_filters(
480
-            "FHEE__{$classname}__filters",
481
-            (array) $this->_get_table_filters(),
482
-            $this,
483
-            $this->_screen
484
-        );
485
-
486
-        if (empty($filters)) {
487
-            return;
488
-        }
489
-
490
-        $filters_html = '';
491
-        foreach ($filters as $filter) {
492
-            $filters_html .= wp_kses($filter, AllowedTags::getWithFormTags());
493
-        }
494
-        $filter_submit_btn_text = esc_html__('Filter', 'event_espresso');
495
-        $filter_reset_btn_text = esc_html__('Reset Filters', 'event_espresso');
496
-        $filter_reset_btn_url = esc_url_raw($this->_admin_page->get_current_page_view_url());
497
-
498
-        echo "
465
+	}
466
+
467
+
468
+	/**
469
+	 * _filters
470
+	 * This receives the filters array from children _get_table_filters() and assembles the string including the filter
471
+	 * button.
472
+	 *
473
+	 * @access private
474
+	 * @return void  echos html showing filters
475
+	 */
476
+	private function _filters()
477
+	{
478
+		$classname = get_class($this);
479
+		$filters   = apply_filters(
480
+			"FHEE__{$classname}__filters",
481
+			(array) $this->_get_table_filters(),
482
+			$this,
483
+			$this->_screen
484
+		);
485
+
486
+		if (empty($filters)) {
487
+			return;
488
+		}
489
+
490
+		$filters_html = '';
491
+		foreach ($filters as $filter) {
492
+			$filters_html .= wp_kses($filter, AllowedTags::getWithFormTags());
493
+		}
494
+		$filter_submit_btn_text = esc_html__('Filter', 'event_espresso');
495
+		$filter_reset_btn_text = esc_html__('Reset Filters', 'event_espresso');
496
+		$filter_reset_btn_url = esc_url_raw($this->_admin_page->get_current_page_view_url());
497
+
498
+		echo "
499 499
         <div class='ee-list-table-filters actions alignleft'>
500 500
            $filters_html
501 501
             <span class='ee-list-table-filters__submit-buttons'>
@@ -510,443 +510,443 @@  discard block
 block discarded – undo
510 510
                 </a>
511 511
             </span>
512 512
         </div>";
513
-    }
514
-
515
-
516
-    /**
517
-     * Callback for 'list_table_primary_column' WordPress filter
518
-     * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
519
-     * column when class is instantiated.
520
-     *
521
-     * @param string $column_name
522
-     * @return string
523
-     * @see WP_List_Table::get_primary_column_name
524
-     */
525
-    public function set_primary_column($column_name)
526
-    {
527
-        return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
528
-    }
529
-
530
-
531
-    /**
532
-     *
533
-     */
534
-    public function prepare_items()
535
-    {
536
-        $this->_set_column_info();
537
-        // $this->_column_headers = $this->get_column_info();
538
-        $total_items = $this->_all_data_count;
539
-        $this->process_bulk_action();
540
-
541
-        $this->items = $this->_data;
542
-        $this->set_pagination_args(
543
-            [
544
-                'total_items' => $total_items,
545
-                'per_page'    => $this->_per_page,
546
-                'total_pages' => ceil($total_items / $this->_per_page),
547
-            ]
548
-        );
549
-    }
550
-
551
-
552
-    /**
553
-     * @param object|array $item
554
-     * @return string html content for the column
555
-     */
556
-    protected function column_cb($item)
557
-    {
558
-        return '';
559
-    }
560
-
561
-
562
-    /**
563
-     * This column is the default for when there is no defined column method for a registered column.
564
-     * This can be overridden by child classes, but allows for hooking in for custom columns.
565
-     *
566
-     * @param EE_Base_Class $item
567
-     * @param string        $column_name The column being called.
568
-     * @return string html content for the column
569
-     */
570
-    public function column_default($item, $column_name)
571
-    {
572
-        /**
573
-         * Dynamic hook allowing for adding additional column content in this list table.
574
-         * Note that $this->screen->id is in the format
575
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
576
-         * table it is: event-espresso_page_espresso_messages.
577
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
578
-         * hook prefix ("event-espresso") will be different.
579
-         */
580
-        ob_start();
581
-        do_action(
582
-            'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
583
-            $item,
584
-            $this->_screen
585
-        );
586
-        return ob_get_clean();
587
-    }
588
-
589
-
590
-    /**
591
-     * Get a list of columns. The format is:
592
-     * 'internal-name' => 'Title'
593
-     *
594
-     * @return array
595
-     * @since  3.1.0
596
-     * @access public
597
-     * @abstract
598
-     */
599
-    public function get_columns()
600
-    {
601
-        /**
602
-         * Dynamic hook allowing for adding additional columns in this list table.
603
-         * Note that $this->screen->id is in the format
604
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
605
-         * table it is: event-espresso_page_espresso_messages.
606
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
607
-         * hook prefix ("event-espresso") will be different.
608
-         *
609
-         * @var array
610
-         */
611
-        return apply_filters('FHEE_manage_' . $this->screen->id . '_columns', $this->_columns, $this->_screen);
612
-    }
613
-
614
-
615
-    /**
616
-     * Get an associative array ( id => link ) with the list
617
-     * of views available on this table.
618
-     *
619
-     * @return array
620
-     * @since  3.1.0
621
-     * @access protected
622
-     */
623
-    public function get_views()
624
-    {
625
-        return $this->_views;
626
-    }
627
-
628
-
629
-    /**
630
-     * Generate the views html.
631
-     */
632
-    public function display_views()
633
-    {
634
-        $views           = $this->get_views();
635
-        $assembled_views = [];
636
-
637
-        if (empty($views)) {
638
-            return;
639
-        }
640
-        echo "<ul class='subsubsub'>\n";
641
-        foreach ($views as $view) {
642
-            $count = isset($view['count']) && ! empty($view['count']) ? absint($view['count']) : 0;
643
-            if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
644
-                $filter = "<li";
645
-                $filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
646
-                $filter .= ">";
647
-                $filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html($view['label']) . '</a>';
648
-                $filter .= '<span class="count">(' . $count . ')</span>';
649
-                $filter .= '</li>';
650
-                $assembled_views[ $view['slug'] ] = $filter;
651
-            }
652
-        }
653
-
654
-        echo ! empty($assembled_views)
655
-            ? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
656
-            : '';
657
-        echo "</ul>";
658
-    }
659
-
660
-
661
-    /**
662
-     * Generates content for a single row of the table
663
-     *
664
-     * @param EE_Base_Class $item The current item
665
-     * @since  4.1
666
-     * @access public
667
-     */
668
-    public function single_row($item)
669
-    {
670
-        $row_class = $this->_get_row_class($item);
671
-        echo '<tr class="' . esc_attr($row_class) . '">';
672
-        $this->single_row_columns($item); // already escaped
673
-        echo '</tr>';
674
-    }
675
-
676
-
677
-    /**
678
-     * This simply sets up the row class for the table rows.
679
-     * Allows for easier overriding of child methods for setting up sorting.
680
-     *
681
-     * @param EE_Base_Class $item the current item
682
-     * @return string
683
-     */
684
-    protected function _get_row_class($item)
685
-    {
686
-        static $row_class = '';
687
-        $row_class = ($row_class === '' ? 'alternate' : '');
688
-
689
-        $new_row_class = $row_class;
690
-
691
-        if (! empty($this->_ajax_sorting_callback)) {
692
-            $new_row_class .= ' rowsortable';
693
-        }
694
-
695
-        return $new_row_class;
696
-    }
697
-
698
-
699
-    /**
700
-     * @return array
701
-     */
702
-    public function get_sortable_columns()
703
-    {
704
-        return (array) $this->_sortable_columns;
705
-    }
706
-
707
-
708
-    /**
709
-     * @return string
710
-     */
711
-    public function get_ajax_sorting_callback()
712
-    {
713
-        return $this->_ajax_sorting_callback;
714
-    }
715
-
716
-
717
-    /**
718
-     * @return array
719
-     */
720
-    public function get_hidden_columns()
721
-    {
722
-        $user_id     = get_current_user_id();
723
-        $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
724
-        if (empty($has_default) && ! empty($this->_hidden_columns)) {
725
-            update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
726
-            update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
727
-        }
728
-        $ref = 'manage' . $this->screen->id . 'columnshidden';
729
-        return (array) get_user_option($ref, $user_id);
730
-    }
731
-
732
-
733
-    /**
734
-     * Generates the columns for a single row of the table.
735
-     * Overridden from wp_list_table so as to allow us to filter the column content for a given
736
-     * column.
737
-     *
738
-     * @param EE_Base_Class $item The current item
739
-     * @since 3.1.0
740
-     */
741
-    public function single_row_columns($item)
742
-    {
743
-        [$columns, $hidden, $sortable, $primary] = $this->get_column_info();
744
-
745
-        foreach ($columns as $column_name => $column_display_name) {
746
-
747
-            /**
748
-             * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
749
-             * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
750
-             */
751
-            $hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
752
-
753
-            $classes = $column_name . ' column-' . $column_name . $hidden_class;
754
-            if ($primary === $column_name) {
755
-                $classes .= ' has-row-actions column-primary';
756
-            }
757
-
758
-            $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
759
-
760
-            $class = 'class="' . esc_attr($classes) . '"';
761
-
762
-            $attributes = "{$class}{$data}";
763
-
764
-            if ($column_name === 'cb') {
765
-                echo '<th scope="row" class="check-column">';
766
-                echo apply_filters(
767
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
768
-                    $this->column_cb($item), // already escaped
769
-                    $item,
770
-                    $this
771
-                );
772
-                echo '</th>';
773
-            } elseif (method_exists($this, 'column_' . $column_name)) {
774
-                echo "<td $attributes>"; // already escaped
775
-                echo apply_filters(
776
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
777
-                    call_user_func([$this, 'column_' . $column_name], $item),
778
-                    $item,
779
-                    $this
780
-                );
781
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
782
-                echo "</td>";
783
-            } else {
784
-                echo "<td $attributes>"; // already escaped
785
-                echo apply_filters(
786
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
787
-                    $this->column_default($item, $column_name),
788
-                    $item,
789
-                    $column_name,
790
-                    $this
791
-                );
792
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
793
-                echo "</td>";
794
-            }
795
-        }
796
-    }
797
-
798
-
799
-    /**
800
-     * Extra controls to be displayed between bulk actions and pagination
801
-     *
802
-     * @access public
803
-     * @param string $which
804
-     * @throws EE_Error
805
-     */
806
-    public function extra_tablenav($which)
807
-    {
808
-        if ($which === 'top') {
809
-            $this->_filters();
810
-            echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
811
-        } else {
812
-            echo '<div class="list-table-bottom-buttons alignleft actions">';
813
-            foreach ($this->_bottom_buttons as $type => $action) {
814
-                $route         = $action['route'] ?? '';
815
-                $extra_request = $action['extra_request'] ?? '';
816
-                // already escaped
817
-                echo wp_kses($this->_admin_page->get_action_link_or_button(
818
-                    $route,
819
-                    $type,
820
-                    $extra_request,
821
-                    'button button--secondary'
822
-                ), AllowedTags::getWithFormTags());
823
-            }
824
-            do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
825
-            echo '</div>';
826
-        }
827
-    }
828
-
829
-
830
-    /**
831
-     * Get an associative array ( option_name => option_title ) with the list
832
-     * of bulk actions available on this table.
833
-     *
834
-     * @return array
835
-     * @since  3.1.0
836
-     * @access protected
837
-     */
838
-    public function get_bulk_actions()
839
-    {
840
-        return (array) $this->_get_bulk_actions();
841
-    }
842
-
843
-
844
-    /**
845
-     * Processing bulk actions.
846
-     */
847
-    public function process_bulk_action()
848
-    {
849
-        // this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
850
-        // reference in case there is a case where it gets used.
851
-    }
852
-
853
-
854
-    /**
855
-     * returns the EE admin page this list table is associated with
856
-     *
857
-     * @return EE_Admin_Page
858
-     */
859
-    public function get_admin_page()
860
-    {
861
-        return $this->_admin_page;
862
-    }
863
-
864
-
865
-    /**
866
-     * A "helper" function for all children to provide an html string of
867
-     * actions to output in their content.  It is preferable for child classes
868
-     * to use this method for generating their actions content so that it's
869
-     * filterable by plugins
870
-     *
871
-     * @param string        $action_container           what are the html container
872
-     *                                                  elements for this actions string?
873
-     * @param string        $action_class               What class is for the container
874
-     *                                                  element.
875
-     * @param string        $action_items               The contents for the action items
876
-     *                                                  container.  This is filtered before
877
-     *                                                  returned.
878
-     * @param string        $action_id                  What id (optional) is used for the
879
-     *                                                  container element.
880
-     * @param EE_Base_Class $item                       The object for the column displaying
881
-     *                                                  the actions.
882
-     * @return string The assembled action elements container.
883
-     */
884
-    protected function _action_string(
885
-        $action_items,
886
-        $item,
887
-        $action_container = 'ul',
888
-        $action_class = '',
889
-        $action_id = ''
890
-    ) {
891
-        $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
892
-        $action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
893
-        $open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
894
-        $close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
895
-        try {
896
-            $content = apply_filters(
897
-                'FHEE__EE_Admin_List_Table___action_string__action_items',
898
-                $action_items,
899
-                $item,
900
-                $this
901
-            );
902
-        } catch (Exception $e) {
903
-            if (WP_DEBUG) {
904
-                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
905
-            }
906
-            $content = $action_items;
907
-        }
908
-        return "{$open_tag}{$content}{$close_tag}";
909
-    }
910
-
911
-
912
-    /**
913
-     * @return string
914
-     */
915
-    protected function getReturnUrl()
916
-    {
917
-        $host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
918
-        $uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
919
-        return urlencode(esc_url_raw("//{$host}{$uri}"));
920
-    }
921
-
922
-
923
-    /**
924
-     * @param string $id
925
-     * @param string $content
926
-     * @param string $align     start (default), center, end
927
-     * @return string
928
-     * @since   $VID:$
929
-     */
930
-    protected function columnContent($id, $content, $align = 'start')
931
-    {
932
-        if (! isset($this->_columns[ $id ])) {
933
-            throw new DomainException('missing column id');
934
-        }
935
-        $heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
936
-        $align = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
937
-        $align = "ee-responsive-table-cell--{$align}";
938
-
939
-        $html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-{$id} {$align} ee-layout-row'>";
940
-        $html .= "<div class='ee-responsive-table-cell__heading'>{$heading}</div>";
941
-        $html .= "<div class='ee-responsive-table-cell__content ee-layout-row'>{$content}</div>";
942
-        $html .= "</div>";
943
-        return $html;
944
-    }
945
-
946
-
947
-    protected function actionsModalMenu($actions): string
948
-    {
949
-        return '
513
+	}
514
+
515
+
516
+	/**
517
+	 * Callback for 'list_table_primary_column' WordPress filter
518
+	 * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
519
+	 * column when class is instantiated.
520
+	 *
521
+	 * @param string $column_name
522
+	 * @return string
523
+	 * @see WP_List_Table::get_primary_column_name
524
+	 */
525
+	public function set_primary_column($column_name)
526
+	{
527
+		return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
528
+	}
529
+
530
+
531
+	/**
532
+	 *
533
+	 */
534
+	public function prepare_items()
535
+	{
536
+		$this->_set_column_info();
537
+		// $this->_column_headers = $this->get_column_info();
538
+		$total_items = $this->_all_data_count;
539
+		$this->process_bulk_action();
540
+
541
+		$this->items = $this->_data;
542
+		$this->set_pagination_args(
543
+			[
544
+				'total_items' => $total_items,
545
+				'per_page'    => $this->_per_page,
546
+				'total_pages' => ceil($total_items / $this->_per_page),
547
+			]
548
+		);
549
+	}
550
+
551
+
552
+	/**
553
+	 * @param object|array $item
554
+	 * @return string html content for the column
555
+	 */
556
+	protected function column_cb($item)
557
+	{
558
+		return '';
559
+	}
560
+
561
+
562
+	/**
563
+	 * This column is the default for when there is no defined column method for a registered column.
564
+	 * This can be overridden by child classes, but allows for hooking in for custom columns.
565
+	 *
566
+	 * @param EE_Base_Class $item
567
+	 * @param string        $column_name The column being called.
568
+	 * @return string html content for the column
569
+	 */
570
+	public function column_default($item, $column_name)
571
+	{
572
+		/**
573
+		 * Dynamic hook allowing for adding additional column content in this list table.
574
+		 * Note that $this->screen->id is in the format
575
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
576
+		 * table it is: event-espresso_page_espresso_messages.
577
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
578
+		 * hook prefix ("event-espresso") will be different.
579
+		 */
580
+		ob_start();
581
+		do_action(
582
+			'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
583
+			$item,
584
+			$this->_screen
585
+		);
586
+		return ob_get_clean();
587
+	}
588
+
589
+
590
+	/**
591
+	 * Get a list of columns. The format is:
592
+	 * 'internal-name' => 'Title'
593
+	 *
594
+	 * @return array
595
+	 * @since  3.1.0
596
+	 * @access public
597
+	 * @abstract
598
+	 */
599
+	public function get_columns()
600
+	{
601
+		/**
602
+		 * Dynamic hook allowing for adding additional columns in this list table.
603
+		 * Note that $this->screen->id is in the format
604
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
605
+		 * table it is: event-espresso_page_espresso_messages.
606
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
607
+		 * hook prefix ("event-espresso") will be different.
608
+		 *
609
+		 * @var array
610
+		 */
611
+		return apply_filters('FHEE_manage_' . $this->screen->id . '_columns', $this->_columns, $this->_screen);
612
+	}
613
+
614
+
615
+	/**
616
+	 * Get an associative array ( id => link ) with the list
617
+	 * of views available on this table.
618
+	 *
619
+	 * @return array
620
+	 * @since  3.1.0
621
+	 * @access protected
622
+	 */
623
+	public function get_views()
624
+	{
625
+		return $this->_views;
626
+	}
627
+
628
+
629
+	/**
630
+	 * Generate the views html.
631
+	 */
632
+	public function display_views()
633
+	{
634
+		$views           = $this->get_views();
635
+		$assembled_views = [];
636
+
637
+		if (empty($views)) {
638
+			return;
639
+		}
640
+		echo "<ul class='subsubsub'>\n";
641
+		foreach ($views as $view) {
642
+			$count = isset($view['count']) && ! empty($view['count']) ? absint($view['count']) : 0;
643
+			if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
644
+				$filter = "<li";
645
+				$filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
646
+				$filter .= ">";
647
+				$filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html($view['label']) . '</a>';
648
+				$filter .= '<span class="count">(' . $count . ')</span>';
649
+				$filter .= '</li>';
650
+				$assembled_views[ $view['slug'] ] = $filter;
651
+			}
652
+		}
653
+
654
+		echo ! empty($assembled_views)
655
+			? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
656
+			: '';
657
+		echo "</ul>";
658
+	}
659
+
660
+
661
+	/**
662
+	 * Generates content for a single row of the table
663
+	 *
664
+	 * @param EE_Base_Class $item The current item
665
+	 * @since  4.1
666
+	 * @access public
667
+	 */
668
+	public function single_row($item)
669
+	{
670
+		$row_class = $this->_get_row_class($item);
671
+		echo '<tr class="' . esc_attr($row_class) . '">';
672
+		$this->single_row_columns($item); // already escaped
673
+		echo '</tr>';
674
+	}
675
+
676
+
677
+	/**
678
+	 * This simply sets up the row class for the table rows.
679
+	 * Allows for easier overriding of child methods for setting up sorting.
680
+	 *
681
+	 * @param EE_Base_Class $item the current item
682
+	 * @return string
683
+	 */
684
+	protected function _get_row_class($item)
685
+	{
686
+		static $row_class = '';
687
+		$row_class = ($row_class === '' ? 'alternate' : '');
688
+
689
+		$new_row_class = $row_class;
690
+
691
+		if (! empty($this->_ajax_sorting_callback)) {
692
+			$new_row_class .= ' rowsortable';
693
+		}
694
+
695
+		return $new_row_class;
696
+	}
697
+
698
+
699
+	/**
700
+	 * @return array
701
+	 */
702
+	public function get_sortable_columns()
703
+	{
704
+		return (array) $this->_sortable_columns;
705
+	}
706
+
707
+
708
+	/**
709
+	 * @return string
710
+	 */
711
+	public function get_ajax_sorting_callback()
712
+	{
713
+		return $this->_ajax_sorting_callback;
714
+	}
715
+
716
+
717
+	/**
718
+	 * @return array
719
+	 */
720
+	public function get_hidden_columns()
721
+	{
722
+		$user_id     = get_current_user_id();
723
+		$has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
724
+		if (empty($has_default) && ! empty($this->_hidden_columns)) {
725
+			update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
726
+			update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
727
+		}
728
+		$ref = 'manage' . $this->screen->id . 'columnshidden';
729
+		return (array) get_user_option($ref, $user_id);
730
+	}
731
+
732
+
733
+	/**
734
+	 * Generates the columns for a single row of the table.
735
+	 * Overridden from wp_list_table so as to allow us to filter the column content for a given
736
+	 * column.
737
+	 *
738
+	 * @param EE_Base_Class $item The current item
739
+	 * @since 3.1.0
740
+	 */
741
+	public function single_row_columns($item)
742
+	{
743
+		[$columns, $hidden, $sortable, $primary] = $this->get_column_info();
744
+
745
+		foreach ($columns as $column_name => $column_display_name) {
746
+
747
+			/**
748
+			 * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
749
+			 * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
750
+			 */
751
+			$hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
752
+
753
+			$classes = $column_name . ' column-' . $column_name . $hidden_class;
754
+			if ($primary === $column_name) {
755
+				$classes .= ' has-row-actions column-primary';
756
+			}
757
+
758
+			$data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
759
+
760
+			$class = 'class="' . esc_attr($classes) . '"';
761
+
762
+			$attributes = "{$class}{$data}";
763
+
764
+			if ($column_name === 'cb') {
765
+				echo '<th scope="row" class="check-column">';
766
+				echo apply_filters(
767
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
768
+					$this->column_cb($item), // already escaped
769
+					$item,
770
+					$this
771
+				);
772
+				echo '</th>';
773
+			} elseif (method_exists($this, 'column_' . $column_name)) {
774
+				echo "<td $attributes>"; // already escaped
775
+				echo apply_filters(
776
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
777
+					call_user_func([$this, 'column_' . $column_name], $item),
778
+					$item,
779
+					$this
780
+				);
781
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
782
+				echo "</td>";
783
+			} else {
784
+				echo "<td $attributes>"; // already escaped
785
+				echo apply_filters(
786
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
787
+					$this->column_default($item, $column_name),
788
+					$item,
789
+					$column_name,
790
+					$this
791
+				);
792
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
793
+				echo "</td>";
794
+			}
795
+		}
796
+	}
797
+
798
+
799
+	/**
800
+	 * Extra controls to be displayed between bulk actions and pagination
801
+	 *
802
+	 * @access public
803
+	 * @param string $which
804
+	 * @throws EE_Error
805
+	 */
806
+	public function extra_tablenav($which)
807
+	{
808
+		if ($which === 'top') {
809
+			$this->_filters();
810
+			echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
811
+		} else {
812
+			echo '<div class="list-table-bottom-buttons alignleft actions">';
813
+			foreach ($this->_bottom_buttons as $type => $action) {
814
+				$route         = $action['route'] ?? '';
815
+				$extra_request = $action['extra_request'] ?? '';
816
+				// already escaped
817
+				echo wp_kses($this->_admin_page->get_action_link_or_button(
818
+					$route,
819
+					$type,
820
+					$extra_request,
821
+					'button button--secondary'
822
+				), AllowedTags::getWithFormTags());
823
+			}
824
+			do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
825
+			echo '</div>';
826
+		}
827
+	}
828
+
829
+
830
+	/**
831
+	 * Get an associative array ( option_name => option_title ) with the list
832
+	 * of bulk actions available on this table.
833
+	 *
834
+	 * @return array
835
+	 * @since  3.1.0
836
+	 * @access protected
837
+	 */
838
+	public function get_bulk_actions()
839
+	{
840
+		return (array) $this->_get_bulk_actions();
841
+	}
842
+
843
+
844
+	/**
845
+	 * Processing bulk actions.
846
+	 */
847
+	public function process_bulk_action()
848
+	{
849
+		// this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
850
+		// reference in case there is a case where it gets used.
851
+	}
852
+
853
+
854
+	/**
855
+	 * returns the EE admin page this list table is associated with
856
+	 *
857
+	 * @return EE_Admin_Page
858
+	 */
859
+	public function get_admin_page()
860
+	{
861
+		return $this->_admin_page;
862
+	}
863
+
864
+
865
+	/**
866
+	 * A "helper" function for all children to provide an html string of
867
+	 * actions to output in their content.  It is preferable for child classes
868
+	 * to use this method for generating their actions content so that it's
869
+	 * filterable by plugins
870
+	 *
871
+	 * @param string        $action_container           what are the html container
872
+	 *                                                  elements for this actions string?
873
+	 * @param string        $action_class               What class is for the container
874
+	 *                                                  element.
875
+	 * @param string        $action_items               The contents for the action items
876
+	 *                                                  container.  This is filtered before
877
+	 *                                                  returned.
878
+	 * @param string        $action_id                  What id (optional) is used for the
879
+	 *                                                  container element.
880
+	 * @param EE_Base_Class $item                       The object for the column displaying
881
+	 *                                                  the actions.
882
+	 * @return string The assembled action elements container.
883
+	 */
884
+	protected function _action_string(
885
+		$action_items,
886
+		$item,
887
+		$action_container = 'ul',
888
+		$action_class = '',
889
+		$action_id = ''
890
+	) {
891
+		$action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
892
+		$action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
893
+		$open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
894
+		$close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
895
+		try {
896
+			$content = apply_filters(
897
+				'FHEE__EE_Admin_List_Table___action_string__action_items',
898
+				$action_items,
899
+				$item,
900
+				$this
901
+			);
902
+		} catch (Exception $e) {
903
+			if (WP_DEBUG) {
904
+				EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
905
+			}
906
+			$content = $action_items;
907
+		}
908
+		return "{$open_tag}{$content}{$close_tag}";
909
+	}
910
+
911
+
912
+	/**
913
+	 * @return string
914
+	 */
915
+	protected function getReturnUrl()
916
+	{
917
+		$host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
918
+		$uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
919
+		return urlencode(esc_url_raw("//{$host}{$uri}"));
920
+	}
921
+
922
+
923
+	/**
924
+	 * @param string $id
925
+	 * @param string $content
926
+	 * @param string $align     start (default), center, end
927
+	 * @return string
928
+	 * @since   $VID:$
929
+	 */
930
+	protected function columnContent($id, $content, $align = 'start')
931
+	{
932
+		if (! isset($this->_columns[ $id ])) {
933
+			throw new DomainException('missing column id');
934
+		}
935
+		$heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
936
+		$align = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
937
+		$align = "ee-responsive-table-cell--{$align}";
938
+
939
+		$html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-{$id} {$align} ee-layout-row'>";
940
+		$html .= "<div class='ee-responsive-table-cell__heading'>{$heading}</div>";
941
+		$html .= "<div class='ee-responsive-table-cell__content ee-layout-row'>{$content}</div>";
942
+		$html .= "</div>";
943
+		return $html;
944
+	}
945
+
946
+
947
+	protected function actionsModalMenu($actions): string
948
+	{
949
+		return '
950 950
         <div class="ee-modal-menu">
951 951
             <button class="ee-modal-menu__button button button--small button--icon-only ee-aria-tooltip"
952 952
                     aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '"
@@ -958,24 +958,24 @@  discard block
 block discarded – undo
958 958
                 ' . $actions . '
959 959
             </div>
960 960
         </div>';
961
-    }
961
+	}
962 962
 
963 963
 
964
-    protected function actionsColumnHeader(): string
965
-    {
966
-        return '
964
+	protected function actionsColumnHeader(): string
965
+	{
966
+		return '
967 967
             <span class="ee-actions-column-header-wrap">
968 968
                 <span class="dashicons dashicons-screenoptions"></span>
969 969
                 <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span>
970 970
             </span>';
971
-    }
971
+	}
972 972
 
973 973
 
974
-    protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
975
-    {
976
-        $class = ! empty($class) ? "{$class} ee-list-table-action" : 'ee-list-table-action';
977
-        $class = ! empty($label) ? "{$class} ee-aria-tooltip" : $class;
978
-        $label = ! empty($label) ? " aria-label='{$label}'" : '';
979
-        return "<a href='{$url}' class='{$class}'{$label}>{$display_text}</a>";
980
-    }
974
+	protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
975
+	{
976
+		$class = ! empty($class) ? "{$class} ee-list-table-action" : 'ee-list-table-action';
977
+		$class = ! empty($label) ? "{$class} ee-aria-tooltip" : $class;
978
+		$label = ! empty($label) ? " aria-label='{$label}'" : '';
979
+		return "<a href='{$url}' class='{$class}'{$label}>{$display_text}</a>";
980
+	}
981 981
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4186 added lines, -4186 removed lines patch added patch discarded remove patch
@@ -22,4274 +22,4274 @@
 block discarded – undo
22 22
  */
23 23
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
24 24
 {
25
-    /**
26
-     * @var EE_Admin_Config
27
-     */
28
-    protected $admin_config;
25
+	/**
26
+	 * @var EE_Admin_Config
27
+	 */
28
+	protected $admin_config;
29 29
 
30
-    /**
31
-     * @var LoaderInterface
32
-     */
33
-    protected $loader;
30
+	/**
31
+	 * @var LoaderInterface
32
+	 */
33
+	protected $loader;
34 34
 
35
-    /**
36
-     * @var RequestInterface
37
-     */
38
-    protected $request;
35
+	/**
36
+	 * @var RequestInterface
37
+	 */
38
+	protected $request;
39 39
 
40
-    // set in _init_page_props()
41
-    public $page_slug;
40
+	// set in _init_page_props()
41
+	public $page_slug;
42 42
 
43
-    public $page_label;
43
+	public $page_label;
44 44
 
45
-    public $page_folder;
45
+	public $page_folder;
46 46
 
47
-    // set in define_page_props()
48
-    protected $_admin_base_url;
47
+	// set in define_page_props()
48
+	protected $_admin_base_url;
49 49
 
50
-    protected $_admin_base_path;
50
+	protected $_admin_base_path;
51 51
 
52
-    protected $_admin_page_title;
52
+	protected $_admin_page_title;
53 53
 
54
-    protected $_labels;
54
+	protected $_labels;
55 55
 
56 56
 
57
-    // set early within EE_Admin_Init
58
-    protected $_wp_page_slug;
57
+	// set early within EE_Admin_Init
58
+	protected $_wp_page_slug;
59 59
 
60
-    // nav tabs
61
-    protected $_nav_tabs;
60
+	// nav tabs
61
+	protected $_nav_tabs;
62 62
 
63
-    protected $_default_nav_tab_name;
63
+	protected $_default_nav_tab_name;
64 64
 
65 65
 
66
-    // template variables (used by templates)
67
-    protected $_template_path;
66
+	// template variables (used by templates)
67
+	protected $_template_path;
68 68
 
69
-    protected $_column_template_path;
69
+	protected $_column_template_path;
70 70
 
71
-    /**
72
-     * @var array $_template_args
73
-     */
74
-    protected $_template_args = [];
71
+	/**
72
+	 * @var array $_template_args
73
+	 */
74
+	protected $_template_args = [];
75 75
 
76
-    /**
77
-     * this will hold the list table object for a given view.
78
-     *
79
-     * @var EE_Admin_List_Table $_list_table_object
80
-     */
81
-    protected $_list_table_object;
76
+	/**
77
+	 * this will hold the list table object for a given view.
78
+	 *
79
+	 * @var EE_Admin_List_Table $_list_table_object
80
+	 */
81
+	protected $_list_table_object;
82 82
 
83
-    // boolean
84
-    protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
83
+	// boolean
84
+	protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
85 85
 
86
-    protected $_routing;
86
+	protected $_routing;
87 87
 
88
-    // list table args
89
-    protected $_view;
88
+	// list table args
89
+	protected $_view;
90 90
 
91
-    protected $_views;
91
+	protected $_views;
92 92
 
93 93
 
94
-    // action => method pairs used for routing incoming requests
95
-    protected $_page_routes;
94
+	// action => method pairs used for routing incoming requests
95
+	protected $_page_routes;
96 96
 
97
-    /**
98
-     * @var array $_page_config
99
-     */
100
-    protected $_page_config;
97
+	/**
98
+	 * @var array $_page_config
99
+	 */
100
+	protected $_page_config;
101 101
 
102
-    /**
103
-     * the current page route and route config
104
-     *
105
-     * @var string $_route
106
-     */
107
-    protected $_route;
102
+	/**
103
+	 * the current page route and route config
104
+	 *
105
+	 * @var string $_route
106
+	 */
107
+	protected $_route;
108 108
 
109
-    /**
110
-     * @var string $_cpt_route
111
-     */
112
-    protected $_cpt_route;
109
+	/**
110
+	 * @var string $_cpt_route
111
+	 */
112
+	protected $_cpt_route;
113 113
 
114
-    /**
115
-     * @var array $_route_config
116
-     */
117
-    protected $_route_config;
114
+	/**
115
+	 * @var array $_route_config
116
+	 */
117
+	protected $_route_config;
118 118
 
119
-    /**
120
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
121
-     * actions.
122
-     *
123
-     * @since 4.6.x
124
-     * @var array.
125
-     */
126
-    protected $_default_route_query_args;
119
+	/**
120
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
121
+	 * actions.
122
+	 *
123
+	 * @since 4.6.x
124
+	 * @var array.
125
+	 */
126
+	protected $_default_route_query_args;
127 127
 
128
-    // set via request page and action args.
129
-    protected $_current_page;
128
+	// set via request page and action args.
129
+	protected $_current_page;
130 130
 
131
-    protected $_current_view;
131
+	protected $_current_view;
132 132
 
133
-    protected $_current_page_view_url;
133
+	protected $_current_page_view_url;
134 134
 
135
-    /**
136
-     * unprocessed value for the 'action' request param (default '')
137
-     *
138
-     * @var string
139
-     */
140
-    protected $raw_req_action = '';
135
+	/**
136
+	 * unprocessed value for the 'action' request param (default '')
137
+	 *
138
+	 * @var string
139
+	 */
140
+	protected $raw_req_action = '';
141 141
 
142
-    /**
143
-     * unprocessed value for the 'page' request param (default '')
144
-     *
145
-     * @var string
146
-     */
147
-    protected $raw_req_page = '';
148
-
149
-    /**
150
-     * sanitized request action (and nonce)
151
-     *
152
-     * @var string
153
-     */
154
-    protected $_req_action = '';
155
-
156
-    /**
157
-     * sanitized request action nonce
158
-     *
159
-     * @var string
160
-     */
161
-    protected $_req_nonce = '';
162
-
163
-    /**
164
-     * @var string
165
-     */
166
-    protected $_search_btn_label = '';
167
-
168
-    /**
169
-     * @var string
170
-     */
171
-    protected $_search_box_callback = '';
172
-
173
-    /**
174
-     * @var WP_Screen
175
-     */
176
-    protected $_current_screen;
177
-
178
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
179
-    protected $_hook_obj;
180
-
181
-    // for holding incoming request data
182
-    protected $_req_data = [];
183
-
184
-    // yes / no array for admin form fields
185
-    protected $_yes_no_values = [];
186
-
187
-    // some default things shared by all child classes
188
-    protected $_default_espresso_metaboxes = [
189
-        '_espresso_news_post_box',
190
-        '_espresso_links_post_box',
191
-        '_espresso_ratings_request',
192
-        '_espresso_sponsors_post_box',
193
-    ];
194
-
195
-    /**
196
-     * @var EE_Registry
197
-     */
198
-    protected $EE;
199
-
200
-
201
-    /**
202
-     * This is just a property that flags whether the given route is a caffeinated route or not.
203
-     *
204
-     * @var boolean
205
-     */
206
-    protected $_is_caf = false;
207
-
208
-    /**
209
-     * whether or not initializePage() has run
210
-     *
211
-     * @var boolean
212
-     */
213
-    protected $initialized = false;
214
-
215
-    /**
216
-     * @var FeatureFlags
217
-     */
218
-    protected $feature;
219
-
220
-
221
-    /**
222
-     * @var string
223
-     */
224
-    protected $class_name;
225
-
226
-    /**
227
-     * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
228
-     * then this would be the parent classname: Events_Admin_Page
229
-     *
230
-     * @var string
231
-     */
232
-    protected $base_class_name;
233
-
234
-
235
-    /**
236
-     * @Constructor
237
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
238
-     * @throws InvalidArgumentException
239
-     * @throws InvalidDataTypeException
240
-     * @throws InvalidInterfaceException
241
-     * @throws ReflectionException
242
-     */
243
-    public function __construct($routing = true)
244
-    {
245
-        $this->loader = LoaderFactory::getLoader();
246
-        $this->admin_config = $this->loader->getShared('EE_Admin_Config');
247
-        $this->feature = $this->loader->getShared(FeatureFlags::class);
248
-        $this->request = $this->loader->getShared(RequestInterface::class);
249
-        // routing enabled?
250
-        $this->_routing = $routing;
251
-
252
-        $this->class_name = get_class($this);
253
-        $this->base_class_name = strpos($this->class_name, 'Extend_') === 0
254
-            ? str_replace('Extend_', '', $this->class_name)
255
-            : '';
256
-
257
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
258
-            $this->_is_caf = true;
259
-        }
260
-        $this->_yes_no_values = [
261
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
262
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
263
-        ];
264
-        // set the _req_data property.
265
-        $this->_req_data = $this->request->requestParams();
266
-    }
267
-
268
-
269
-    /**
270
-     * @return EE_Admin_Config
271
-     */
272
-    public function adminConfig(): EE_Admin_Config
273
-    {
274
-        return $this->admin_config;
275
-    }
276
-
277
-
278
-    /**
279
-     * @return FeatureFlags
280
-     */
281
-    public function feature(): FeatureFlags
282
-    {
283
-        return $this->feature;
284
-    }
285
-
286
-
287
-    /**
288
-     * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
289
-     * for child classes that needed to set properties prior to these methods getting called,
290
-     * but also needed the parent class to have its construction completed as well.
291
-     * Bottom line is that constructors should ONLY be used for setting initial properties
292
-     * and any complex initialization logic should only run after instantiation is complete.
293
-     *
294
-     * This method gets called immediately after construction from within
295
-     *      EE_Admin_Page_Init::_initialize_admin_page()
296
-     *
297
-     * @throws EE_Error
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     * @throws ReflectionException
302
-     * @since $VID:$
303
-     */
304
-    public function initializePage()
305
-    {
306
-        if ($this->initialized) {
307
-            return;
308
-        }
309
-        // set initial page props (child method)
310
-        $this->_init_page_props();
311
-        // set global defaults
312
-        $this->_set_defaults();
313
-        // set early because incoming requests could be ajax related and we need to register those hooks.
314
-        $this->_global_ajax_hooks();
315
-        $this->_ajax_hooks();
316
-        // other_page_hooks have to be early too.
317
-        $this->_do_other_page_hooks();
318
-        // set up page dependencies
319
-        $this->_before_page_setup();
320
-        $this->_page_setup();
321
-        $this->initialized = true;
322
-    }
323
-
324
-
325
-    /**
326
-     * _init_page_props
327
-     * Child classes use to set at least the following properties:
328
-     * $page_slug.
329
-     * $page_label.
330
-     *
331
-     * @abstract
332
-     * @return void
333
-     */
334
-    abstract protected function _init_page_props();
335
-
336
-
337
-    /**
338
-     * _ajax_hooks
339
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
340
-     * Note: within the ajax callback methods.
341
-     *
342
-     * @abstract
343
-     * @return void
344
-     */
345
-    abstract protected function _ajax_hooks();
346
-
347
-
348
-    /**
349
-     * _define_page_props
350
-     * child classes define page properties in here.  Must include at least:
351
-     * $_admin_base_url = base_url for all admin pages
352
-     * $_admin_page_title = default admin_page_title for admin pages
353
-     * $_labels = array of default labels for various automatically generated elements:
354
-     *    array(
355
-     *        'buttons' => array(
356
-     *            'add' => esc_html__('label for add new button'),
357
-     *            'edit' => esc_html__('label for edit button'),
358
-     *            'delete' => esc_html__('label for delete button')
359
-     *            )
360
-     *        )
361
-     *
362
-     * @abstract
363
-     * @return void
364
-     */
365
-    abstract protected function _define_page_props();
366
-
367
-
368
-    /**
369
-     * _set_page_routes
370
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
371
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
372
-     * have a 'default' route. Here's the format
373
-     * $this->_page_routes = array(
374
-     *        'default' => array(
375
-     *            'func' => '_default_method_handling_route',
376
-     *            'args' => array('array','of','args'),
377
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
378
-     *            ajax request, backend processing)
379
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
380
-     *            headers route after.  The string you enter here should match the defined route reference for a
381
-     *            headers sent route.
382
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
383
-     *            this route.
384
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
385
-     *            checks).
386
-     *        ),
387
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
388
-     *        handling method.
389
-     *        )
390
-     * )
391
-     *
392
-     * @abstract
393
-     * @return void
394
-     */
395
-    abstract protected function _set_page_routes();
396
-
397
-
398
-    /**
399
-     * _set_page_config
400
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
401
-     * array corresponds to the page_route for the loaded page. Format:
402
-     * $this->_page_config = array(
403
-     *        'default' => array(
404
-     *            'labels' => array(
405
-     *                'buttons' => array(
406
-     *                    'add' => esc_html__('label for adding item'),
407
-     *                    'edit' => esc_html__('label for editing item'),
408
-     *                    'delete' => esc_html__('label for deleting item')
409
-     *                ),
410
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
411
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
412
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
413
-     *            _define_page_props() method
414
-     *            'nav' => array(
415
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
416
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
417
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
418
-     *                'order' => 10, //required to indicate tab position.
419
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
420
-     *                displayed then add this parameter.
421
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
422
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
423
-     *            metaboxes set for eventespresso admin pages.
424
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
425
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
426
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
427
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
428
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
429
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
430
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
431
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
432
-     *            want to display.
433
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
434
-     *                'tab_id' => array(
435
-     *                    'title' => 'tab_title',
436
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
437
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
438
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
439
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
440
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
441
-     *                    attempt to use the callback which should match the name of a method in the class
442
-     *                    ),
443
-     *                'tab2_id' => array(
444
-     *                    'title' => 'tab2 title',
445
-     *                    'filename' => 'file_name_2'
446
-     *                    'callback' => 'callback_method_for_content',
447
-     *                 ),
448
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
449
-     *            help tab area on an admin page. @return void
450
-     *
451
-     * @abstract
452
-     */
453
-    abstract protected function _set_page_config();
454
-
455
-
456
-    /**
457
-     * _add_screen_options
458
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
459
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
460
-     * to a particular view.
461
-     *
462
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
463
-     *         see also WP_Screen object documents...
464
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
465
-     * @abstract
466
-     * @return void
467
-     */
468
-    abstract protected function _add_screen_options();
469
-
470
-
471
-    /**
472
-     * _add_feature_pointers
473
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
474
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
475
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
476
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
477
-     * extended) also see:
478
-     *
479
-     * @link   http://eamann.com/tech/wordpress-portland/
480
-     * @abstract
481
-     * @return void
482
-     */
483
-    abstract protected function _add_feature_pointers();
484
-
485
-
486
-    /**
487
-     * load_scripts_styles
488
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
489
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
490
-     * scripts/styles per view by putting them in a dynamic function in this format
491
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
492
-     *
493
-     * @abstract
494
-     * @return void
495
-     */
496
-    abstract public function load_scripts_styles();
497
-
498
-
499
-    /**
500
-     * admin_init
501
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
502
-     * all pages/views loaded by child class.
503
-     *
504
-     * @abstract
505
-     * @return void
506
-     */
507
-    abstract public function admin_init();
508
-
509
-
510
-    /**
511
-     * admin_notices
512
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
513
-     * all pages/views loaded by child class.
514
-     *
515
-     * @abstract
516
-     * @return void
517
-     */
518
-    abstract public function admin_notices();
519
-
520
-
521
-    /**
522
-     * admin_footer_scripts
523
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
524
-     * will apply to all pages/views loaded by child class.
525
-     *
526
-     * @return void
527
-     */
528
-    abstract public function admin_footer_scripts();
529
-
530
-
531
-    /**
532
-     * admin_footer
533
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
534
-     * apply to all pages/views loaded by child class.
535
-     *
536
-     * @return void
537
-     */
538
-    public function admin_footer()
539
-    {
540
-    }
541
-
542
-
543
-    /**
544
-     * _global_ajax_hooks
545
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
546
-     * Note: within the ajax callback methods.
547
-     *
548
-     * @abstract
549
-     * @return void
550
-     */
551
-    protected function _global_ajax_hooks()
552
-    {
553
-        // for lazy loading of metabox content
554
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
555
-
556
-        add_action(
557
-            'wp_ajax_espresso_hide_status_change_notice',
558
-            [$this, 'hideStatusChangeNotice']
559
-        );
560
-        add_action(
561
-            'wp_ajax_nopriv_espresso_hide_status_change_notice',
562
-            [$this, 'hideStatusChangeNotice']
563
-        );
564
-    }
565
-
566
-
567
-    public function ajax_metabox_content()
568
-    {
569
-        $content_id  = $this->request->getRequestParam('contentid', '');
570
-        $content_url = $this->request->getRequestParam('contenturl', '', 'url');
571
-        EE_Admin_Page::cached_rss_display($content_id, $content_url);
572
-        wp_die();
573
-    }
574
-
575
-
576
-    public function hideStatusChangeNotice()
577
-    {
578
-        $response = [];
579
-        try {
580
-            /** @var StatusChangeNotice $status_change_notice */
581
-            $status_change_notice = $this->loader->getShared(
582
-                'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
583
-            );
584
-            $response['success'] = $status_change_notice->dismiss() > -1;
585
-        } catch (Exception $exception) {
586
-            $response['errors'] = $exception->getMessage();
587
-        }
588
-        echo wp_json_encode($response);
589
-        exit();
590
-    }
591
-
592
-
593
-    /**
594
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
595
-     *
596
-     * @return void
597
-     */
598
-    protected function _before_page_setup()
599
-    {
600
-        // default is to do nothing
601
-    }
602
-
603
-
604
-    /**
605
-     * Makes sure any things that need to be loaded early get handled.
606
-     * We also escape early here if the page requested doesn't match the object.
607
-     *
608
-     * @final
609
-     * @return void
610
-     * @throws EE_Error
611
-     * @throws InvalidArgumentException
612
-     * @throws ReflectionException
613
-     * @throws InvalidDataTypeException
614
-     * @throws InvalidInterfaceException
615
-     */
616
-    final protected function _page_setup()
617
-    {
618
-        // requires?
619
-        // admin_init stuff - global - we're setting this REALLY early
620
-        // so if EE_Admin pages have to hook into other WP pages they can.
621
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
622
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
623
-        // next verify if we need to load anything...
624
-        $this->_current_page = $this->request->getRequestParam('page', '', 'key');
625
-        $this->page_folder   = strtolower(
626
-            str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
627
-        );
628
-        global $ee_menu_slugs;
629
-        $ee_menu_slugs = (array) $ee_menu_slugs;
630
-        if (
631
-            ! $this->request->isAjax()
632
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
633
-        ) {
634
-            return;
635
-        }
636
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
637
-        // we need to copy the action from the second to the first
638
-        $action     = $this->request->getRequestParam('action', '-1', 'key');
639
-        $action2    = $this->request->getRequestParam('action2', '-1', 'key');
640
-        $action     = $action !== '-1' ? $action : $action2;
641
-        $req_action = $action !== '-1' ? $action : 'default';
642
-
643
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
644
-        // then let's use the route as the action.
645
-        // This covers cases where we're coming in from a list table that isn't on the default route.
646
-        $route = $this->request->getRequestParam('route');
647
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
648
-            ? $route
649
-            : $req_action;
650
-
651
-        $this->_current_view = $this->_req_action;
652
-        $this->_req_nonce    = $this->_req_action . '_nonce';
653
-        $this->_define_page_props();
654
-        $this->_current_page_view_url = add_query_arg(
655
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
656
-            $this->_admin_base_url
657
-        );
658
-        // set page configs
659
-        $this->_set_page_routes();
660
-        $this->_set_page_config();
661
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
662
-        if ($this->request->requestParamIsSet('wp_referer')) {
663
-            $wp_referer = $this->request->getRequestParam('wp_referer');
664
-            if ($wp_referer) {
665
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
666
-            }
667
-        }
668
-        // for caffeinated and other extended functionality.
669
-        //  If there is a _extend_page_config method
670
-        // then let's run that to modify the all the various page configuration arrays
671
-        if (method_exists($this, '_extend_page_config')) {
672
-            $this->_extend_page_config();
673
-        }
674
-        // for CPT and other extended functionality.
675
-        // If there is an _extend_page_config_for_cpt
676
-        // then let's run that to modify all the various page configuration arrays.
677
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
678
-            $this->_extend_page_config_for_cpt();
679
-        }
680
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
681
-        $this->_page_routes = apply_filters(
682
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
683
-            $this->_page_routes,
684
-            $this
685
-        );
686
-        $this->_page_config = apply_filters(
687
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
688
-            $this->_page_config,
689
-            $this
690
-        );
691
-        if ($this->base_class_name !== '') {
692
-            $this->_page_routes = apply_filters(
693
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
694
-                $this->_page_routes,
695
-                $this
696
-            );
697
-            $this->_page_config = apply_filters(
698
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
699
-                $this->_page_config,
700
-                $this
701
-            );
702
-        }
703
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
706
-            add_action(
707
-                'AHEE__EE_Admin_Page__route_admin_request',
708
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
709
-                10,
710
-                2
711
-            );
712
-        }
713
-        // next route only if routing enabled
714
-        if ($this->_routing && ! $this->request->isAjax()) {
715
-            $this->_verify_routes();
716
-            // next let's just check user_access and kill if no access
717
-            $this->check_user_access();
718
-            if ($this->_is_UI_request) {
719
-                // admin_init stuff - global, all views for this page class, specific view
720
-                add_action('admin_init', [$this, 'admin_init'], 10);
721
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
723
-                }
724
-            } else {
725
-                // hijack regular WP loading and route admin request immediately
726
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
727
-                $this->route_admin_request();
728
-            }
729
-        }
730
-    }
731
-
732
-
733
-    /**
734
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
735
-     *
736
-     * @return void
737
-     * @throws EE_Error
738
-     */
739
-    private function _do_other_page_hooks()
740
-    {
741
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
742
-        foreach ($registered_pages as $page) {
743
-            // now let's setup the file name and class that should be present
744
-            $classname = str_replace('.class.php', '', $page);
745
-            // autoloaders should take care of loading file
746
-            if (! class_exists($classname)) {
747
-                $error_msg[] = sprintf(
748
-                    esc_html__(
749
-                        'Something went wrong with loading the %s admin hooks page.',
750
-                        'event_espresso'
751
-                    ),
752
-                    $page
753
-                );
754
-                $error_msg[] = $error_msg[0]
755
-                               . "\r\n"
756
-                               . sprintf(
757
-                                   esc_html__(
758
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
759
-                                       'event_espresso'
760
-                                   ),
761
-                                   $page,
762
-                                   '<br />',
763
-                                   '<strong>' . $classname . '</strong>'
764
-                               );
765
-                throw new EE_Error(implode('||', $error_msg));
766
-            }
767
-            // notice we are passing the instance of this class to the hook object.
768
-            $this->loader->getShared($classname, [$this]);
769
-        }
770
-    }
771
-
772
-
773
-    /**
774
-     * @throws ReflectionException
775
-     * @throws EE_Error
776
-     */
777
-    public function load_page_dependencies()
778
-    {
779
-        try {
780
-            $this->_load_page_dependencies();
781
-        } catch (EE_Error $e) {
782
-            $e->get_error();
783
-        }
784
-    }
785
-
786
-
787
-    /**
788
-     * load_page_dependencies
789
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
790
-     *
791
-     * @return void
792
-     * @throws DomainException
793
-     * @throws EE_Error
794
-     * @throws InvalidArgumentException
795
-     * @throws InvalidDataTypeException
796
-     * @throws InvalidInterfaceException
797
-     */
798
-    protected function _load_page_dependencies()
799
-    {
800
-        // let's set the current_screen and screen options to override what WP set
801
-        $this->_current_screen = get_current_screen();
802
-        // load admin_notices - global, page class, and view specific
803
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804
-        add_action('admin_notices', [$this, 'admin_notices'], 10);
805
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
807
-        }
808
-        // load network admin_notices - global, page class, and view specific
809
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
812
-        }
813
-        // this will save any per_page screen options if they are present
814
-        $this->_set_per_page_screen_options();
815
-        // setup list table properties
816
-        $this->_set_list_table();
817
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
818
-        // However in some cases the metaboxes will need to be added within a route handling callback.
819
-        $this->_add_registered_meta_boxes();
820
-        $this->_add_screen_columns();
821
-        // add screen options - global, page child class, and view specific
822
-        $this->_add_global_screen_options();
823
-        $this->_add_screen_options();
824
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
825
-        if (method_exists($this, $add_screen_options)) {
826
-            $this->{$add_screen_options}();
827
-        }
828
-        // add help tab(s) - set via page_config and qtips.
829
-        $this->_add_help_tabs();
830
-        $this->_add_qtips();
831
-        // add feature_pointers - global, page child class, and view specific
832
-        $this->_add_feature_pointers();
833
-        $this->_add_global_feature_pointers();
834
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
835
-        if (method_exists($this, $add_feature_pointer)) {
836
-            $this->{$add_feature_pointer}();
837
-        }
838
-        // enqueue scripts/styles - global, page class, and view specific
839
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
840
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
841
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
842
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
843
-        }
844
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
845
-        // admin_print_footer_scripts - global, page child class, and view specific.
846
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
847
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
848
-        // is a good use case. Notice the late priority we're giving these
849
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
850
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
851
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
852
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
853
-        }
854
-        // admin footer scripts
855
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
856
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
857
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
858
-            add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
859
-        }
860
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
861
-        // targeted hook
862
-        do_action(
863
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
864
-        );
865
-    }
866
-
867
-
868
-    /**
869
-     * _set_defaults
870
-     * This sets some global defaults for class properties.
871
-     */
872
-    private function _set_defaults()
873
-    {
874
-        $this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
875
-        $this->_event                = $this->_template_path = $this->_column_template_path = null;
876
-        $this->_nav_tabs             = $this->_views = $this->_page_routes = [];
877
-        $this->_page_config          = $this->_default_route_query_args = [];
878
-        $this->_default_nav_tab_name = 'overview';
879
-        // init template args
880
-        $this->_template_args = [
881
-            'admin_page_header'  => '',
882
-            'admin_page_content' => '',
883
-            'post_body_content'  => '',
884
-            'before_list_table'  => '',
885
-            'after_list_table'   => '',
886
-        ];
887
-    }
888
-
889
-
890
-    /**
891
-     * route_admin_request
892
-     *
893
-     * @return void
894
-     * @throws InvalidArgumentException
895
-     * @throws InvalidInterfaceException
896
-     * @throws InvalidDataTypeException
897
-     * @throws EE_Error
898
-     * @throws ReflectionException
899
-     * @see    _route_admin_request()
900
-     */
901
-    public function route_admin_request()
902
-    {
903
-        try {
904
-            $this->_route_admin_request();
905
-        } catch (EE_Error $e) {
906
-            $e->get_error();
907
-        }
908
-    }
909
-
910
-
911
-    public function set_wp_page_slug($wp_page_slug)
912
-    {
913
-        $this->_wp_page_slug = $wp_page_slug;
914
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
915
-        if (is_network_admin()) {
916
-            $this->_wp_page_slug .= '-network';
917
-        }
918
-    }
919
-
920
-
921
-    /**
922
-     * _verify_routes
923
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
924
-     * we know if we need to drop out.
925
-     *
926
-     * @return bool
927
-     * @throws EE_Error
928
-     */
929
-    protected function _verify_routes()
930
-    {
931
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
-        if (! $this->_current_page && ! $this->request->isAjax()) {
933
-            return false;
934
-        }
935
-        $this->_route = false;
936
-        // check that the page_routes array is not empty
937
-        if (empty($this->_page_routes)) {
938
-            // user error msg
939
-            $error_msg = sprintf(
940
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
941
-                $this->_admin_page_title
942
-            );
943
-            // developer error msg
944
-            $error_msg .= '||' . $error_msg
945
-                          . esc_html__(
946
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947
-                              'event_espresso'
948
-                          );
949
-            throw new EE_Error($error_msg);
950
-        }
951
-        // and that the requested page route exists
952
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
954
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
955
-        } else {
956
-            // user error msg
957
-            $error_msg = sprintf(
958
-                esc_html__(
959
-                    'The requested page route does not exist for the %s admin page.',
960
-                    'event_espresso'
961
-                ),
962
-                $this->_admin_page_title
963
-            );
964
-            // developer error msg
965
-            $error_msg .= '||' . $error_msg
966
-                          . sprintf(
967
-                              esc_html__(
968
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
969
-                                  'event_espresso'
970
-                              ),
971
-                              $this->_req_action
972
-                          );
973
-            throw new EE_Error($error_msg);
974
-        }
975
-        // and that a default route exists
976
-        if (! array_key_exists('default', $this->_page_routes)) {
977
-            // user error msg
978
-            $error_msg = sprintf(
979
-                esc_html__(
980
-                    'A default page route has not been set for the % admin page.',
981
-                    'event_espresso'
982
-                ),
983
-                $this->_admin_page_title
984
-            );
985
-            // developer error msg
986
-            $error_msg .= '||' . $error_msg
987
-                          . esc_html__(
988
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989
-                              'event_espresso'
990
-                          );
991
-            throw new EE_Error($error_msg);
992
-        }
993
-
994
-        // first lets' catch if the UI request has EVER been set.
995
-        if ($this->_is_UI_request === null) {
996
-            // lets set if this is a UI request or not.
997
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
998
-            // wait a minute... we might have a noheader in the route array
999
-            $this->_is_UI_request = ! (
1000
-                is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
1001
-            )
1002
-                ? $this->_is_UI_request
1003
-                : false;
1004
-        }
1005
-        $this->_set_current_labels();
1006
-        return true;
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1012
-     *
1013
-     * @param string $route the route name we're verifying
1014
-     * @return bool we'll throw an exception if this isn't a valid route.
1015
-     * @throws EE_Error
1016
-     */
1017
-    protected function _verify_route($route)
1018
-    {
1019
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
1020
-            return true;
1021
-        }
1022
-        // user error msg
1023
-        $error_msg = sprintf(
1024
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1025
-            $this->_admin_page_title
1026
-        );
1027
-        // developer error msg
1028
-        $error_msg .= '||' . $error_msg
1029
-                      . sprintf(
1030
-                          esc_html__(
1031
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1032
-                              'event_espresso'
1033
-                          ),
1034
-                          $route
1035
-                      );
1036
-        throw new EE_Error($error_msg);
1037
-    }
1038
-
1039
-
1040
-    /**
1041
-     * perform nonce verification
1042
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1043
-     * using this method (and save retyping!)
1044
-     *
1045
-     * @param string $nonce     The nonce sent
1046
-     * @param string $nonce_ref The nonce reference string (name0)
1047
-     * @return void
1048
-     * @throws EE_Error
1049
-     * @throws InvalidArgumentException
1050
-     * @throws InvalidDataTypeException
1051
-     * @throws InvalidInterfaceException
1052
-     */
1053
-    protected function _verify_nonce($nonce, $nonce_ref)
1054
-    {
1055
-        // verify nonce against expected value
1056
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1057
-            // these are not the droids you are looking for !!!
1058
-            $msg = sprintf(
1059
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
1060
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1061
-                '</a>'
1062
-            );
1063
-            if (WP_DEBUG) {
1064
-                $msg .= "\n  ";
1065
-                $msg .= sprintf(
1066
-                    esc_html__(
1067
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1068
-                        'event_espresso'
1069
-                    ),
1070
-                    __CLASS__
1071
-                );
1072
-            }
1073
-            if (! $this->request->isAjax()) {
1074
-                wp_die($msg);
1075
-            }
1076
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
-            $this->_return_json();
1078
-        }
1079
-    }
1080
-
1081
-
1082
-    /**
1083
-     * _route_admin_request()
1084
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1085
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1086
-     * in the page routes and then will try to load the corresponding method.
1087
-     *
1088
-     * @return void
1089
-     * @throws EE_Error
1090
-     * @throws InvalidArgumentException
1091
-     * @throws InvalidDataTypeException
1092
-     * @throws InvalidInterfaceException
1093
-     * @throws ReflectionException
1094
-     */
1095
-    protected function _route_admin_request()
1096
-    {
1097
-        if (! $this->_is_UI_request) {
1098
-            $this->_verify_routes();
1099
-        }
1100
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1101
-        if ($this->_req_action !== 'default' && $nonce_check) {
1102
-            // set nonce from post data
1103
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
1104
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1105
-        }
1106
-        // set the nav_tabs array but ONLY if this is  UI_request
1107
-        if ($this->_is_UI_request) {
1108
-            $this->_set_nav_tabs();
1109
-        }
1110
-        // grab callback function
1111
-        $func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1112
-        // check if callback has args
1113
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1114
-        $error_msg = '';
1115
-        // action right before calling route
1116
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119
-        }
1120
-        // strip _wp_http_referer from the server REQUEST_URI
1121
-        // else it grows in length on every submission due to recursion,
1122
-        // ultimately causing a "Request-URI Too Large" error
1123
-        $this->request->unSetRequestParam('_wp_http_referer');
1124
-        $this->request->unSetServerParam('_wp_http_referer');
1125
-        $cleaner_request_uri = remove_query_arg(
1126
-            '_wp_http_referer',
1127
-            wp_unslash($this->request->getServerParam('REQUEST_URI'))
1128
-        );
1129
-        $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1130
-        $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1131
-        if (! empty($func)) {
1132
-            if (is_array($func)) {
1133
-                [$class, $method] = $func;
1134
-            } elseif (strpos($func, '::') !== false) {
1135
-                [$class, $method] = explode('::', $func);
1136
-            } else {
1137
-                $class  = $this;
1138
-                $method = $func;
1139
-            }
1140
-            if (! (is_object($class) && $class === $this)) {
1141
-                // send along this admin page object for access by addons.
1142
-                $args['admin_page_object'] = $this;
1143
-            }
1144
-            if (
1145
-                // is it a method on a class that doesn't work?
1146
-                (
1147
-                    (
1148
-                        method_exists($class, $method)
1149
-                        && call_user_func_array([$class, $method], $args) === false
1150
-                    )
1151
-                    && (
1152
-                        // is it a standalone function that doesn't work?
1153
-                        function_exists($method)
1154
-                        && call_user_func_array(
1155
-                            $func,
1156
-                            array_merge(['admin_page_object' => $this], $args)
1157
-                        ) === false
1158
-                    )
1159
-                )
1160
-                || (
1161
-                    // is it neither a class method NOR a standalone function?
1162
-                    ! method_exists($class, $method)
1163
-                    && ! function_exists($method)
1164
-                )
1165
-            ) {
1166
-                // user error msg
1167
-                $error_msg = esc_html__(
1168
-                    'An error occurred. The  requested page route could not be found.',
1169
-                    'event_espresso'
1170
-                );
1171
-                // developer error msg
1172
-                $error_msg .= '||';
1173
-                $error_msg .= sprintf(
1174
-                    esc_html__(
1175
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1176
-                        'event_espresso'
1177
-                    ),
1178
-                    $method
1179
-                );
1180
-            }
1181
-            if (! empty($error_msg)) {
1182
-                throw new EE_Error($error_msg);
1183
-            }
1184
-        }
1185
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1186
-        // then we need to reset the routing properties to the new route.
1187
-        // now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1188
-        if (
1189
-            $this->_is_UI_request === false
1190
-            && is_array($this->_route)
1191
-            && ! empty($this->_route['headers_sent_route'])
1192
-        ) {
1193
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1194
-        }
1195
-    }
1196
-
1197
-
1198
-    /**
1199
-     * This method just allows the resetting of page properties in the case where a no headers
1200
-     * route redirects to a headers route in its route config.
1201
-     *
1202
-     * @param string $new_route New (non header) route to redirect to.
1203
-     * @return   void
1204
-     * @throws ReflectionException
1205
-     * @throws InvalidArgumentException
1206
-     * @throws InvalidInterfaceException
1207
-     * @throws InvalidDataTypeException
1208
-     * @throws EE_Error
1209
-     * @since   4.3.0
1210
-     */
1211
-    protected function _reset_routing_properties($new_route)
1212
-    {
1213
-        $this->_is_UI_request = true;
1214
-        // now we set the current route to whatever the headers_sent_route is set at
1215
-        $this->request->setRequestParam('action', $new_route);
1216
-        // rerun page setup
1217
-        $this->_page_setup();
1218
-    }
1219
-
1220
-
1221
-    /**
1222
-     * _add_query_arg
1223
-     * adds nonce to array of arguments then calls WP add_query_arg function
1224
-     *(internally just uses EEH_URL's function with the same name)
1225
-     *
1226
-     * @param array  $args
1227
-     * @param string $url
1228
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1229
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1230
-     *                                        Example usage: If the current page is:
1231
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1232
-     *                                        &action=default&event_id=20&month_range=March%202015
1233
-     *                                        &_wpnonce=5467821
1234
-     *                                        and you call:
1235
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1236
-     *                                        array(
1237
-     *                                        'action' => 'resend_something',
1238
-     *                                        'page=>espresso_registrations'
1239
-     *                                        ),
1240
-     *                                        $some_url,
1241
-     *                                        true
1242
-     *                                        );
1243
-     *                                        It will produce a url in this structure:
1244
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1245
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1246
-     *                                        month_range]=March%202015
1247
-     * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1248
-     * @return string
1249
-     */
1250
-    public static function add_query_args_and_nonce(
1251
-        $args = [],
1252
-        $url = '',
1253
-        $sticky = false,
1254
-        $exclude_nonce = false
1255
-    ) {
1256
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1257
-        if ($sticky) {
1258
-            /** @var RequestInterface $request */
1259
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1260
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1261
-            $request->unSetServerParam('_wp_http_referer', true);
1262
-            foreach ($request->requestParams() as $key => $value) {
1263
-                // do not add nonces
1264
-                if (strpos($key, 'nonce') !== false) {
1265
-                    continue;
1266
-                }
1267
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1268
-            }
1269
-        }
1270
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * This returns a generated link that will load the related help tab.
1276
-     *
1277
-     * @param string $help_tab_id the id for the connected help tab
1278
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1279
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1280
-     * @return string              generated link
1281
-     * @uses EEH_Template::get_help_tab_link()
1282
-     */
1283
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1284
-    {
1285
-        return EEH_Template::get_help_tab_link(
1286
-            $help_tab_id,
1287
-            $this->page_slug,
1288
-            $this->_req_action,
1289
-            $icon_style,
1290
-            $help_text
1291
-        );
1292
-    }
1293
-
1294
-
1295
-    /**
1296
-     * _add_help_tabs
1297
-     * Note child classes define their help tabs within the page_config array.
1298
-     *
1299
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1300
-     * @return void
1301
-     * @throws DomainException
1302
-     * @throws EE_Error
1303
-     * @throws ReflectionException
1304
-     */
1305
-    protected function _add_help_tabs()
1306
-    {
1307
-        if (isset($this->_page_config[ $this->_req_action ])) {
1308
-            $config = $this->_page_config[ $this->_req_action ];
1309
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1310
-            if (is_array($config) && isset($config['help_sidebar'])) {
1311
-                // check that the callback given is valid
1312
-                if (! method_exists($this, $config['help_sidebar'])) {
1313
-                    throw new EE_Error(
1314
-                        sprintf(
1315
-                            esc_html__(
1316
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1317
-                                'event_espresso'
1318
-                            ),
1319
-                            $config['help_sidebar'],
1320
-                            $this->class_name
1321
-                        )
1322
-                    );
1323
-                }
1324
-                $content = apply_filters(
1325
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1326
-                    $this->{$config['help_sidebar']}()
1327
-                );
1328
-                $this->_current_screen->set_help_sidebar($content);
1329
-            }
1330
-            if (! isset($config['help_tabs'])) {
1331
-                return;
1332
-            } //no help tabs for this route
1333
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1334
-                // we're here so there ARE help tabs!
1335
-                // make sure we've got what we need
1336
-                if (! isset($cfg['title'])) {
1337
-                    throw new EE_Error(
1338
-                        esc_html__(
1339
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1340
-                            'event_espresso'
1341
-                        )
1342
-                    );
1343
-                }
1344
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1345
-                    throw new EE_Error(
1346
-                        esc_html__(
1347
-                            'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1348
-                            'event_espresso'
1349
-                        )
1350
-                    );
1351
-                }
1352
-                // first priority goes to content.
1353
-                if (! empty($cfg['content'])) {
1354
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1355
-                    // second priority goes to filename
1356
-                } elseif (! empty($cfg['filename'])) {
1357
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1358
-                    // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1359
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1360
-                                                             . basename($this->_get_dir())
1361
-                                                             . '/help_tabs/'
1362
-                                                             . $cfg['filename']
1363
-                                                             . '.help_tab.php' : $file_path;
1364
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1365
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1366
-                        EE_Error::add_error(
1367
-                            sprintf(
1368
-                                esc_html__(
1369
-                                    'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1370
-                                    'event_espresso'
1371
-                                ),
1372
-                                $tab_id,
1373
-                                key($config),
1374
-                                $file_path
1375
-                            ),
1376
-                            __FILE__,
1377
-                            __FUNCTION__,
1378
-                            __LINE__
1379
-                        );
1380
-                        return;
1381
-                    }
1382
-                    $template_args['admin_page_obj'] = $this;
1383
-                    $content                         = EEH_Template::display_template(
1384
-                        $file_path,
1385
-                        $template_args,
1386
-                        true
1387
-                    );
1388
-                } else {
1389
-                    $content = '';
1390
-                }
1391
-                // check if callback is valid
1392
-                if (
1393
-                    empty($content)
1394
-                    && (
1395
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1396
-                    )
1397
-                ) {
1398
-                    EE_Error::add_error(
1399
-                        sprintf(
1400
-                            esc_html__(
1401
-                                'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1402
-                                'event_espresso'
1403
-                            ),
1404
-                            $cfg['title']
1405
-                        ),
1406
-                        __FILE__,
1407
-                        __FUNCTION__,
1408
-                        __LINE__
1409
-                    );
1410
-                    return;
1411
-                }
1412
-                // setup config array for help tab method
1413
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1414
-                $_ht = [
1415
-                    'id'       => $id,
1416
-                    'title'    => $cfg['title'],
1417
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1418
-                    'content'  => $content,
1419
-                ];
1420
-                $this->_current_screen->add_help_tab($_ht);
1421
-            }
1422
-        }
1423
-    }
1424
-
1425
-
1426
-    /**
1427
-     * This simply sets up any qtips that have been defined in the page config
1428
-     *
1429
-     * @return void
1430
-     * @throws ReflectionException
1431
-     * @throws EE_Error
1432
-     */
1433
-    protected function _add_qtips()
1434
-    {
1435
-        if (isset($this->_route_config['qtips'])) {
1436
-            $qtips = (array) $this->_route_config['qtips'];
1437
-            // load qtip loader
1438
-            $path = [
1439
-                $this->_get_dir() . '/qtips/',
1440
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1441
-            ];
1442
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1443
-        }
1444
-    }
1445
-
1446
-
1447
-    /**
1448
-     * _set_nav_tabs
1449
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1450
-     * wish to add additional tabs or modify accordingly.
1451
-     *
1452
-     * @return void
1453
-     * @throws InvalidArgumentException
1454
-     * @throws InvalidInterfaceException
1455
-     * @throws InvalidDataTypeException
1456
-     */
1457
-    protected function _set_nav_tabs()
1458
-    {
1459
-        $i = 0;
1460
-        $only_tab = count($this->_page_config) < 2;
1461
-        foreach ($this->_page_config as $slug => $config) {
1462
-            if (! is_array($config) || empty($config['nav'])) {
1463
-                continue;
1464
-            }
1465
-            // no nav tab for this config
1466
-            // check for persistent flag
1467
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1468
-                // nav tab is only to appear when route requested.
1469
-                continue;
1470
-            }
1471
-            if (! $this->check_user_access($slug, true)) {
1472
-                // no nav tab because current user does not have access.
1473
-                continue;
1474
-            }
1475
-            $css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1476
-            $css_class .= $only_tab ? ' ee-only-tab' : '';
1477
-
1478
-            $this->_nav_tabs[ $slug ] = [
1479
-                'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1480
-                    ['action' => $slug],
1481
-                    $this->_admin_base_url
1482
-                ),
1483
-                'link_text' => $this->navTabLabel($config['nav'], $slug),
1484
-                'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1485
-                'order'     => $config['nav']['order'] ?? $i,
1486
-            ];
1487
-            $i++;
1488
-        }
1489
-        // if $this->_nav_tabs is empty then lets set the default
1490
-        if (empty($this->_nav_tabs)) {
1491
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1492
-                'url'       => $this->_admin_base_url,
1493
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1494
-                'css_class' => 'nav-tab-active',
1495
-                'order'     => 10,
1496
-            ];
1497
-        }
1498
-        // now let's sort the tabs according to order
1499
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1500
-    }
1501
-
1502
-
1503
-    private function navTabLabel(array $nav_tab, string $slug): string
1504
-    {
1505
-        $label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1506
-        $icon = $nav_tab['icon'] ?? null;
1507
-        $icon = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1508
-        return '
142
+	/**
143
+	 * unprocessed value for the 'page' request param (default '')
144
+	 *
145
+	 * @var string
146
+	 */
147
+	protected $raw_req_page = '';
148
+
149
+	/**
150
+	 * sanitized request action (and nonce)
151
+	 *
152
+	 * @var string
153
+	 */
154
+	protected $_req_action = '';
155
+
156
+	/**
157
+	 * sanitized request action nonce
158
+	 *
159
+	 * @var string
160
+	 */
161
+	protected $_req_nonce = '';
162
+
163
+	/**
164
+	 * @var string
165
+	 */
166
+	protected $_search_btn_label = '';
167
+
168
+	/**
169
+	 * @var string
170
+	 */
171
+	protected $_search_box_callback = '';
172
+
173
+	/**
174
+	 * @var WP_Screen
175
+	 */
176
+	protected $_current_screen;
177
+
178
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
179
+	protected $_hook_obj;
180
+
181
+	// for holding incoming request data
182
+	protected $_req_data = [];
183
+
184
+	// yes / no array for admin form fields
185
+	protected $_yes_no_values = [];
186
+
187
+	// some default things shared by all child classes
188
+	protected $_default_espresso_metaboxes = [
189
+		'_espresso_news_post_box',
190
+		'_espresso_links_post_box',
191
+		'_espresso_ratings_request',
192
+		'_espresso_sponsors_post_box',
193
+	];
194
+
195
+	/**
196
+	 * @var EE_Registry
197
+	 */
198
+	protected $EE;
199
+
200
+
201
+	/**
202
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
203
+	 *
204
+	 * @var boolean
205
+	 */
206
+	protected $_is_caf = false;
207
+
208
+	/**
209
+	 * whether or not initializePage() has run
210
+	 *
211
+	 * @var boolean
212
+	 */
213
+	protected $initialized = false;
214
+
215
+	/**
216
+	 * @var FeatureFlags
217
+	 */
218
+	protected $feature;
219
+
220
+
221
+	/**
222
+	 * @var string
223
+	 */
224
+	protected $class_name;
225
+
226
+	/**
227
+	 * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
228
+	 * then this would be the parent classname: Events_Admin_Page
229
+	 *
230
+	 * @var string
231
+	 */
232
+	protected $base_class_name;
233
+
234
+
235
+	/**
236
+	 * @Constructor
237
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
238
+	 * @throws InvalidArgumentException
239
+	 * @throws InvalidDataTypeException
240
+	 * @throws InvalidInterfaceException
241
+	 * @throws ReflectionException
242
+	 */
243
+	public function __construct($routing = true)
244
+	{
245
+		$this->loader = LoaderFactory::getLoader();
246
+		$this->admin_config = $this->loader->getShared('EE_Admin_Config');
247
+		$this->feature = $this->loader->getShared(FeatureFlags::class);
248
+		$this->request = $this->loader->getShared(RequestInterface::class);
249
+		// routing enabled?
250
+		$this->_routing = $routing;
251
+
252
+		$this->class_name = get_class($this);
253
+		$this->base_class_name = strpos($this->class_name, 'Extend_') === 0
254
+			? str_replace('Extend_', '', $this->class_name)
255
+			: '';
256
+
257
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
258
+			$this->_is_caf = true;
259
+		}
260
+		$this->_yes_no_values = [
261
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
262
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
263
+		];
264
+		// set the _req_data property.
265
+		$this->_req_data = $this->request->requestParams();
266
+	}
267
+
268
+
269
+	/**
270
+	 * @return EE_Admin_Config
271
+	 */
272
+	public function adminConfig(): EE_Admin_Config
273
+	{
274
+		return $this->admin_config;
275
+	}
276
+
277
+
278
+	/**
279
+	 * @return FeatureFlags
280
+	 */
281
+	public function feature(): FeatureFlags
282
+	{
283
+		return $this->feature;
284
+	}
285
+
286
+
287
+	/**
288
+	 * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
289
+	 * for child classes that needed to set properties prior to these methods getting called,
290
+	 * but also needed the parent class to have its construction completed as well.
291
+	 * Bottom line is that constructors should ONLY be used for setting initial properties
292
+	 * and any complex initialization logic should only run after instantiation is complete.
293
+	 *
294
+	 * This method gets called immediately after construction from within
295
+	 *      EE_Admin_Page_Init::_initialize_admin_page()
296
+	 *
297
+	 * @throws EE_Error
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 * @throws ReflectionException
302
+	 * @since $VID:$
303
+	 */
304
+	public function initializePage()
305
+	{
306
+		if ($this->initialized) {
307
+			return;
308
+		}
309
+		// set initial page props (child method)
310
+		$this->_init_page_props();
311
+		// set global defaults
312
+		$this->_set_defaults();
313
+		// set early because incoming requests could be ajax related and we need to register those hooks.
314
+		$this->_global_ajax_hooks();
315
+		$this->_ajax_hooks();
316
+		// other_page_hooks have to be early too.
317
+		$this->_do_other_page_hooks();
318
+		// set up page dependencies
319
+		$this->_before_page_setup();
320
+		$this->_page_setup();
321
+		$this->initialized = true;
322
+	}
323
+
324
+
325
+	/**
326
+	 * _init_page_props
327
+	 * Child classes use to set at least the following properties:
328
+	 * $page_slug.
329
+	 * $page_label.
330
+	 *
331
+	 * @abstract
332
+	 * @return void
333
+	 */
334
+	abstract protected function _init_page_props();
335
+
336
+
337
+	/**
338
+	 * _ajax_hooks
339
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
340
+	 * Note: within the ajax callback methods.
341
+	 *
342
+	 * @abstract
343
+	 * @return void
344
+	 */
345
+	abstract protected function _ajax_hooks();
346
+
347
+
348
+	/**
349
+	 * _define_page_props
350
+	 * child classes define page properties in here.  Must include at least:
351
+	 * $_admin_base_url = base_url for all admin pages
352
+	 * $_admin_page_title = default admin_page_title for admin pages
353
+	 * $_labels = array of default labels for various automatically generated elements:
354
+	 *    array(
355
+	 *        'buttons' => array(
356
+	 *            'add' => esc_html__('label for add new button'),
357
+	 *            'edit' => esc_html__('label for edit button'),
358
+	 *            'delete' => esc_html__('label for delete button')
359
+	 *            )
360
+	 *        )
361
+	 *
362
+	 * @abstract
363
+	 * @return void
364
+	 */
365
+	abstract protected function _define_page_props();
366
+
367
+
368
+	/**
369
+	 * _set_page_routes
370
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
371
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
372
+	 * have a 'default' route. Here's the format
373
+	 * $this->_page_routes = array(
374
+	 *        'default' => array(
375
+	 *            'func' => '_default_method_handling_route',
376
+	 *            'args' => array('array','of','args'),
377
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
378
+	 *            ajax request, backend processing)
379
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
380
+	 *            headers route after.  The string you enter here should match the defined route reference for a
381
+	 *            headers sent route.
382
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
383
+	 *            this route.
384
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
385
+	 *            checks).
386
+	 *        ),
387
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
388
+	 *        handling method.
389
+	 *        )
390
+	 * )
391
+	 *
392
+	 * @abstract
393
+	 * @return void
394
+	 */
395
+	abstract protected function _set_page_routes();
396
+
397
+
398
+	/**
399
+	 * _set_page_config
400
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
401
+	 * array corresponds to the page_route for the loaded page. Format:
402
+	 * $this->_page_config = array(
403
+	 *        'default' => array(
404
+	 *            'labels' => array(
405
+	 *                'buttons' => array(
406
+	 *                    'add' => esc_html__('label for adding item'),
407
+	 *                    'edit' => esc_html__('label for editing item'),
408
+	 *                    'delete' => esc_html__('label for deleting item')
409
+	 *                ),
410
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
411
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
412
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
413
+	 *            _define_page_props() method
414
+	 *            'nav' => array(
415
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
416
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
417
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
418
+	 *                'order' => 10, //required to indicate tab position.
419
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
420
+	 *                displayed then add this parameter.
421
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
422
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
423
+	 *            metaboxes set for eventespresso admin pages.
424
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
425
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
426
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
427
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
428
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
429
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
430
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
431
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
432
+	 *            want to display.
433
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
434
+	 *                'tab_id' => array(
435
+	 *                    'title' => 'tab_title',
436
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
437
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
438
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
439
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
440
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
441
+	 *                    attempt to use the callback which should match the name of a method in the class
442
+	 *                    ),
443
+	 *                'tab2_id' => array(
444
+	 *                    'title' => 'tab2 title',
445
+	 *                    'filename' => 'file_name_2'
446
+	 *                    'callback' => 'callback_method_for_content',
447
+	 *                 ),
448
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
449
+	 *            help tab area on an admin page. @return void
450
+	 *
451
+	 * @abstract
452
+	 */
453
+	abstract protected function _set_page_config();
454
+
455
+
456
+	/**
457
+	 * _add_screen_options
458
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
459
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
460
+	 * to a particular view.
461
+	 *
462
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
463
+	 *         see also WP_Screen object documents...
464
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
465
+	 * @abstract
466
+	 * @return void
467
+	 */
468
+	abstract protected function _add_screen_options();
469
+
470
+
471
+	/**
472
+	 * _add_feature_pointers
473
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
474
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
475
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
476
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
477
+	 * extended) also see:
478
+	 *
479
+	 * @link   http://eamann.com/tech/wordpress-portland/
480
+	 * @abstract
481
+	 * @return void
482
+	 */
483
+	abstract protected function _add_feature_pointers();
484
+
485
+
486
+	/**
487
+	 * load_scripts_styles
488
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
489
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
490
+	 * scripts/styles per view by putting them in a dynamic function in this format
491
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
492
+	 *
493
+	 * @abstract
494
+	 * @return void
495
+	 */
496
+	abstract public function load_scripts_styles();
497
+
498
+
499
+	/**
500
+	 * admin_init
501
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
502
+	 * all pages/views loaded by child class.
503
+	 *
504
+	 * @abstract
505
+	 * @return void
506
+	 */
507
+	abstract public function admin_init();
508
+
509
+
510
+	/**
511
+	 * admin_notices
512
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
513
+	 * all pages/views loaded by child class.
514
+	 *
515
+	 * @abstract
516
+	 * @return void
517
+	 */
518
+	abstract public function admin_notices();
519
+
520
+
521
+	/**
522
+	 * admin_footer_scripts
523
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
524
+	 * will apply to all pages/views loaded by child class.
525
+	 *
526
+	 * @return void
527
+	 */
528
+	abstract public function admin_footer_scripts();
529
+
530
+
531
+	/**
532
+	 * admin_footer
533
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
534
+	 * apply to all pages/views loaded by child class.
535
+	 *
536
+	 * @return void
537
+	 */
538
+	public function admin_footer()
539
+	{
540
+	}
541
+
542
+
543
+	/**
544
+	 * _global_ajax_hooks
545
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
546
+	 * Note: within the ajax callback methods.
547
+	 *
548
+	 * @abstract
549
+	 * @return void
550
+	 */
551
+	protected function _global_ajax_hooks()
552
+	{
553
+		// for lazy loading of metabox content
554
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
555
+
556
+		add_action(
557
+			'wp_ajax_espresso_hide_status_change_notice',
558
+			[$this, 'hideStatusChangeNotice']
559
+		);
560
+		add_action(
561
+			'wp_ajax_nopriv_espresso_hide_status_change_notice',
562
+			[$this, 'hideStatusChangeNotice']
563
+		);
564
+	}
565
+
566
+
567
+	public function ajax_metabox_content()
568
+	{
569
+		$content_id  = $this->request->getRequestParam('contentid', '');
570
+		$content_url = $this->request->getRequestParam('contenturl', '', 'url');
571
+		EE_Admin_Page::cached_rss_display($content_id, $content_url);
572
+		wp_die();
573
+	}
574
+
575
+
576
+	public function hideStatusChangeNotice()
577
+	{
578
+		$response = [];
579
+		try {
580
+			/** @var StatusChangeNotice $status_change_notice */
581
+			$status_change_notice = $this->loader->getShared(
582
+				'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
583
+			);
584
+			$response['success'] = $status_change_notice->dismiss() > -1;
585
+		} catch (Exception $exception) {
586
+			$response['errors'] = $exception->getMessage();
587
+		}
588
+		echo wp_json_encode($response);
589
+		exit();
590
+	}
591
+
592
+
593
+	/**
594
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
595
+	 *
596
+	 * @return void
597
+	 */
598
+	protected function _before_page_setup()
599
+	{
600
+		// default is to do nothing
601
+	}
602
+
603
+
604
+	/**
605
+	 * Makes sure any things that need to be loaded early get handled.
606
+	 * We also escape early here if the page requested doesn't match the object.
607
+	 *
608
+	 * @final
609
+	 * @return void
610
+	 * @throws EE_Error
611
+	 * @throws InvalidArgumentException
612
+	 * @throws ReflectionException
613
+	 * @throws InvalidDataTypeException
614
+	 * @throws InvalidInterfaceException
615
+	 */
616
+	final protected function _page_setup()
617
+	{
618
+		// requires?
619
+		// admin_init stuff - global - we're setting this REALLY early
620
+		// so if EE_Admin pages have to hook into other WP pages they can.
621
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
622
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
623
+		// next verify if we need to load anything...
624
+		$this->_current_page = $this->request->getRequestParam('page', '', 'key');
625
+		$this->page_folder   = strtolower(
626
+			str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
627
+		);
628
+		global $ee_menu_slugs;
629
+		$ee_menu_slugs = (array) $ee_menu_slugs;
630
+		if (
631
+			! $this->request->isAjax()
632
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
633
+		) {
634
+			return;
635
+		}
636
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
637
+		// we need to copy the action from the second to the first
638
+		$action     = $this->request->getRequestParam('action', '-1', 'key');
639
+		$action2    = $this->request->getRequestParam('action2', '-1', 'key');
640
+		$action     = $action !== '-1' ? $action : $action2;
641
+		$req_action = $action !== '-1' ? $action : 'default';
642
+
643
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
644
+		// then let's use the route as the action.
645
+		// This covers cases where we're coming in from a list table that isn't on the default route.
646
+		$route = $this->request->getRequestParam('route');
647
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
648
+			? $route
649
+			: $req_action;
650
+
651
+		$this->_current_view = $this->_req_action;
652
+		$this->_req_nonce    = $this->_req_action . '_nonce';
653
+		$this->_define_page_props();
654
+		$this->_current_page_view_url = add_query_arg(
655
+			['page' => $this->_current_page, 'action' => $this->_current_view],
656
+			$this->_admin_base_url
657
+		);
658
+		// set page configs
659
+		$this->_set_page_routes();
660
+		$this->_set_page_config();
661
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
662
+		if ($this->request->requestParamIsSet('wp_referer')) {
663
+			$wp_referer = $this->request->getRequestParam('wp_referer');
664
+			if ($wp_referer) {
665
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
666
+			}
667
+		}
668
+		// for caffeinated and other extended functionality.
669
+		//  If there is a _extend_page_config method
670
+		// then let's run that to modify the all the various page configuration arrays
671
+		if (method_exists($this, '_extend_page_config')) {
672
+			$this->_extend_page_config();
673
+		}
674
+		// for CPT and other extended functionality.
675
+		// If there is an _extend_page_config_for_cpt
676
+		// then let's run that to modify all the various page configuration arrays.
677
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
678
+			$this->_extend_page_config_for_cpt();
679
+		}
680
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
681
+		$this->_page_routes = apply_filters(
682
+			'FHEE__' . $this->class_name . '__page_setup__page_routes',
683
+			$this->_page_routes,
684
+			$this
685
+		);
686
+		$this->_page_config = apply_filters(
687
+			'FHEE__' . $this->class_name . '__page_setup__page_config',
688
+			$this->_page_config,
689
+			$this
690
+		);
691
+		if ($this->base_class_name !== '') {
692
+			$this->_page_routes = apply_filters(
693
+				'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
694
+				$this->_page_routes,
695
+				$this
696
+			);
697
+			$this->_page_config = apply_filters(
698
+				'FHEE__' . $this->base_class_name . '__page_setup__page_config',
699
+				$this->_page_config,
700
+				$this
701
+			);
702
+		}
703
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
706
+			add_action(
707
+				'AHEE__EE_Admin_Page__route_admin_request',
708
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
709
+				10,
710
+				2
711
+			);
712
+		}
713
+		// next route only if routing enabled
714
+		if ($this->_routing && ! $this->request->isAjax()) {
715
+			$this->_verify_routes();
716
+			// next let's just check user_access and kill if no access
717
+			$this->check_user_access();
718
+			if ($this->_is_UI_request) {
719
+				// admin_init stuff - global, all views for this page class, specific view
720
+				add_action('admin_init', [$this, 'admin_init'], 10);
721
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
723
+				}
724
+			} else {
725
+				// hijack regular WP loading and route admin request immediately
726
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
727
+				$this->route_admin_request();
728
+			}
729
+		}
730
+	}
731
+
732
+
733
+	/**
734
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
735
+	 *
736
+	 * @return void
737
+	 * @throws EE_Error
738
+	 */
739
+	private function _do_other_page_hooks()
740
+	{
741
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
742
+		foreach ($registered_pages as $page) {
743
+			// now let's setup the file name and class that should be present
744
+			$classname = str_replace('.class.php', '', $page);
745
+			// autoloaders should take care of loading file
746
+			if (! class_exists($classname)) {
747
+				$error_msg[] = sprintf(
748
+					esc_html__(
749
+						'Something went wrong with loading the %s admin hooks page.',
750
+						'event_espresso'
751
+					),
752
+					$page
753
+				);
754
+				$error_msg[] = $error_msg[0]
755
+							   . "\r\n"
756
+							   . sprintf(
757
+								   esc_html__(
758
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
759
+									   'event_espresso'
760
+								   ),
761
+								   $page,
762
+								   '<br />',
763
+								   '<strong>' . $classname . '</strong>'
764
+							   );
765
+				throw new EE_Error(implode('||', $error_msg));
766
+			}
767
+			// notice we are passing the instance of this class to the hook object.
768
+			$this->loader->getShared($classname, [$this]);
769
+		}
770
+	}
771
+
772
+
773
+	/**
774
+	 * @throws ReflectionException
775
+	 * @throws EE_Error
776
+	 */
777
+	public function load_page_dependencies()
778
+	{
779
+		try {
780
+			$this->_load_page_dependencies();
781
+		} catch (EE_Error $e) {
782
+			$e->get_error();
783
+		}
784
+	}
785
+
786
+
787
+	/**
788
+	 * load_page_dependencies
789
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
790
+	 *
791
+	 * @return void
792
+	 * @throws DomainException
793
+	 * @throws EE_Error
794
+	 * @throws InvalidArgumentException
795
+	 * @throws InvalidDataTypeException
796
+	 * @throws InvalidInterfaceException
797
+	 */
798
+	protected function _load_page_dependencies()
799
+	{
800
+		// let's set the current_screen and screen options to override what WP set
801
+		$this->_current_screen = get_current_screen();
802
+		// load admin_notices - global, page class, and view specific
803
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804
+		add_action('admin_notices', [$this, 'admin_notices'], 10);
805
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
807
+		}
808
+		// load network admin_notices - global, page class, and view specific
809
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
812
+		}
813
+		// this will save any per_page screen options if they are present
814
+		$this->_set_per_page_screen_options();
815
+		// setup list table properties
816
+		$this->_set_list_table();
817
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
818
+		// However in some cases the metaboxes will need to be added within a route handling callback.
819
+		$this->_add_registered_meta_boxes();
820
+		$this->_add_screen_columns();
821
+		// add screen options - global, page child class, and view specific
822
+		$this->_add_global_screen_options();
823
+		$this->_add_screen_options();
824
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
825
+		if (method_exists($this, $add_screen_options)) {
826
+			$this->{$add_screen_options}();
827
+		}
828
+		// add help tab(s) - set via page_config and qtips.
829
+		$this->_add_help_tabs();
830
+		$this->_add_qtips();
831
+		// add feature_pointers - global, page child class, and view specific
832
+		$this->_add_feature_pointers();
833
+		$this->_add_global_feature_pointers();
834
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
835
+		if (method_exists($this, $add_feature_pointer)) {
836
+			$this->{$add_feature_pointer}();
837
+		}
838
+		// enqueue scripts/styles - global, page class, and view specific
839
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
840
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
841
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
842
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
843
+		}
844
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
845
+		// admin_print_footer_scripts - global, page child class, and view specific.
846
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
847
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
848
+		// is a good use case. Notice the late priority we're giving these
849
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
850
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
851
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
852
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
853
+		}
854
+		// admin footer scripts
855
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
856
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
857
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
858
+			add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
859
+		}
860
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
861
+		// targeted hook
862
+		do_action(
863
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
864
+		);
865
+	}
866
+
867
+
868
+	/**
869
+	 * _set_defaults
870
+	 * This sets some global defaults for class properties.
871
+	 */
872
+	private function _set_defaults()
873
+	{
874
+		$this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
875
+		$this->_event                = $this->_template_path = $this->_column_template_path = null;
876
+		$this->_nav_tabs             = $this->_views = $this->_page_routes = [];
877
+		$this->_page_config          = $this->_default_route_query_args = [];
878
+		$this->_default_nav_tab_name = 'overview';
879
+		// init template args
880
+		$this->_template_args = [
881
+			'admin_page_header'  => '',
882
+			'admin_page_content' => '',
883
+			'post_body_content'  => '',
884
+			'before_list_table'  => '',
885
+			'after_list_table'   => '',
886
+		];
887
+	}
888
+
889
+
890
+	/**
891
+	 * route_admin_request
892
+	 *
893
+	 * @return void
894
+	 * @throws InvalidArgumentException
895
+	 * @throws InvalidInterfaceException
896
+	 * @throws InvalidDataTypeException
897
+	 * @throws EE_Error
898
+	 * @throws ReflectionException
899
+	 * @see    _route_admin_request()
900
+	 */
901
+	public function route_admin_request()
902
+	{
903
+		try {
904
+			$this->_route_admin_request();
905
+		} catch (EE_Error $e) {
906
+			$e->get_error();
907
+		}
908
+	}
909
+
910
+
911
+	public function set_wp_page_slug($wp_page_slug)
912
+	{
913
+		$this->_wp_page_slug = $wp_page_slug;
914
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
915
+		if (is_network_admin()) {
916
+			$this->_wp_page_slug .= '-network';
917
+		}
918
+	}
919
+
920
+
921
+	/**
922
+	 * _verify_routes
923
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
924
+	 * we know if we need to drop out.
925
+	 *
926
+	 * @return bool
927
+	 * @throws EE_Error
928
+	 */
929
+	protected function _verify_routes()
930
+	{
931
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
+		if (! $this->_current_page && ! $this->request->isAjax()) {
933
+			return false;
934
+		}
935
+		$this->_route = false;
936
+		// check that the page_routes array is not empty
937
+		if (empty($this->_page_routes)) {
938
+			// user error msg
939
+			$error_msg = sprintf(
940
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
941
+				$this->_admin_page_title
942
+			);
943
+			// developer error msg
944
+			$error_msg .= '||' . $error_msg
945
+						  . esc_html__(
946
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947
+							  'event_espresso'
948
+						  );
949
+			throw new EE_Error($error_msg);
950
+		}
951
+		// and that the requested page route exists
952
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
954
+			$this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
955
+		} else {
956
+			// user error msg
957
+			$error_msg = sprintf(
958
+				esc_html__(
959
+					'The requested page route does not exist for the %s admin page.',
960
+					'event_espresso'
961
+				),
962
+				$this->_admin_page_title
963
+			);
964
+			// developer error msg
965
+			$error_msg .= '||' . $error_msg
966
+						  . sprintf(
967
+							  esc_html__(
968
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
969
+								  'event_espresso'
970
+							  ),
971
+							  $this->_req_action
972
+						  );
973
+			throw new EE_Error($error_msg);
974
+		}
975
+		// and that a default route exists
976
+		if (! array_key_exists('default', $this->_page_routes)) {
977
+			// user error msg
978
+			$error_msg = sprintf(
979
+				esc_html__(
980
+					'A default page route has not been set for the % admin page.',
981
+					'event_espresso'
982
+				),
983
+				$this->_admin_page_title
984
+			);
985
+			// developer error msg
986
+			$error_msg .= '||' . $error_msg
987
+						  . esc_html__(
988
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989
+							  'event_espresso'
990
+						  );
991
+			throw new EE_Error($error_msg);
992
+		}
993
+
994
+		// first lets' catch if the UI request has EVER been set.
995
+		if ($this->_is_UI_request === null) {
996
+			// lets set if this is a UI request or not.
997
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
998
+			// wait a minute... we might have a noheader in the route array
999
+			$this->_is_UI_request = ! (
1000
+				is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
1001
+			)
1002
+				? $this->_is_UI_request
1003
+				: false;
1004
+		}
1005
+		$this->_set_current_labels();
1006
+		return true;
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1012
+	 *
1013
+	 * @param string $route the route name we're verifying
1014
+	 * @return bool we'll throw an exception if this isn't a valid route.
1015
+	 * @throws EE_Error
1016
+	 */
1017
+	protected function _verify_route($route)
1018
+	{
1019
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
1020
+			return true;
1021
+		}
1022
+		// user error msg
1023
+		$error_msg = sprintf(
1024
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1025
+			$this->_admin_page_title
1026
+		);
1027
+		// developer error msg
1028
+		$error_msg .= '||' . $error_msg
1029
+					  . sprintf(
1030
+						  esc_html__(
1031
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1032
+							  'event_espresso'
1033
+						  ),
1034
+						  $route
1035
+					  );
1036
+		throw new EE_Error($error_msg);
1037
+	}
1038
+
1039
+
1040
+	/**
1041
+	 * perform nonce verification
1042
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1043
+	 * using this method (and save retyping!)
1044
+	 *
1045
+	 * @param string $nonce     The nonce sent
1046
+	 * @param string $nonce_ref The nonce reference string (name0)
1047
+	 * @return void
1048
+	 * @throws EE_Error
1049
+	 * @throws InvalidArgumentException
1050
+	 * @throws InvalidDataTypeException
1051
+	 * @throws InvalidInterfaceException
1052
+	 */
1053
+	protected function _verify_nonce($nonce, $nonce_ref)
1054
+	{
1055
+		// verify nonce against expected value
1056
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
1057
+			// these are not the droids you are looking for !!!
1058
+			$msg = sprintf(
1059
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
1060
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1061
+				'</a>'
1062
+			);
1063
+			if (WP_DEBUG) {
1064
+				$msg .= "\n  ";
1065
+				$msg .= sprintf(
1066
+					esc_html__(
1067
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1068
+						'event_espresso'
1069
+					),
1070
+					__CLASS__
1071
+				);
1072
+			}
1073
+			if (! $this->request->isAjax()) {
1074
+				wp_die($msg);
1075
+			}
1076
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
+			$this->_return_json();
1078
+		}
1079
+	}
1080
+
1081
+
1082
+	/**
1083
+	 * _route_admin_request()
1084
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1085
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1086
+	 * in the page routes and then will try to load the corresponding method.
1087
+	 *
1088
+	 * @return void
1089
+	 * @throws EE_Error
1090
+	 * @throws InvalidArgumentException
1091
+	 * @throws InvalidDataTypeException
1092
+	 * @throws InvalidInterfaceException
1093
+	 * @throws ReflectionException
1094
+	 */
1095
+	protected function _route_admin_request()
1096
+	{
1097
+		if (! $this->_is_UI_request) {
1098
+			$this->_verify_routes();
1099
+		}
1100
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1101
+		if ($this->_req_action !== 'default' && $nonce_check) {
1102
+			// set nonce from post data
1103
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
1104
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1105
+		}
1106
+		// set the nav_tabs array but ONLY if this is  UI_request
1107
+		if ($this->_is_UI_request) {
1108
+			$this->_set_nav_tabs();
1109
+		}
1110
+		// grab callback function
1111
+		$func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1112
+		// check if callback has args
1113
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1114
+		$error_msg = '';
1115
+		// action right before calling route
1116
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119
+		}
1120
+		// strip _wp_http_referer from the server REQUEST_URI
1121
+		// else it grows in length on every submission due to recursion,
1122
+		// ultimately causing a "Request-URI Too Large" error
1123
+		$this->request->unSetRequestParam('_wp_http_referer');
1124
+		$this->request->unSetServerParam('_wp_http_referer');
1125
+		$cleaner_request_uri = remove_query_arg(
1126
+			'_wp_http_referer',
1127
+			wp_unslash($this->request->getServerParam('REQUEST_URI'))
1128
+		);
1129
+		$this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1130
+		$this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1131
+		if (! empty($func)) {
1132
+			if (is_array($func)) {
1133
+				[$class, $method] = $func;
1134
+			} elseif (strpos($func, '::') !== false) {
1135
+				[$class, $method] = explode('::', $func);
1136
+			} else {
1137
+				$class  = $this;
1138
+				$method = $func;
1139
+			}
1140
+			if (! (is_object($class) && $class === $this)) {
1141
+				// send along this admin page object for access by addons.
1142
+				$args['admin_page_object'] = $this;
1143
+			}
1144
+			if (
1145
+				// is it a method on a class that doesn't work?
1146
+				(
1147
+					(
1148
+						method_exists($class, $method)
1149
+						&& call_user_func_array([$class, $method], $args) === false
1150
+					)
1151
+					&& (
1152
+						// is it a standalone function that doesn't work?
1153
+						function_exists($method)
1154
+						&& call_user_func_array(
1155
+							$func,
1156
+							array_merge(['admin_page_object' => $this], $args)
1157
+						) === false
1158
+					)
1159
+				)
1160
+				|| (
1161
+					// is it neither a class method NOR a standalone function?
1162
+					! method_exists($class, $method)
1163
+					&& ! function_exists($method)
1164
+				)
1165
+			) {
1166
+				// user error msg
1167
+				$error_msg = esc_html__(
1168
+					'An error occurred. The  requested page route could not be found.',
1169
+					'event_espresso'
1170
+				);
1171
+				// developer error msg
1172
+				$error_msg .= '||';
1173
+				$error_msg .= sprintf(
1174
+					esc_html__(
1175
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1176
+						'event_espresso'
1177
+					),
1178
+					$method
1179
+				);
1180
+			}
1181
+			if (! empty($error_msg)) {
1182
+				throw new EE_Error($error_msg);
1183
+			}
1184
+		}
1185
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1186
+		// then we need to reset the routing properties to the new route.
1187
+		// now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1188
+		if (
1189
+			$this->_is_UI_request === false
1190
+			&& is_array($this->_route)
1191
+			&& ! empty($this->_route['headers_sent_route'])
1192
+		) {
1193
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1194
+		}
1195
+	}
1196
+
1197
+
1198
+	/**
1199
+	 * This method just allows the resetting of page properties in the case where a no headers
1200
+	 * route redirects to a headers route in its route config.
1201
+	 *
1202
+	 * @param string $new_route New (non header) route to redirect to.
1203
+	 * @return   void
1204
+	 * @throws ReflectionException
1205
+	 * @throws InvalidArgumentException
1206
+	 * @throws InvalidInterfaceException
1207
+	 * @throws InvalidDataTypeException
1208
+	 * @throws EE_Error
1209
+	 * @since   4.3.0
1210
+	 */
1211
+	protected function _reset_routing_properties($new_route)
1212
+	{
1213
+		$this->_is_UI_request = true;
1214
+		// now we set the current route to whatever the headers_sent_route is set at
1215
+		$this->request->setRequestParam('action', $new_route);
1216
+		// rerun page setup
1217
+		$this->_page_setup();
1218
+	}
1219
+
1220
+
1221
+	/**
1222
+	 * _add_query_arg
1223
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1224
+	 *(internally just uses EEH_URL's function with the same name)
1225
+	 *
1226
+	 * @param array  $args
1227
+	 * @param string $url
1228
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1229
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1230
+	 *                                        Example usage: If the current page is:
1231
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1232
+	 *                                        &action=default&event_id=20&month_range=March%202015
1233
+	 *                                        &_wpnonce=5467821
1234
+	 *                                        and you call:
1235
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1236
+	 *                                        array(
1237
+	 *                                        'action' => 'resend_something',
1238
+	 *                                        'page=>espresso_registrations'
1239
+	 *                                        ),
1240
+	 *                                        $some_url,
1241
+	 *                                        true
1242
+	 *                                        );
1243
+	 *                                        It will produce a url in this structure:
1244
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1245
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1246
+	 *                                        month_range]=March%202015
1247
+	 * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1248
+	 * @return string
1249
+	 */
1250
+	public static function add_query_args_and_nonce(
1251
+		$args = [],
1252
+		$url = '',
1253
+		$sticky = false,
1254
+		$exclude_nonce = false
1255
+	) {
1256
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1257
+		if ($sticky) {
1258
+			/** @var RequestInterface $request */
1259
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1260
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1261
+			$request->unSetServerParam('_wp_http_referer', true);
1262
+			foreach ($request->requestParams() as $key => $value) {
1263
+				// do not add nonces
1264
+				if (strpos($key, 'nonce') !== false) {
1265
+					continue;
1266
+				}
1267
+				$args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1268
+			}
1269
+		}
1270
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * This returns a generated link that will load the related help tab.
1276
+	 *
1277
+	 * @param string $help_tab_id the id for the connected help tab
1278
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1279
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1280
+	 * @return string              generated link
1281
+	 * @uses EEH_Template::get_help_tab_link()
1282
+	 */
1283
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1284
+	{
1285
+		return EEH_Template::get_help_tab_link(
1286
+			$help_tab_id,
1287
+			$this->page_slug,
1288
+			$this->_req_action,
1289
+			$icon_style,
1290
+			$help_text
1291
+		);
1292
+	}
1293
+
1294
+
1295
+	/**
1296
+	 * _add_help_tabs
1297
+	 * Note child classes define their help tabs within the page_config array.
1298
+	 *
1299
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1300
+	 * @return void
1301
+	 * @throws DomainException
1302
+	 * @throws EE_Error
1303
+	 * @throws ReflectionException
1304
+	 */
1305
+	protected function _add_help_tabs()
1306
+	{
1307
+		if (isset($this->_page_config[ $this->_req_action ])) {
1308
+			$config = $this->_page_config[ $this->_req_action ];
1309
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1310
+			if (is_array($config) && isset($config['help_sidebar'])) {
1311
+				// check that the callback given is valid
1312
+				if (! method_exists($this, $config['help_sidebar'])) {
1313
+					throw new EE_Error(
1314
+						sprintf(
1315
+							esc_html__(
1316
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1317
+								'event_espresso'
1318
+							),
1319
+							$config['help_sidebar'],
1320
+							$this->class_name
1321
+						)
1322
+					);
1323
+				}
1324
+				$content = apply_filters(
1325
+					'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1326
+					$this->{$config['help_sidebar']}()
1327
+				);
1328
+				$this->_current_screen->set_help_sidebar($content);
1329
+			}
1330
+			if (! isset($config['help_tabs'])) {
1331
+				return;
1332
+			} //no help tabs for this route
1333
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1334
+				// we're here so there ARE help tabs!
1335
+				// make sure we've got what we need
1336
+				if (! isset($cfg['title'])) {
1337
+					throw new EE_Error(
1338
+						esc_html__(
1339
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1340
+							'event_espresso'
1341
+						)
1342
+					);
1343
+				}
1344
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1345
+					throw new EE_Error(
1346
+						esc_html__(
1347
+							'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1348
+							'event_espresso'
1349
+						)
1350
+					);
1351
+				}
1352
+				// first priority goes to content.
1353
+				if (! empty($cfg['content'])) {
1354
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1355
+					// second priority goes to filename
1356
+				} elseif (! empty($cfg['filename'])) {
1357
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1358
+					// it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1359
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1360
+															 . basename($this->_get_dir())
1361
+															 . '/help_tabs/'
1362
+															 . $cfg['filename']
1363
+															 . '.help_tab.php' : $file_path;
1364
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1365
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1366
+						EE_Error::add_error(
1367
+							sprintf(
1368
+								esc_html__(
1369
+									'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1370
+									'event_espresso'
1371
+								),
1372
+								$tab_id,
1373
+								key($config),
1374
+								$file_path
1375
+							),
1376
+							__FILE__,
1377
+							__FUNCTION__,
1378
+							__LINE__
1379
+						);
1380
+						return;
1381
+					}
1382
+					$template_args['admin_page_obj'] = $this;
1383
+					$content                         = EEH_Template::display_template(
1384
+						$file_path,
1385
+						$template_args,
1386
+						true
1387
+					);
1388
+				} else {
1389
+					$content = '';
1390
+				}
1391
+				// check if callback is valid
1392
+				if (
1393
+					empty($content)
1394
+					&& (
1395
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1396
+					)
1397
+				) {
1398
+					EE_Error::add_error(
1399
+						sprintf(
1400
+							esc_html__(
1401
+								'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1402
+								'event_espresso'
1403
+							),
1404
+							$cfg['title']
1405
+						),
1406
+						__FILE__,
1407
+						__FUNCTION__,
1408
+						__LINE__
1409
+					);
1410
+					return;
1411
+				}
1412
+				// setup config array for help tab method
1413
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1414
+				$_ht = [
1415
+					'id'       => $id,
1416
+					'title'    => $cfg['title'],
1417
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1418
+					'content'  => $content,
1419
+				];
1420
+				$this->_current_screen->add_help_tab($_ht);
1421
+			}
1422
+		}
1423
+	}
1424
+
1425
+
1426
+	/**
1427
+	 * This simply sets up any qtips that have been defined in the page config
1428
+	 *
1429
+	 * @return void
1430
+	 * @throws ReflectionException
1431
+	 * @throws EE_Error
1432
+	 */
1433
+	protected function _add_qtips()
1434
+	{
1435
+		if (isset($this->_route_config['qtips'])) {
1436
+			$qtips = (array) $this->_route_config['qtips'];
1437
+			// load qtip loader
1438
+			$path = [
1439
+				$this->_get_dir() . '/qtips/',
1440
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1441
+			];
1442
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1443
+		}
1444
+	}
1445
+
1446
+
1447
+	/**
1448
+	 * _set_nav_tabs
1449
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1450
+	 * wish to add additional tabs or modify accordingly.
1451
+	 *
1452
+	 * @return void
1453
+	 * @throws InvalidArgumentException
1454
+	 * @throws InvalidInterfaceException
1455
+	 * @throws InvalidDataTypeException
1456
+	 */
1457
+	protected function _set_nav_tabs()
1458
+	{
1459
+		$i = 0;
1460
+		$only_tab = count($this->_page_config) < 2;
1461
+		foreach ($this->_page_config as $slug => $config) {
1462
+			if (! is_array($config) || empty($config['nav'])) {
1463
+				continue;
1464
+			}
1465
+			// no nav tab for this config
1466
+			// check for persistent flag
1467
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1468
+				// nav tab is only to appear when route requested.
1469
+				continue;
1470
+			}
1471
+			if (! $this->check_user_access($slug, true)) {
1472
+				// no nav tab because current user does not have access.
1473
+				continue;
1474
+			}
1475
+			$css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1476
+			$css_class .= $only_tab ? ' ee-only-tab' : '';
1477
+
1478
+			$this->_nav_tabs[ $slug ] = [
1479
+				'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1480
+					['action' => $slug],
1481
+					$this->_admin_base_url
1482
+				),
1483
+				'link_text' => $this->navTabLabel($config['nav'], $slug),
1484
+				'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1485
+				'order'     => $config['nav']['order'] ?? $i,
1486
+			];
1487
+			$i++;
1488
+		}
1489
+		// if $this->_nav_tabs is empty then lets set the default
1490
+		if (empty($this->_nav_tabs)) {
1491
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1492
+				'url'       => $this->_admin_base_url,
1493
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1494
+				'css_class' => 'nav-tab-active',
1495
+				'order'     => 10,
1496
+			];
1497
+		}
1498
+		// now let's sort the tabs according to order
1499
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1500
+	}
1501
+
1502
+
1503
+	private function navTabLabel(array $nav_tab, string $slug): string
1504
+	{
1505
+		$label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1506
+		$icon = $nav_tab['icon'] ?? null;
1507
+		$icon = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1508
+		return '
1509 1509
             <span class="ee-admin-screen-tab__label">
1510 1510
                 ' . $icon . '
1511 1511
                 <span class="ee-nav-label__text">' . $label . '</span>
1512 1512
             </span>';
1513
-    }
1514
-
1515
-    /**
1516
-     * _set_current_labels
1517
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1518
-     * property array
1519
-     *
1520
-     * @return void
1521
-     */
1522
-    private function _set_current_labels()
1523
-    {
1524
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1525
-            foreach ($this->_route_config['labels'] as $label => $text) {
1526
-                if (is_array($text)) {
1527
-                    foreach ($text as $sublabel => $subtext) {
1528
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1529
-                    }
1530
-                } else {
1531
-                    $this->_labels[ $label ] = $text;
1532
-                }
1533
-            }
1534
-        }
1535
-    }
1536
-
1537
-
1538
-    /**
1539
-     *        verifies user access for this admin page
1540
-     *
1541
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1542
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1543
-     *                               return false if verify fail.
1544
-     * @return bool
1545
-     * @throws InvalidArgumentException
1546
-     * @throws InvalidDataTypeException
1547
-     * @throws InvalidInterfaceException
1548
-     */
1549
-    public function check_user_access($route_to_check = '', $verify_only = false)
1550
-    {
1551
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1552
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1553
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1554
-                                      && is_array($this->_page_routes[ $route_to_check ])
1555
-                        && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1556
-            ? $this->_page_routes[ $route_to_check ]['capability']
1557
-            : null;
1558
-
1559
-        if (empty($capability) && empty($route_to_check)) {
1560
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1561
-                : $this->_route['capability'];
1562
-        } else {
1563
-            $capability = empty($capability) ? 'manage_options' : $capability;
1564
-        }
1565
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1566
-        if (
1567
-            ! $this->request->isAjax()
1568
-            && (
1569
-                ! function_exists('is_admin')
1570
-                || ! EE_Registry::instance()->CAP->current_user_can(
1571
-                    $capability,
1572
-                    $this->page_slug
1573
-                    . '_'
1574
-                    . $route_to_check,
1575
-                    $id
1576
-                )
1577
-            )
1578
-        ) {
1579
-            if ($verify_only) {
1580
-                return false;
1581
-            }
1582
-            if (is_user_logged_in()) {
1583
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1584
-            } else {
1585
-                return false;
1586
-            }
1587
-        }
1588
-        return true;
1589
-    }
1590
-
1591
-
1592
-    /**
1593
-     * @param string                 $box_id
1594
-     * @param string                 $title
1595
-     * @param callable|string|null   $callback
1596
-     * @param string|array|WP_Screen $screen
1597
-     * @param string                 $context
1598
-     * @param string                 $priority
1599
-     * @param array|null             $callback_args
1600
-     */
1601
-    protected function addMetaBox(
1602
-        string $box_id,
1603
-        string $title,
1604
-        $callback,
1605
-        $screen,
1606
-        string $context = 'normal',
1607
-        string $priority = 'default',
1608
-        ?array $callback_args = null
1609
-    ) {
1610
-        if (! is_callable($callback)) {
1611
-            return;
1612
-        }
1613
-
1614
-        add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1615
-        add_filter(
1616
-            "postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1617
-            function ($classes) {
1618
-                array_push($classes, 'ee-admin-container');
1619
-                return $classes;
1620
-            }
1621
-        );
1622
-    }
1623
-
1624
-
1625
-    /**
1626
-     * admin_init_global
1627
-     * This runs all the code that we want executed within the WP admin_init hook.
1628
-     * This method executes for ALL EE Admin pages.
1629
-     *
1630
-     * @return void
1631
-     */
1632
-    public function admin_init_global()
1633
-    {
1634
-    }
1635
-
1636
-
1637
-    /**
1638
-     * wp_loaded_global
1639
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1640
-     * EE_Admin page and will execute on every EE Admin Page load
1641
-     *
1642
-     * @return void
1643
-     */
1644
-    public function wp_loaded()
1645
-    {
1646
-    }
1647
-
1648
-
1649
-    /**
1650
-     * admin_notices
1651
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1652
-     * ALL EE_Admin pages.
1653
-     *
1654
-     * @return void
1655
-     */
1656
-    public function admin_notices_global()
1657
-    {
1658
-        $this->_display_no_javascript_warning();
1659
-        $this->_display_espresso_notices();
1660
-    }
1661
-
1662
-
1663
-    public function network_admin_notices_global()
1664
-    {
1665
-        $this->_display_no_javascript_warning();
1666
-        $this->_display_espresso_notices();
1667
-    }
1668
-
1669
-
1670
-    /**
1671
-     * admin_footer_scripts_global
1672
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1673
-     * will apply on ALL EE_Admin pages.
1674
-     *
1675
-     * @return void
1676
-     */
1677
-    public function admin_footer_scripts_global()
1678
-    {
1679
-        $this->_add_admin_page_ajax_loading_img();
1680
-        $this->_add_admin_page_overlay();
1681
-        // if metaboxes are present we need to add the nonce field
1682
-        if (
1683
-            isset($this->_route_config['metaboxes'])
1684
-            || isset($this->_route_config['list_table'])
1685
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1686
-        ) {
1687
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1688
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1689
-        }
1690
-    }
1691
-
1692
-
1693
-    /**
1694
-     * admin_footer_global
1695
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1696
-     * This particular method will apply on ALL EE_Admin Pages.
1697
-     *
1698
-     * @return void
1699
-     */
1700
-    public function admin_footer_global()
1701
-    {
1702
-        // dialog container for dialog helper
1703
-        echo '
1513
+	}
1514
+
1515
+	/**
1516
+	 * _set_current_labels
1517
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1518
+	 * property array
1519
+	 *
1520
+	 * @return void
1521
+	 */
1522
+	private function _set_current_labels()
1523
+	{
1524
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1525
+			foreach ($this->_route_config['labels'] as $label => $text) {
1526
+				if (is_array($text)) {
1527
+					foreach ($text as $sublabel => $subtext) {
1528
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1529
+					}
1530
+				} else {
1531
+					$this->_labels[ $label ] = $text;
1532
+				}
1533
+			}
1534
+		}
1535
+	}
1536
+
1537
+
1538
+	/**
1539
+	 *        verifies user access for this admin page
1540
+	 *
1541
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1542
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1543
+	 *                               return false if verify fail.
1544
+	 * @return bool
1545
+	 * @throws InvalidArgumentException
1546
+	 * @throws InvalidDataTypeException
1547
+	 * @throws InvalidInterfaceException
1548
+	 */
1549
+	public function check_user_access($route_to_check = '', $verify_only = false)
1550
+	{
1551
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1552
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1553
+		$capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1554
+									  && is_array($this->_page_routes[ $route_to_check ])
1555
+						&& ! empty($this->_page_routes[ $route_to_check ]['capability'])
1556
+			? $this->_page_routes[ $route_to_check ]['capability']
1557
+			: null;
1558
+
1559
+		if (empty($capability) && empty($route_to_check)) {
1560
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1561
+				: $this->_route['capability'];
1562
+		} else {
1563
+			$capability = empty($capability) ? 'manage_options' : $capability;
1564
+		}
1565
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1566
+		if (
1567
+			! $this->request->isAjax()
1568
+			&& (
1569
+				! function_exists('is_admin')
1570
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1571
+					$capability,
1572
+					$this->page_slug
1573
+					. '_'
1574
+					. $route_to_check,
1575
+					$id
1576
+				)
1577
+			)
1578
+		) {
1579
+			if ($verify_only) {
1580
+				return false;
1581
+			}
1582
+			if (is_user_logged_in()) {
1583
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1584
+			} else {
1585
+				return false;
1586
+			}
1587
+		}
1588
+		return true;
1589
+	}
1590
+
1591
+
1592
+	/**
1593
+	 * @param string                 $box_id
1594
+	 * @param string                 $title
1595
+	 * @param callable|string|null   $callback
1596
+	 * @param string|array|WP_Screen $screen
1597
+	 * @param string                 $context
1598
+	 * @param string                 $priority
1599
+	 * @param array|null             $callback_args
1600
+	 */
1601
+	protected function addMetaBox(
1602
+		string $box_id,
1603
+		string $title,
1604
+		$callback,
1605
+		$screen,
1606
+		string $context = 'normal',
1607
+		string $priority = 'default',
1608
+		?array $callback_args = null
1609
+	) {
1610
+		if (! is_callable($callback)) {
1611
+			return;
1612
+		}
1613
+
1614
+		add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1615
+		add_filter(
1616
+			"postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1617
+			function ($classes) {
1618
+				array_push($classes, 'ee-admin-container');
1619
+				return $classes;
1620
+			}
1621
+		);
1622
+	}
1623
+
1624
+
1625
+	/**
1626
+	 * admin_init_global
1627
+	 * This runs all the code that we want executed within the WP admin_init hook.
1628
+	 * This method executes for ALL EE Admin pages.
1629
+	 *
1630
+	 * @return void
1631
+	 */
1632
+	public function admin_init_global()
1633
+	{
1634
+	}
1635
+
1636
+
1637
+	/**
1638
+	 * wp_loaded_global
1639
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1640
+	 * EE_Admin page and will execute on every EE Admin Page load
1641
+	 *
1642
+	 * @return void
1643
+	 */
1644
+	public function wp_loaded()
1645
+	{
1646
+	}
1647
+
1648
+
1649
+	/**
1650
+	 * admin_notices
1651
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1652
+	 * ALL EE_Admin pages.
1653
+	 *
1654
+	 * @return void
1655
+	 */
1656
+	public function admin_notices_global()
1657
+	{
1658
+		$this->_display_no_javascript_warning();
1659
+		$this->_display_espresso_notices();
1660
+	}
1661
+
1662
+
1663
+	public function network_admin_notices_global()
1664
+	{
1665
+		$this->_display_no_javascript_warning();
1666
+		$this->_display_espresso_notices();
1667
+	}
1668
+
1669
+
1670
+	/**
1671
+	 * admin_footer_scripts_global
1672
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1673
+	 * will apply on ALL EE_Admin pages.
1674
+	 *
1675
+	 * @return void
1676
+	 */
1677
+	public function admin_footer_scripts_global()
1678
+	{
1679
+		$this->_add_admin_page_ajax_loading_img();
1680
+		$this->_add_admin_page_overlay();
1681
+		// if metaboxes are present we need to add the nonce field
1682
+		if (
1683
+			isset($this->_route_config['metaboxes'])
1684
+			|| isset($this->_route_config['list_table'])
1685
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1686
+		) {
1687
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1688
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1689
+		}
1690
+	}
1691
+
1692
+
1693
+	/**
1694
+	 * admin_footer_global
1695
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1696
+	 * This particular method will apply on ALL EE_Admin Pages.
1697
+	 *
1698
+	 * @return void
1699
+	 */
1700
+	public function admin_footer_global()
1701
+	{
1702
+		// dialog container for dialog helper
1703
+		echo '
1704 1704
         <div class="ee-admin-dialog-container auto-hide hidden">
1705 1705
             <div class="ee-notices"></div>
1706 1706
             <div class="ee-admin-dialog-container-inner-content"></div>
1707 1707
         </div>
1708 1708
         ';
1709 1709
 
1710
-        // current set timezone for timezone js
1711
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1712
-    }
1713
-
1714
-
1715
-    /**
1716
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1717
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1718
-     * help popups then in your templates or your content you set "triggers" for the content using the
1719
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1720
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1721
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1722
-     * for the
1723
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1724
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1725
-     *    'help_trigger_id' => array(
1726
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1727
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1728
-     *    )
1729
-     * );
1730
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1731
-     *
1732
-     * @param array $help_array
1733
-     * @param bool  $display
1734
-     * @return string content
1735
-     * @throws DomainException
1736
-     * @throws EE_Error
1737
-     */
1738
-    protected function _set_help_popup_content($help_array = [], $display = false)
1739
-    {
1740
-        $content    = '';
1741
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1742
-        // loop through the array and setup content
1743
-        foreach ($help_array as $trigger => $help) {
1744
-            // make sure the array is setup properly
1745
-            if (! isset($help['title'], $help['content'])) {
1746
-                throw new EE_Error(
1747
-                    esc_html__(
1748
-                        'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1749
-                        'event_espresso'
1750
-                    )
1751
-                );
1752
-            }
1753
-            // we're good so let's setup the template vars and then assign parsed template content to our content.
1754
-            $template_args = [
1755
-                'help_popup_id'      => $trigger,
1756
-                'help_popup_title'   => $help['title'],
1757
-                'help_popup_content' => $help['content'],
1758
-            ];
1759
-            $content       .= EEH_Template::display_template(
1760
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1761
-                $template_args,
1762
-                true
1763
-            );
1764
-        }
1765
-        if ($display) {
1766
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1767
-            return '';
1768
-        }
1769
-        return $content;
1770
-    }
1771
-
1772
-
1773
-    /**
1774
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1775
-     *
1776
-     * @return array properly formatted array for help popup content
1777
-     * @throws EE_Error
1778
-     */
1779
-    private function _get_help_content()
1780
-    {
1781
-        // what is the method we're looking for?
1782
-        $method_name = '_help_popup_content_' . $this->_req_action;
1783
-        // if method doesn't exist let's get out.
1784
-        if (! method_exists($this, $method_name)) {
1785
-            return [];
1786
-        }
1787
-        // k we're good to go let's retrieve the help array
1788
-        $help_array = $this->{$method_name}();
1789
-        // make sure we've got an array!
1790
-        if (! is_array($help_array)) {
1791
-            throw new EE_Error(
1792
-                esc_html__(
1793
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1794
-                    'event_espresso'
1795
-                )
1796
-            );
1797
-        }
1798
-        return $help_array;
1799
-    }
1800
-
1801
-
1802
-    /**
1803
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1804
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1805
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1806
-     *
1807
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1808
-     * @param boolean $display    if false then we return the trigger string
1809
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1810
-     * @return string
1811
-     * @throws DomainException
1812
-     * @throws EE_Error
1813
-     */
1814
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1815
-    {
1816
-        if ($this->request->isAjax()) {
1817
-            return '';
1818
-        }
1819
-        // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1820
-        $help_array   = $this->_get_help_content();
1821
-        $help_content = '';
1822
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1823
-            $help_array[ $trigger_id ] = [
1824
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1825
-                'content' => esc_html__(
1826
-                    'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1827
-                    'event_espresso'
1828
-                ),
1829
-            ];
1830
-            $help_content = $this->_set_help_popup_content($help_array);
1831
-        }
1832
-        // let's setup the trigger
1833
-        $content = '<a class="ee-dialog" href="?height='
1834
-                   . esc_attr($dimensions[0])
1835
-                   . '&width='
1836
-                   . esc_attr($dimensions[1])
1837
-                   . '&inlineId='
1838
-                   . esc_attr($trigger_id)
1839
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1840
-        $content .= $help_content;
1841
-        if ($display) {
1842
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1843
-            return '';
1844
-        }
1845
-        return $content;
1846
-    }
1847
-
1848
-
1849
-    /**
1850
-     * _add_global_screen_options
1851
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1852
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1853
-     *
1854
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1855
-     *         see also WP_Screen object documents...
1856
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1857
-     * @abstract
1858
-     * @return void
1859
-     */
1860
-    private function _add_global_screen_options()
1861
-    {
1862
-    }
1863
-
1864
-
1865
-    /**
1866
-     * _add_global_feature_pointers
1867
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1868
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1869
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1870
-     *
1871
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1872
-     *         extended) also see:
1873
-     * @link   http://eamann.com/tech/wordpress-portland/
1874
-     * @abstract
1875
-     * @return void
1876
-     */
1877
-    private function _add_global_feature_pointers()
1878
-    {
1879
-    }
1880
-
1881
-
1882
-    /**
1883
-     * load_global_scripts_styles
1884
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1885
-     *
1886
-     * @return void
1887
-     */
1888
-    public function load_global_scripts_styles()
1889
-    {
1890
-        // add debugging styles
1891
-        if (WP_DEBUG) {
1892
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1893
-        }
1894
-        // taking care of metaboxes
1895
-        if (
1896
-            empty($this->_cpt_route)
1897
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1898
-        ) {
1899
-            wp_enqueue_script('dashboard');
1900
-        }
1901
-
1902
-        wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1903
-        wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1904
-        // LOCALIZED DATA
1905
-        // localize script for ajax lazy loading
1906
-        wp_localize_script(
1907
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1908
-            'eeLazyLoadingContainers',
1909
-            apply_filters(
1910
-                'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1911
-                ['espresso_news_post_box_content']
1912
-            )
1913
-        );
1914
-        StatusChangeNotice::loadAssets();
1915
-
1916
-        add_filter(
1917
-            'admin_body_class',
1918
-            function ($classes) {
1919
-                if (strpos($classes, 'espresso-admin') === false) {
1920
-                    $classes .= ' espresso-admin';
1921
-                }
1922
-                return $classes;
1923
-            }
1924
-        );
1925
-    }
1926
-
1927
-
1928
-    /**
1929
-     *        admin_footer_scripts_eei18n_js_strings
1930
-     *
1931
-     * @return        void
1932
-     */
1933
-    public function admin_footer_scripts_eei18n_js_strings()
1934
-    {
1935
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1936
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1937
-            __(
1938
-                'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
1939
-                'event_espresso'
1940
-            )
1941
-        );
1942
-        EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1943
-        EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1944
-        EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1945
-        EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1946
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1947
-        EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1948
-        EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1949
-        EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1950
-        EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1951
-        EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1952
-        EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1953
-        EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1954
-        EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1955
-        EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1956
-        EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1957
-        EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1958
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1959
-        EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1960
-        EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1961
-        EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1962
-        EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1963
-        EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1964
-        EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1965
-        EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1966
-        EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1967
-        EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1968
-        EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1969
-        EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1970
-        EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1971
-        EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1972
-        EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1973
-        EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1974
-        EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1975
-        EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1976
-        EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1977
-        EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1978
-        EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1979
-        EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1980
-    }
1981
-
1982
-
1983
-    /**
1984
-     *        load enhanced xdebug styles for ppl with failing eyesight
1985
-     *
1986
-     * @return        void
1987
-     */
1988
-    public function add_xdebug_style()
1989
-    {
1990
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1991
-    }
1992
-
1993
-
1994
-    /************************/
1995
-    /** LIST TABLE METHODS **/
1996
-    /************************/
1997
-    /**
1998
-     * this sets up the list table if the current view requires it.
1999
-     *
2000
-     * @return void
2001
-     * @throws EE_Error
2002
-     * @throws InvalidArgumentException
2003
-     * @throws InvalidDataTypeException
2004
-     * @throws InvalidInterfaceException
2005
-     */
2006
-    protected function _set_list_table()
2007
-    {
2008
-        // first is this a list_table view?
2009
-        if (! isset($this->_route_config['list_table'])) {
2010
-            return;
2011
-        } //not a list_table view so get out.
2012
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2013
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2014
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2015
-            // user error msg
2016
-            $error_msg = esc_html__(
2017
-                'An error occurred. The requested list table views could not be found.',
2018
-                'event_espresso'
2019
-            );
2020
-            // developer error msg
2021
-            $error_msg .= '||'
2022
-                          . sprintf(
2023
-                              esc_html__(
2024
-                                  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2025
-                                  'event_espresso'
2026
-                              ),
2027
-                              $this->_req_action,
2028
-                              $list_table_view
2029
-                          );
2030
-            throw new EE_Error($error_msg);
2031
-        }
2032
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2033
-        $this->_views = apply_filters(
2034
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2035
-            $this->_views
2036
-        );
2037
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2038
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2039
-        $this->_set_list_table_view();
2040
-        $this->_set_list_table_object();
2041
-    }
2042
-
2043
-
2044
-    /**
2045
-     * set current view for List Table
2046
-     *
2047
-     * @return void
2048
-     */
2049
-    protected function _set_list_table_view()
2050
-    {
2051
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2052
-        $status = $this->request->getRequestParam('status', null, 'key');
2053
-        $this->_view = $status && array_key_exists($status, $this->_views)
2054
-            ? $status
2055
-            : $this->_view;
2056
-    }
2057
-
2058
-
2059
-    /**
2060
-     * _set_list_table_object
2061
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2062
-     *
2063
-     * @throws InvalidInterfaceException
2064
-     * @throws InvalidArgumentException
2065
-     * @throws InvalidDataTypeException
2066
-     * @throws EE_Error
2067
-     * @throws InvalidInterfaceException
2068
-     */
2069
-    protected function _set_list_table_object()
2070
-    {
2071
-        if (isset($this->_route_config['list_table'])) {
2072
-            if (! class_exists($this->_route_config['list_table'])) {
2073
-                throw new EE_Error(
2074
-                    sprintf(
2075
-                        esc_html__(
2076
-                            'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2077
-                            'event_espresso'
2078
-                        ),
2079
-                        $this->_route_config['list_table'],
2080
-                        $this->class_name
2081
-                    )
2082
-                );
2083
-            }
2084
-            $this->_list_table_object = $this->loader->getShared(
2085
-                $this->_route_config['list_table'],
2086
-                [$this]
2087
-            );
2088
-        }
2089
-    }
2090
-
2091
-
2092
-    /**
2093
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2094
-     *
2095
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2096
-     *                                                    urls.  The array should be indexed by the view it is being
2097
-     *                                                    added to.
2098
-     * @return array
2099
-     */
2100
-    public function get_list_table_view_RLs($extra_query_args = [])
2101
-    {
2102
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2103
-        if (empty($this->_views)) {
2104
-            $this->_views = [];
2105
-        }
2106
-        // cycle thru views
2107
-        foreach ($this->_views as $key => $view) {
2108
-            $query_args = [];
2109
-            // check for current view
2110
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2111
-            $query_args['action']                        = $this->_req_action;
2112
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2113
-            $query_args['status']                        = $view['slug'];
2114
-            // merge any other arguments sent in.
2115
-            if (isset($extra_query_args[ $view['slug'] ])) {
2116
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2117
-                    $query_args[] = $extra_query_arg;
2118
-                }
2119
-            }
2120
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2121
-        }
2122
-        return $this->_views;
2123
-    }
2124
-
2125
-
2126
-    /**
2127
-     * _entries_per_page_dropdown
2128
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2129
-     *
2130
-     * @param int $max_entries total number of rows in the table
2131
-     * @return string
2132
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2133
-     *         WP does it.
2134
-     */
2135
-    protected function _entries_per_page_dropdown($max_entries = 0)
2136
-    {
2137
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2138
-        $values   = [10, 25, 50, 100];
2139
-        $per_page = $this->request->getRequestParam('per_page', 10, 'int');
2140
-        if ($max_entries) {
2141
-            $values[] = $max_entries;
2142
-            sort($values);
2143
-        }
2144
-        $entries_per_page_dropdown = '
1710
+		// current set timezone for timezone js
1711
+		echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1712
+	}
1713
+
1714
+
1715
+	/**
1716
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1717
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1718
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1719
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1720
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1721
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1722
+	 * for the
1723
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1724
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1725
+	 *    'help_trigger_id' => array(
1726
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1727
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1728
+	 *    )
1729
+	 * );
1730
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1731
+	 *
1732
+	 * @param array $help_array
1733
+	 * @param bool  $display
1734
+	 * @return string content
1735
+	 * @throws DomainException
1736
+	 * @throws EE_Error
1737
+	 */
1738
+	protected function _set_help_popup_content($help_array = [], $display = false)
1739
+	{
1740
+		$content    = '';
1741
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1742
+		// loop through the array and setup content
1743
+		foreach ($help_array as $trigger => $help) {
1744
+			// make sure the array is setup properly
1745
+			if (! isset($help['title'], $help['content'])) {
1746
+				throw new EE_Error(
1747
+					esc_html__(
1748
+						'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1749
+						'event_espresso'
1750
+					)
1751
+				);
1752
+			}
1753
+			// we're good so let's setup the template vars and then assign parsed template content to our content.
1754
+			$template_args = [
1755
+				'help_popup_id'      => $trigger,
1756
+				'help_popup_title'   => $help['title'],
1757
+				'help_popup_content' => $help['content'],
1758
+			];
1759
+			$content       .= EEH_Template::display_template(
1760
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1761
+				$template_args,
1762
+				true
1763
+			);
1764
+		}
1765
+		if ($display) {
1766
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1767
+			return '';
1768
+		}
1769
+		return $content;
1770
+	}
1771
+
1772
+
1773
+	/**
1774
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1775
+	 *
1776
+	 * @return array properly formatted array for help popup content
1777
+	 * @throws EE_Error
1778
+	 */
1779
+	private function _get_help_content()
1780
+	{
1781
+		// what is the method we're looking for?
1782
+		$method_name = '_help_popup_content_' . $this->_req_action;
1783
+		// if method doesn't exist let's get out.
1784
+		if (! method_exists($this, $method_name)) {
1785
+			return [];
1786
+		}
1787
+		// k we're good to go let's retrieve the help array
1788
+		$help_array = $this->{$method_name}();
1789
+		// make sure we've got an array!
1790
+		if (! is_array($help_array)) {
1791
+			throw new EE_Error(
1792
+				esc_html__(
1793
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1794
+					'event_espresso'
1795
+				)
1796
+			);
1797
+		}
1798
+		return $help_array;
1799
+	}
1800
+
1801
+
1802
+	/**
1803
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1804
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1805
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1806
+	 *
1807
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1808
+	 * @param boolean $display    if false then we return the trigger string
1809
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1810
+	 * @return string
1811
+	 * @throws DomainException
1812
+	 * @throws EE_Error
1813
+	 */
1814
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1815
+	{
1816
+		if ($this->request->isAjax()) {
1817
+			return '';
1818
+		}
1819
+		// let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1820
+		$help_array   = $this->_get_help_content();
1821
+		$help_content = '';
1822
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1823
+			$help_array[ $trigger_id ] = [
1824
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1825
+				'content' => esc_html__(
1826
+					'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1827
+					'event_espresso'
1828
+				),
1829
+			];
1830
+			$help_content = $this->_set_help_popup_content($help_array);
1831
+		}
1832
+		// let's setup the trigger
1833
+		$content = '<a class="ee-dialog" href="?height='
1834
+				   . esc_attr($dimensions[0])
1835
+				   . '&width='
1836
+				   . esc_attr($dimensions[1])
1837
+				   . '&inlineId='
1838
+				   . esc_attr($trigger_id)
1839
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1840
+		$content .= $help_content;
1841
+		if ($display) {
1842
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1843
+			return '';
1844
+		}
1845
+		return $content;
1846
+	}
1847
+
1848
+
1849
+	/**
1850
+	 * _add_global_screen_options
1851
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1852
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1853
+	 *
1854
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1855
+	 *         see also WP_Screen object documents...
1856
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1857
+	 * @abstract
1858
+	 * @return void
1859
+	 */
1860
+	private function _add_global_screen_options()
1861
+	{
1862
+	}
1863
+
1864
+
1865
+	/**
1866
+	 * _add_global_feature_pointers
1867
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1868
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1869
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1870
+	 *
1871
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1872
+	 *         extended) also see:
1873
+	 * @link   http://eamann.com/tech/wordpress-portland/
1874
+	 * @abstract
1875
+	 * @return void
1876
+	 */
1877
+	private function _add_global_feature_pointers()
1878
+	{
1879
+	}
1880
+
1881
+
1882
+	/**
1883
+	 * load_global_scripts_styles
1884
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1885
+	 *
1886
+	 * @return void
1887
+	 */
1888
+	public function load_global_scripts_styles()
1889
+	{
1890
+		// add debugging styles
1891
+		if (WP_DEBUG) {
1892
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1893
+		}
1894
+		// taking care of metaboxes
1895
+		if (
1896
+			empty($this->_cpt_route)
1897
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1898
+		) {
1899
+			wp_enqueue_script('dashboard');
1900
+		}
1901
+
1902
+		wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1903
+		wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1904
+		// LOCALIZED DATA
1905
+		// localize script for ajax lazy loading
1906
+		wp_localize_script(
1907
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1908
+			'eeLazyLoadingContainers',
1909
+			apply_filters(
1910
+				'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1911
+				['espresso_news_post_box_content']
1912
+			)
1913
+		);
1914
+		StatusChangeNotice::loadAssets();
1915
+
1916
+		add_filter(
1917
+			'admin_body_class',
1918
+			function ($classes) {
1919
+				if (strpos($classes, 'espresso-admin') === false) {
1920
+					$classes .= ' espresso-admin';
1921
+				}
1922
+				return $classes;
1923
+			}
1924
+		);
1925
+	}
1926
+
1927
+
1928
+	/**
1929
+	 *        admin_footer_scripts_eei18n_js_strings
1930
+	 *
1931
+	 * @return        void
1932
+	 */
1933
+	public function admin_footer_scripts_eei18n_js_strings()
1934
+	{
1935
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1936
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1937
+			__(
1938
+				'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
1939
+				'event_espresso'
1940
+			)
1941
+		);
1942
+		EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1943
+		EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1944
+		EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1945
+		EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1946
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1947
+		EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1948
+		EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1949
+		EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1950
+		EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1951
+		EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1952
+		EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1953
+		EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1954
+		EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1955
+		EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1956
+		EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1957
+		EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1958
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1959
+		EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1960
+		EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1961
+		EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1962
+		EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1963
+		EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1964
+		EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1965
+		EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1966
+		EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1967
+		EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1968
+		EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1969
+		EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1970
+		EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1971
+		EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1972
+		EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1973
+		EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1974
+		EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1975
+		EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1976
+		EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1977
+		EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1978
+		EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1979
+		EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1980
+	}
1981
+
1982
+
1983
+	/**
1984
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1985
+	 *
1986
+	 * @return        void
1987
+	 */
1988
+	public function add_xdebug_style()
1989
+	{
1990
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1991
+	}
1992
+
1993
+
1994
+	/************************/
1995
+	/** LIST TABLE METHODS **/
1996
+	/************************/
1997
+	/**
1998
+	 * this sets up the list table if the current view requires it.
1999
+	 *
2000
+	 * @return void
2001
+	 * @throws EE_Error
2002
+	 * @throws InvalidArgumentException
2003
+	 * @throws InvalidDataTypeException
2004
+	 * @throws InvalidInterfaceException
2005
+	 */
2006
+	protected function _set_list_table()
2007
+	{
2008
+		// first is this a list_table view?
2009
+		if (! isset($this->_route_config['list_table'])) {
2010
+			return;
2011
+		} //not a list_table view so get out.
2012
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2013
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2014
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2015
+			// user error msg
2016
+			$error_msg = esc_html__(
2017
+				'An error occurred. The requested list table views could not be found.',
2018
+				'event_espresso'
2019
+			);
2020
+			// developer error msg
2021
+			$error_msg .= '||'
2022
+						  . sprintf(
2023
+							  esc_html__(
2024
+								  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2025
+								  'event_espresso'
2026
+							  ),
2027
+							  $this->_req_action,
2028
+							  $list_table_view
2029
+						  );
2030
+			throw new EE_Error($error_msg);
2031
+		}
2032
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2033
+		$this->_views = apply_filters(
2034
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2035
+			$this->_views
2036
+		);
2037
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2038
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2039
+		$this->_set_list_table_view();
2040
+		$this->_set_list_table_object();
2041
+	}
2042
+
2043
+
2044
+	/**
2045
+	 * set current view for List Table
2046
+	 *
2047
+	 * @return void
2048
+	 */
2049
+	protected function _set_list_table_view()
2050
+	{
2051
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2052
+		$status = $this->request->getRequestParam('status', null, 'key');
2053
+		$this->_view = $status && array_key_exists($status, $this->_views)
2054
+			? $status
2055
+			: $this->_view;
2056
+	}
2057
+
2058
+
2059
+	/**
2060
+	 * _set_list_table_object
2061
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2062
+	 *
2063
+	 * @throws InvalidInterfaceException
2064
+	 * @throws InvalidArgumentException
2065
+	 * @throws InvalidDataTypeException
2066
+	 * @throws EE_Error
2067
+	 * @throws InvalidInterfaceException
2068
+	 */
2069
+	protected function _set_list_table_object()
2070
+	{
2071
+		if (isset($this->_route_config['list_table'])) {
2072
+			if (! class_exists($this->_route_config['list_table'])) {
2073
+				throw new EE_Error(
2074
+					sprintf(
2075
+						esc_html__(
2076
+							'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2077
+							'event_espresso'
2078
+						),
2079
+						$this->_route_config['list_table'],
2080
+						$this->class_name
2081
+					)
2082
+				);
2083
+			}
2084
+			$this->_list_table_object = $this->loader->getShared(
2085
+				$this->_route_config['list_table'],
2086
+				[$this]
2087
+			);
2088
+		}
2089
+	}
2090
+
2091
+
2092
+	/**
2093
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2094
+	 *
2095
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2096
+	 *                                                    urls.  The array should be indexed by the view it is being
2097
+	 *                                                    added to.
2098
+	 * @return array
2099
+	 */
2100
+	public function get_list_table_view_RLs($extra_query_args = [])
2101
+	{
2102
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2103
+		if (empty($this->_views)) {
2104
+			$this->_views = [];
2105
+		}
2106
+		// cycle thru views
2107
+		foreach ($this->_views as $key => $view) {
2108
+			$query_args = [];
2109
+			// check for current view
2110
+			$this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2111
+			$query_args['action']                        = $this->_req_action;
2112
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2113
+			$query_args['status']                        = $view['slug'];
2114
+			// merge any other arguments sent in.
2115
+			if (isset($extra_query_args[ $view['slug'] ])) {
2116
+				foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2117
+					$query_args[] = $extra_query_arg;
2118
+				}
2119
+			}
2120
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2121
+		}
2122
+		return $this->_views;
2123
+	}
2124
+
2125
+
2126
+	/**
2127
+	 * _entries_per_page_dropdown
2128
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2129
+	 *
2130
+	 * @param int $max_entries total number of rows in the table
2131
+	 * @return string
2132
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2133
+	 *         WP does it.
2134
+	 */
2135
+	protected function _entries_per_page_dropdown($max_entries = 0)
2136
+	{
2137
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2138
+		$values   = [10, 25, 50, 100];
2139
+		$per_page = $this->request->getRequestParam('per_page', 10, 'int');
2140
+		if ($max_entries) {
2141
+			$values[] = $max_entries;
2142
+			sort($values);
2143
+		}
2144
+		$entries_per_page_dropdown = '
2145 2145
 			<div id="entries-per-page-dv" class="alignleft actions">
2146 2146
 				<label class="hide-if-no-js">
2147 2147
 					Show
2148 2148
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2149
-        foreach ($values as $value) {
2150
-            if ($value < $max_entries) {
2151
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2152
-                $entries_per_page_dropdown .= '
2149
+		foreach ($values as $value) {
2150
+			if ($value < $max_entries) {
2151
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2152
+				$entries_per_page_dropdown .= '
2153 2153
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2154
-            }
2155
-        }
2156
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2157
-        $entries_per_page_dropdown .= '
2154
+			}
2155
+		}
2156
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2157
+		$entries_per_page_dropdown .= '
2158 2158
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2159
-        $entries_per_page_dropdown .= '
2159
+		$entries_per_page_dropdown .= '
2160 2160
 					</select>
2161 2161
 					entries
2162 2162
 				</label>
2163 2163
 				<input id="entries-per-page-btn" class="button button--secondary" type="submit" value="Go" >
2164 2164
 			</div>
2165 2165
 		';
2166
-        return $entries_per_page_dropdown;
2167
-    }
2168
-
2169
-
2170
-    /**
2171
-     *        _set_search_attributes
2172
-     *
2173
-     * @return        void
2174
-     */
2175
-    public function _set_search_attributes()
2176
-    {
2177
-        $this->_template_args['search']['btn_label'] = sprintf(
2178
-            esc_html__('Search %s', 'event_espresso'),
2179
-            empty($this->_search_btn_label) ? $this->page_label
2180
-                : $this->_search_btn_label
2181
-        );
2182
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2183
-    }
2184
-
2185
-
2186
-
2187
-    /*** END LIST TABLE METHODS **/
2188
-
2189
-
2190
-    /**
2191
-     * _add_registered_metaboxes
2192
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2193
-     *
2194
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2195
-     * @return void
2196
-     * @throws EE_Error
2197
-     */
2198
-    private function _add_registered_meta_boxes()
2199
-    {
2200
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2201
-        // we only add meta boxes if the page_route calls for it
2202
-        if (
2203
-            is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2204
-            && is_array(
2205
-                $this->_route_config['metaboxes']
2206
-            )
2207
-        ) {
2208
-            // this simply loops through the callbacks provided
2209
-            // and checks if there is a corresponding callback registered by the child
2210
-            // if there is then we go ahead and process the metabox loader.
2211
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2212
-                // first check for Closures
2213
-                if ($metabox_callback instanceof Closure) {
2214
-                    $result = $metabox_callback();
2215
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2216
-                    $result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2217
-                } else {
2218
-                    $result = $this->{$metabox_callback}();
2219
-                }
2220
-                if ($result === false) {
2221
-                    // user error msg
2222
-                    $error_msg = esc_html__(
2223
-                        'An error occurred. The  requested metabox could not be found.',
2224
-                        'event_espresso'
2225
-                    );
2226
-                    // developer error msg
2227
-                    $error_msg .= '||'
2228
-                                  . sprintf(
2229
-                                      esc_html__(
2230
-                                          'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2231
-                                          'event_espresso'
2232
-                                      ),
2233
-                                      $metabox_callback
2234
-                                  );
2235
-                    throw new EE_Error($error_msg);
2236
-                }
2237
-            }
2238
-        }
2239
-    }
2240
-
2241
-
2242
-    /**
2243
-     * _add_screen_columns
2244
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2245
-     * the dynamic column template and we'll setup the column options for the page.
2246
-     *
2247
-     * @return void
2248
-     */
2249
-    private function _add_screen_columns()
2250
-    {
2251
-        if (
2252
-            is_array($this->_route_config)
2253
-            && isset($this->_route_config['columns'])
2254
-            && is_array($this->_route_config['columns'])
2255
-            && count($this->_route_config['columns']) === 2
2256
-        ) {
2257
-            add_screen_option(
2258
-                'layout_columns',
2259
-                [
2260
-                    'max'     => (int) $this->_route_config['columns'][0],
2261
-                    'default' => (int) $this->_route_config['columns'][1],
2262
-                ]
2263
-            );
2264
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2265
-            $screen_id                                           = $this->_current_screen->id;
2266
-            $screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2267
-            $total_columns                                       = ! empty($screen_columns)
2268
-                ? $screen_columns
2269
-                : $this->_route_config['columns'][1];
2270
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2271
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2272
-            $this->_template_args['screen']                      = $this->_current_screen;
2273
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2274
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2275
-            // finally if we don't have has_metaboxes set in the route config
2276
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2277
-            $this->_route_config['has_metaboxes'] = true;
2278
-        }
2279
-    }
2280
-
2281
-
2282
-
2283
-    /** GLOBALLY AVAILABLE METABOXES **/
2284
-
2285
-
2286
-    /**
2287
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2288
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2289
-     * these get loaded on.
2290
-     */
2291
-    private function _espresso_news_post_box()
2292
-    {
2293
-        $news_box_title = apply_filters(
2294
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2295
-            esc_html__('New @ Event Espresso', 'event_espresso')
2296
-        );
2297
-        $this->addMetaBox(
2298
-            'espresso_news_post_box',
2299
-            $news_box_title,
2300
-            [
2301
-                $this,
2302
-                'espresso_news_post_box',
2303
-            ],
2304
-            $this->_wp_page_slug,
2305
-            'side',
2306
-            'low'
2307
-        );
2308
-    }
2309
-
2310
-
2311
-    /**
2312
-     * Code for setting up espresso ratings request metabox.
2313
-     */
2314
-    protected function _espresso_ratings_request()
2315
-    {
2316
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2317
-            return;
2318
-        }
2319
-        $ratings_box_title = apply_filters(
2320
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2321
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2322
-        );
2323
-        $this->addMetaBox(
2324
-            'espresso_ratings_request',
2325
-            $ratings_box_title,
2326
-            [
2327
-                $this,
2328
-                'espresso_ratings_request',
2329
-            ],
2330
-            $this->_wp_page_slug,
2331
-            'side'
2332
-        );
2333
-    }
2334
-
2335
-
2336
-    /**
2337
-     * Code for setting up espresso ratings request metabox content.
2338
-     *
2339
-     * @throws DomainException
2340
-     */
2341
-    public function espresso_ratings_request()
2342
-    {
2343
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2344
-    }
2345
-
2346
-
2347
-    public static function cached_rss_display($rss_id, $url)
2348
-    {
2349
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2350
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2351
-                     . '</p><p class="hide-if-js">'
2352
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2353
-                     . '</p>';
2354
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2355
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2356
-        $post      = '</div>' . "\n";
2357
-        $cache_key = 'ee_rss_' . md5($rss_id);
2358
-        $output    = get_transient($cache_key);
2359
-        if ($output !== false) {
2360
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2361
-            return true;
2362
-        }
2363
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2364
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2365
-            return false;
2366
-        }
2367
-        ob_start();
2368
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2369
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2370
-        return true;
2371
-    }
2372
-
2373
-
2374
-    public function espresso_news_post_box()
2375
-    {
2376
-        ?>
2166
+		return $entries_per_page_dropdown;
2167
+	}
2168
+
2169
+
2170
+	/**
2171
+	 *        _set_search_attributes
2172
+	 *
2173
+	 * @return        void
2174
+	 */
2175
+	public function _set_search_attributes()
2176
+	{
2177
+		$this->_template_args['search']['btn_label'] = sprintf(
2178
+			esc_html__('Search %s', 'event_espresso'),
2179
+			empty($this->_search_btn_label) ? $this->page_label
2180
+				: $this->_search_btn_label
2181
+		);
2182
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2183
+	}
2184
+
2185
+
2186
+
2187
+	/*** END LIST TABLE METHODS **/
2188
+
2189
+
2190
+	/**
2191
+	 * _add_registered_metaboxes
2192
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2193
+	 *
2194
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2195
+	 * @return void
2196
+	 * @throws EE_Error
2197
+	 */
2198
+	private function _add_registered_meta_boxes()
2199
+	{
2200
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2201
+		// we only add meta boxes if the page_route calls for it
2202
+		if (
2203
+			is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2204
+			&& is_array(
2205
+				$this->_route_config['metaboxes']
2206
+			)
2207
+		) {
2208
+			// this simply loops through the callbacks provided
2209
+			// and checks if there is a corresponding callback registered by the child
2210
+			// if there is then we go ahead and process the metabox loader.
2211
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2212
+				// first check for Closures
2213
+				if ($metabox_callback instanceof Closure) {
2214
+					$result = $metabox_callback();
2215
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2216
+					$result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2217
+				} else {
2218
+					$result = $this->{$metabox_callback}();
2219
+				}
2220
+				if ($result === false) {
2221
+					// user error msg
2222
+					$error_msg = esc_html__(
2223
+						'An error occurred. The  requested metabox could not be found.',
2224
+						'event_espresso'
2225
+					);
2226
+					// developer error msg
2227
+					$error_msg .= '||'
2228
+								  . sprintf(
2229
+									  esc_html__(
2230
+										  'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2231
+										  'event_espresso'
2232
+									  ),
2233
+									  $metabox_callback
2234
+								  );
2235
+					throw new EE_Error($error_msg);
2236
+				}
2237
+			}
2238
+		}
2239
+	}
2240
+
2241
+
2242
+	/**
2243
+	 * _add_screen_columns
2244
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2245
+	 * the dynamic column template and we'll setup the column options for the page.
2246
+	 *
2247
+	 * @return void
2248
+	 */
2249
+	private function _add_screen_columns()
2250
+	{
2251
+		if (
2252
+			is_array($this->_route_config)
2253
+			&& isset($this->_route_config['columns'])
2254
+			&& is_array($this->_route_config['columns'])
2255
+			&& count($this->_route_config['columns']) === 2
2256
+		) {
2257
+			add_screen_option(
2258
+				'layout_columns',
2259
+				[
2260
+					'max'     => (int) $this->_route_config['columns'][0],
2261
+					'default' => (int) $this->_route_config['columns'][1],
2262
+				]
2263
+			);
2264
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2265
+			$screen_id                                           = $this->_current_screen->id;
2266
+			$screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2267
+			$total_columns                                       = ! empty($screen_columns)
2268
+				? $screen_columns
2269
+				: $this->_route_config['columns'][1];
2270
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2271
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2272
+			$this->_template_args['screen']                      = $this->_current_screen;
2273
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2274
+																   . 'admin_details_metabox_column_wrapper.template.php';
2275
+			// finally if we don't have has_metaboxes set in the route config
2276
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2277
+			$this->_route_config['has_metaboxes'] = true;
2278
+		}
2279
+	}
2280
+
2281
+
2282
+
2283
+	/** GLOBALLY AVAILABLE METABOXES **/
2284
+
2285
+
2286
+	/**
2287
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2288
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2289
+	 * these get loaded on.
2290
+	 */
2291
+	private function _espresso_news_post_box()
2292
+	{
2293
+		$news_box_title = apply_filters(
2294
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2295
+			esc_html__('New @ Event Espresso', 'event_espresso')
2296
+		);
2297
+		$this->addMetaBox(
2298
+			'espresso_news_post_box',
2299
+			$news_box_title,
2300
+			[
2301
+				$this,
2302
+				'espresso_news_post_box',
2303
+			],
2304
+			$this->_wp_page_slug,
2305
+			'side',
2306
+			'low'
2307
+		);
2308
+	}
2309
+
2310
+
2311
+	/**
2312
+	 * Code for setting up espresso ratings request metabox.
2313
+	 */
2314
+	protected function _espresso_ratings_request()
2315
+	{
2316
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2317
+			return;
2318
+		}
2319
+		$ratings_box_title = apply_filters(
2320
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2321
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2322
+		);
2323
+		$this->addMetaBox(
2324
+			'espresso_ratings_request',
2325
+			$ratings_box_title,
2326
+			[
2327
+				$this,
2328
+				'espresso_ratings_request',
2329
+			],
2330
+			$this->_wp_page_slug,
2331
+			'side'
2332
+		);
2333
+	}
2334
+
2335
+
2336
+	/**
2337
+	 * Code for setting up espresso ratings request metabox content.
2338
+	 *
2339
+	 * @throws DomainException
2340
+	 */
2341
+	public function espresso_ratings_request()
2342
+	{
2343
+		EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2344
+	}
2345
+
2346
+
2347
+	public static function cached_rss_display($rss_id, $url)
2348
+	{
2349
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2350
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2351
+					 . '</p><p class="hide-if-js">'
2352
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2353
+					 . '</p>';
2354
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2355
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2356
+		$post      = '</div>' . "\n";
2357
+		$cache_key = 'ee_rss_' . md5($rss_id);
2358
+		$output    = get_transient($cache_key);
2359
+		if ($output !== false) {
2360
+			echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2361
+			return true;
2362
+		}
2363
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2364
+			echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2365
+			return false;
2366
+		}
2367
+		ob_start();
2368
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2369
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2370
+		return true;
2371
+	}
2372
+
2373
+
2374
+	public function espresso_news_post_box()
2375
+	{
2376
+		?>
2377 2377
         <div class="padding">
2378 2378
             <div id="espresso_news_post_box_content" class="infolinks">
2379 2379
                 <?php
2380
-                // Get RSS Feed(s)
2381
-                EE_Admin_Page::cached_rss_display(
2382
-                    'espresso_news_post_box_content',
2383
-                    esc_url_raw(
2384
-                        apply_filters(
2385
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2386
-                            'https://eventespresso.com/feed/'
2387
-                        )
2388
-                    )
2389
-                );
2390
-                ?>
2380
+				// Get RSS Feed(s)
2381
+				EE_Admin_Page::cached_rss_display(
2382
+					'espresso_news_post_box_content',
2383
+					esc_url_raw(
2384
+						apply_filters(
2385
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2386
+							'https://eventespresso.com/feed/'
2387
+						)
2388
+					)
2389
+				);
2390
+				?>
2391 2391
             </div>
2392 2392
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2393 2393
         </div>
2394 2394
         <?php
2395
-    }
2396
-
2397
-
2398
-    private function _espresso_links_post_box()
2399
-    {
2400
-        // Hiding until we actually have content to put in here...
2401
-        // $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2402
-    }
2403
-
2404
-
2405
-    public function espresso_links_post_box()
2406
-    {
2407
-        // Hiding until we actually have content to put in here...
2408
-        // EEH_Template::display_template(
2409
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2410
-        // );
2411
-    }
2412
-
2413
-
2414
-    protected function _espresso_sponsors_post_box()
2415
-    {
2416
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2417
-            $this->addMetaBox(
2418
-                'espresso_sponsors_post_box',
2419
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2420
-                [$this, 'espresso_sponsors_post_box'],
2421
-                $this->_wp_page_slug,
2422
-                'side'
2423
-            );
2424
-        }
2425
-    }
2426
-
2427
-
2428
-    public function espresso_sponsors_post_box()
2429
-    {
2430
-        EEH_Template::display_template(
2431
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2432
-        );
2433
-    }
2434
-
2435
-
2436
-    private function _publish_post_box()
2437
-    {
2438
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2439
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2440
-        // then we'll use that for the metabox label.
2441
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2442
-        if (! empty($this->_labels['publishbox'])) {
2443
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2444
-                : $this->_labels['publishbox'];
2445
-        } else {
2446
-            $box_label = esc_html__('Publish', 'event_espresso');
2447
-        }
2448
-        $box_label = apply_filters(
2449
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2450
-            $box_label,
2451
-            $this->_req_action,
2452
-            $this
2453
-        );
2454
-        $this->addMetaBox(
2455
-            $meta_box_ref,
2456
-            $box_label,
2457
-            [$this, 'editor_overview'],
2458
-            $this->_current_screen->id,
2459
-            'side',
2460
-            'high'
2461
-        );
2462
-    }
2463
-
2464
-
2465
-    public function editor_overview()
2466
-    {
2467
-        // if we have extra content set let's add it in if not make sure its empty
2468
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2469
-            ? $this->_template_args['publish_box_extra_content']
2470
-            : '';
2471
-        echo EEH_Template::display_template(
2472
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2473
-            $this->_template_args,
2474
-            true
2475
-        );
2476
-    }
2477
-
2478
-
2479
-    /** end of globally available metaboxes section **/
2480
-
2481
-
2482
-    /**
2483
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2484
-     * protected method.
2485
-     *
2486
-     * @param string $name
2487
-     * @param int    $id
2488
-     * @param bool   $delete
2489
-     * @param string $save_close_redirect_URL
2490
-     * @param bool   $both_btns
2491
-     * @throws EE_Error
2492
-     * @throws InvalidArgumentException
2493
-     * @throws InvalidDataTypeException
2494
-     * @throws InvalidInterfaceException
2495
-     * @see   $this->_set_publish_post_box_vars for param details
2496
-     * @since 4.6.0
2497
-     */
2498
-    public function set_publish_post_box_vars(
2499
-        $name = '',
2500
-        $id = 0,
2501
-        $delete = false,
2502
-        $save_close_redirect_URL = '',
2503
-        $both_btns = true
2504
-    ) {
2505
-        $this->_set_publish_post_box_vars(
2506
-            $name,
2507
-            $id,
2508
-            $delete,
2509
-            $save_close_redirect_URL,
2510
-            $both_btns
2511
-        );
2512
-    }
2513
-
2514
-
2515
-    /**
2516
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2517
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2518
-     * save, and save and close buttons to work properly, then you will want to include a
2519
-     * values for the name and id arguments.
2520
-     *
2521
-     * @param string  $name                       key used for the action ID (i.e. event_id)
2522
-     * @param int     $id                         id attached to the item published
2523
-     * @param string  $delete                     page route callback for the delete action
2524
-     * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2525
-     * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2526
-     *                                            the Save button
2527
-     * @throws EE_Error
2528
-     * @throws InvalidArgumentException
2529
-     * @throws InvalidDataTypeException
2530
-     * @throws InvalidInterfaceException
2531
-     * @todo  Add in validation for name/id arguments.
2532
-     */
2533
-    protected function _set_publish_post_box_vars(
2534
-        $name = '',
2535
-        $id = 0,
2536
-        $delete = '',
2537
-        $save_close_redirect_URL = '',
2538
-        $both_btns = true
2539
-    ) {
2540
-        // if Save & Close, use a custom redirect URL or default to the main page?
2541
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2542
-            ? $save_close_redirect_URL
2543
-            : $this->_admin_base_url;
2544
-        // create the Save & Close and Save buttons
2545
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2546
-        // if we have extra content set let's add it in if not make sure its empty
2547
-        $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2548
-        $delete_link = '';
2549
-        if ($delete && ! empty($id)) {
2550
-            // make sure we have a default if just true is sent.
2551
-            $delete           = ! empty($delete) ? $delete : 'delete';
2552
-            $delete_link      = $this->get_action_link_or_button(
2553
-                $delete,
2554
-                $delete,
2555
-                [$name => $id],
2556
-                'submitdelete deletion button button--outline button--caution'
2557
-            );
2558
-        }
2559
-        $this->_template_args['publish_delete_link'] = $delete_link;
2560
-        if (! empty($name) && ! empty($id)) {
2561
-            $hidden_field_arr[ $name ] = [
2562
-                'type'  => 'hidden',
2563
-                'value' => $id,
2564
-            ];
2565
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2566
-        } else {
2567
-            $hf = '';
2568
-        }
2569
-        // add hidden field
2570
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2571
-            ? $hf[ $name ]['field']
2572
-            : $hf;
2573
-    }
2574
-
2575
-
2576
-    /**
2577
-     * displays an error message to ppl who have javascript disabled
2578
-     *
2579
-     * @return void
2580
-     */
2581
-    private function _display_no_javascript_warning()
2582
-    {
2583
-        ?>
2395
+	}
2396
+
2397
+
2398
+	private function _espresso_links_post_box()
2399
+	{
2400
+		// Hiding until we actually have content to put in here...
2401
+		// $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2402
+	}
2403
+
2404
+
2405
+	public function espresso_links_post_box()
2406
+	{
2407
+		// Hiding until we actually have content to put in here...
2408
+		// EEH_Template::display_template(
2409
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2410
+		// );
2411
+	}
2412
+
2413
+
2414
+	protected function _espresso_sponsors_post_box()
2415
+	{
2416
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2417
+			$this->addMetaBox(
2418
+				'espresso_sponsors_post_box',
2419
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2420
+				[$this, 'espresso_sponsors_post_box'],
2421
+				$this->_wp_page_slug,
2422
+				'side'
2423
+			);
2424
+		}
2425
+	}
2426
+
2427
+
2428
+	public function espresso_sponsors_post_box()
2429
+	{
2430
+		EEH_Template::display_template(
2431
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2432
+		);
2433
+	}
2434
+
2435
+
2436
+	private function _publish_post_box()
2437
+	{
2438
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2439
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2440
+		// then we'll use that for the metabox label.
2441
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2442
+		if (! empty($this->_labels['publishbox'])) {
2443
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2444
+				: $this->_labels['publishbox'];
2445
+		} else {
2446
+			$box_label = esc_html__('Publish', 'event_espresso');
2447
+		}
2448
+		$box_label = apply_filters(
2449
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2450
+			$box_label,
2451
+			$this->_req_action,
2452
+			$this
2453
+		);
2454
+		$this->addMetaBox(
2455
+			$meta_box_ref,
2456
+			$box_label,
2457
+			[$this, 'editor_overview'],
2458
+			$this->_current_screen->id,
2459
+			'side',
2460
+			'high'
2461
+		);
2462
+	}
2463
+
2464
+
2465
+	public function editor_overview()
2466
+	{
2467
+		// if we have extra content set let's add it in if not make sure its empty
2468
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2469
+			? $this->_template_args['publish_box_extra_content']
2470
+			: '';
2471
+		echo EEH_Template::display_template(
2472
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2473
+			$this->_template_args,
2474
+			true
2475
+		);
2476
+	}
2477
+
2478
+
2479
+	/** end of globally available metaboxes section **/
2480
+
2481
+
2482
+	/**
2483
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2484
+	 * protected method.
2485
+	 *
2486
+	 * @param string $name
2487
+	 * @param int    $id
2488
+	 * @param bool   $delete
2489
+	 * @param string $save_close_redirect_URL
2490
+	 * @param bool   $both_btns
2491
+	 * @throws EE_Error
2492
+	 * @throws InvalidArgumentException
2493
+	 * @throws InvalidDataTypeException
2494
+	 * @throws InvalidInterfaceException
2495
+	 * @see   $this->_set_publish_post_box_vars for param details
2496
+	 * @since 4.6.0
2497
+	 */
2498
+	public function set_publish_post_box_vars(
2499
+		$name = '',
2500
+		$id = 0,
2501
+		$delete = false,
2502
+		$save_close_redirect_URL = '',
2503
+		$both_btns = true
2504
+	) {
2505
+		$this->_set_publish_post_box_vars(
2506
+			$name,
2507
+			$id,
2508
+			$delete,
2509
+			$save_close_redirect_URL,
2510
+			$both_btns
2511
+		);
2512
+	}
2513
+
2514
+
2515
+	/**
2516
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2517
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2518
+	 * save, and save and close buttons to work properly, then you will want to include a
2519
+	 * values for the name and id arguments.
2520
+	 *
2521
+	 * @param string  $name                       key used for the action ID (i.e. event_id)
2522
+	 * @param int     $id                         id attached to the item published
2523
+	 * @param string  $delete                     page route callback for the delete action
2524
+	 * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2525
+	 * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2526
+	 *                                            the Save button
2527
+	 * @throws EE_Error
2528
+	 * @throws InvalidArgumentException
2529
+	 * @throws InvalidDataTypeException
2530
+	 * @throws InvalidInterfaceException
2531
+	 * @todo  Add in validation for name/id arguments.
2532
+	 */
2533
+	protected function _set_publish_post_box_vars(
2534
+		$name = '',
2535
+		$id = 0,
2536
+		$delete = '',
2537
+		$save_close_redirect_URL = '',
2538
+		$both_btns = true
2539
+	) {
2540
+		// if Save & Close, use a custom redirect URL or default to the main page?
2541
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2542
+			? $save_close_redirect_URL
2543
+			: $this->_admin_base_url;
2544
+		// create the Save & Close and Save buttons
2545
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2546
+		// if we have extra content set let's add it in if not make sure its empty
2547
+		$this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2548
+		$delete_link = '';
2549
+		if ($delete && ! empty($id)) {
2550
+			// make sure we have a default if just true is sent.
2551
+			$delete           = ! empty($delete) ? $delete : 'delete';
2552
+			$delete_link      = $this->get_action_link_or_button(
2553
+				$delete,
2554
+				$delete,
2555
+				[$name => $id],
2556
+				'submitdelete deletion button button--outline button--caution'
2557
+			);
2558
+		}
2559
+		$this->_template_args['publish_delete_link'] = $delete_link;
2560
+		if (! empty($name) && ! empty($id)) {
2561
+			$hidden_field_arr[ $name ] = [
2562
+				'type'  => 'hidden',
2563
+				'value' => $id,
2564
+			];
2565
+			$hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2566
+		} else {
2567
+			$hf = '';
2568
+		}
2569
+		// add hidden field
2570
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2571
+			? $hf[ $name ]['field']
2572
+			: $hf;
2573
+	}
2574
+
2575
+
2576
+	/**
2577
+	 * displays an error message to ppl who have javascript disabled
2578
+	 *
2579
+	 * @return void
2580
+	 */
2581
+	private function _display_no_javascript_warning()
2582
+	{
2583
+		?>
2584 2584
         <noscript>
2585 2585
             <div id="no-js-message" class="error">
2586 2586
                 <p style="font-size:1.3em;">
2587 2587
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2588 2588
                     <?php esc_html_e(
2589
-                        'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2590
-                        'event_espresso'
2591
-                    ); ?>
2589
+						'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2590
+						'event_espresso'
2591
+					); ?>
2592 2592
                 </p>
2593 2593
             </div>
2594 2594
         </noscript>
2595 2595
         <?php
2596
-    }
2597
-
2598
-
2599
-    /**
2600
-     * displays espresso success and/or error notices
2601
-     *
2602
-     * @return void
2603
-     */
2604
-    protected function _display_espresso_notices()
2605
-    {
2606
-        $notices = $this->_get_transient(true);
2607
-        echo stripslashes($notices);
2608
-    }
2609
-
2610
-
2611
-    /**
2612
-     * spinny things pacify the masses
2613
-     *
2614
-     * @return void
2615
-     */
2616
-    protected function _add_admin_page_ajax_loading_img()
2617
-    {
2618
-        ?>
2596
+	}
2597
+
2598
+
2599
+	/**
2600
+	 * displays espresso success and/or error notices
2601
+	 *
2602
+	 * @return void
2603
+	 */
2604
+	protected function _display_espresso_notices()
2605
+	{
2606
+		$notices = $this->_get_transient(true);
2607
+		echo stripslashes($notices);
2608
+	}
2609
+
2610
+
2611
+	/**
2612
+	 * spinny things pacify the masses
2613
+	 *
2614
+	 * @return void
2615
+	 */
2616
+	protected function _add_admin_page_ajax_loading_img()
2617
+	{
2618
+		?>
2619 2619
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2620 2620
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2621
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2621
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2622 2622
         </div>
2623 2623
         <?php
2624
-    }
2624
+	}
2625 2625
 
2626 2626
 
2627
-    /**
2628
-     * add admin page overlay for modal boxes
2629
-     *
2630
-     * @return void
2631
-     */
2632
-    protected function _add_admin_page_overlay()
2633
-    {
2634
-        ?>
2627
+	/**
2628
+	 * add admin page overlay for modal boxes
2629
+	 *
2630
+	 * @return void
2631
+	 */
2632
+	protected function _add_admin_page_overlay()
2633
+	{
2634
+		?>
2635 2635
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2636 2636
         <?php
2637
-    }
2638
-
2639
-
2640
-    /**
2641
-     * facade for $this->addMetaBox()
2642
-     *
2643
-     * @param string  $action        where the metabox gets displayed
2644
-     * @param string  $title         Title of Metabox (output in metabox header)
2645
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2646
-     *                               instead of the one created in here.
2647
-     * @param array   $callback_args an array of args supplied for the metabox
2648
-     * @param string  $column        what metabox column
2649
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2650
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2651
-     *                               created but just set our own callback for wp's add_meta_box.
2652
-     * @throws DomainException
2653
-     */
2654
-    public function _add_admin_page_meta_box(
2655
-        $action,
2656
-        $title,
2657
-        $callback,
2658
-        $callback_args,
2659
-        $column = 'normal',
2660
-        $priority = 'high',
2661
-        $create_func = true
2662
-    ) {
2663
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2664
-        // if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2665
-        if (empty($callback_args) && $create_func) {
2666
-            $callback_args = [
2667
-                'template_path' => $this->_template_path,
2668
-                'template_args' => $this->_template_args,
2669
-            ];
2670
-        }
2671
-        // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2672
-        $call_back_func = $create_func
2673
-            ? static function ($post, $metabox) {
2674
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2675
-                echo EEH_Template::display_template(
2676
-                    $metabox['args']['template_path'],
2677
-                    $metabox['args']['template_args'],
2678
-                    true
2679
-                );
2680
-            }
2681
-            : $callback;
2682
-        $this->addMetaBox(
2683
-            str_replace('_', '-', $action) . '-mbox',
2684
-            $title,
2685
-            $call_back_func,
2686
-            $this->_wp_page_slug,
2687
-            $column,
2688
-            $priority,
2689
-            $callback_args
2690
-        );
2691
-    }
2692
-
2693
-
2694
-    /**
2695
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2696
-     *
2697
-     * @throws DomainException
2698
-     * @throws EE_Error
2699
-     * @throws InvalidArgumentException
2700
-     * @throws InvalidDataTypeException
2701
-     * @throws InvalidInterfaceException
2702
-     */
2703
-    public function display_admin_page_with_metabox_columns()
2704
-    {
2705
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2706
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2707
-            $this->_column_template_path,
2708
-            $this->_template_args,
2709
-            true
2710
-        );
2711
-        // the final wrapper
2712
-        $this->admin_page_wrapper();
2713
-    }
2714
-
2715
-
2716
-    /**
2717
-     * generates  HTML wrapper for an admin details page
2718
-     *
2719
-     * @return void
2720
-     * @throws DomainException
2721
-     * @throws EE_Error
2722
-     * @throws InvalidArgumentException
2723
-     * @throws InvalidDataTypeException
2724
-     * @throws InvalidInterfaceException
2725
-     */
2726
-    public function display_admin_page_with_sidebar()
2727
-    {
2728
-        $this->_display_admin_page(true);
2729
-    }
2730
-
2731
-
2732
-    /**
2733
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2734
-     *
2735
-     * @return void
2736
-     * @throws DomainException
2737
-     * @throws EE_Error
2738
-     * @throws InvalidArgumentException
2739
-     * @throws InvalidDataTypeException
2740
-     * @throws InvalidInterfaceException
2741
-     */
2742
-    public function display_admin_page_with_no_sidebar()
2743
-    {
2744
-        $this->_display_admin_page();
2745
-    }
2746
-
2747
-
2748
-    /**
2749
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2750
-     *
2751
-     * @return void
2752
-     * @throws DomainException
2753
-     * @throws EE_Error
2754
-     * @throws InvalidArgumentException
2755
-     * @throws InvalidDataTypeException
2756
-     * @throws InvalidInterfaceException
2757
-     */
2758
-    public function display_about_admin_page()
2759
-    {
2760
-        $this->_display_admin_page(false, true);
2761
-    }
2762
-
2763
-
2764
-    /**
2765
-     * display_admin_page
2766
-     * contains the code for actually displaying an admin page
2767
-     *
2768
-     * @param boolean $sidebar true with sidebar, false without
2769
-     * @param boolean $about   use the about admin wrapper instead of the default.
2770
-     * @return void
2771
-     * @throws DomainException
2772
-     * @throws EE_Error
2773
-     * @throws InvalidArgumentException
2774
-     * @throws InvalidDataTypeException
2775
-     * @throws InvalidInterfaceException
2776
-     */
2777
-    private function _display_admin_page($sidebar = false, $about = false)
2778
-    {
2779
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2780
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2781
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2782
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2783
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2784
-
2785
-        $post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2786
-
2787
-        $this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2788
-                                                 && $this->_req_action !== 'data_reset'
2789
-                                                 && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2790
-                                                 && strpos($post_body_content, 'wp-list-table') === false;
2791
-
2792
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2793
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2794
-            ? 'poststuff'
2795
-            : 'espresso-default-admin';
2796
-        $this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2797
-            'event-espresso_page_espresso_',
2798
-            '',
2799
-            $this->_wp_page_slug
2800
-        ) . ' ' . $this->_req_action . '-route';
2801
-
2802
-        $template_path = $sidebar
2803
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2804
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2805
-        if ($this->request->isAjax()) {
2806
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2807
-        }
2808
-        $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2809
-
2810
-        $this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2811
-        $this->_template_args['before_admin_page_content'] = $post_body_content;
2812
-        $this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2813
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2814
-            $template_path,
2815
-            $this->_template_args,
2816
-            true
2817
-        );
2818
-        // the final template wrapper
2819
-        $this->admin_page_wrapper($about);
2820
-    }
2821
-
2822
-
2823
-    /**
2824
-     * This is used to display caf preview pages.
2825
-     *
2826
-     * @param string $utm_campaign_source what is the key used for google analytics link
2827
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2828
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2829
-     * @return void
2830
-     * @throws DomainException
2831
-     * @throws EE_Error
2832
-     * @throws InvalidArgumentException
2833
-     * @throws InvalidDataTypeException
2834
-     * @throws InvalidInterfaceException
2835
-     * @since 4.3.2
2836
-     */
2837
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2838
-    {
2839
-        // let's generate a default preview action button if there isn't one already present.
2840
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2841
-            'Upgrade to Event Espresso 4 Right Now',
2842
-            'event_espresso'
2843
-        );
2844
-        $buy_now_url                                   = add_query_arg(
2845
-            [
2846
-                'ee_ver'       => 'ee4',
2847
-                'utm_source'   => 'ee4_plugin_admin',
2848
-                'utm_medium'   => 'link',
2849
-                'utm_campaign' => $utm_campaign_source,
2850
-                'utm_content'  => 'buy_now_button',
2851
-            ],
2852
-            'https://eventespresso.com/pricing/'
2853
-        );
2854
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2855
-            ? $this->get_action_link_or_button(
2856
-                '',
2857
-                'buy_now',
2858
-                [],
2859
-                'button button--primary button--big',
2860
-                esc_url_raw($buy_now_url),
2861
-                true
2862
-            )
2863
-            : $this->_template_args['preview_action_button'];
2864
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2865
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2866
-            $this->_template_args,
2867
-            true
2868
-        );
2869
-        $this->_display_admin_page($display_sidebar);
2870
-    }
2871
-
2872
-
2873
-    /**
2874
-     * display_admin_list_table_page_with_sidebar
2875
-     * generates HTML wrapper for an admin_page with list_table
2876
-     *
2877
-     * @return void
2878
-     * @throws DomainException
2879
-     * @throws EE_Error
2880
-     * @throws InvalidArgumentException
2881
-     * @throws InvalidDataTypeException
2882
-     * @throws InvalidInterfaceException
2883
-     */
2884
-    public function display_admin_list_table_page_with_sidebar()
2885
-    {
2886
-        $this->_display_admin_list_table_page(true);
2887
-    }
2888
-
2889
-
2890
-    /**
2891
-     * display_admin_list_table_page_with_no_sidebar
2892
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2893
-     *
2894
-     * @return void
2895
-     * @throws DomainException
2896
-     * @throws EE_Error
2897
-     * @throws InvalidArgumentException
2898
-     * @throws InvalidDataTypeException
2899
-     * @throws InvalidInterfaceException
2900
-     */
2901
-    public function display_admin_list_table_page_with_no_sidebar()
2902
-    {
2903
-        $this->_display_admin_list_table_page();
2904
-    }
2905
-
2906
-
2907
-    /**
2908
-     * generates html wrapper for an admin_list_table page
2909
-     *
2910
-     * @param boolean $sidebar whether to display with sidebar or not.
2911
-     * @return void
2912
-     * @throws DomainException
2913
-     * @throws EE_Error
2914
-     * @throws InvalidArgumentException
2915
-     * @throws InvalidDataTypeException
2916
-     * @throws InvalidInterfaceException
2917
-     */
2918
-    private function _display_admin_list_table_page($sidebar = false)
2919
-    {
2920
-        // setup search attributes
2921
-        $this->_set_search_attributes();
2922
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
2923
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2924
-        $this->_template_args['table_url']        = $this->request->isAjax()
2925
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2926
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2927
-        $this->_template_args['list_table']       = $this->_list_table_object;
2928
-        $this->_template_args['current_route']    = $this->_req_action;
2929
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2930
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2931
-        if (! empty($ajax_sorting_callback)) {
2932
-            $sortable_list_table_form_fields = wp_nonce_field(
2933
-                $ajax_sorting_callback . '_nonce',
2934
-                $ajax_sorting_callback . '_nonce',
2935
-                false,
2936
-                false
2937
-            );
2938
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2939
-                                                . $this->page_slug
2940
-                                                . '" />';
2941
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2942
-                                                . $ajax_sorting_callback
2943
-                                                . '" />';
2944
-        } else {
2945
-            $sortable_list_table_form_fields = '';
2946
-        }
2947
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2948
-
2949
-        $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2950
-
2951
-        $nonce_ref          = $this->_req_action . '_nonce';
2952
-        $hidden_form_fields .= '
2637
+	}
2638
+
2639
+
2640
+	/**
2641
+	 * facade for $this->addMetaBox()
2642
+	 *
2643
+	 * @param string  $action        where the metabox gets displayed
2644
+	 * @param string  $title         Title of Metabox (output in metabox header)
2645
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2646
+	 *                               instead of the one created in here.
2647
+	 * @param array   $callback_args an array of args supplied for the metabox
2648
+	 * @param string  $column        what metabox column
2649
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2650
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2651
+	 *                               created but just set our own callback for wp's add_meta_box.
2652
+	 * @throws DomainException
2653
+	 */
2654
+	public function _add_admin_page_meta_box(
2655
+		$action,
2656
+		$title,
2657
+		$callback,
2658
+		$callback_args,
2659
+		$column = 'normal',
2660
+		$priority = 'high',
2661
+		$create_func = true
2662
+	) {
2663
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2664
+		// if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2665
+		if (empty($callback_args) && $create_func) {
2666
+			$callback_args = [
2667
+				'template_path' => $this->_template_path,
2668
+				'template_args' => $this->_template_args,
2669
+			];
2670
+		}
2671
+		// if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2672
+		$call_back_func = $create_func
2673
+			? static function ($post, $metabox) {
2674
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2675
+				echo EEH_Template::display_template(
2676
+					$metabox['args']['template_path'],
2677
+					$metabox['args']['template_args'],
2678
+					true
2679
+				);
2680
+			}
2681
+			: $callback;
2682
+		$this->addMetaBox(
2683
+			str_replace('_', '-', $action) . '-mbox',
2684
+			$title,
2685
+			$call_back_func,
2686
+			$this->_wp_page_slug,
2687
+			$column,
2688
+			$priority,
2689
+			$callback_args
2690
+		);
2691
+	}
2692
+
2693
+
2694
+	/**
2695
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2696
+	 *
2697
+	 * @throws DomainException
2698
+	 * @throws EE_Error
2699
+	 * @throws InvalidArgumentException
2700
+	 * @throws InvalidDataTypeException
2701
+	 * @throws InvalidInterfaceException
2702
+	 */
2703
+	public function display_admin_page_with_metabox_columns()
2704
+	{
2705
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2706
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2707
+			$this->_column_template_path,
2708
+			$this->_template_args,
2709
+			true
2710
+		);
2711
+		// the final wrapper
2712
+		$this->admin_page_wrapper();
2713
+	}
2714
+
2715
+
2716
+	/**
2717
+	 * generates  HTML wrapper for an admin details page
2718
+	 *
2719
+	 * @return void
2720
+	 * @throws DomainException
2721
+	 * @throws EE_Error
2722
+	 * @throws InvalidArgumentException
2723
+	 * @throws InvalidDataTypeException
2724
+	 * @throws InvalidInterfaceException
2725
+	 */
2726
+	public function display_admin_page_with_sidebar()
2727
+	{
2728
+		$this->_display_admin_page(true);
2729
+	}
2730
+
2731
+
2732
+	/**
2733
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2734
+	 *
2735
+	 * @return void
2736
+	 * @throws DomainException
2737
+	 * @throws EE_Error
2738
+	 * @throws InvalidArgumentException
2739
+	 * @throws InvalidDataTypeException
2740
+	 * @throws InvalidInterfaceException
2741
+	 */
2742
+	public function display_admin_page_with_no_sidebar()
2743
+	{
2744
+		$this->_display_admin_page();
2745
+	}
2746
+
2747
+
2748
+	/**
2749
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2750
+	 *
2751
+	 * @return void
2752
+	 * @throws DomainException
2753
+	 * @throws EE_Error
2754
+	 * @throws InvalidArgumentException
2755
+	 * @throws InvalidDataTypeException
2756
+	 * @throws InvalidInterfaceException
2757
+	 */
2758
+	public function display_about_admin_page()
2759
+	{
2760
+		$this->_display_admin_page(false, true);
2761
+	}
2762
+
2763
+
2764
+	/**
2765
+	 * display_admin_page
2766
+	 * contains the code for actually displaying an admin page
2767
+	 *
2768
+	 * @param boolean $sidebar true with sidebar, false without
2769
+	 * @param boolean $about   use the about admin wrapper instead of the default.
2770
+	 * @return void
2771
+	 * @throws DomainException
2772
+	 * @throws EE_Error
2773
+	 * @throws InvalidArgumentException
2774
+	 * @throws InvalidDataTypeException
2775
+	 * @throws InvalidInterfaceException
2776
+	 */
2777
+	private function _display_admin_page($sidebar = false, $about = false)
2778
+	{
2779
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2780
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2781
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2782
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2783
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2784
+
2785
+		$post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2786
+
2787
+		$this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2788
+												 && $this->_req_action !== 'data_reset'
2789
+												 && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2790
+												 && strpos($post_body_content, 'wp-list-table') === false;
2791
+
2792
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2793
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2794
+			? 'poststuff'
2795
+			: 'espresso-default-admin';
2796
+		$this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2797
+			'event-espresso_page_espresso_',
2798
+			'',
2799
+			$this->_wp_page_slug
2800
+		) . ' ' . $this->_req_action . '-route';
2801
+
2802
+		$template_path = $sidebar
2803
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2804
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2805
+		if ($this->request->isAjax()) {
2806
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2807
+		}
2808
+		$template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2809
+
2810
+		$this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2811
+		$this->_template_args['before_admin_page_content'] = $post_body_content;
2812
+		$this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2813
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2814
+			$template_path,
2815
+			$this->_template_args,
2816
+			true
2817
+		);
2818
+		// the final template wrapper
2819
+		$this->admin_page_wrapper($about);
2820
+	}
2821
+
2822
+
2823
+	/**
2824
+	 * This is used to display caf preview pages.
2825
+	 *
2826
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2827
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2828
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2829
+	 * @return void
2830
+	 * @throws DomainException
2831
+	 * @throws EE_Error
2832
+	 * @throws InvalidArgumentException
2833
+	 * @throws InvalidDataTypeException
2834
+	 * @throws InvalidInterfaceException
2835
+	 * @since 4.3.2
2836
+	 */
2837
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2838
+	{
2839
+		// let's generate a default preview action button if there isn't one already present.
2840
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2841
+			'Upgrade to Event Espresso 4 Right Now',
2842
+			'event_espresso'
2843
+		);
2844
+		$buy_now_url                                   = add_query_arg(
2845
+			[
2846
+				'ee_ver'       => 'ee4',
2847
+				'utm_source'   => 'ee4_plugin_admin',
2848
+				'utm_medium'   => 'link',
2849
+				'utm_campaign' => $utm_campaign_source,
2850
+				'utm_content'  => 'buy_now_button',
2851
+			],
2852
+			'https://eventespresso.com/pricing/'
2853
+		);
2854
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2855
+			? $this->get_action_link_or_button(
2856
+				'',
2857
+				'buy_now',
2858
+				[],
2859
+				'button button--primary button--big',
2860
+				esc_url_raw($buy_now_url),
2861
+				true
2862
+			)
2863
+			: $this->_template_args['preview_action_button'];
2864
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2865
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2866
+			$this->_template_args,
2867
+			true
2868
+		);
2869
+		$this->_display_admin_page($display_sidebar);
2870
+	}
2871
+
2872
+
2873
+	/**
2874
+	 * display_admin_list_table_page_with_sidebar
2875
+	 * generates HTML wrapper for an admin_page with list_table
2876
+	 *
2877
+	 * @return void
2878
+	 * @throws DomainException
2879
+	 * @throws EE_Error
2880
+	 * @throws InvalidArgumentException
2881
+	 * @throws InvalidDataTypeException
2882
+	 * @throws InvalidInterfaceException
2883
+	 */
2884
+	public function display_admin_list_table_page_with_sidebar()
2885
+	{
2886
+		$this->_display_admin_list_table_page(true);
2887
+	}
2888
+
2889
+
2890
+	/**
2891
+	 * display_admin_list_table_page_with_no_sidebar
2892
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2893
+	 *
2894
+	 * @return void
2895
+	 * @throws DomainException
2896
+	 * @throws EE_Error
2897
+	 * @throws InvalidArgumentException
2898
+	 * @throws InvalidDataTypeException
2899
+	 * @throws InvalidInterfaceException
2900
+	 */
2901
+	public function display_admin_list_table_page_with_no_sidebar()
2902
+	{
2903
+		$this->_display_admin_list_table_page();
2904
+	}
2905
+
2906
+
2907
+	/**
2908
+	 * generates html wrapper for an admin_list_table page
2909
+	 *
2910
+	 * @param boolean $sidebar whether to display with sidebar or not.
2911
+	 * @return void
2912
+	 * @throws DomainException
2913
+	 * @throws EE_Error
2914
+	 * @throws InvalidArgumentException
2915
+	 * @throws InvalidDataTypeException
2916
+	 * @throws InvalidInterfaceException
2917
+	 */
2918
+	private function _display_admin_list_table_page($sidebar = false)
2919
+	{
2920
+		// setup search attributes
2921
+		$this->_set_search_attributes();
2922
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
2923
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2924
+		$this->_template_args['table_url']        = $this->request->isAjax()
2925
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2926
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2927
+		$this->_template_args['list_table']       = $this->_list_table_object;
2928
+		$this->_template_args['current_route']    = $this->_req_action;
2929
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2930
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2931
+		if (! empty($ajax_sorting_callback)) {
2932
+			$sortable_list_table_form_fields = wp_nonce_field(
2933
+				$ajax_sorting_callback . '_nonce',
2934
+				$ajax_sorting_callback . '_nonce',
2935
+				false,
2936
+				false
2937
+			);
2938
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2939
+												. $this->page_slug
2940
+												. '" />';
2941
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2942
+												. $ajax_sorting_callback
2943
+												. '" />';
2944
+		} else {
2945
+			$sortable_list_table_form_fields = '';
2946
+		}
2947
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2948
+
2949
+		$hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2950
+
2951
+		$nonce_ref          = $this->_req_action . '_nonce';
2952
+		$hidden_form_fields .= '
2953 2953
             <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2954 2954
 
2955
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2956
-        // display message about search results?
2957
-        $search = $this->request->getRequestParam('s');
2958
-        $this->_template_args['before_list_table'] .= ! empty($search)
2959
-            ? '<p class="ee-search-results">' . sprintf(
2960
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2961
-                trim($search, '%')
2962
-            ) . '</p>'
2963
-            : '';
2964
-        // filter before_list_table template arg
2965
-        $this->_template_args['before_list_table'] = apply_filters(
2966
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2967
-            $this->_template_args['before_list_table'],
2968
-            $this->page_slug,
2969
-            $this->request->requestParams(),
2970
-            $this->_req_action
2971
-        );
2972
-        // convert to array and filter again
2973
-        // arrays are easier to inject new items in a specific location,
2974
-        // but would not be backwards compatible, so we have to add a new filter
2975
-        $this->_template_args['before_list_table'] = implode(
2976
-            " \n",
2977
-            (array) apply_filters(
2978
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2979
-                (array) $this->_template_args['before_list_table'],
2980
-                $this->page_slug,
2981
-                $this->request->requestParams(),
2982
-                $this->_req_action
2983
-            )
2984
-        );
2985
-        // filter after_list_table template arg
2986
-        $this->_template_args['after_list_table'] = apply_filters(
2987
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2988
-            $this->_template_args['after_list_table'],
2989
-            $this->page_slug,
2990
-            $this->request->requestParams(),
2991
-            $this->_req_action
2992
-        );
2993
-        // convert to array and filter again
2994
-        // arrays are easier to inject new items in a specific location,
2995
-        // but would not be backwards compatible, so we have to add a new filter
2996
-        $this->_template_args['after_list_table']   = implode(
2997
-            " \n",
2998
-            (array) apply_filters(
2999
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3000
-                (array) $this->_template_args['after_list_table'],
3001
-                $this->page_slug,
3002
-                $this->request->requestParams(),
3003
-                $this->_req_action
3004
-            )
3005
-        );
3006
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3007
-            $template_path,
3008
-            $this->_template_args,
3009
-            true
3010
-        );
3011
-        // the final template wrapper
3012
-        if ($sidebar) {
3013
-            $this->display_admin_page_with_sidebar();
3014
-        } else {
3015
-            $this->display_admin_page_with_no_sidebar();
3016
-        }
3017
-    }
3018
-
3019
-
3020
-    /**
3021
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3022
-     * html string for the legend.
3023
-     * $items are expected in an array in the following format:
3024
-     * $legend_items = array(
3025
-     *        'item_id' => array(
3026
-     *            'icon' => 'http://url_to_icon_being_described.png',
3027
-     *            'desc' => esc_html__('localized description of item');
3028
-     *        )
3029
-     * );
3030
-     *
3031
-     * @param array $items see above for format of array
3032
-     * @return string html string of legend
3033
-     * @throws DomainException
3034
-     */
3035
-    protected function _display_legend($items)
3036
-    {
3037
-        $this->_template_args['items'] = apply_filters(
3038
-            'FHEE__EE_Admin_Page___display_legend__items',
3039
-            (array) $items,
3040
-            $this
3041
-        );
3042
-        /** @var StatusChangeNotice $status_change_notice */
3043
-        $status_change_notice = $this->loader->getShared(
3044
-            'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3045
-        );
3046
-        $this->_template_args['status_change_notice'] = $status_change_notice->display(
3047
-            '__admin-legend',
3048
-            $this->page_slug
3049
-        );
3050
-        return EEH_Template::display_template(
3051
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3052
-            $this->_template_args,
3053
-            true
3054
-        );
3055
-    }
3056
-
3057
-
3058
-    /**
3059
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3060
-     * The returned json object is created from an array in the following format:
3061
-     * array(
3062
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3063
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3064
-     *  'notices' => '', // - contains any EE_Error formatted notices
3065
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3066
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3067
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3068
-     *  that might be included in here)
3069
-     * )
3070
-     * The json object is populated by whatever is set in the $_template_args property.
3071
-     *
3072
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3073
-     *                                 instead of displayed.
3074
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3075
-     * @return void
3076
-     * @throws EE_Error
3077
-     * @throws InvalidArgumentException
3078
-     * @throws InvalidDataTypeException
3079
-     * @throws InvalidInterfaceException
3080
-     */
3081
-    protected function _return_json($sticky_notices = false, $notices_arguments = [])
3082
-    {
3083
-        // make sure any EE_Error notices have been handled.
3084
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3085
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3086
-        unset($this->_template_args['data']);
3087
-        $json = [
3088
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3089
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3090
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3091
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3092
-            'notices'   => EE_Error::get_notices(),
3093
-            'content'   => isset($this->_template_args['admin_page_content'])
3094
-                ? $this->_template_args['admin_page_content'] : '',
3095
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3096
-            'isEEajax'  => true
3097
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3098
-        ];
3099
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3100
-        if (null === error_get_last() || ! headers_sent()) {
3101
-            header('Content-Type: application/json; charset=UTF-8');
3102
-        }
3103
-        echo wp_json_encode($json);
3104
-        exit();
3105
-    }
3106
-
3107
-
3108
-    /**
3109
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3110
-     *
3111
-     * @return void
3112
-     * @throws EE_Error
3113
-     * @throws InvalidArgumentException
3114
-     * @throws InvalidDataTypeException
3115
-     * @throws InvalidInterfaceException
3116
-     */
3117
-    public function return_json()
3118
-    {
3119
-        if ($this->request->isAjax()) {
3120
-            $this->_return_json();
3121
-        } else {
3122
-            throw new EE_Error(
3123
-                sprintf(
3124
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3125
-                    __FUNCTION__
3126
-                )
3127
-            );
3128
-        }
3129
-    }
3130
-
3131
-
3132
-    /**
3133
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3134
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3135
-     *
3136
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3137
-     */
3138
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3139
-    {
3140
-        $this->_hook_obj = $hook_obj;
3141
-    }
3142
-
3143
-
3144
-    /**
3145
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3146
-     *
3147
-     * @param boolean $about whether to use the special about page wrapper or default.
3148
-     * @return void
3149
-     * @throws DomainException
3150
-     * @throws EE_Error
3151
-     * @throws InvalidArgumentException
3152
-     * @throws InvalidDataTypeException
3153
-     * @throws InvalidInterfaceException
3154
-     */
3155
-    public function admin_page_wrapper($about = false)
3156
-    {
3157
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3158
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3159
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3160
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3161
-
3162
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3163
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3164
-            $this->_template_args['before_admin_page_content'] ?? ''
3165
-        );
3166
-
3167
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3168
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3169
-            $this->_template_args['after_admin_page_content'] ?? ''
3170
-        );
3171
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3172
-
3173
-        if ($this->request->isAjax()) {
3174
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3175
-                // $template_path,
3176
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3177
-                $this->_template_args,
3178
-                true
3179
-            );
3180
-            $this->_return_json();
3181
-        }
3182
-        // load settings page wrapper template
3183
-        $template_path = $about
3184
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3185
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3186
-
3187
-        EEH_Template::display_template($template_path, $this->_template_args);
3188
-    }
3189
-
3190
-
3191
-    /**
3192
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3193
-     *
3194
-     * @return string html
3195
-     * @throws EE_Error
3196
-     */
3197
-    protected function _get_main_nav_tabs()
3198
-    {
3199
-        // let's generate the html using the EEH_Tabbed_Content helper.
3200
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3201
-        // (rather than setting in the page_routes array)
3202
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs, $this->page_slug);
3203
-    }
3204
-
3205
-
3206
-    /**
3207
-     *        sort nav tabs
3208
-     *
3209
-     * @param $a
3210
-     * @param $b
3211
-     * @return int
3212
-     */
3213
-    private function _sort_nav_tabs($a, $b)
3214
-    {
3215
-        if ($a['order'] === $b['order']) {
3216
-            return 0;
3217
-        }
3218
-        return ($a['order'] < $b['order']) ? -1 : 1;
3219
-    }
3220
-
3221
-
3222
-    /**
3223
-     * generates HTML for the forms used on admin pages
3224
-     *
3225
-     * @param array  $input_vars - array of input field details
3226
-     * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3227
-     * @param bool   $id
3228
-     * @return array|string
3229
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3230
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3231
-     */
3232
-    protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3233
-    {
3234
-        return $generator === 'string'
3235
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3236
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3237
-    }
3238
-
3239
-
3240
-    /**
3241
-     * generates the "Save" and "Save & Close" buttons for edit forms
3242
-     *
3243
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3244
-     *                                   Close" button.
3245
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3246
-     *                                   'Save', [1] => 'save & close')
3247
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3248
-     *                                   via the "name" value in the button).  We can also use this to just dump
3249
-     *                                   default actions by submitting some other value.
3250
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3251
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3252
-     *                                   close (normal form handling).
3253
-     */
3254
-    protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3255
-    {
3256
-        // make sure $text and $actions are in an array
3257
-        $text          = (array) $text;
3258
-        $actions       = (array) $actions;
3259
-        $referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3260
-        $button_text   = ! empty($text)
3261
-            ? $text
3262
-            : [
3263
-                esc_html__('Save', 'event_espresso'),
3264
-                esc_html__('Save and Close', 'event_espresso'),
3265
-            ];
3266
-        $default_names = ['save', 'save_and_close'];
3267
-        $buttons = '';
3268
-        foreach ($button_text as $key => $button) {
3269
-            $ref     = $default_names[ $key ];
3270
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3271
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3272
-                        . 'value="' . $button . '" name="' . $name . '" '
3273
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3274
-            if (! $both) {
3275
-                break;
3276
-            }
3277
-        }
3278
-        // add in a hidden index for the current page (so save and close redirects properly)
3279
-        $buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3280
-                   . $referrer_url
3281
-                   . '" />';
3282
-        $this->_template_args['save_buttons'] = $buttons;
3283
-    }
3284
-
3285
-
3286
-    /**
3287
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3288
-     *
3289
-     * @param string $route
3290
-     * @param array  $additional_hidden_fields
3291
-     * @see   $this->_set_add_edit_form_tags() for details on params
3292
-     * @since 4.6.0
3293
-     */
3294
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3295
-    {
3296
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3297
-    }
3298
-
3299
-
3300
-    /**
3301
-     * set form open and close tags on add/edit pages.
3302
-     *
3303
-     * @param string $route                    the route you want the form to direct to
3304
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3305
-     * @return void
3306
-     */
3307
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3308
-    {
3309
-        if (empty($route)) {
3310
-            $user_msg = esc_html__(
3311
-                'An error occurred. No action was set for this page\'s form.',
3312
-                'event_espresso'
3313
-            );
3314
-            $dev_msg  = $user_msg . "\n"
3315
-                        . sprintf(
3316
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3317
-                            __FUNCTION__,
3318
-                            __CLASS__
3319
-                        );
3320
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3321
-        }
3322
-        // open form
3323
-        $action = $this->_admin_base_url;
3324
-        $this->_template_args['before_admin_page_content'] = "
2955
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2956
+		// display message about search results?
2957
+		$search = $this->request->getRequestParam('s');
2958
+		$this->_template_args['before_list_table'] .= ! empty($search)
2959
+			? '<p class="ee-search-results">' . sprintf(
2960
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2961
+				trim($search, '%')
2962
+			) . '</p>'
2963
+			: '';
2964
+		// filter before_list_table template arg
2965
+		$this->_template_args['before_list_table'] = apply_filters(
2966
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2967
+			$this->_template_args['before_list_table'],
2968
+			$this->page_slug,
2969
+			$this->request->requestParams(),
2970
+			$this->_req_action
2971
+		);
2972
+		// convert to array and filter again
2973
+		// arrays are easier to inject new items in a specific location,
2974
+		// but would not be backwards compatible, so we have to add a new filter
2975
+		$this->_template_args['before_list_table'] = implode(
2976
+			" \n",
2977
+			(array) apply_filters(
2978
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2979
+				(array) $this->_template_args['before_list_table'],
2980
+				$this->page_slug,
2981
+				$this->request->requestParams(),
2982
+				$this->_req_action
2983
+			)
2984
+		);
2985
+		// filter after_list_table template arg
2986
+		$this->_template_args['after_list_table'] = apply_filters(
2987
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2988
+			$this->_template_args['after_list_table'],
2989
+			$this->page_slug,
2990
+			$this->request->requestParams(),
2991
+			$this->_req_action
2992
+		);
2993
+		// convert to array and filter again
2994
+		// arrays are easier to inject new items in a specific location,
2995
+		// but would not be backwards compatible, so we have to add a new filter
2996
+		$this->_template_args['after_list_table']   = implode(
2997
+			" \n",
2998
+			(array) apply_filters(
2999
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3000
+				(array) $this->_template_args['after_list_table'],
3001
+				$this->page_slug,
3002
+				$this->request->requestParams(),
3003
+				$this->_req_action
3004
+			)
3005
+		);
3006
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3007
+			$template_path,
3008
+			$this->_template_args,
3009
+			true
3010
+		);
3011
+		// the final template wrapper
3012
+		if ($sidebar) {
3013
+			$this->display_admin_page_with_sidebar();
3014
+		} else {
3015
+			$this->display_admin_page_with_no_sidebar();
3016
+		}
3017
+	}
3018
+
3019
+
3020
+	/**
3021
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3022
+	 * html string for the legend.
3023
+	 * $items are expected in an array in the following format:
3024
+	 * $legend_items = array(
3025
+	 *        'item_id' => array(
3026
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3027
+	 *            'desc' => esc_html__('localized description of item');
3028
+	 *        )
3029
+	 * );
3030
+	 *
3031
+	 * @param array $items see above for format of array
3032
+	 * @return string html string of legend
3033
+	 * @throws DomainException
3034
+	 */
3035
+	protected function _display_legend($items)
3036
+	{
3037
+		$this->_template_args['items'] = apply_filters(
3038
+			'FHEE__EE_Admin_Page___display_legend__items',
3039
+			(array) $items,
3040
+			$this
3041
+		);
3042
+		/** @var StatusChangeNotice $status_change_notice */
3043
+		$status_change_notice = $this->loader->getShared(
3044
+			'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3045
+		);
3046
+		$this->_template_args['status_change_notice'] = $status_change_notice->display(
3047
+			'__admin-legend',
3048
+			$this->page_slug
3049
+		);
3050
+		return EEH_Template::display_template(
3051
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3052
+			$this->_template_args,
3053
+			true
3054
+		);
3055
+	}
3056
+
3057
+
3058
+	/**
3059
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3060
+	 * The returned json object is created from an array in the following format:
3061
+	 * array(
3062
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3063
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3064
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3065
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3066
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3067
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3068
+	 *  that might be included in here)
3069
+	 * )
3070
+	 * The json object is populated by whatever is set in the $_template_args property.
3071
+	 *
3072
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3073
+	 *                                 instead of displayed.
3074
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3075
+	 * @return void
3076
+	 * @throws EE_Error
3077
+	 * @throws InvalidArgumentException
3078
+	 * @throws InvalidDataTypeException
3079
+	 * @throws InvalidInterfaceException
3080
+	 */
3081
+	protected function _return_json($sticky_notices = false, $notices_arguments = [])
3082
+	{
3083
+		// make sure any EE_Error notices have been handled.
3084
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3085
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3086
+		unset($this->_template_args['data']);
3087
+		$json = [
3088
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3089
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3090
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3091
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3092
+			'notices'   => EE_Error::get_notices(),
3093
+			'content'   => isset($this->_template_args['admin_page_content'])
3094
+				? $this->_template_args['admin_page_content'] : '',
3095
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3096
+			'isEEajax'  => true
3097
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3098
+		];
3099
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3100
+		if (null === error_get_last() || ! headers_sent()) {
3101
+			header('Content-Type: application/json; charset=UTF-8');
3102
+		}
3103
+		echo wp_json_encode($json);
3104
+		exit();
3105
+	}
3106
+
3107
+
3108
+	/**
3109
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3110
+	 *
3111
+	 * @return void
3112
+	 * @throws EE_Error
3113
+	 * @throws InvalidArgumentException
3114
+	 * @throws InvalidDataTypeException
3115
+	 * @throws InvalidInterfaceException
3116
+	 */
3117
+	public function return_json()
3118
+	{
3119
+		if ($this->request->isAjax()) {
3120
+			$this->_return_json();
3121
+		} else {
3122
+			throw new EE_Error(
3123
+				sprintf(
3124
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3125
+					__FUNCTION__
3126
+				)
3127
+			);
3128
+		}
3129
+	}
3130
+
3131
+
3132
+	/**
3133
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3134
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3135
+	 *
3136
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3137
+	 */
3138
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3139
+	{
3140
+		$this->_hook_obj = $hook_obj;
3141
+	}
3142
+
3143
+
3144
+	/**
3145
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3146
+	 *
3147
+	 * @param boolean $about whether to use the special about page wrapper or default.
3148
+	 * @return void
3149
+	 * @throws DomainException
3150
+	 * @throws EE_Error
3151
+	 * @throws InvalidArgumentException
3152
+	 * @throws InvalidDataTypeException
3153
+	 * @throws InvalidInterfaceException
3154
+	 */
3155
+	public function admin_page_wrapper($about = false)
3156
+	{
3157
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3158
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3159
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3160
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3161
+
3162
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3163
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3164
+			$this->_template_args['before_admin_page_content'] ?? ''
3165
+		);
3166
+
3167
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3168
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3169
+			$this->_template_args['after_admin_page_content'] ?? ''
3170
+		);
3171
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3172
+
3173
+		if ($this->request->isAjax()) {
3174
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3175
+				// $template_path,
3176
+				EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3177
+				$this->_template_args,
3178
+				true
3179
+			);
3180
+			$this->_return_json();
3181
+		}
3182
+		// load settings page wrapper template
3183
+		$template_path = $about
3184
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3185
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3186
+
3187
+		EEH_Template::display_template($template_path, $this->_template_args);
3188
+	}
3189
+
3190
+
3191
+	/**
3192
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3193
+	 *
3194
+	 * @return string html
3195
+	 * @throws EE_Error
3196
+	 */
3197
+	protected function _get_main_nav_tabs()
3198
+	{
3199
+		// let's generate the html using the EEH_Tabbed_Content helper.
3200
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3201
+		// (rather than setting in the page_routes array)
3202
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs, $this->page_slug);
3203
+	}
3204
+
3205
+
3206
+	/**
3207
+	 *        sort nav tabs
3208
+	 *
3209
+	 * @param $a
3210
+	 * @param $b
3211
+	 * @return int
3212
+	 */
3213
+	private function _sort_nav_tabs($a, $b)
3214
+	{
3215
+		if ($a['order'] === $b['order']) {
3216
+			return 0;
3217
+		}
3218
+		return ($a['order'] < $b['order']) ? -1 : 1;
3219
+	}
3220
+
3221
+
3222
+	/**
3223
+	 * generates HTML for the forms used on admin pages
3224
+	 *
3225
+	 * @param array  $input_vars - array of input field details
3226
+	 * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3227
+	 * @param bool   $id
3228
+	 * @return array|string
3229
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3230
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3231
+	 */
3232
+	protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3233
+	{
3234
+		return $generator === 'string'
3235
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3236
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3237
+	}
3238
+
3239
+
3240
+	/**
3241
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3242
+	 *
3243
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3244
+	 *                                   Close" button.
3245
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3246
+	 *                                   'Save', [1] => 'save & close')
3247
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3248
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3249
+	 *                                   default actions by submitting some other value.
3250
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3251
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3252
+	 *                                   close (normal form handling).
3253
+	 */
3254
+	protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3255
+	{
3256
+		// make sure $text and $actions are in an array
3257
+		$text          = (array) $text;
3258
+		$actions       = (array) $actions;
3259
+		$referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3260
+		$button_text   = ! empty($text)
3261
+			? $text
3262
+			: [
3263
+				esc_html__('Save', 'event_espresso'),
3264
+				esc_html__('Save and Close', 'event_espresso'),
3265
+			];
3266
+		$default_names = ['save', 'save_and_close'];
3267
+		$buttons = '';
3268
+		foreach ($button_text as $key => $button) {
3269
+			$ref     = $default_names[ $key ];
3270
+			$name    = ! empty($actions) ? $actions[ $key ] : $ref;
3271
+			$buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3272
+						. 'value="' . $button . '" name="' . $name . '" '
3273
+						. 'id="' . $this->_current_view . '_' . $ref . '" />';
3274
+			if (! $both) {
3275
+				break;
3276
+			}
3277
+		}
3278
+		// add in a hidden index for the current page (so save and close redirects properly)
3279
+		$buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3280
+				   . $referrer_url
3281
+				   . '" />';
3282
+		$this->_template_args['save_buttons'] = $buttons;
3283
+	}
3284
+
3285
+
3286
+	/**
3287
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3288
+	 *
3289
+	 * @param string $route
3290
+	 * @param array  $additional_hidden_fields
3291
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3292
+	 * @since 4.6.0
3293
+	 */
3294
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3295
+	{
3296
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3297
+	}
3298
+
3299
+
3300
+	/**
3301
+	 * set form open and close tags on add/edit pages.
3302
+	 *
3303
+	 * @param string $route                    the route you want the form to direct to
3304
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3305
+	 * @return void
3306
+	 */
3307
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3308
+	{
3309
+		if (empty($route)) {
3310
+			$user_msg = esc_html__(
3311
+				'An error occurred. No action was set for this page\'s form.',
3312
+				'event_espresso'
3313
+			);
3314
+			$dev_msg  = $user_msg . "\n"
3315
+						. sprintf(
3316
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3317
+							__FUNCTION__,
3318
+							__CLASS__
3319
+						);
3320
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3321
+		}
3322
+		// open form
3323
+		$action = $this->_admin_base_url;
3324
+		$this->_template_args['before_admin_page_content'] = "
3325 3325
             <form name='form' method='post' action='{$action}' id='{$route}_event_form' class='ee-admin-page-form' >
3326 3326
             ";
3327
-        // add nonce
3328
-        $nonce                                             =
3329
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3330
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3331
-        // add REQUIRED form action
3332
-        $hidden_fields = [
3333
-            'action' => ['type' => 'hidden', 'value' => $route],
3334
-        ];
3335
-        // merge arrays
3336
-        $hidden_fields = is_array($additional_hidden_fields)
3337
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3338
-            : $hidden_fields;
3339
-        // generate form fields
3340
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3341
-        // add fields to form
3342
-        foreach ((array) $form_fields as $form_field) {
3343
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3344
-        }
3345
-        // close form
3346
-        $this->_template_args['after_admin_page_content'] = '</form>';
3347
-    }
3348
-
3349
-
3350
-    /**
3351
-     * Public Wrapper for _redirect_after_action() method since its
3352
-     * discovered it would be useful for external code to have access.
3353
-     *
3354
-     * @param bool   $success
3355
-     * @param string $what
3356
-     * @param string $action_desc
3357
-     * @param array  $query_args
3358
-     * @param bool   $override_overwrite
3359
-     * @throws EE_Error
3360
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3361
-     * @since 4.5.0
3362
-     */
3363
-    public function redirect_after_action(
3364
-        $success = false,
3365
-        $what = 'item',
3366
-        $action_desc = 'processed',
3367
-        $query_args = [],
3368
-        $override_overwrite = false
3369
-    ) {
3370
-        $this->_redirect_after_action(
3371
-            $success,
3372
-            $what,
3373
-            $action_desc,
3374
-            $query_args,
3375
-            $override_overwrite
3376
-        );
3377
-    }
3378
-
3379
-
3380
-    /**
3381
-     * Helper method for merging existing request data with the returned redirect url.
3382
-     *
3383
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3384
-     * filters are still applied.
3385
-     *
3386
-     * @param array $new_route_data
3387
-     * @return array
3388
-     */
3389
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3390
-    {
3391
-        foreach ($this->request->requestParams() as $ref => $value) {
3392
-            // unset nonces
3393
-            if (strpos($ref, 'nonce') !== false) {
3394
-                $this->request->unSetRequestParam($ref);
3395
-                continue;
3396
-            }
3397
-            // urlencode values.
3398
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3399
-            $this->request->setRequestParam($ref, $value);
3400
-        }
3401
-        return array_merge($this->request->requestParams(), $new_route_data);
3402
-    }
3403
-
3404
-
3405
-    /**
3406
-     * @param int|float|string $success      - whether success was for two or more records, or just one, or none
3407
-     * @param string           $what         - what the action was performed on
3408
-     * @param string           $action_desc  - what was done ie: updated, deleted, etc
3409
-     * @param array $query_args              - an array of query_args to be added to the URL to redirect to
3410
-     * @param BOOL $override_overwrite       - by default all EE_Error::success messages are overwritten,
3411
-     *                                         this allows you to override this so that they show.
3412
-     * @return void
3413
-     * @throws EE_Error
3414
-     * @throws InvalidArgumentException
3415
-     * @throws InvalidDataTypeException
3416
-     * @throws InvalidInterfaceException
3417
-     */
3418
-    protected function _redirect_after_action(
3419
-        $success = 0,
3420
-        string $what = 'item',
3421
-        string $action_desc = 'processed',
3422
-        array $query_args = [],
3423
-        bool $override_overwrite = false
3424
-    ) {
3425
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3426
-        $notices      = EE_Error::get_notices(false);
3427
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3428
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3429
-            EE_Error::overwrite_success();
3430
-        }
3431
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3432
-            // how many records affected ? more than one record ? or just one ?
3433
-            EE_Error::add_success(
3434
-                sprintf(
3435
-                    esc_html(
3436
-                        _n(
3437
-                            'The "%1$s" has been successfully %2$s.',
3438
-                            'The "%1$s" have been successfully %2$s.',
3439
-                            $success,
3440
-                            'event_espresso'
3441
-                        )
3442
-                    ),
3443
-                    $what,
3444
-                    $action_desc
3445
-                ),
3446
-                __FILE__,
3447
-                __FUNCTION__,
3448
-                __LINE__
3449
-            );
3450
-        }
3451
-        // check that $query_args isn't something crazy
3452
-        if (! is_array($query_args)) {
3453
-            $query_args = [];
3454
-        }
3455
-        /**
3456
-         * Allow injecting actions before the query_args are modified for possible different
3457
-         * redirections on save and close actions
3458
-         *
3459
-         * @param array $query_args       The original query_args array coming into the
3460
-         *                                method.
3461
-         * @since 4.2.0
3462
-         */
3463
-        do_action(
3464
-            "AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3465
-            $query_args
3466
-        );
3467
-        // set redirect url.
3468
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3469
-        // otherwise we go with whatever is set as the _admin_base_url
3470
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3471
-        // calculate where we're going (if we have a "save and close" button pushed)
3472
-        if (
3473
-            $this->request->requestParamIsSet('save_and_close')
3474
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3475
-        ) {
3476
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3477
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3478
-            // regenerate query args array from referrer URL
3479
-            parse_str($parsed_url['query'], $query_args);
3480
-            // correct page and action will be in the query args now
3481
-            $redirect_url = admin_url('admin.php');
3482
-        }
3483
-        // merge any default query_args set in _default_route_query_args property
3484
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3485
-            $args_to_merge = [];
3486
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3487
-                // is there a wp_referer array in our _default_route_query_args property?
3488
-                if ($query_param === 'wp_referer') {
3489
-                    $query_value = (array) $query_value;
3490
-                    foreach ($query_value as $reference => $value) {
3491
-                        if (strpos($reference, 'nonce') !== false) {
3492
-                            continue;
3493
-                        }
3494
-                        // finally we will override any arguments in the referer with
3495
-                        // what might be set on the _default_route_query_args array.
3496
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3497
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3498
-                        } else {
3499
-                            $args_to_merge[ $reference ] = urlencode($value);
3500
-                        }
3501
-                    }
3502
-                    continue;
3503
-                }
3504
-                $args_to_merge[ $query_param ] = $query_value;
3505
-            }
3506
-            // now let's merge these arguments but override with what was specifically sent in to the
3507
-            // redirect.
3508
-            $query_args = array_merge($args_to_merge, $query_args);
3509
-        }
3510
-        $this->_process_notices($query_args);
3511
-        // generate redirect url
3512
-        // if redirecting to anything other than the main page, add a nonce
3513
-        if (isset($query_args['action'])) {
3514
-            // manually generate wp_nonce and merge that with the query vars
3515
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3516
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3517
-        }
3518
-        // we're adding some hooks and filters in here for processing any things just before redirects
3519
-        // (example: an admin page has done an insert or update and we want to run something after that).
3520
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3521
-        $redirect_url = apply_filters(
3522
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3523
-            EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3524
-            $query_args
3525
-        );
3526
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3527
-        if ($this->request->isAjax()) {
3528
-            $default_data                    = [
3529
-                'close'        => true,
3530
-                'redirect_url' => $redirect_url,
3531
-                'where'        => 'main',
3532
-                'what'         => 'append',
3533
-            ];
3534
-            $this->_template_args['success'] = $success;
3535
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3536
-                $default_data,
3537
-                $this->_template_args['data']
3538
-            ) : $default_data;
3539
-            $this->_return_json();
3540
-        }
3541
-        wp_safe_redirect($redirect_url);
3542
-        exit();
3543
-    }
3544
-
3545
-
3546
-    /**
3547
-     * process any notices before redirecting (or returning ajax request)
3548
-     * This method sets the $this->_template_args['notices'] attribute;
3549
-     *
3550
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3551
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3552
-     *                                  page_routes haven't been defined yet.
3553
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3554
-     *                                  still save a transient for the notice.
3555
-     * @return void
3556
-     * @throws EE_Error
3557
-     * @throws InvalidArgumentException
3558
-     * @throws InvalidDataTypeException
3559
-     * @throws InvalidInterfaceException
3560
-     */
3561
-    protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3562
-    {
3563
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3564
-        if ($this->request->isAjax()) {
3565
-            $notices = EE_Error::get_notices(false);
3566
-            if (empty($this->_template_args['success'])) {
3567
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3568
-            }
3569
-            if (empty($this->_template_args['errors'])) {
3570
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3571
-            }
3572
-            if (empty($this->_template_args['attention'])) {
3573
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3574
-            }
3575
-        }
3576
-        $this->_template_args['notices'] = EE_Error::get_notices();
3577
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3578
-        if (! $this->request->isAjax() || $sticky_notices) {
3579
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3580
-            $this->_add_transient(
3581
-                $route,
3582
-                $this->_template_args['notices'],
3583
-                true,
3584
-                $skip_route_verify
3585
-            );
3586
-        }
3587
-    }
3588
-
3589
-
3590
-    /**
3591
-     * get_action_link_or_button
3592
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3593
-     *
3594
-     * @param string $action        use this to indicate which action the url is generated with.
3595
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3596
-     *                              property.
3597
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3598
-     * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3599
-     * @param string $base_url      If this is not provided
3600
-     *                              the _admin_base_url will be used as the default for the button base_url.
3601
-     *                              Otherwise this value will be used.
3602
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3603
-     * @return string
3604
-     * @throws InvalidArgumentException
3605
-     * @throws InvalidInterfaceException
3606
-     * @throws InvalidDataTypeException
3607
-     * @throws EE_Error
3608
-     */
3609
-    public function get_action_link_or_button(
3610
-        $action,
3611
-        $type = 'add',
3612
-        $extra_request = [],
3613
-        $class = 'button button--primary',
3614
-        $base_url = '',
3615
-        $exclude_nonce = false
3616
-    ) {
3617
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3618
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3619
-            throw new EE_Error(
3620
-                sprintf(
3621
-                    esc_html__(
3622
-                        'There is no page route for given action for the button.  This action was given: %s',
3623
-                        'event_espresso'
3624
-                    ),
3625
-                    $action
3626
-                )
3627
-            );
3628
-        }
3629
-        if (! isset($this->_labels['buttons'][ $type ])) {
3630
-            throw new EE_Error(
3631
-                sprintf(
3632
-                    esc_html__(
3633
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3634
-                        'event_espresso'
3635
-                    ),
3636
-                    $type
3637
-                )
3638
-            );
3639
-        }
3640
-        // finally check user access for this button.
3641
-        $has_access = $this->check_user_access($action, true);
3642
-        if (! $has_access) {
3643
-            return '';
3644
-        }
3645
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3646
-        $query_args = [
3647
-            'action' => $action,
3648
-        ];
3649
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3650
-        if (! empty($extra_request)) {
3651
-            $query_args = array_merge($extra_request, $query_args);
3652
-        }
3653
-        $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3654
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3655
-    }
3656
-
3657
-
3658
-    /**
3659
-     * _per_page_screen_option
3660
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3661
-     *
3662
-     * @return void
3663
-     * @throws InvalidArgumentException
3664
-     * @throws InvalidInterfaceException
3665
-     * @throws InvalidDataTypeException
3666
-     */
3667
-    protected function _per_page_screen_option()
3668
-    {
3669
-        $option = 'per_page';
3670
-        $args   = [
3671
-            'label'   => apply_filters(
3672
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3673
-                $this->_admin_page_title,
3674
-                $this
3675
-            ),
3676
-            'default' => (int) apply_filters(
3677
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3678
-                20
3679
-            ),
3680
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3681
-        ];
3682
-        // ONLY add the screen option if the user has access to it.
3683
-        if ($this->check_user_access($this->_current_view, true)) {
3684
-            add_screen_option($option, $args);
3685
-        }
3686
-    }
3687
-
3688
-
3689
-    /**
3690
-     * set_per_page_screen_option
3691
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3692
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3693
-     * admin_menu.
3694
-     *
3695
-     * @return void
3696
-     */
3697
-    private function _set_per_page_screen_options()
3698
-    {
3699
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3700
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3701
-            if (! $user = wp_get_current_user()) {
3702
-                return;
3703
-            }
3704
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3705
-            if (! $option) {
3706
-                return;
3707
-            }
3708
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3709
-            $map_option = $option;
3710
-            $option     = str_replace('-', '_', $option);
3711
-            switch ($map_option) {
3712
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3713
-                    $max_value = apply_filters(
3714
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3715
-                        999,
3716
-                        $this->_current_page,
3717
-                        $this->_current_view
3718
-                    );
3719
-                    if ($value < 1) {
3720
-                        return;
3721
-                    }
3722
-                    $value = min($value, $max_value);
3723
-                    break;
3724
-                default:
3725
-                    $value = apply_filters(
3726
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3727
-                        false,
3728
-                        $option,
3729
-                        $value
3730
-                    );
3731
-                    if (false === $value) {
3732
-                        return;
3733
-                    }
3734
-                    break;
3735
-            }
3736
-            update_user_meta($user->ID, $option, $value);
3737
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3738
-            exit;
3739
-        }
3740
-    }
3741
-
3742
-
3743
-    /**
3744
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3745
-     *
3746
-     * @param array $data array that will be assigned to template args.
3747
-     */
3748
-    public function set_template_args($data)
3749
-    {
3750
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3751
-    }
3752
-
3753
-
3754
-    /**
3755
-     * This makes available the WP transient system for temporarily moving data between routes
3756
-     *
3757
-     * @param string $route             the route that should receive the transient
3758
-     * @param array  $data              the data that gets sent
3759
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3760
-     *                                  normal route transient.
3761
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3762
-     *                                  when we are adding a transient before page_routes have been defined.
3763
-     * @return void
3764
-     * @throws EE_Error
3765
-     */
3766
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3767
-    {
3768
-        $user_id = get_current_user_id();
3769
-        if (! $skip_route_verify) {
3770
-            $this->_verify_route($route);
3771
-        }
3772
-        // now let's set the string for what kind of transient we're setting
3773
-        $transient = $notices
3774
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3775
-            : 'rte_tx_' . $route . '_' . $user_id;
3776
-        $data      = $notices ? ['notices' => $data] : $data;
3777
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3778
-        $existing = is_multisite() && is_network_admin()
3779
-            ? get_site_transient($transient)
3780
-            : get_transient($transient);
3781
-        if ($existing) {
3782
-            $data = array_merge((array) $data, (array) $existing);
3783
-        }
3784
-        if (is_multisite() && is_network_admin()) {
3785
-            set_site_transient($transient, $data, 8);
3786
-        } else {
3787
-            set_transient($transient, $data, 8);
3788
-        }
3789
-    }
3790
-
3791
-
3792
-    /**
3793
-     * this retrieves the temporary transient that has been set for moving data between routes.
3794
-     *
3795
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3796
-     * @param string $route
3797
-     * @return mixed data
3798
-     */
3799
-    protected function _get_transient($notices = false, $route = '')
3800
-    {
3801
-        $user_id   = get_current_user_id();
3802
-        $route     = ! $route ? $this->_req_action : $route;
3803
-        $transient = $notices
3804
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3805
-            : 'rte_tx_' . $route . '_' . $user_id;
3806
-        $data      = is_multisite() && is_network_admin()
3807
-            ? get_site_transient($transient)
3808
-            : get_transient($transient);
3809
-        // delete transient after retrieval (just in case it hasn't expired);
3810
-        if (is_multisite() && is_network_admin()) {
3811
-            delete_site_transient($transient);
3812
-        } else {
3813
-            delete_transient($transient);
3814
-        }
3815
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3816
-    }
3817
-
3818
-
3819
-    /**
3820
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3821
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3822
-     * default route callback on the EE_Admin page you want it run.)
3823
-     *
3824
-     * @return void
3825
-     */
3826
-    protected function _transient_garbage_collection()
3827
-    {
3828
-        global $wpdb;
3829
-        // retrieve all existing transients
3830
-        $query =
3831
-            "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3832
-        if ($results = $wpdb->get_results($query)) {
3833
-            foreach ($results as $result) {
3834
-                $transient = str_replace('_transient_', '', $result->option_name);
3835
-                get_transient($transient);
3836
-                if (is_multisite() && is_network_admin()) {
3837
-                    get_site_transient($transient);
3838
-                }
3839
-            }
3840
-        }
3841
-    }
3842
-
3843
-
3844
-    /**
3845
-     * get_view
3846
-     *
3847
-     * @return string content of _view property
3848
-     */
3849
-    public function get_view()
3850
-    {
3851
-        return $this->_view;
3852
-    }
3853
-
3854
-
3855
-    /**
3856
-     * getter for the protected $_views property
3857
-     *
3858
-     * @return array
3859
-     */
3860
-    public function get_views()
3861
-    {
3862
-        return $this->_views;
3863
-    }
3864
-
3865
-
3866
-    /**
3867
-     * get_current_page
3868
-     *
3869
-     * @return string _current_page property value
3870
-     */
3871
-    public function get_current_page()
3872
-    {
3873
-        return $this->_current_page;
3874
-    }
3875
-
3876
-
3877
-    /**
3878
-     * get_current_view
3879
-     *
3880
-     * @return string _current_view property value
3881
-     */
3882
-    public function get_current_view()
3883
-    {
3884
-        return $this->_current_view;
3885
-    }
3886
-
3887
-
3888
-    /**
3889
-     * get_current_screen
3890
-     *
3891
-     * @return object The current WP_Screen object
3892
-     */
3893
-    public function get_current_screen()
3894
-    {
3895
-        return $this->_current_screen;
3896
-    }
3897
-
3898
-
3899
-    /**
3900
-     * get_current_page_view_url
3901
-     *
3902
-     * @return string This returns the url for the current_page_view.
3903
-     */
3904
-    public function get_current_page_view_url()
3905
-    {
3906
-        return $this->_current_page_view_url;
3907
-    }
3908
-
3909
-
3910
-    /**
3911
-     * just returns the Request
3912
-     *
3913
-     * @return RequestInterface
3914
-     */
3915
-    public function get_request()
3916
-    {
3917
-        return $this->request;
3918
-    }
3919
-
3920
-
3921
-    /**
3922
-     * just returns the _req_data property
3923
-     *
3924
-     * @return array
3925
-     */
3926
-    public function get_request_data()
3927
-    {
3928
-        return $this->request->requestParams();
3929
-    }
3930
-
3931
-
3932
-    /**
3933
-     * returns the _req_data protected property
3934
-     *
3935
-     * @return string
3936
-     */
3937
-    public function get_req_action()
3938
-    {
3939
-        return $this->_req_action;
3940
-    }
3941
-
3942
-
3943
-    /**
3944
-     * @return bool  value of $_is_caf property
3945
-     */
3946
-    public function is_caf()
3947
-    {
3948
-        return $this->_is_caf;
3949
-    }
3950
-
3951
-
3952
-    /**
3953
-     * @return mixed
3954
-     */
3955
-    public function default_espresso_metaboxes()
3956
-    {
3957
-        return $this->_default_espresso_metaboxes;
3958
-    }
3959
-
3960
-
3961
-    /**
3962
-     * @return mixed
3963
-     */
3964
-    public function admin_base_url()
3965
-    {
3966
-        return $this->_admin_base_url;
3967
-    }
3968
-
3969
-
3970
-    /**
3971
-     * @return mixed
3972
-     */
3973
-    public function wp_page_slug()
3974
-    {
3975
-        return $this->_wp_page_slug;
3976
-    }
3977
-
3978
-
3979
-    /**
3980
-     * updates  espresso configuration settings
3981
-     *
3982
-     * @param string                   $tab
3983
-     * @param EE_Config_Base|EE_Config $config
3984
-     * @param string                   $file file where error occurred
3985
-     * @param string                   $func function  where error occurred
3986
-     * @param string                   $line line no where error occurred
3987
-     * @return boolean
3988
-     */
3989
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3990
-    {
3991
-        // remove any options that are NOT going to be saved with the config settings.
3992
-        if (isset($config->core->ee_ueip_optin)) {
3993
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
3994
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3995
-            update_option('ee_ueip_has_notified', true);
3996
-        }
3997
-        // and save it (note we're also doing the network save here)
3998
-        $net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3999
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4000
-        if ($config_saved && $net_saved) {
4001
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4002
-            return true;
4003
-        }
4004
-        EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4005
-        return false;
4006
-    }
4007
-
4008
-
4009
-    /**
4010
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4011
-     *
4012
-     * @return array
4013
-     */
4014
-    public function get_yes_no_values()
4015
-    {
4016
-        return $this->_yes_no_values;
4017
-    }
4018
-
4019
-
4020
-    /**
4021
-     * @return string
4022
-     * @throws ReflectionException
4023
-     * @since $VID:$
4024
-     */
4025
-    protected function _get_dir()
4026
-    {
4027
-        $reflector = new ReflectionClass($this->class_name);
4028
-        return dirname($reflector->getFileName());
4029
-    }
4030
-
4031
-
4032
-    /**
4033
-     * A helper for getting a "next link".
4034
-     *
4035
-     * @param string $url   The url to link to
4036
-     * @param string $class The class to use.
4037
-     * @return string
4038
-     */
4039
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4040
-    {
4041
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4042
-    }
4043
-
4044
-
4045
-    /**
4046
-     * A helper for getting a "previous link".
4047
-     *
4048
-     * @param string $url   The url to link to
4049
-     * @param string $class The class to use.
4050
-     * @return string
4051
-     */
4052
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4053
-    {
4054
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4055
-    }
4056
-
4057
-
4058
-
4059
-
4060
-
4061
-
4062
-
4063
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4064
-
4065
-
4066
-    /**
4067
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4068
-     * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4069
-     * _req_data array.
4070
-     *
4071
-     * @return bool success/fail
4072
-     * @throws EE_Error
4073
-     * @throws InvalidArgumentException
4074
-     * @throws ReflectionException
4075
-     * @throws InvalidDataTypeException
4076
-     * @throws InvalidInterfaceException
4077
-     */
4078
-    protected function _process_resend_registration()
4079
-    {
4080
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4081
-        do_action(
4082
-            'AHEE__EE_Admin_Page___process_resend_registration',
4083
-            $this->_template_args['success'],
4084
-            $this->request->requestParams()
4085
-        );
4086
-        return $this->_template_args['success'];
4087
-    }
4088
-
4089
-
4090
-    /**
4091
-     * This automatically processes any payment message notifications when manual payment has been applied.
4092
-     *
4093
-     * @param EE_Payment $payment
4094
-     * @return bool success/fail
4095
-     */
4096
-    protected function _process_payment_notification(EE_Payment $payment)
4097
-    {
4098
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4099
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4100
-        $this->_template_args['success'] = apply_filters(
4101
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4102
-            false,
4103
-            $payment
4104
-        );
4105
-        return $this->_template_args['success'];
4106
-    }
4107
-
4108
-
4109
-    /**
4110
-     * @param EEM_Base      $entity_model
4111
-     * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4112
-     * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4113
-     * @param string        $delete_column  name of the field that denotes whether entity is trashed
4114
-     * @param callable|null $callback       called after entity is trashed, restored, or deleted
4115
-     * @return int|float
4116
-     * @throws EE_Error
4117
-     */
4118
-    protected function trashRestoreDeleteEntities(
4119
-        EEM_Base $entity_model,
4120
-        string $entity_PK_name,
4121
-        string $action = EE_Admin_List_Table::ACTION_DELETE,
4122
-        string $delete_column = '',
4123
-        callable $callback = null
4124
-    ) {
4125
-        $entity_PK      = $entity_model->get_primary_key_field();
4126
-        $entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4127
-        $entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4128
-        // grab ID if deleting a single entity
4129
-        if ($this->request->requestParamIsSet($entity_PK_name)) {
4130
-            $ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4131
-            return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4132
-        }
4133
-        // or grab checkbox array if bulk deleting
4134
-        $checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4135
-        if (empty($checkboxes)) {
4136
-            return 0;
4137
-        }
4138
-        $success = 0;
4139
-        $IDs     = array_keys($checkboxes);
4140
-        // cycle thru bulk action checkboxes
4141
-        foreach ($IDs as $ID) {
4142
-            // increment $success
4143
-            if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4144
-                $success++;
4145
-            }
4146
-        }
4147
-        $count = (int) count($checkboxes);
4148
-        // if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4149
-        // otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4150
-        return $success === $count ? $count : $success / $count;
4151
-    }
4152
-
4153
-
4154
-    /**
4155
-     * @param EE_Primary_Key_Field_Base $entity_PK
4156
-     * @return string
4157
-     * @throws EE_Error
4158
-     * @since   4.10.30.p
4159
-     */
4160
-    private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4161
-    {
4162
-        $entity_PK_type = $entity_PK->getSchemaType();
4163
-        switch ($entity_PK_type) {
4164
-            case 'boolean':
4165
-                return 'bool';
4166
-            case 'integer':
4167
-                return 'int';
4168
-            case 'number':
4169
-                return 'float';
4170
-            case 'string':
4171
-                return 'string';
4172
-        }
4173
-        throw new RuntimeException(
4174
-            sprintf(
4175
-                esc_html__(
4176
-                    '"%1$s" is an invalid schema type for the %2$s primary key.',
4177
-                    'event_espresso'
4178
-                ),
4179
-                $entity_PK_type,
4180
-                $entity_PK->get_name()
4181
-            )
4182
-        );
4183
-    }
4184
-
4185
-
4186
-    /**
4187
-     * @param EEM_Base      $entity_model
4188
-     * @param int|string    $entity_ID
4189
-     * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4190
-     * @param string        $delete_column name of the field that denotes whether entity is trashed
4191
-     * @param callable|null $callback      called after entity is trashed, restored, or deleted
4192
-     * @return bool
4193
-     */
4194
-    protected function trashRestoreDeleteEntity(
4195
-        EEM_Base $entity_model,
4196
-        $entity_ID,
4197
-        string $action,
4198
-        string $delete_column,
4199
-        ?callable $callback = null
4200
-    ): bool {
4201
-        $entity_ID = absint($entity_ID);
4202
-        if (! $entity_ID) {
4203
-            $this->trashRestoreDeleteError($action, $entity_model);
4204
-        }
4205
-        $result = 0;
4206
-        try {
4207
-            switch ($action) {
4208
-                case EE_Admin_List_Table::ACTION_DELETE:
4209
-                    $result = (bool) $entity_model->delete_permanently_by_ID($entity_ID);
4210
-                    break;
4211
-                case EE_Admin_List_Table::ACTION_RESTORE:
4212
-                    $this->validateDeleteColumn($entity_model, $delete_column);
4213
-                    $result = $entity_model->update_by_ID([$delete_column => 0], $entity_ID);
4214
-                    break;
4215
-                case EE_Admin_List_Table::ACTION_TRASH:
4216
-                    $this->validateDeleteColumn($entity_model, $delete_column);
4217
-                    $result = $entity_model->update_by_ID([$delete_column => 1], $entity_ID);
4218
-                    break;
4219
-            }
4220
-        } catch (Exception $exception) {
4221
-            $this->trashRestoreDeleteError($action, $entity_model, $exception);
4222
-        }
4223
-        if (is_callable($callback)) {
4224
-            call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4225
-        }
4226
-        return $result;
4227
-    }
4228
-
4229
-
4230
-    /**
4231
-     * @param EEM_Base $entity_model
4232
-     * @param string   $delete_column
4233
-     * @since 4.10.30.p
4234
-     */
4235
-    private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4236
-    {
4237
-        if (empty($delete_column)) {
4238
-            throw new DomainException(
4239
-                sprintf(
4240
-                    esc_html__(
4241
-                        'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4242
-                        'event_espresso'
4243
-                    ),
4244
-                    $entity_model->get_this_model_name()
4245
-                )
4246
-            );
4247
-        }
4248
-        if (! $entity_model->has_field($delete_column)) {
4249
-            throw new DomainException(
4250
-                sprintf(
4251
-                    esc_html__(
4252
-                        'The %1$s field does not exist on the %2$s model.',
4253
-                        'event_espresso'
4254
-                    ),
4255
-                    $delete_column,
4256
-                    $entity_model->get_this_model_name()
4257
-                )
4258
-            );
4259
-        }
4260
-    }
4261
-
4262
-
4263
-    /**
4264
-     * @param EEM_Base       $entity_model
4265
-     * @param Exception|null $exception
4266
-     * @param string         $action
4267
-     * @since 4.10.30.p
4268
-     */
4269
-    private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, ?Exception $exception = null)
4270
-    {
4271
-        if ($exception instanceof Exception) {
4272
-            throw new RuntimeException(
4273
-                sprintf(
4274
-                    esc_html__(
4275
-                        'Could not %1$s the %2$s because the following error occurred: %3$s',
4276
-                        'event_espresso'
4277
-                    ),
4278
-                    $action,
4279
-                    $entity_model->get_this_model_name(),
4280
-                    $exception->getMessage()
4281
-                )
4282
-            );
4283
-        }
4284
-        throw new RuntimeException(
4285
-            sprintf(
4286
-                esc_html__(
4287
-                    'Could not %1$s the %2$s because an invalid ID was received.',
4288
-                    'event_espresso'
4289
-                ),
4290
-                $action,
4291
-                $entity_model->get_this_model_name()
4292
-            )
4293
-        );
4294
-    }
3327
+		// add nonce
3328
+		$nonce                                             =
3329
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3330
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3331
+		// add REQUIRED form action
3332
+		$hidden_fields = [
3333
+			'action' => ['type' => 'hidden', 'value' => $route],
3334
+		];
3335
+		// merge arrays
3336
+		$hidden_fields = is_array($additional_hidden_fields)
3337
+			? array_merge($hidden_fields, $additional_hidden_fields)
3338
+			: $hidden_fields;
3339
+		// generate form fields
3340
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3341
+		// add fields to form
3342
+		foreach ((array) $form_fields as $form_field) {
3343
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3344
+		}
3345
+		// close form
3346
+		$this->_template_args['after_admin_page_content'] = '</form>';
3347
+	}
3348
+
3349
+
3350
+	/**
3351
+	 * Public Wrapper for _redirect_after_action() method since its
3352
+	 * discovered it would be useful for external code to have access.
3353
+	 *
3354
+	 * @param bool   $success
3355
+	 * @param string $what
3356
+	 * @param string $action_desc
3357
+	 * @param array  $query_args
3358
+	 * @param bool   $override_overwrite
3359
+	 * @throws EE_Error
3360
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3361
+	 * @since 4.5.0
3362
+	 */
3363
+	public function redirect_after_action(
3364
+		$success = false,
3365
+		$what = 'item',
3366
+		$action_desc = 'processed',
3367
+		$query_args = [],
3368
+		$override_overwrite = false
3369
+	) {
3370
+		$this->_redirect_after_action(
3371
+			$success,
3372
+			$what,
3373
+			$action_desc,
3374
+			$query_args,
3375
+			$override_overwrite
3376
+		);
3377
+	}
3378
+
3379
+
3380
+	/**
3381
+	 * Helper method for merging existing request data with the returned redirect url.
3382
+	 *
3383
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3384
+	 * filters are still applied.
3385
+	 *
3386
+	 * @param array $new_route_data
3387
+	 * @return array
3388
+	 */
3389
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3390
+	{
3391
+		foreach ($this->request->requestParams() as $ref => $value) {
3392
+			// unset nonces
3393
+			if (strpos($ref, 'nonce') !== false) {
3394
+				$this->request->unSetRequestParam($ref);
3395
+				continue;
3396
+			}
3397
+			// urlencode values.
3398
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3399
+			$this->request->setRequestParam($ref, $value);
3400
+		}
3401
+		return array_merge($this->request->requestParams(), $new_route_data);
3402
+	}
3403
+
3404
+
3405
+	/**
3406
+	 * @param int|float|string $success      - whether success was for two or more records, or just one, or none
3407
+	 * @param string           $what         - what the action was performed on
3408
+	 * @param string           $action_desc  - what was done ie: updated, deleted, etc
3409
+	 * @param array $query_args              - an array of query_args to be added to the URL to redirect to
3410
+	 * @param BOOL $override_overwrite       - by default all EE_Error::success messages are overwritten,
3411
+	 *                                         this allows you to override this so that they show.
3412
+	 * @return void
3413
+	 * @throws EE_Error
3414
+	 * @throws InvalidArgumentException
3415
+	 * @throws InvalidDataTypeException
3416
+	 * @throws InvalidInterfaceException
3417
+	 */
3418
+	protected function _redirect_after_action(
3419
+		$success = 0,
3420
+		string $what = 'item',
3421
+		string $action_desc = 'processed',
3422
+		array $query_args = [],
3423
+		bool $override_overwrite = false
3424
+	) {
3425
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3426
+		$notices      = EE_Error::get_notices(false);
3427
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3428
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3429
+			EE_Error::overwrite_success();
3430
+		}
3431
+		if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3432
+			// how many records affected ? more than one record ? or just one ?
3433
+			EE_Error::add_success(
3434
+				sprintf(
3435
+					esc_html(
3436
+						_n(
3437
+							'The "%1$s" has been successfully %2$s.',
3438
+							'The "%1$s" have been successfully %2$s.',
3439
+							$success,
3440
+							'event_espresso'
3441
+						)
3442
+					),
3443
+					$what,
3444
+					$action_desc
3445
+				),
3446
+				__FILE__,
3447
+				__FUNCTION__,
3448
+				__LINE__
3449
+			);
3450
+		}
3451
+		// check that $query_args isn't something crazy
3452
+		if (! is_array($query_args)) {
3453
+			$query_args = [];
3454
+		}
3455
+		/**
3456
+		 * Allow injecting actions before the query_args are modified for possible different
3457
+		 * redirections on save and close actions
3458
+		 *
3459
+		 * @param array $query_args       The original query_args array coming into the
3460
+		 *                                method.
3461
+		 * @since 4.2.0
3462
+		 */
3463
+		do_action(
3464
+			"AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3465
+			$query_args
3466
+		);
3467
+		// set redirect url.
3468
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3469
+		// otherwise we go with whatever is set as the _admin_base_url
3470
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3471
+		// calculate where we're going (if we have a "save and close" button pushed)
3472
+		if (
3473
+			$this->request->requestParamIsSet('save_and_close')
3474
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3475
+		) {
3476
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3477
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3478
+			// regenerate query args array from referrer URL
3479
+			parse_str($parsed_url['query'], $query_args);
3480
+			// correct page and action will be in the query args now
3481
+			$redirect_url = admin_url('admin.php');
3482
+		}
3483
+		// merge any default query_args set in _default_route_query_args property
3484
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3485
+			$args_to_merge = [];
3486
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3487
+				// is there a wp_referer array in our _default_route_query_args property?
3488
+				if ($query_param === 'wp_referer') {
3489
+					$query_value = (array) $query_value;
3490
+					foreach ($query_value as $reference => $value) {
3491
+						if (strpos($reference, 'nonce') !== false) {
3492
+							continue;
3493
+						}
3494
+						// finally we will override any arguments in the referer with
3495
+						// what might be set on the _default_route_query_args array.
3496
+						if (isset($this->_default_route_query_args[ $reference ])) {
3497
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3498
+						} else {
3499
+							$args_to_merge[ $reference ] = urlencode($value);
3500
+						}
3501
+					}
3502
+					continue;
3503
+				}
3504
+				$args_to_merge[ $query_param ] = $query_value;
3505
+			}
3506
+			// now let's merge these arguments but override with what was specifically sent in to the
3507
+			// redirect.
3508
+			$query_args = array_merge($args_to_merge, $query_args);
3509
+		}
3510
+		$this->_process_notices($query_args);
3511
+		// generate redirect url
3512
+		// if redirecting to anything other than the main page, add a nonce
3513
+		if (isset($query_args['action'])) {
3514
+			// manually generate wp_nonce and merge that with the query vars
3515
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3516
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3517
+		}
3518
+		// we're adding some hooks and filters in here for processing any things just before redirects
3519
+		// (example: an admin page has done an insert or update and we want to run something after that).
3520
+		do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3521
+		$redirect_url = apply_filters(
3522
+			'FHEE_redirect_' . $this->class_name . $this->_req_action,
3523
+			EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3524
+			$query_args
3525
+		);
3526
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3527
+		if ($this->request->isAjax()) {
3528
+			$default_data                    = [
3529
+				'close'        => true,
3530
+				'redirect_url' => $redirect_url,
3531
+				'where'        => 'main',
3532
+				'what'         => 'append',
3533
+			];
3534
+			$this->_template_args['success'] = $success;
3535
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3536
+				$default_data,
3537
+				$this->_template_args['data']
3538
+			) : $default_data;
3539
+			$this->_return_json();
3540
+		}
3541
+		wp_safe_redirect($redirect_url);
3542
+		exit();
3543
+	}
3544
+
3545
+
3546
+	/**
3547
+	 * process any notices before redirecting (or returning ajax request)
3548
+	 * This method sets the $this->_template_args['notices'] attribute;
3549
+	 *
3550
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3551
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3552
+	 *                                  page_routes haven't been defined yet.
3553
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3554
+	 *                                  still save a transient for the notice.
3555
+	 * @return void
3556
+	 * @throws EE_Error
3557
+	 * @throws InvalidArgumentException
3558
+	 * @throws InvalidDataTypeException
3559
+	 * @throws InvalidInterfaceException
3560
+	 */
3561
+	protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3562
+	{
3563
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3564
+		if ($this->request->isAjax()) {
3565
+			$notices = EE_Error::get_notices(false);
3566
+			if (empty($this->_template_args['success'])) {
3567
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3568
+			}
3569
+			if (empty($this->_template_args['errors'])) {
3570
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3571
+			}
3572
+			if (empty($this->_template_args['attention'])) {
3573
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3574
+			}
3575
+		}
3576
+		$this->_template_args['notices'] = EE_Error::get_notices();
3577
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3578
+		if (! $this->request->isAjax() || $sticky_notices) {
3579
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3580
+			$this->_add_transient(
3581
+				$route,
3582
+				$this->_template_args['notices'],
3583
+				true,
3584
+				$skip_route_verify
3585
+			);
3586
+		}
3587
+	}
3588
+
3589
+
3590
+	/**
3591
+	 * get_action_link_or_button
3592
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3593
+	 *
3594
+	 * @param string $action        use this to indicate which action the url is generated with.
3595
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3596
+	 *                              property.
3597
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3598
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3599
+	 * @param string $base_url      If this is not provided
3600
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3601
+	 *                              Otherwise this value will be used.
3602
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3603
+	 * @return string
3604
+	 * @throws InvalidArgumentException
3605
+	 * @throws InvalidInterfaceException
3606
+	 * @throws InvalidDataTypeException
3607
+	 * @throws EE_Error
3608
+	 */
3609
+	public function get_action_link_or_button(
3610
+		$action,
3611
+		$type = 'add',
3612
+		$extra_request = [],
3613
+		$class = 'button button--primary',
3614
+		$base_url = '',
3615
+		$exclude_nonce = false
3616
+	) {
3617
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3618
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3619
+			throw new EE_Error(
3620
+				sprintf(
3621
+					esc_html__(
3622
+						'There is no page route for given action for the button.  This action was given: %s',
3623
+						'event_espresso'
3624
+					),
3625
+					$action
3626
+				)
3627
+			);
3628
+		}
3629
+		if (! isset($this->_labels['buttons'][ $type ])) {
3630
+			throw new EE_Error(
3631
+				sprintf(
3632
+					esc_html__(
3633
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3634
+						'event_espresso'
3635
+					),
3636
+					$type
3637
+				)
3638
+			);
3639
+		}
3640
+		// finally check user access for this button.
3641
+		$has_access = $this->check_user_access($action, true);
3642
+		if (! $has_access) {
3643
+			return '';
3644
+		}
3645
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3646
+		$query_args = [
3647
+			'action' => $action,
3648
+		];
3649
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3650
+		if (! empty($extra_request)) {
3651
+			$query_args = array_merge($extra_request, $query_args);
3652
+		}
3653
+		$url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3654
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3655
+	}
3656
+
3657
+
3658
+	/**
3659
+	 * _per_page_screen_option
3660
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3661
+	 *
3662
+	 * @return void
3663
+	 * @throws InvalidArgumentException
3664
+	 * @throws InvalidInterfaceException
3665
+	 * @throws InvalidDataTypeException
3666
+	 */
3667
+	protected function _per_page_screen_option()
3668
+	{
3669
+		$option = 'per_page';
3670
+		$args   = [
3671
+			'label'   => apply_filters(
3672
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3673
+				$this->_admin_page_title,
3674
+				$this
3675
+			),
3676
+			'default' => (int) apply_filters(
3677
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3678
+				20
3679
+			),
3680
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3681
+		];
3682
+		// ONLY add the screen option if the user has access to it.
3683
+		if ($this->check_user_access($this->_current_view, true)) {
3684
+			add_screen_option($option, $args);
3685
+		}
3686
+	}
3687
+
3688
+
3689
+	/**
3690
+	 * set_per_page_screen_option
3691
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3692
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3693
+	 * admin_menu.
3694
+	 *
3695
+	 * @return void
3696
+	 */
3697
+	private function _set_per_page_screen_options()
3698
+	{
3699
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3700
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3701
+			if (! $user = wp_get_current_user()) {
3702
+				return;
3703
+			}
3704
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3705
+			if (! $option) {
3706
+				return;
3707
+			}
3708
+			$value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3709
+			$map_option = $option;
3710
+			$option     = str_replace('-', '_', $option);
3711
+			switch ($map_option) {
3712
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3713
+					$max_value = apply_filters(
3714
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3715
+						999,
3716
+						$this->_current_page,
3717
+						$this->_current_view
3718
+					);
3719
+					if ($value < 1) {
3720
+						return;
3721
+					}
3722
+					$value = min($value, $max_value);
3723
+					break;
3724
+				default:
3725
+					$value = apply_filters(
3726
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3727
+						false,
3728
+						$option,
3729
+						$value
3730
+					);
3731
+					if (false === $value) {
3732
+						return;
3733
+					}
3734
+					break;
3735
+			}
3736
+			update_user_meta($user->ID, $option, $value);
3737
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3738
+			exit;
3739
+		}
3740
+	}
3741
+
3742
+
3743
+	/**
3744
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3745
+	 *
3746
+	 * @param array $data array that will be assigned to template args.
3747
+	 */
3748
+	public function set_template_args($data)
3749
+	{
3750
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3751
+	}
3752
+
3753
+
3754
+	/**
3755
+	 * This makes available the WP transient system for temporarily moving data between routes
3756
+	 *
3757
+	 * @param string $route             the route that should receive the transient
3758
+	 * @param array  $data              the data that gets sent
3759
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3760
+	 *                                  normal route transient.
3761
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3762
+	 *                                  when we are adding a transient before page_routes have been defined.
3763
+	 * @return void
3764
+	 * @throws EE_Error
3765
+	 */
3766
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3767
+	{
3768
+		$user_id = get_current_user_id();
3769
+		if (! $skip_route_verify) {
3770
+			$this->_verify_route($route);
3771
+		}
3772
+		// now let's set the string for what kind of transient we're setting
3773
+		$transient = $notices
3774
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3775
+			: 'rte_tx_' . $route . '_' . $user_id;
3776
+		$data      = $notices ? ['notices' => $data] : $data;
3777
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3778
+		$existing = is_multisite() && is_network_admin()
3779
+			? get_site_transient($transient)
3780
+			: get_transient($transient);
3781
+		if ($existing) {
3782
+			$data = array_merge((array) $data, (array) $existing);
3783
+		}
3784
+		if (is_multisite() && is_network_admin()) {
3785
+			set_site_transient($transient, $data, 8);
3786
+		} else {
3787
+			set_transient($transient, $data, 8);
3788
+		}
3789
+	}
3790
+
3791
+
3792
+	/**
3793
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3794
+	 *
3795
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3796
+	 * @param string $route
3797
+	 * @return mixed data
3798
+	 */
3799
+	protected function _get_transient($notices = false, $route = '')
3800
+	{
3801
+		$user_id   = get_current_user_id();
3802
+		$route     = ! $route ? $this->_req_action : $route;
3803
+		$transient = $notices
3804
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3805
+			: 'rte_tx_' . $route . '_' . $user_id;
3806
+		$data      = is_multisite() && is_network_admin()
3807
+			? get_site_transient($transient)
3808
+			: get_transient($transient);
3809
+		// delete transient after retrieval (just in case it hasn't expired);
3810
+		if (is_multisite() && is_network_admin()) {
3811
+			delete_site_transient($transient);
3812
+		} else {
3813
+			delete_transient($transient);
3814
+		}
3815
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3816
+	}
3817
+
3818
+
3819
+	/**
3820
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3821
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3822
+	 * default route callback on the EE_Admin page you want it run.)
3823
+	 *
3824
+	 * @return void
3825
+	 */
3826
+	protected function _transient_garbage_collection()
3827
+	{
3828
+		global $wpdb;
3829
+		// retrieve all existing transients
3830
+		$query =
3831
+			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3832
+		if ($results = $wpdb->get_results($query)) {
3833
+			foreach ($results as $result) {
3834
+				$transient = str_replace('_transient_', '', $result->option_name);
3835
+				get_transient($transient);
3836
+				if (is_multisite() && is_network_admin()) {
3837
+					get_site_transient($transient);
3838
+				}
3839
+			}
3840
+		}
3841
+	}
3842
+
3843
+
3844
+	/**
3845
+	 * get_view
3846
+	 *
3847
+	 * @return string content of _view property
3848
+	 */
3849
+	public function get_view()
3850
+	{
3851
+		return $this->_view;
3852
+	}
3853
+
3854
+
3855
+	/**
3856
+	 * getter for the protected $_views property
3857
+	 *
3858
+	 * @return array
3859
+	 */
3860
+	public function get_views()
3861
+	{
3862
+		return $this->_views;
3863
+	}
3864
+
3865
+
3866
+	/**
3867
+	 * get_current_page
3868
+	 *
3869
+	 * @return string _current_page property value
3870
+	 */
3871
+	public function get_current_page()
3872
+	{
3873
+		return $this->_current_page;
3874
+	}
3875
+
3876
+
3877
+	/**
3878
+	 * get_current_view
3879
+	 *
3880
+	 * @return string _current_view property value
3881
+	 */
3882
+	public function get_current_view()
3883
+	{
3884
+		return $this->_current_view;
3885
+	}
3886
+
3887
+
3888
+	/**
3889
+	 * get_current_screen
3890
+	 *
3891
+	 * @return object The current WP_Screen object
3892
+	 */
3893
+	public function get_current_screen()
3894
+	{
3895
+		return $this->_current_screen;
3896
+	}
3897
+
3898
+
3899
+	/**
3900
+	 * get_current_page_view_url
3901
+	 *
3902
+	 * @return string This returns the url for the current_page_view.
3903
+	 */
3904
+	public function get_current_page_view_url()
3905
+	{
3906
+		return $this->_current_page_view_url;
3907
+	}
3908
+
3909
+
3910
+	/**
3911
+	 * just returns the Request
3912
+	 *
3913
+	 * @return RequestInterface
3914
+	 */
3915
+	public function get_request()
3916
+	{
3917
+		return $this->request;
3918
+	}
3919
+
3920
+
3921
+	/**
3922
+	 * just returns the _req_data property
3923
+	 *
3924
+	 * @return array
3925
+	 */
3926
+	public function get_request_data()
3927
+	{
3928
+		return $this->request->requestParams();
3929
+	}
3930
+
3931
+
3932
+	/**
3933
+	 * returns the _req_data protected property
3934
+	 *
3935
+	 * @return string
3936
+	 */
3937
+	public function get_req_action()
3938
+	{
3939
+		return $this->_req_action;
3940
+	}
3941
+
3942
+
3943
+	/**
3944
+	 * @return bool  value of $_is_caf property
3945
+	 */
3946
+	public function is_caf()
3947
+	{
3948
+		return $this->_is_caf;
3949
+	}
3950
+
3951
+
3952
+	/**
3953
+	 * @return mixed
3954
+	 */
3955
+	public function default_espresso_metaboxes()
3956
+	{
3957
+		return $this->_default_espresso_metaboxes;
3958
+	}
3959
+
3960
+
3961
+	/**
3962
+	 * @return mixed
3963
+	 */
3964
+	public function admin_base_url()
3965
+	{
3966
+		return $this->_admin_base_url;
3967
+	}
3968
+
3969
+
3970
+	/**
3971
+	 * @return mixed
3972
+	 */
3973
+	public function wp_page_slug()
3974
+	{
3975
+		return $this->_wp_page_slug;
3976
+	}
3977
+
3978
+
3979
+	/**
3980
+	 * updates  espresso configuration settings
3981
+	 *
3982
+	 * @param string                   $tab
3983
+	 * @param EE_Config_Base|EE_Config $config
3984
+	 * @param string                   $file file where error occurred
3985
+	 * @param string                   $func function  where error occurred
3986
+	 * @param string                   $line line no where error occurred
3987
+	 * @return boolean
3988
+	 */
3989
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3990
+	{
3991
+		// remove any options that are NOT going to be saved with the config settings.
3992
+		if (isset($config->core->ee_ueip_optin)) {
3993
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
3994
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3995
+			update_option('ee_ueip_has_notified', true);
3996
+		}
3997
+		// and save it (note we're also doing the network save here)
3998
+		$net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3999
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4000
+		if ($config_saved && $net_saved) {
4001
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4002
+			return true;
4003
+		}
4004
+		EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4005
+		return false;
4006
+	}
4007
+
4008
+
4009
+	/**
4010
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4011
+	 *
4012
+	 * @return array
4013
+	 */
4014
+	public function get_yes_no_values()
4015
+	{
4016
+		return $this->_yes_no_values;
4017
+	}
4018
+
4019
+
4020
+	/**
4021
+	 * @return string
4022
+	 * @throws ReflectionException
4023
+	 * @since $VID:$
4024
+	 */
4025
+	protected function _get_dir()
4026
+	{
4027
+		$reflector = new ReflectionClass($this->class_name);
4028
+		return dirname($reflector->getFileName());
4029
+	}
4030
+
4031
+
4032
+	/**
4033
+	 * A helper for getting a "next link".
4034
+	 *
4035
+	 * @param string $url   The url to link to
4036
+	 * @param string $class The class to use.
4037
+	 * @return string
4038
+	 */
4039
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4040
+	{
4041
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4042
+	}
4043
+
4044
+
4045
+	/**
4046
+	 * A helper for getting a "previous link".
4047
+	 *
4048
+	 * @param string $url   The url to link to
4049
+	 * @param string $class The class to use.
4050
+	 * @return string
4051
+	 */
4052
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4053
+	{
4054
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4055
+	}
4056
+
4057
+
4058
+
4059
+
4060
+
4061
+
4062
+
4063
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4064
+
4065
+
4066
+	/**
4067
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4068
+	 * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4069
+	 * _req_data array.
4070
+	 *
4071
+	 * @return bool success/fail
4072
+	 * @throws EE_Error
4073
+	 * @throws InvalidArgumentException
4074
+	 * @throws ReflectionException
4075
+	 * @throws InvalidDataTypeException
4076
+	 * @throws InvalidInterfaceException
4077
+	 */
4078
+	protected function _process_resend_registration()
4079
+	{
4080
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4081
+		do_action(
4082
+			'AHEE__EE_Admin_Page___process_resend_registration',
4083
+			$this->_template_args['success'],
4084
+			$this->request->requestParams()
4085
+		);
4086
+		return $this->_template_args['success'];
4087
+	}
4088
+
4089
+
4090
+	/**
4091
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4092
+	 *
4093
+	 * @param EE_Payment $payment
4094
+	 * @return bool success/fail
4095
+	 */
4096
+	protected function _process_payment_notification(EE_Payment $payment)
4097
+	{
4098
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4099
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4100
+		$this->_template_args['success'] = apply_filters(
4101
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4102
+			false,
4103
+			$payment
4104
+		);
4105
+		return $this->_template_args['success'];
4106
+	}
4107
+
4108
+
4109
+	/**
4110
+	 * @param EEM_Base      $entity_model
4111
+	 * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4112
+	 * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4113
+	 * @param string        $delete_column  name of the field that denotes whether entity is trashed
4114
+	 * @param callable|null $callback       called after entity is trashed, restored, or deleted
4115
+	 * @return int|float
4116
+	 * @throws EE_Error
4117
+	 */
4118
+	protected function trashRestoreDeleteEntities(
4119
+		EEM_Base $entity_model,
4120
+		string $entity_PK_name,
4121
+		string $action = EE_Admin_List_Table::ACTION_DELETE,
4122
+		string $delete_column = '',
4123
+		callable $callback = null
4124
+	) {
4125
+		$entity_PK      = $entity_model->get_primary_key_field();
4126
+		$entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4127
+		$entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4128
+		// grab ID if deleting a single entity
4129
+		if ($this->request->requestParamIsSet($entity_PK_name)) {
4130
+			$ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4131
+			return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4132
+		}
4133
+		// or grab checkbox array if bulk deleting
4134
+		$checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4135
+		if (empty($checkboxes)) {
4136
+			return 0;
4137
+		}
4138
+		$success = 0;
4139
+		$IDs     = array_keys($checkboxes);
4140
+		// cycle thru bulk action checkboxes
4141
+		foreach ($IDs as $ID) {
4142
+			// increment $success
4143
+			if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4144
+				$success++;
4145
+			}
4146
+		}
4147
+		$count = (int) count($checkboxes);
4148
+		// if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4149
+		// otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4150
+		return $success === $count ? $count : $success / $count;
4151
+	}
4152
+
4153
+
4154
+	/**
4155
+	 * @param EE_Primary_Key_Field_Base $entity_PK
4156
+	 * @return string
4157
+	 * @throws EE_Error
4158
+	 * @since   4.10.30.p
4159
+	 */
4160
+	private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4161
+	{
4162
+		$entity_PK_type = $entity_PK->getSchemaType();
4163
+		switch ($entity_PK_type) {
4164
+			case 'boolean':
4165
+				return 'bool';
4166
+			case 'integer':
4167
+				return 'int';
4168
+			case 'number':
4169
+				return 'float';
4170
+			case 'string':
4171
+				return 'string';
4172
+		}
4173
+		throw new RuntimeException(
4174
+			sprintf(
4175
+				esc_html__(
4176
+					'"%1$s" is an invalid schema type for the %2$s primary key.',
4177
+					'event_espresso'
4178
+				),
4179
+				$entity_PK_type,
4180
+				$entity_PK->get_name()
4181
+			)
4182
+		);
4183
+	}
4184
+
4185
+
4186
+	/**
4187
+	 * @param EEM_Base      $entity_model
4188
+	 * @param int|string    $entity_ID
4189
+	 * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4190
+	 * @param string        $delete_column name of the field that denotes whether entity is trashed
4191
+	 * @param callable|null $callback      called after entity is trashed, restored, or deleted
4192
+	 * @return bool
4193
+	 */
4194
+	protected function trashRestoreDeleteEntity(
4195
+		EEM_Base $entity_model,
4196
+		$entity_ID,
4197
+		string $action,
4198
+		string $delete_column,
4199
+		?callable $callback = null
4200
+	): bool {
4201
+		$entity_ID = absint($entity_ID);
4202
+		if (! $entity_ID) {
4203
+			$this->trashRestoreDeleteError($action, $entity_model);
4204
+		}
4205
+		$result = 0;
4206
+		try {
4207
+			switch ($action) {
4208
+				case EE_Admin_List_Table::ACTION_DELETE:
4209
+					$result = (bool) $entity_model->delete_permanently_by_ID($entity_ID);
4210
+					break;
4211
+				case EE_Admin_List_Table::ACTION_RESTORE:
4212
+					$this->validateDeleteColumn($entity_model, $delete_column);
4213
+					$result = $entity_model->update_by_ID([$delete_column => 0], $entity_ID);
4214
+					break;
4215
+				case EE_Admin_List_Table::ACTION_TRASH:
4216
+					$this->validateDeleteColumn($entity_model, $delete_column);
4217
+					$result = $entity_model->update_by_ID([$delete_column => 1], $entity_ID);
4218
+					break;
4219
+			}
4220
+		} catch (Exception $exception) {
4221
+			$this->trashRestoreDeleteError($action, $entity_model, $exception);
4222
+		}
4223
+		if (is_callable($callback)) {
4224
+			call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4225
+		}
4226
+		return $result;
4227
+	}
4228
+
4229
+
4230
+	/**
4231
+	 * @param EEM_Base $entity_model
4232
+	 * @param string   $delete_column
4233
+	 * @since 4.10.30.p
4234
+	 */
4235
+	private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4236
+	{
4237
+		if (empty($delete_column)) {
4238
+			throw new DomainException(
4239
+				sprintf(
4240
+					esc_html__(
4241
+						'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4242
+						'event_espresso'
4243
+					),
4244
+					$entity_model->get_this_model_name()
4245
+				)
4246
+			);
4247
+		}
4248
+		if (! $entity_model->has_field($delete_column)) {
4249
+			throw new DomainException(
4250
+				sprintf(
4251
+					esc_html__(
4252
+						'The %1$s field does not exist on the %2$s model.',
4253
+						'event_espresso'
4254
+					),
4255
+					$delete_column,
4256
+					$entity_model->get_this_model_name()
4257
+				)
4258
+			);
4259
+		}
4260
+	}
4261
+
4262
+
4263
+	/**
4264
+	 * @param EEM_Base       $entity_model
4265
+	 * @param Exception|null $exception
4266
+	 * @param string         $action
4267
+	 * @since 4.10.30.p
4268
+	 */
4269
+	private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, ?Exception $exception = null)
4270
+	{
4271
+		if ($exception instanceof Exception) {
4272
+			throw new RuntimeException(
4273
+				sprintf(
4274
+					esc_html__(
4275
+						'Could not %1$s the %2$s because the following error occurred: %3$s',
4276
+						'event_espresso'
4277
+					),
4278
+					$action,
4279
+					$entity_model->get_this_model_name(),
4280
+					$exception->getMessage()
4281
+				)
4282
+			);
4283
+		}
4284
+		throw new RuntimeException(
4285
+			sprintf(
4286
+				esc_html__(
4287
+					'Could not %1$s the %2$s because an invalid ID was received.',
4288
+					'event_espresso'
4289
+				),
4290
+				$action,
4291
+				$entity_model->get_this_model_name()
4292
+			)
4293
+		);
4294
+	}
4295 4295
 }
Please login to merge, or discard this patch.
Spacing   +179 added lines, -179 removed lines patch added patch discarded remove patch
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
         $ee_menu_slugs = (array) $ee_menu_slugs;
630 630
         if (
631 631
             ! $this->request->isAjax()
632
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
632
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
633 633
         ) {
634 634
             return;
635 635
         }
@@ -649,7 +649,7 @@  discard block
 block discarded – undo
649 649
             : $req_action;
650 650
 
651 651
         $this->_current_view = $this->_req_action;
652
-        $this->_req_nonce    = $this->_req_action . '_nonce';
652
+        $this->_req_nonce    = $this->_req_action.'_nonce';
653 653
         $this->_define_page_props();
654 654
         $this->_current_page_view_url = add_query_arg(
655 655
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -679,33 +679,33 @@  discard block
 block discarded – undo
679 679
         }
680 680
         // filter routes and page_config so addons can add their stuff. Filtering done per class
681 681
         $this->_page_routes = apply_filters(
682
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
682
+            'FHEE__'.$this->class_name.'__page_setup__page_routes',
683 683
             $this->_page_routes,
684 684
             $this
685 685
         );
686 686
         $this->_page_config = apply_filters(
687
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
687
+            'FHEE__'.$this->class_name.'__page_setup__page_config',
688 688
             $this->_page_config,
689 689
             $this
690 690
         );
691 691
         if ($this->base_class_name !== '') {
692 692
             $this->_page_routes = apply_filters(
693
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
693
+                'FHEE__'.$this->base_class_name.'__page_setup__page_routes',
694 694
                 $this->_page_routes,
695 695
                 $this
696 696
             );
697 697
             $this->_page_config = apply_filters(
698
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
698
+                'FHEE__'.$this->base_class_name.'__page_setup__page_config',
699 699
                 $this->_page_config,
700 700
                 $this
701 701
             );
702 702
         }
703 703
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704 704
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
705
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
706 706
             add_action(
707 707
                 'AHEE__EE_Admin_Page__route_admin_request',
708
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
708
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
709 709
                 10,
710 710
                 2
711 711
             );
@@ -718,8 +718,8 @@  discard block
 block discarded – undo
718 718
             if ($this->_is_UI_request) {
719 719
                 // admin_init stuff - global, all views for this page class, specific view
720 720
                 add_action('admin_init', [$this, 'admin_init'], 10);
721
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
721
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
722
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
723 723
                 }
724 724
             } else {
725 725
                 // hijack regular WP loading and route admin request immediately
@@ -738,12 +738,12 @@  discard block
 block discarded – undo
738 738
      */
739 739
     private function _do_other_page_hooks()
740 740
     {
741
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
741
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
742 742
         foreach ($registered_pages as $page) {
743 743
             // now let's setup the file name and class that should be present
744 744
             $classname = str_replace('.class.php', '', $page);
745 745
             // autoloaders should take care of loading file
746
-            if (! class_exists($classname)) {
746
+            if ( ! class_exists($classname)) {
747 747
                 $error_msg[] = sprintf(
748 748
                     esc_html__(
749 749
                         'Something went wrong with loading the %s admin hooks page.',
@@ -760,7 +760,7 @@  discard block
 block discarded – undo
760 760
                                    ),
761 761
                                    $page,
762 762
                                    '<br />',
763
-                                   '<strong>' . $classname . '</strong>'
763
+                                   '<strong>'.$classname.'</strong>'
764 764
                                );
765 765
                 throw new EE_Error(implode('||', $error_msg));
766 766
             }
@@ -802,13 +802,13 @@  discard block
 block discarded – undo
802 802
         // load admin_notices - global, page class, and view specific
803 803
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804 804
         add_action('admin_notices', [$this, 'admin_notices'], 10);
805
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
805
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
806
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
807 807
         }
808 808
         // load network admin_notices - global, page class, and view specific
809 809
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
810
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
811
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
812 812
         }
813 813
         // this will save any per_page screen options if they are present
814 814
         $this->_set_per_page_screen_options();
@@ -929,7 +929,7 @@  discard block
 block discarded – undo
929 929
     protected function _verify_routes()
930 930
     {
931 931
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
-        if (! $this->_current_page && ! $this->request->isAjax()) {
932
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
933 933
             return false;
934 934
         }
935 935
         $this->_route = false;
@@ -941,7 +941,7 @@  discard block
 block discarded – undo
941 941
                 $this->_admin_page_title
942 942
             );
943 943
             // developer error msg
944
-            $error_msg .= '||' . $error_msg
944
+            $error_msg .= '||'.$error_msg
945 945
                           . esc_html__(
946 946
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947 947
                               'event_espresso'
@@ -950,8 +950,8 @@  discard block
 block discarded – undo
950 950
         }
951 951
         // and that the requested page route exists
952 952
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
954
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
953
+            $this->_route        = $this->_page_routes[$this->_req_action];
954
+            $this->_route_config = $this->_page_config[$this->_req_action] ?? [];
955 955
         } else {
956 956
             // user error msg
957 957
             $error_msg = sprintf(
@@ -962,7 +962,7 @@  discard block
 block discarded – undo
962 962
                 $this->_admin_page_title
963 963
             );
964 964
             // developer error msg
965
-            $error_msg .= '||' . $error_msg
965
+            $error_msg .= '||'.$error_msg
966 966
                           . sprintf(
967 967
                               esc_html__(
968 968
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
             throw new EE_Error($error_msg);
974 974
         }
975 975
         // and that a default route exists
976
-        if (! array_key_exists('default', $this->_page_routes)) {
976
+        if ( ! array_key_exists('default', $this->_page_routes)) {
977 977
             // user error msg
978 978
             $error_msg = sprintf(
979 979
                 esc_html__(
@@ -983,7 +983,7 @@  discard block
 block discarded – undo
983 983
                 $this->_admin_page_title
984 984
             );
985 985
             // developer error msg
986
-            $error_msg .= '||' . $error_msg
986
+            $error_msg .= '||'.$error_msg
987 987
                           . esc_html__(
988 988
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989 989
                               'event_espresso'
@@ -1025,7 +1025,7 @@  discard block
 block discarded – undo
1025 1025
             $this->_admin_page_title
1026 1026
         );
1027 1027
         // developer error msg
1028
-        $error_msg .= '||' . $error_msg
1028
+        $error_msg .= '||'.$error_msg
1029 1029
                       . sprintf(
1030 1030
                           esc_html__(
1031 1031
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -1053,7 +1053,7 @@  discard block
 block discarded – undo
1053 1053
     protected function _verify_nonce($nonce, $nonce_ref)
1054 1054
     {
1055 1055
         // verify nonce against expected value
1056
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1056
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
1057 1057
             // these are not the droids you are looking for !!!
1058 1058
             $msg = sprintf(
1059 1059
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -1070,7 +1070,7 @@  discard block
 block discarded – undo
1070 1070
                     __CLASS__
1071 1071
                 );
1072 1072
             }
1073
-            if (! $this->request->isAjax()) {
1073
+            if ( ! $this->request->isAjax()) {
1074 1074
                 wp_die($msg);
1075 1075
             }
1076 1076
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -1094,7 +1094,7 @@  discard block
 block discarded – undo
1094 1094
      */
1095 1095
     protected function _route_admin_request()
1096 1096
     {
1097
-        if (! $this->_is_UI_request) {
1097
+        if ( ! $this->_is_UI_request) {
1098 1098
             $this->_verify_routes();
1099 1099
         }
1100 1100
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -1114,7 +1114,7 @@  discard block
 block discarded – undo
1114 1114
         $error_msg = '';
1115 1115
         // action right before calling route
1116 1116
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1117
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118 1118
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119 1119
         }
1120 1120
         // strip _wp_http_referer from the server REQUEST_URI
@@ -1128,7 +1128,7 @@  discard block
 block discarded – undo
1128 1128
         );
1129 1129
         $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1130 1130
         $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1131
-        if (! empty($func)) {
1131
+        if ( ! empty($func)) {
1132 1132
             if (is_array($func)) {
1133 1133
                 [$class, $method] = $func;
1134 1134
             } elseif (strpos($func, '::') !== false) {
@@ -1137,7 +1137,7 @@  discard block
 block discarded – undo
1137 1137
                 $class  = $this;
1138 1138
                 $method = $func;
1139 1139
             }
1140
-            if (! (is_object($class) && $class === $this)) {
1140
+            if ( ! (is_object($class) && $class === $this)) {
1141 1141
                 // send along this admin page object for access by addons.
1142 1142
                 $args['admin_page_object'] = $this;
1143 1143
             }
@@ -1178,7 +1178,7 @@  discard block
 block discarded – undo
1178 1178
                     $method
1179 1179
                 );
1180 1180
             }
1181
-            if (! empty($error_msg)) {
1181
+            if ( ! empty($error_msg)) {
1182 1182
                 throw new EE_Error($error_msg);
1183 1183
             }
1184 1184
         }
@@ -1264,7 +1264,7 @@  discard block
 block discarded – undo
1264 1264
                 if (strpos($key, 'nonce') !== false) {
1265 1265
                     continue;
1266 1266
                 }
1267
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1267
+                $args['wp_referer['.$key.']'] = is_string($value) ? htmlspecialchars($value) : $value;
1268 1268
             }
1269 1269
         }
1270 1270
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
@@ -1304,12 +1304,12 @@  discard block
 block discarded – undo
1304 1304
      */
1305 1305
     protected function _add_help_tabs()
1306 1306
     {
1307
-        if (isset($this->_page_config[ $this->_req_action ])) {
1308
-            $config = $this->_page_config[ $this->_req_action ];
1307
+        if (isset($this->_page_config[$this->_req_action])) {
1308
+            $config = $this->_page_config[$this->_req_action];
1309 1309
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1310 1310
             if (is_array($config) && isset($config['help_sidebar'])) {
1311 1311
                 // check that the callback given is valid
1312
-                if (! method_exists($this, $config['help_sidebar'])) {
1312
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1313 1313
                     throw new EE_Error(
1314 1314
                         sprintf(
1315 1315
                             esc_html__(
@@ -1322,18 +1322,18 @@  discard block
 block discarded – undo
1322 1322
                     );
1323 1323
                 }
1324 1324
                 $content = apply_filters(
1325
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1325
+                    'FHEE__'.$this->class_name.'__add_help_tabs__help_sidebar',
1326 1326
                     $this->{$config['help_sidebar']}()
1327 1327
                 );
1328 1328
                 $this->_current_screen->set_help_sidebar($content);
1329 1329
             }
1330
-            if (! isset($config['help_tabs'])) {
1330
+            if ( ! isset($config['help_tabs'])) {
1331 1331
                 return;
1332 1332
             } //no help tabs for this route
1333 1333
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1334 1334
                 // we're here so there ARE help tabs!
1335 1335
                 // make sure we've got what we need
1336
-                if (! isset($cfg['title'])) {
1336
+                if ( ! isset($cfg['title'])) {
1337 1337
                     throw new EE_Error(
1338 1338
                         esc_html__(
1339 1339
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1341,7 +1341,7 @@  discard block
 block discarded – undo
1341 1341
                         )
1342 1342
                     );
1343 1343
                 }
1344
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1344
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1345 1345
                     throw new EE_Error(
1346 1346
                         esc_html__(
1347 1347
                             'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
@@ -1350,11 +1350,11 @@  discard block
 block discarded – undo
1350 1350
                     );
1351 1351
                 }
1352 1352
                 // first priority goes to content.
1353
-                if (! empty($cfg['content'])) {
1353
+                if ( ! empty($cfg['content'])) {
1354 1354
                     $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1355 1355
                     // second priority goes to filename
1356
-                } elseif (! empty($cfg['filename'])) {
1357
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1356
+                } elseif ( ! empty($cfg['filename'])) {
1357
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1358 1358
                     // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1359 1359
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1360 1360
                                                              . basename($this->_get_dir())
@@ -1362,7 +1362,7 @@  discard block
 block discarded – undo
1362 1362
                                                              . $cfg['filename']
1363 1363
                                                              . '.help_tab.php' : $file_path;
1364 1364
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1365
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1365
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1366 1366
                         EE_Error::add_error(
1367 1367
                             sprintf(
1368 1368
                                 esc_html__(
@@ -1410,7 +1410,7 @@  discard block
 block discarded – undo
1410 1410
                     return;
1411 1411
                 }
1412 1412
                 // setup config array for help tab method
1413
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1413
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1414 1414
                 $_ht = [
1415 1415
                     'id'       => $id,
1416 1416
                     'title'    => $cfg['title'],
@@ -1436,8 +1436,8 @@  discard block
 block discarded – undo
1436 1436
             $qtips = (array) $this->_route_config['qtips'];
1437 1437
             // load qtip loader
1438 1438
             $path = [
1439
-                $this->_get_dir() . '/qtips/',
1440
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1439
+                $this->_get_dir().'/qtips/',
1440
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1441 1441
             ];
1442 1442
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1443 1443
         }
@@ -1459,7 +1459,7 @@  discard block
 block discarded – undo
1459 1459
         $i = 0;
1460 1460
         $only_tab = count($this->_page_config) < 2;
1461 1461
         foreach ($this->_page_config as $slug => $config) {
1462
-            if (! is_array($config) || empty($config['nav'])) {
1462
+            if ( ! is_array($config) || empty($config['nav'])) {
1463 1463
                 continue;
1464 1464
             }
1465 1465
             // no nav tab for this config
@@ -1468,27 +1468,27 @@  discard block
 block discarded – undo
1468 1468
                 // nav tab is only to appear when route requested.
1469 1469
                 continue;
1470 1470
             }
1471
-            if (! $this->check_user_access($slug, true)) {
1471
+            if ( ! $this->check_user_access($slug, true)) {
1472 1472
                 // no nav tab because current user does not have access.
1473 1473
                 continue;
1474 1474
             }
1475
-            $css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1475
+            $css_class = isset($config['css_class']) ? $config['css_class'].' ' : '';
1476 1476
             $css_class .= $only_tab ? ' ee-only-tab' : '';
1477 1477
 
1478
-            $this->_nav_tabs[ $slug ] = [
1478
+            $this->_nav_tabs[$slug] = [
1479 1479
                 'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1480 1480
                     ['action' => $slug],
1481 1481
                     $this->_admin_base_url
1482 1482
                 ),
1483 1483
                 'link_text' => $this->navTabLabel($config['nav'], $slug),
1484
-                'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1484
+                'css_class' => $this->_req_action === $slug ? $css_class.' nav-tab-active' : $css_class,
1485 1485
                 'order'     => $config['nav']['order'] ?? $i,
1486 1486
             ];
1487 1487
             $i++;
1488 1488
         }
1489 1489
         // if $this->_nav_tabs is empty then lets set the default
1490 1490
         if (empty($this->_nav_tabs)) {
1491
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1491
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1492 1492
                 'url'       => $this->_admin_base_url,
1493 1493
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1494 1494
                 'css_class' => 'nav-tab-active',
@@ -1504,11 +1504,11 @@  discard block
 block discarded – undo
1504 1504
     {
1505 1505
         $label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1506 1506
         $icon = $nav_tab['icon'] ?? null;
1507
-        $icon = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1507
+        $icon = $icon ? '<span class="dashicons '.$icon.'"></span>' : '';
1508 1508
         return '
1509 1509
             <span class="ee-admin-screen-tab__label">
1510
-                ' . $icon . '
1511
-                <span class="ee-nav-label__text">' . $label . '</span>
1510
+                ' . $icon.'
1511
+                <span class="ee-nav-label__text">' . $label.'</span>
1512 1512
             </span>';
1513 1513
     }
1514 1514
 
@@ -1525,10 +1525,10 @@  discard block
 block discarded – undo
1525 1525
             foreach ($this->_route_config['labels'] as $label => $text) {
1526 1526
                 if (is_array($text)) {
1527 1527
                     foreach ($text as $sublabel => $subtext) {
1528
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1528
+                        $this->_labels[$label][$sublabel] = $subtext;
1529 1529
                     }
1530 1530
                 } else {
1531
-                    $this->_labels[ $label ] = $text;
1531
+                    $this->_labels[$label] = $text;
1532 1532
                 }
1533 1533
             }
1534 1534
         }
@@ -1550,10 +1550,10 @@  discard block
 block discarded – undo
1550 1550
     {
1551 1551
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1552 1552
         $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1553
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1554
-                                      && is_array($this->_page_routes[ $route_to_check ])
1555
-                        && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1556
-            ? $this->_page_routes[ $route_to_check ]['capability']
1553
+        $capability = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1554
+                                      && is_array($this->_page_routes[$route_to_check])
1555
+                        && ! empty($this->_page_routes[$route_to_check]['capability'])
1556
+            ? $this->_page_routes[$route_to_check]['capability']
1557 1557
             : null;
1558 1558
 
1559 1559
         if (empty($capability) && empty($route_to_check)) {
@@ -1607,14 +1607,14 @@  discard block
 block discarded – undo
1607 1607
         string $priority = 'default',
1608 1608
         ?array $callback_args = null
1609 1609
     ) {
1610
-        if (! is_callable($callback)) {
1610
+        if ( ! is_callable($callback)) {
1611 1611
             return;
1612 1612
         }
1613 1613
 
1614 1614
         add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1615 1615
         add_filter(
1616 1616
             "postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1617
-            function ($classes) {
1617
+            function($classes) {
1618 1618
                 array_push($classes, 'ee-admin-container');
1619 1619
                 return $classes;
1620 1620
             }
@@ -1708,7 +1708,7 @@  discard block
 block discarded – undo
1708 1708
         ';
1709 1709
 
1710 1710
         // current set timezone for timezone js
1711
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1711
+        echo '<span id="current_timezone" class="hidden">'.esc_html(EEH_DTT_Helper::get_timezone()).'</span>';
1712 1712
     }
1713 1713
 
1714 1714
 
@@ -1742,7 +1742,7 @@  discard block
 block discarded – undo
1742 1742
         // loop through the array and setup content
1743 1743
         foreach ($help_array as $trigger => $help) {
1744 1744
             // make sure the array is setup properly
1745
-            if (! isset($help['title'], $help['content'])) {
1745
+            if ( ! isset($help['title'], $help['content'])) {
1746 1746
                 throw new EE_Error(
1747 1747
                     esc_html__(
1748 1748
                         'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
@@ -1756,8 +1756,8 @@  discard block
 block discarded – undo
1756 1756
                 'help_popup_title'   => $help['title'],
1757 1757
                 'help_popup_content' => $help['content'],
1758 1758
             ];
1759
-            $content       .= EEH_Template::display_template(
1760
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1759
+            $content .= EEH_Template::display_template(
1760
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1761 1761
                 $template_args,
1762 1762
                 true
1763 1763
             );
@@ -1779,15 +1779,15 @@  discard block
 block discarded – undo
1779 1779
     private function _get_help_content()
1780 1780
     {
1781 1781
         // what is the method we're looking for?
1782
-        $method_name = '_help_popup_content_' . $this->_req_action;
1782
+        $method_name = '_help_popup_content_'.$this->_req_action;
1783 1783
         // if method doesn't exist let's get out.
1784
-        if (! method_exists($this, $method_name)) {
1784
+        if ( ! method_exists($this, $method_name)) {
1785 1785
             return [];
1786 1786
         }
1787 1787
         // k we're good to go let's retrieve the help array
1788 1788
         $help_array = $this->{$method_name}();
1789 1789
         // make sure we've got an array!
1790
-        if (! is_array($help_array)) {
1790
+        if ( ! is_array($help_array)) {
1791 1791
             throw new EE_Error(
1792 1792
                 esc_html__(
1793 1793
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1819,8 +1819,8 @@  discard block
 block discarded – undo
1819 1819
         // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1820 1820
         $help_array   = $this->_get_help_content();
1821 1821
         $help_content = '';
1822
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1823
-            $help_array[ $trigger_id ] = [
1822
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1823
+            $help_array[$trigger_id] = [
1824 1824
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1825 1825
                 'content' => esc_html__(
1826 1826
                     'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
@@ -1915,7 +1915,7 @@  discard block
 block discarded – undo
1915 1915
 
1916 1916
         add_filter(
1917 1917
             'admin_body_class',
1918
-            function ($classes) {
1918
+            function($classes) {
1919 1919
                 if (strpos($classes, 'espresso-admin') === false) {
1920 1920
                     $classes .= ' espresso-admin';
1921 1921
                 }
@@ -2006,12 +2006,12 @@  discard block
 block discarded – undo
2006 2006
     protected function _set_list_table()
2007 2007
     {
2008 2008
         // first is this a list_table view?
2009
-        if (! isset($this->_route_config['list_table'])) {
2009
+        if ( ! isset($this->_route_config['list_table'])) {
2010 2010
             return;
2011 2011
         } //not a list_table view so get out.
2012 2012
         // list table functions are per view specific (because some admin pages might have more than one list table!)
2013
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2014
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2013
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
2014
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2015 2015
             // user error msg
2016 2016
             $error_msg = esc_html__(
2017 2017
                 'An error occurred. The requested list table views could not be found.',
@@ -2031,10 +2031,10 @@  discard block
 block discarded – undo
2031 2031
         }
2032 2032
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2033 2033
         $this->_views = apply_filters(
2034
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2034
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2035 2035
             $this->_views
2036 2036
         );
2037
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2037
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2038 2038
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2039 2039
         $this->_set_list_table_view();
2040 2040
         $this->_set_list_table_object();
@@ -2069,7 +2069,7 @@  discard block
 block discarded – undo
2069 2069
     protected function _set_list_table_object()
2070 2070
     {
2071 2071
         if (isset($this->_route_config['list_table'])) {
2072
-            if (! class_exists($this->_route_config['list_table'])) {
2072
+            if ( ! class_exists($this->_route_config['list_table'])) {
2073 2073
                 throw new EE_Error(
2074 2074
                     sprintf(
2075 2075
                         esc_html__(
@@ -2107,17 +2107,17 @@  discard block
 block discarded – undo
2107 2107
         foreach ($this->_views as $key => $view) {
2108 2108
             $query_args = [];
2109 2109
             // check for current view
2110
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2110
+            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2111 2111
             $query_args['action']                        = $this->_req_action;
2112
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2112
+            $query_args[$this->_req_action.'_nonce'] = wp_create_nonce($query_args['action'].'_nonce');
2113 2113
             $query_args['status']                        = $view['slug'];
2114 2114
             // merge any other arguments sent in.
2115
-            if (isset($extra_query_args[ $view['slug'] ])) {
2116
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2115
+            if (isset($extra_query_args[$view['slug']])) {
2116
+                foreach ($extra_query_args[$view['slug']] as $extra_query_arg) {
2117 2117
                     $query_args[] = $extra_query_arg;
2118 2118
                 }
2119 2119
             }
2120
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2120
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2121 2121
         }
2122 2122
         return $this->_views;
2123 2123
     }
@@ -2148,14 +2148,14 @@  discard block
 block discarded – undo
2148 2148
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2149 2149
         foreach ($values as $value) {
2150 2150
             if ($value < $max_entries) {
2151
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2151
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2152 2152
                 $entries_per_page_dropdown .= '
2153
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2153
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2154 2154
             }
2155 2155
         }
2156
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2156
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2157 2157
         $entries_per_page_dropdown .= '
2158
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2158
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2159 2159
         $entries_per_page_dropdown .= '
2160 2160
 					</select>
2161 2161
 					entries
@@ -2179,7 +2179,7 @@  discard block
 block discarded – undo
2179 2179
             empty($this->_search_btn_label) ? $this->page_label
2180 2180
                 : $this->_search_btn_label
2181 2181
         );
2182
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2182
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2183 2183
     }
2184 2184
 
2185 2185
 
@@ -2267,7 +2267,7 @@  discard block
 block discarded – undo
2267 2267
             $total_columns                                       = ! empty($screen_columns)
2268 2268
                 ? $screen_columns
2269 2269
                 : $this->_route_config['columns'][1];
2270
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2270
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2271 2271
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2272 2272
             $this->_template_args['screen']                      = $this->_current_screen;
2273 2273
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2313,7 +2313,7 @@  discard block
 block discarded – undo
2313 2313
      */
2314 2314
     protected function _espresso_ratings_request()
2315 2315
     {
2316
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2316
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2317 2317
             return;
2318 2318
         }
2319 2319
         $ratings_box_title = apply_filters(
@@ -2340,28 +2340,28 @@  discard block
 block discarded – undo
2340 2340
      */
2341 2341
     public function espresso_ratings_request()
2342 2342
     {
2343
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2343
+        EEH_Template::display_template(EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php');
2344 2344
     }
2345 2345
 
2346 2346
 
2347 2347
     public static function cached_rss_display($rss_id, $url)
2348 2348
     {
2349
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2349
+        $loading = '<p class="widget-loading hide-if-no-js">'
2350 2350
                      . esc_html__('Loading&#8230;', 'event_espresso')
2351 2351
                      . '</p><p class="hide-if-js">'
2352 2352
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2353 2353
                      . '</p>';
2354
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2355
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2356
-        $post      = '</div>' . "\n";
2357
-        $cache_key = 'ee_rss_' . md5($rss_id);
2354
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2355
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2356
+        $post      = '</div>'."\n";
2357
+        $cache_key = 'ee_rss_'.md5($rss_id);
2358 2358
         $output    = get_transient($cache_key);
2359 2359
         if ($output !== false) {
2360
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2360
+            echo wp_kses($pre.$output.$post, AllowedTags::getWithFormTags());
2361 2361
             return true;
2362 2362
         }
2363
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2364
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2363
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2364
+            echo wp_kses($pre.$loading.$post, AllowedTags::getWithFormTags());
2365 2365
             return false;
2366 2366
         }
2367 2367
         ob_start();
@@ -2428,19 +2428,19 @@  discard block
 block discarded – undo
2428 2428
     public function espresso_sponsors_post_box()
2429 2429
     {
2430 2430
         EEH_Template::display_template(
2431
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2431
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2432 2432
         );
2433 2433
     }
2434 2434
 
2435 2435
 
2436 2436
     private function _publish_post_box()
2437 2437
     {
2438
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2438
+        $meta_box_ref = 'espresso_'.$this->page_slug.'_editor_overview';
2439 2439
         // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2440 2440
         // then we'll use that for the metabox label.
2441 2441
         // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2442
-        if (! empty($this->_labels['publishbox'])) {
2443
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2442
+        if ( ! empty($this->_labels['publishbox'])) {
2443
+            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2444 2444
                 : $this->_labels['publishbox'];
2445 2445
         } else {
2446 2446
             $box_label = esc_html__('Publish', 'event_espresso');
@@ -2469,7 +2469,7 @@  discard block
 block discarded – undo
2469 2469
             ? $this->_template_args['publish_box_extra_content']
2470 2470
             : '';
2471 2471
         echo EEH_Template::display_template(
2472
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2472
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2473 2473
             $this->_template_args,
2474 2474
             true
2475 2475
         );
@@ -2557,18 +2557,18 @@  discard block
 block discarded – undo
2557 2557
             );
2558 2558
         }
2559 2559
         $this->_template_args['publish_delete_link'] = $delete_link;
2560
-        if (! empty($name) && ! empty($id)) {
2561
-            $hidden_field_arr[ $name ] = [
2560
+        if ( ! empty($name) && ! empty($id)) {
2561
+            $hidden_field_arr[$name] = [
2562 2562
                 'type'  => 'hidden',
2563 2563
                 'value' => $id,
2564 2564
             ];
2565
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2565
+            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2566 2566
         } else {
2567 2567
             $hf = '';
2568 2568
         }
2569 2569
         // add hidden field
2570 2570
         $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2571
-            ? $hf[ $name ]['field']
2571
+            ? $hf[$name]['field']
2572 2572
             : $hf;
2573 2573
     }
2574 2574
 
@@ -2670,7 +2670,7 @@  discard block
 block discarded – undo
2670 2670
         }
2671 2671
         // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2672 2672
         $call_back_func = $create_func
2673
-            ? static function ($post, $metabox) {
2673
+            ? static function($post, $metabox) {
2674 2674
                 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2675 2675
                 echo EEH_Template::display_template(
2676 2676
                     $metabox['args']['template_path'],
@@ -2680,7 +2680,7 @@  discard block
 block discarded – undo
2680 2680
             }
2681 2681
             : $callback;
2682 2682
         $this->addMetaBox(
2683
-            str_replace('_', '-', $action) . '-mbox',
2683
+            str_replace('_', '-', $action).'-mbox',
2684 2684
             $title,
2685 2685
             $call_back_func,
2686 2686
             $this->_wp_page_slug,
@@ -2797,13 +2797,13 @@  discard block
 block discarded – undo
2797 2797
             'event-espresso_page_espresso_',
2798 2798
             '',
2799 2799
             $this->_wp_page_slug
2800
-        ) . ' ' . $this->_req_action . '-route';
2800
+        ).' '.$this->_req_action.'-route';
2801 2801
 
2802 2802
         $template_path = $sidebar
2803 2803
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2804
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2804
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2805 2805
         if ($this->request->isAjax()) {
2806
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2806
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2807 2807
         }
2808 2808
         $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2809 2809
 
@@ -2837,11 +2837,11 @@  discard block
 block discarded – undo
2837 2837
     public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2838 2838
     {
2839 2839
         // let's generate a default preview action button if there isn't one already present.
2840
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2840
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2841 2841
             'Upgrade to Event Espresso 4 Right Now',
2842 2842
             'event_espresso'
2843 2843
         );
2844
-        $buy_now_url                                   = add_query_arg(
2844
+        $buy_now_url = add_query_arg(
2845 2845
             [
2846 2846
                 'ee_ver'       => 'ee4',
2847 2847
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2861,8 +2861,8 @@  discard block
 block discarded – undo
2861 2861
                 true
2862 2862
             )
2863 2863
             : $this->_template_args['preview_action_button'];
2864
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2865
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2864
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2865
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2866 2866
             $this->_template_args,
2867 2867
             true
2868 2868
         );
@@ -2920,7 +2920,7 @@  discard block
 block discarded – undo
2920 2920
         // setup search attributes
2921 2921
         $this->_set_search_attributes();
2922 2922
         $this->_template_args['current_page']     = $this->_wp_page_slug;
2923
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2923
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
2924 2924
         $this->_template_args['table_url']        = $this->request->isAjax()
2925 2925
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2926 2926
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -2928,10 +2928,10 @@  discard block
 block discarded – undo
2928 2928
         $this->_template_args['current_route']    = $this->_req_action;
2929 2929
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2930 2930
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2931
-        if (! empty($ajax_sorting_callback)) {
2931
+        if ( ! empty($ajax_sorting_callback)) {
2932 2932
             $sortable_list_table_form_fields = wp_nonce_field(
2933
-                $ajax_sorting_callback . '_nonce',
2934
-                $ajax_sorting_callback . '_nonce',
2933
+                $ajax_sorting_callback.'_nonce',
2934
+                $ajax_sorting_callback.'_nonce',
2935 2935
                 false,
2936 2936
                 false
2937 2937
             );
@@ -2948,18 +2948,18 @@  discard block
 block discarded – undo
2948 2948
 
2949 2949
         $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2950 2950
 
2951
-        $nonce_ref          = $this->_req_action . '_nonce';
2951
+        $nonce_ref          = $this->_req_action.'_nonce';
2952 2952
         $hidden_form_fields .= '
2953
-            <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2953
+            <input type="hidden" name="' . $nonce_ref.'" value="'.wp_create_nonce($nonce_ref).'">';
2954 2954
 
2955
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2955
+        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2956 2956
         // display message about search results?
2957 2957
         $search = $this->request->getRequestParam('s');
2958 2958
         $this->_template_args['before_list_table'] .= ! empty($search)
2959
-            ? '<p class="ee-search-results">' . sprintf(
2959
+            ? '<p class="ee-search-results">'.sprintf(
2960 2960
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2961 2961
                 trim($search, '%')
2962
-            ) . '</p>'
2962
+            ).'</p>'
2963 2963
             : '';
2964 2964
         // filter before_list_table template arg
2965 2965
         $this->_template_args['before_list_table'] = apply_filters(
@@ -2993,7 +2993,7 @@  discard block
 block discarded – undo
2993 2993
         // convert to array and filter again
2994 2994
         // arrays are easier to inject new items in a specific location,
2995 2995
         // but would not be backwards compatible, so we have to add a new filter
2996
-        $this->_template_args['after_list_table']   = implode(
2996
+        $this->_template_args['after_list_table'] = implode(
2997 2997
             " \n",
2998 2998
             (array) apply_filters(
2999 2999
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -3048,7 +3048,7 @@  discard block
 block discarded – undo
3048 3048
             $this->page_slug
3049 3049
         );
3050 3050
         return EEH_Template::display_template(
3051
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3051
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3052 3052
             $this->_template_args,
3053 3053
             true
3054 3054
         );
@@ -3164,16 +3164,16 @@  discard block
 block discarded – undo
3164 3164
             $this->_template_args['before_admin_page_content'] ?? ''
3165 3165
         );
3166 3166
 
3167
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3167
+        $this->_template_args['after_admin_page_content'] = apply_filters(
3168 3168
             "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3169 3169
             $this->_template_args['after_admin_page_content'] ?? ''
3170 3170
         );
3171
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3171
+        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3172 3172
 
3173 3173
         if ($this->request->isAjax()) {
3174 3174
             $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3175 3175
                 // $template_path,
3176
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3176
+                EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php',
3177 3177
                 $this->_template_args,
3178 3178
                 true
3179 3179
             );
@@ -3182,7 +3182,7 @@  discard block
 block discarded – undo
3182 3182
         // load settings page wrapper template
3183 3183
         $template_path = $about
3184 3184
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3185
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3185
+            : EE_ADMIN_TEMPLATE.'admin_wrapper.template.php';
3186 3186
 
3187 3187
         EEH_Template::display_template($template_path, $this->_template_args);
3188 3188
     }
@@ -3266,12 +3266,12 @@  discard block
 block discarded – undo
3266 3266
         $default_names = ['save', 'save_and_close'];
3267 3267
         $buttons = '';
3268 3268
         foreach ($button_text as $key => $button) {
3269
-            $ref     = $default_names[ $key ];
3270
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3271
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3272
-                        . 'value="' . $button . '" name="' . $name . '" '
3273
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3274
-            if (! $both) {
3269
+            $ref     = $default_names[$key];
3270
+            $name    = ! empty($actions) ? $actions[$key] : $ref;
3271
+            $buttons .= '<input type="submit" class="button button--primary '.$ref.'" '
3272
+                        . 'value="'.$button.'" name="'.$name.'" '
3273
+                        . 'id="'.$this->_current_view.'_'.$ref.'" />';
3274
+            if ( ! $both) {
3275 3275
                 break;
3276 3276
             }
3277 3277
         }
@@ -3311,13 +3311,13 @@  discard block
 block discarded – undo
3311 3311
                 'An error occurred. No action was set for this page\'s form.',
3312 3312
                 'event_espresso'
3313 3313
             );
3314
-            $dev_msg  = $user_msg . "\n"
3314
+            $dev_msg = $user_msg."\n"
3315 3315
                         . sprintf(
3316 3316
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3317 3317
                             __FUNCTION__,
3318 3318
                             __CLASS__
3319 3319
                         );
3320
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3320
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3321 3321
         }
3322 3322
         // open form
3323 3323
         $action = $this->_admin_base_url;
@@ -3325,9 +3325,9 @@  discard block
 block discarded – undo
3325 3325
             <form name='form' method='post' action='{$action}' id='{$route}_event_form' class='ee-admin-page-form' >
3326 3326
             ";
3327 3327
         // add nonce
3328
-        $nonce                                             =
3329
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3330
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3328
+        $nonce =
3329
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3330
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3331 3331
         // add REQUIRED form action
3332 3332
         $hidden_fields = [
3333 3333
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3340,7 +3340,7 @@  discard block
 block discarded – undo
3340 3340
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3341 3341
         // add fields to form
3342 3342
         foreach ((array) $form_fields as $form_field) {
3343
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3343
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3344 3344
         }
3345 3345
         // close form
3346 3346
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3423,12 +3423,12 @@  discard block
 block discarded – undo
3423 3423
         bool $override_overwrite = false
3424 3424
     ) {
3425 3425
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3426
-        $notices      = EE_Error::get_notices(false);
3426
+        $notices = EE_Error::get_notices(false);
3427 3427
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3428
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3428
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3429 3429
             EE_Error::overwrite_success();
3430 3430
         }
3431
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3431
+        if ( ! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3432 3432
             // how many records affected ? more than one record ? or just one ?
3433 3433
             EE_Error::add_success(
3434 3434
                 sprintf(
@@ -3449,7 +3449,7 @@  discard block
 block discarded – undo
3449 3449
             );
3450 3450
         }
3451 3451
         // check that $query_args isn't something crazy
3452
-        if (! is_array($query_args)) {
3452
+        if ( ! is_array($query_args)) {
3453 3453
             $query_args = [];
3454 3454
         }
3455 3455
         /**
@@ -3481,7 +3481,7 @@  discard block
 block discarded – undo
3481 3481
             $redirect_url = admin_url('admin.php');
3482 3482
         }
3483 3483
         // merge any default query_args set in _default_route_query_args property
3484
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3484
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3485 3485
             $args_to_merge = [];
3486 3486
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3487 3487
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3493,15 +3493,15 @@  discard block
 block discarded – undo
3493 3493
                         }
3494 3494
                         // finally we will override any arguments in the referer with
3495 3495
                         // what might be set on the _default_route_query_args array.
3496
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3497
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3496
+                        if (isset($this->_default_route_query_args[$reference])) {
3497
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3498 3498
                         } else {
3499
-                            $args_to_merge[ $reference ] = urlencode($value);
3499
+                            $args_to_merge[$reference] = urlencode($value);
3500 3500
                         }
3501 3501
                     }
3502 3502
                     continue;
3503 3503
                 }
3504
-                $args_to_merge[ $query_param ] = $query_value;
3504
+                $args_to_merge[$query_param] = $query_value;
3505 3505
             }
3506 3506
             // now let's merge these arguments but override with what was specifically sent in to the
3507 3507
             // redirect.
@@ -3513,19 +3513,19 @@  discard block
 block discarded – undo
3513 3513
         if (isset($query_args['action'])) {
3514 3514
             // manually generate wp_nonce and merge that with the query vars
3515 3515
             // becuz the wp_nonce_url function wrecks havoc on some vars
3516
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3516
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3517 3517
         }
3518 3518
         // we're adding some hooks and filters in here for processing any things just before redirects
3519 3519
         // (example: an admin page has done an insert or update and we want to run something after that).
3520
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3520
+        do_action('AHEE_redirect_'.$this->class_name.$this->_req_action, $query_args);
3521 3521
         $redirect_url = apply_filters(
3522
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3522
+            'FHEE_redirect_'.$this->class_name.$this->_req_action,
3523 3523
             EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3524 3524
             $query_args
3525 3525
         );
3526 3526
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3527 3527
         if ($this->request->isAjax()) {
3528
-            $default_data                    = [
3528
+            $default_data = [
3529 3529
                 'close'        => true,
3530 3530
                 'redirect_url' => $redirect_url,
3531 3531
                 'where'        => 'main',
@@ -3575,7 +3575,7 @@  discard block
 block discarded – undo
3575 3575
         }
3576 3576
         $this->_template_args['notices'] = EE_Error::get_notices();
3577 3577
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3578
-        if (! $this->request->isAjax() || $sticky_notices) {
3578
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3579 3579
             $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3580 3580
             $this->_add_transient(
3581 3581
                 $route,
@@ -3615,7 +3615,7 @@  discard block
 block discarded – undo
3615 3615
         $exclude_nonce = false
3616 3616
     ) {
3617 3617
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3618
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3618
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3619 3619
             throw new EE_Error(
3620 3620
                 sprintf(
3621 3621
                     esc_html__(
@@ -3626,7 +3626,7 @@  discard block
 block discarded – undo
3626 3626
                 )
3627 3627
             );
3628 3628
         }
3629
-        if (! isset($this->_labels['buttons'][ $type ])) {
3629
+        if ( ! isset($this->_labels['buttons'][$type])) {
3630 3630
             throw new EE_Error(
3631 3631
                 sprintf(
3632 3632
                     esc_html__(
@@ -3639,7 +3639,7 @@  discard block
 block discarded – undo
3639 3639
         }
3640 3640
         // finally check user access for this button.
3641 3641
         $has_access = $this->check_user_access($action, true);
3642
-        if (! $has_access) {
3642
+        if ( ! $has_access) {
3643 3643
             return '';
3644 3644
         }
3645 3645
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3647,11 +3647,11 @@  discard block
 block discarded – undo
3647 3647
             'action' => $action,
3648 3648
         ];
3649 3649
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3650
-        if (! empty($extra_request)) {
3650
+        if ( ! empty($extra_request)) {
3651 3651
             $query_args = array_merge($extra_request, $query_args);
3652 3652
         }
3653 3653
         $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3654
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3654
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3655 3655
     }
3656 3656
 
3657 3657
 
@@ -3677,7 +3677,7 @@  discard block
 block discarded – undo
3677 3677
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3678 3678
                 20
3679 3679
             ),
3680
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3680
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3681 3681
         ];
3682 3682
         // ONLY add the screen option if the user has access to it.
3683 3683
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3698,18 +3698,18 @@  discard block
 block discarded – undo
3698 3698
     {
3699 3699
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3700 3700
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3701
-            if (! $user = wp_get_current_user()) {
3701
+            if ( ! $user = wp_get_current_user()) {
3702 3702
                 return;
3703 3703
             }
3704 3704
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3705
-            if (! $option) {
3705
+            if ( ! $option) {
3706 3706
                 return;
3707 3707
             }
3708
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3708
+            $value = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3709 3709
             $map_option = $option;
3710 3710
             $option     = str_replace('-', '_', $option);
3711 3711
             switch ($map_option) {
3712
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3712
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3713 3713
                     $max_value = apply_filters(
3714 3714
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3715 3715
                         999,
@@ -3766,13 +3766,13 @@  discard block
 block discarded – undo
3766 3766
     protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3767 3767
     {
3768 3768
         $user_id = get_current_user_id();
3769
-        if (! $skip_route_verify) {
3769
+        if ( ! $skip_route_verify) {
3770 3770
             $this->_verify_route($route);
3771 3771
         }
3772 3772
         // now let's set the string for what kind of transient we're setting
3773 3773
         $transient = $notices
3774
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3775
-            : 'rte_tx_' . $route . '_' . $user_id;
3774
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3775
+            : 'rte_tx_'.$route.'_'.$user_id;
3776 3776
         $data      = $notices ? ['notices' => $data] : $data;
3777 3777
         // is there already a transient for this route?  If there is then let's ADD to that transient
3778 3778
         $existing = is_multisite() && is_network_admin()
@@ -3801,8 +3801,8 @@  discard block
 block discarded – undo
3801 3801
         $user_id   = get_current_user_id();
3802 3802
         $route     = ! $route ? $this->_req_action : $route;
3803 3803
         $transient = $notices
3804
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3805
-            : 'rte_tx_' . $route . '_' . $user_id;
3804
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3805
+            : 'rte_tx_'.$route.'_'.$user_id;
3806 3806
         $data      = is_multisite() && is_network_admin()
3807 3807
             ? get_site_transient($transient)
3808 3808
             : get_transient($transient);
@@ -4038,7 +4038,7 @@  discard block
 block discarded – undo
4038 4038
      */
4039 4039
     protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4040 4040
     {
4041
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4041
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4042 4042
     }
4043 4043
 
4044 4044
 
@@ -4051,7 +4051,7 @@  discard block
 block discarded – undo
4051 4051
      */
4052 4052
     protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4053 4053
     {
4054
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4054
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4055 4055
     }
4056 4056
 
4057 4057
 
@@ -4199,7 +4199,7 @@  discard block
 block discarded – undo
4199 4199
         ?callable $callback = null
4200 4200
     ): bool {
4201 4201
         $entity_ID = absint($entity_ID);
4202
-        if (! $entity_ID) {
4202
+        if ( ! $entity_ID) {
4203 4203
             $this->trashRestoreDeleteError($action, $entity_model);
4204 4204
         }
4205 4205
         $result = 0;
@@ -4245,7 +4245,7 @@  discard block
 block discarded – undo
4245 4245
                 )
4246 4246
             );
4247 4247
         }
4248
-        if (! $entity_model->has_field($delete_column)) {
4248
+        if ( ! $entity_model->has_field($delete_column)) {
4249 4249
             throw new DomainException(
4250 4250
                 sprintf(
4251 4251
                     esc_html__(
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/RegistrationsReport.php 2 patches
Indentation   +580 added lines, -580 removed lines patch added patch discarded remove patch
@@ -42,584 +42,584 @@
 block discarded – undo
42 42
  */
43 43
 class RegistrationsReport extends JobHandlerFile
44 44
 {
45
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
46
-    // phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
47
-    /**
48
-     * Performs any necessary setup for starting the job. This is also a good
49
-     * place to setup the $job_arguments which will be used for subsequent HTTP requests
50
-     * when continue_job will be called
51
-     *
52
-     * @param JobParameters $job_parameters
53
-     * @return JobStepResponse
54
-     * @throws BatchRequestException
55
-     * @throws EE_Error
56
-     * @throws ReflectionException
57
-     */
58
-    public function create_job(JobParameters $job_parameters)
59
-    {
60
-        $event_id = absint($job_parameters->request_datum('EVT_ID', '0'));
61
-        $DTT_ID   = absint($job_parameters->request_datum('DTT_ID', '0'));
62
-        if (! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
63
-            throw new BatchRequestException(
64
-                esc_html__('You do not have permission to view registrations', 'event_espresso')
65
-            );
66
-        }
67
-        $filepath = $this->create_file_from_job_with_name(
68
-            $job_parameters->job_id(),
69
-            $this->get_filename()
70
-        );
71
-        $job_parameters->add_extra_data('filepath', $filepath);
72
-
73
-        if ($job_parameters->request_datum('use_filters', false)) {
74
-            $query_params = maybe_unserialize($job_parameters->request_datum('filters', []));
75
-        } else {
76
-            $query_params = [
77
-                [
78
-                    'OR'                 => [
79
-                        // don't include registrations from failed or abandoned transactions...
80
-                        'Transaction.STS_ID' => [
81
-                            'NOT IN',
82
-                            [
83
-                                EEM_Transaction::failed_status_code,
84
-                                EEM_Transaction::abandoned_status_code,
85
-                            ],
86
-                        ],
87
-                        // unless the registration is approved,
88
-                        // in which case include it regardless of transaction status
89
-                        'STS_ID'             => EEM_Registration::status_id_approved,
90
-                    ],
91
-                    'Ticket.TKT_deleted' => ['IN', [true, false]],
92
-                ],
93
-                'order_by'   => ['Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'],
94
-                'force_join' => ['Transaction', 'Ticket', 'Attendee'],
95
-                'caps'       => EEM_Base::caps_read_admin,
96
-            ];
97
-            if ($event_id) {
98
-                $query_params[0]['EVT_ID'] = $event_id;
99
-            } else {
100
-                $query_params['force_join'][] = 'Event';
101
-            }
102
-        }
103
-
104
-        if (! isset($query_params['force_join'])) {
105
-            $query_params['force_join'] = ['Event', 'Transaction', 'Ticket', 'Attendee'];
106
-        }
107
-
108
-        $query_params = apply_filters(
109
-            'FHEE__EE_Export__report_registration_for_event',
110
-            $query_params,
111
-            $event_id
112
-        );
113
-
114
-        $job_parameters->add_extra_data('query_params', $query_params);
115
-        $question_labels = $this->_get_question_labels($query_params);
116
-        $job_parameters->add_extra_data('question_labels', $question_labels);
117
-        $job_parameters->set_job_size($this->count_units_to_process($query_params));
118
-        // we need to set the header columns
119
-        // but to do that we need to process one row so that we can extract ALL of the column headers
120
-        $csv_data_for_row = $this->get_csv_data_for(
121
-            $event_id,
122
-            0,
123
-            1,
124
-            $question_labels,
125
-            $query_params,
126
-            $DTT_ID
127
-        );
128
-        // but we don't want to write any actual data yet...
129
-        // so let's blank out all of the values for that first row
130
-        array_walk(
131
-            $csv_data_for_row[0],
132
-            function (&$value) {
133
-                $value = null;
134
-            }
135
-        );
136
-
137
-        EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true, true);
138
-        $this->updateTextHeader(
139
-            esc_html__('Registrations report started successfully...', 'event_espresso')
140
-        );
141
-        return new JobStepResponse($job_parameters, $this->feedback);
142
-    }
143
-
144
-
145
-    /**
146
-     * Gets the filename
147
-     *
148
-     * @return string
149
-     */
150
-    protected function get_filename(): string
151
-    {
152
-        return apply_filters(
153
-            'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__get_filename',
154
-            sprintf(
155
-                'event-espresso-registrations-%s.csv',
156
-                str_replace([':', ' '], '-', current_time('mysql'))
157
-            )
158
-        );
159
-    }
160
-
161
-
162
-    /**
163
-     * Gets the questions which are to be used for this report,
164
-     * so they can be remembered for later
165
-     *
166
-     * @param array $registration_query_params
167
-     * @return array question admin labels to be used for this report
168
-     * @throws EE_Error
169
-     * @throws ReflectionException
170
-     */
171
-    protected function _get_question_labels(array $registration_query_params): array
172
-    {
173
-        $where                 = $registration_query_params[0] ?? null;
174
-        $question_query_params = [];
175
-        if ($where !== null) {
176
-            $question_query_params = [
177
-                $this->_change_registration_where_params_to_question_where_params($registration_query_params[0]),
178
-            ];
179
-        }
180
-        // Make sure it's not a system question
181
-        $question_query_params[0]['OR*not-system-questions'] = [
182
-            'QST_system'      => '',
183
-            'QST_system*null' => ['IS_NULL']
184
-        ];
185
-        if (
186
-            apply_filters(
187
-                'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport___get_question_labels__only_include_answered_questions',
188
-                false,
189
-                $registration_query_params
190
-            )
191
-        ) {
192
-            $question_query_params[0]['Answer.ANS_ID'] = ['IS_NOT_NULL'];
193
-        }
194
-        $question_query_params['group_by'] = ['QST_ID'];
195
-        return array_unique(EEM_Question::instance()->get_col($question_query_params, 'QST_admin_label'));
196
-    }
197
-
198
-
199
-    /**
200
-     * Takes where params meant for registrations and changes them to work for questions
201
-     *
202
-     * @param array $reg_where_params
203
-     * @return array
204
-     * @throws EE_Error
205
-     * @throws ReflectionException
206
-     */
207
-    protected function _change_registration_where_params_to_question_where_params(array $reg_where_params): array
208
-    {
209
-        $question_where_params = [];
210
-        foreach ($reg_where_params as $key => $val) {
211
-            if (EEM_Registration::instance()->is_logic_query_param_key($key)) {
212
-                $question_where_params[ $key ] =
213
-                    $this->_change_registration_where_params_to_question_where_params($val);
214
-            } else {
215
-                // it's a normal where condition
216
-                $question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
217
-            }
218
-        }
219
-        return $question_where_params;
220
-    }
221
-
222
-
223
-    /**
224
-     * Performs another step of the job
225
-     *
226
-     * @param JobParameters $job_parameters
227
-     * @param int           $batch_size
228
-     * @return JobStepResponse
229
-     * @throws EE_Error
230
-     * @throws ReflectionException
231
-     */
232
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
233
-    {
234
-        if ($job_parameters->units_processed() < $job_parameters->job_size()) {
235
-            $csv_data = $this->get_csv_data_for(
236
-                (int) $job_parameters->request_datum('EVT_ID', '0'),
237
-                $job_parameters->units_processed(),
238
-                $batch_size,
239
-                $job_parameters->extra_datum('question_labels'),
240
-                $job_parameters->extra_datum('query_params'),
241
-                (int) $job_parameters->request_datum('DTT_ID', '0')
242
-            );
243
-            EEH_Export::write_data_array_to_csv(
244
-                $job_parameters->extra_datum('filepath'),
245
-                $csv_data,
246
-                false
247
-            );
248
-            $units_processed = count($csv_data);
249
-            if ($units_processed) {
250
-                $job_parameters->mark_processed($units_processed);
251
-                $this->updateText(
252
-                    sprintf(
253
-                        esc_html__('Wrote %1$s rows to report CSV file...', 'event_espresso'),
254
-                        $units_processed
255
-                    )
256
-                );
257
-            }
258
-        }
259
-        $extra_response_data = ['file_url' => ''];
260
-        if ($job_parameters->units_processed() >= $job_parameters->job_size()) {
261
-            $job_parameters->set_status(JobParameters::status_complete);
262
-            $extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
263
-            $this->displayJobFinalResults($job_parameters);
264
-        } else {
265
-            $job_parameters->set_status(JobParameters::status_continue);
266
-        }
267
-        return new JobStepResponse($job_parameters, $this->feedback, $extra_response_data);
268
-    }
269
-
270
-
271
-    /**
272
-     * Gets the csv data for a batch of registrations
273
-     *
274
-     * @param int|null $event_id
275
-     * @param int      $offset
276
-     * @param int      $limit
277
-     * @param array    $question_labels the IDs for all the questions which were answered by someone in this selection
278
-     * @param array    $query_params    for using where querying the model
279
-     * @param int      $DTT_ID
280
-     * @return array top-level keys are numeric, next-level keys are column headers
281
-     * @throws EE_Error
282
-     * @throws ReflectionException
283
-     */
284
-    public function get_csv_data_for(
285
-        ?int $event_id,
286
-        int $offset,
287
-        int $limit,
288
-        array $question_labels,
289
-        array $query_params,
290
-        int $DTT_ID = 0
291
-    ): array {
292
-        $reg_fields_to_include = [
293
-            'TXN_ID',
294
-            'ATT_ID',
295
-            'REG_ID',
296
-            'REG_date',
297
-            'REG_code',
298
-            'REG_count',
299
-            'REG_final_price',
300
-        ];
301
-        $att_fields_to_include = [
302
-            'ATT_fname',
303
-            'ATT_lname',
304
-            'ATT_email',
305
-            'ATT_address',
306
-            'ATT_address2',
307
-            'ATT_city',
308
-            'STA_ID',
309
-            'CNT_ISO',
310
-            'ATT_zip',
311
-            'ATT_phone',
312
-        ];
313
-
314
-        // get models
315
-        $event_model   = EEM_Event::instance();
316
-        $date_model    = EEM_Datetime::instance();
317
-        $ticket_model  = EEM_Ticket::instance();
318
-        $txn_model     = EEM_Transaction::instance();
319
-        $reg_model     = EEM_Registration::instance();
320
-        $pay_model     = EEM_Payment::instance();
321
-        $status_model  = EEM_Status::instance();
322
-
323
-        $registrations_csv_ready_array = [];
324
-        $query_params['limit']         = [$offset, $limit];
325
-        $registration_rows             = $reg_model->get_all_wpdb_results($query_params);
326
-
327
-        foreach ($registration_rows as $reg_row) {
328
-            if (! is_array($reg_row)) {
329
-                continue;
330
-            }
331
-            $reg_csv_array = [];
332
-            // registration ID
333
-            $reg_id_field = $reg_model->field_settings_for('REG_ID');
334
-            $reg_csv_array[ EEH_Export::get_column_name_for_field($reg_id_field) ] =
335
-                EEH_Export::prepare_value_from_db_for_display(
336
-                    $reg_model,
337
-                    'REG_ID',
338
-                    $reg_row[ $reg_id_field->get_qualified_column() ]
339
-                );
340
-            // ALL registrations, or is list filtered to just one?
341
-            if (! $event_id) {
342
-                // ALL registrations, so get each event's name and ID
343
-                $reg_csv_array[ esc_html__('Event', 'event_espresso') ] = sprintf(
344
-                    /* translators: 1: event name, 2: event ID */
345
-                    esc_html__('%1$s (%2$s)', 'event_espresso'),
346
-                    EEH_Export::prepare_value_from_db_for_display(
347
-                        $event_model,
348
-                        'EVT_name',
349
-                        $reg_row['Event_CPT.post_title']
350
-                    ),
351
-                    $reg_row['Event_CPT.ID']
352
-                );
353
-            }
354
-            // add attendee columns
355
-            $reg_csv_array = AttendeeCSV::addAttendeeColumns($att_fields_to_include, $reg_row, $reg_csv_array);
356
-            // add registration columns
357
-            $reg_csv_array = RegistrationCSV::addRegistrationColumns($reg_fields_to_include, $reg_row, $reg_csv_array);
358
-            // get pretty status
359
-            $stati = $status_model->localized_status(
360
-                [
361
-                    $reg_row['Registration.STS_ID']     => esc_html__('unknown', 'event_espresso'),
362
-                    $reg_row['TransactionTable.STS_ID'] => esc_html__('unknown', 'event_espresso'),
363
-                ],
364
-                false,
365
-                'sentence'
366
-            );
367
-            $is_primary_reg = $reg_row['Registration.REG_count'] == '1';
368
-
369
-            $reg_csv_array[ esc_html__('Registration Status', 'event_espresso') ] =
370
-                $stati[ $reg_row['Registration.STS_ID'] ];
371
-            // get pretty transaction status
372
-            $reg_csv_array[ esc_html__('Transaction Status', 'event_espresso') ]     =
373
-                $stati[ $reg_row['TransactionTable.STS_ID'] ];
374
-            $reg_csv_array[ esc_html__('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
375
-                ? EEH_Export::prepare_value_from_db_for_display(
376
-                    $txn_model,
377
-                    'TXN_total',
378
-                    $reg_row['TransactionTable.TXN_total'],
379
-                    'localized_float'
380
-                )
381
-                : '0.00';
382
-
383
-            $reg_csv_array[ esc_html__('Amount Paid', 'event_espresso') ]            = $is_primary_reg
384
-                ? EEH_Export::prepare_value_from_db_for_display(
385
-                    $txn_model,
386
-                    'TXN_paid',
387
-                    $reg_row['TransactionTable.TXN_paid'],
388
-                    'localized_float'
389
-                )
390
-                : '0.00';
391
-
392
-            $payment_methods                                                                  = [];
393
-            $gateway_txn_ids_etc                                                              = [];
394
-            $payment_times                                                                    = [];
395
-            if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) {
396
-                $payments_info = $pay_model->get_all_wpdb_results(
397
-                    [
398
-                        [
399
-                            'TXN_ID' => $reg_row['TransactionTable.TXN_ID'],
400
-                            'STS_ID' => EEM_Payment::status_id_approved,
401
-                        ],
402
-                        'force_join' => ['Payment_Method'],
403
-                    ],
404
-                    ARRAY_A,
405
-                    'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time'
406
-                );
407
-                [$payment_methods, $gateway_txn_ids_etc, $payment_times] = PaymentsInfoCSV::extractPaymentInfo(
408
-                    $payments_info
409
-                );
410
-            }
411
-
412
-            $reg_csv_array[ esc_html__('Payment Date(s)', 'event_espresso') ] = implode(
413
-                ',',
414
-                $payment_times
415
-            );
416
-
417
-            $reg_csv_array[ esc_html__('Payment Method(s)', 'event_espresso') ] = implode(
418
-                ',',
419
-                $payment_methods
420
-            );
421
-
422
-            $reg_csv_array[ esc_html__('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
423
-                ',',
424
-                $gateway_txn_ids_etc
425
-            );
426
-
427
-            $ticket_name      = esc_html__('Unknown', 'event_espresso');
428
-            $datetime_strings = [esc_html__('Unknown', 'event_espresso')];
429
-            if ($reg_row['Ticket.TKT_ID']) {
430
-                $ticket_name       = EEH_Export::prepare_value_from_db_for_display(
431
-                    $ticket_model,
432
-                    'TKT_name',
433
-                    $reg_row['Ticket.TKT_name']
434
-                );
435
-                $datetime_strings = [];
436
-                $datetimes        = $date_model->get_all_wpdb_results(
437
-                    [
438
-                        ['Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']],
439
-                        'order_by'                 => ['DTT_EVT_start' => 'ASC'],
440
-                        'default_where_conditions' => 'none',
441
-                    ]
442
-                );
443
-                foreach ($datetimes as $datetime) {
444
-                    $datetime_strings[] = EEH_Export::prepare_value_from_db_for_display(
445
-                        $date_model,
446
-                        'DTT_EVT_start',
447
-                        $datetime['Datetime.DTT_EVT_start']
448
-                    );
449
-                }
450
-            }
451
-
452
-            $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
453
-
454
-
455
-            $reg_csv_array[ esc_html__('Ticket Datetimes', 'event_espresso') ] = implode(
456
-                ', ',
457
-                $datetime_strings
458
-            );
459
-
460
-            // add answer columns
461
-            $reg_csv_array = AnswersCSV::addAnswerColumns($reg_row, $reg_csv_array, $question_labels);
462
-            // Include check-in data
463
-            if ($event_id && $DTT_ID) {
464
-                // get whether or not the user has checked in
465
-                $reg_csv_array[ esc_html__('Datetime Check-ins #', 'event_espresso') ] =
466
-                    $reg_model->count_related(
467
-                        $reg_row['Registration.REG_ID'],
468
-                        'Checkin',
469
-                        [
470
-                            [
471
-                                'DTT_ID' => $DTT_ID
472
-                            ]
473
-                        ]
474
-                    );
475
-                /** @var EE_Datetime $datetime */
476
-                $datetime     = $date_model->get_one_by_ID($DTT_ID);
477
-                $checkin_rows = EEM_Checkin::instance()->get_all(
478
-                    [
479
-                        [
480
-                            'REG_ID' => $reg_row['Registration.REG_ID'],
481
-                            'DTT_ID' => $datetime->get('DTT_ID'),
482
-                        ],
483
-                    ]
484
-                );
485
-                $checkins     = [];
486
-                foreach ($checkin_rows as $checkin_row) {
487
-                    /** @var EE_Checkin $checkin_row */
488
-                    $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
489
-                    if ($checkin_value) {
490
-                        $checkins[] = $checkin_value;
491
-                    }
492
-                }
493
-                $datetime_name                   = CheckinsCSV::getDatetimeLabel($datetime);
494
-                $reg_csv_array[ $datetime_name ] = implode(' --- ', $checkins);
495
-            } elseif ($event_id) {
496
-                // get whether or not the user has checked in
497
-                $reg_csv_array[ esc_html__('Event Check-ins #', 'event_espresso') ] =
498
-                    $reg_model->count_related(
499
-                        $reg_row['Registration.REG_ID'],
500
-                        'Checkin'
501
-                    );
502
-
503
-                $datetimes = $date_model->get_all(
504
-                    [
505
-                        [
506
-                            'Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID'],
507
-                        ],
508
-                        'order_by'                 => ['DTT_EVT_start' => 'ASC'],
509
-                        'default_where_conditions' => 'none',
510
-                    ]
511
-                );
512
-                foreach ($datetimes as $datetime) {
513
-                    if (! $datetime instanceof EE_Datetime) {
514
-                        continue;
515
-                    }
516
-
517
-                    /** @var EE_Checkin $checkin_row */
518
-                    $checkin_row = EEM_Checkin::instance()->get_one(
519
-                        [
520
-                            [
521
-                                'REG_ID' => $reg_row['Registration.REG_ID'],
522
-                                'DTT_ID' => $datetime->get('DTT_ID'),
523
-                            ],
524
-                            'limit'    => 1,
525
-                            'order_by' => [
526
-                                'CHK_ID' => 'DESC'
527
-                            ]
528
-                        ]
529
-                    );
530
-
531
-                    $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
532
-                    $datetime_name = CheckinsCSV::getDatetimeLabel($datetime);
533
-
534
-                    $reg_csv_array[ $datetime_name ] = $checkin_value;
535
-                }
536
-            }
537
-            /**
538
-             * Filter to change the contents of each row of the registrations report CSV file.
539
-             * This can be used to add or remote columns from the CSV file, or change their values.
540
-             * Note when using: all rows in the CSV should have the same columns.
541
-             *
542
-             * @param array $reg_csv_array keys are the column names, values are their cell values
543
-             * @param array $reg_row       one entry from EEM_Registration::get_all_wpdb_results()
544
-             */
545
-            $registrations_csv_ready_array[] = apply_filters(
546
-                'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array',
547
-                $reg_csv_array,
548
-                $reg_row
549
-            );
550
-        }
551
-        // if we couldn't export anything, we want to at least show the column headers
552
-        if (empty($registrations_csv_ready_array)) {
553
-            $reg_csv_array               = [];
554
-            $model_and_fields_to_include = [
555
-                'Registration' => $reg_fields_to_include,
556
-                'Attendee'     => $att_fields_to_include,
557
-            ];
558
-            foreach ($model_and_fields_to_include as $model_name => $field_list) {
559
-                $model = EE_Registry::instance()->load_model($model_name);
560
-                foreach ($field_list as $field_name) {
561
-                    $field                                                          =
562
-                        $model->field_settings_for($field_name);
563
-                    $reg_csv_array[ EEH_Export::get_column_name_for_field($field) ] = null;
564
-                }
565
-            }
566
-            $registrations_csv_ready_array[] = $reg_csv_array;
567
-        }
568
-        return $registrations_csv_ready_array;
569
-    }
570
-
571
-
572
-    /**
573
-     * Counts total unit to process
574
-     *
575
-     * @param array $query_params
576
-     * @return int
577
-     * @throws EE_Error
578
-     * @throws ReflectionException
579
-     */
580
-    public function count_units_to_process(array $query_params): int
581
-    {
582
-        return EEM_Registration::instance()->count(
583
-            array_diff_key(
584
-                $query_params,
585
-                array_flip(
586
-                    ['limit']
587
-                )
588
-            )
589
-        );
590
-    }
591
-
592
-
593
-    /**
594
-     * Performs any clean-up logic when we know the job is completed.
595
-     * In this case, we delete the temporary file
596
-     *
597
-     * @param JobParameters $job_parameters
598
-     * @return JobStepResponse
599
-     */
600
-    public function cleanup_job(JobParameters $job_parameters)
601
-    {
602
-        $this->updateText(esc_html__('File Generation complete and downloaded', 'event_espresso'));
603
-
604
-        $this->_file_helper->delete(
605
-            EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
606
-            true,
607
-            'd'
608
-        );
609
-        $this->updateText(esc_html__('Cleaned up temporary file', 'event_espresso'));
610
-        $this->updateText(
611
-            $this->infoWrapper(
612
-                sprintf(
613
-                    esc_html__(
614
-                        'If not automatically redirected in %1$s seconds, click here to return to the %2$sRegistrations List Table%3$s',
615
-                        'event_espresso'
616
-                    ),
617
-                    '<span id="ee-redirect-timer">10</span>',
618
-                    '<a href="' . $job_parameters->request_datum('return_url') . '">',
619
-                    '</a>'
620
-                )
621
-            )
622
-        );
623
-        return new JobStepResponse($job_parameters, $this->feedback);
624
-    }
45
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
46
+	// phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
47
+	/**
48
+	 * Performs any necessary setup for starting the job. This is also a good
49
+	 * place to setup the $job_arguments which will be used for subsequent HTTP requests
50
+	 * when continue_job will be called
51
+	 *
52
+	 * @param JobParameters $job_parameters
53
+	 * @return JobStepResponse
54
+	 * @throws BatchRequestException
55
+	 * @throws EE_Error
56
+	 * @throws ReflectionException
57
+	 */
58
+	public function create_job(JobParameters $job_parameters)
59
+	{
60
+		$event_id = absint($job_parameters->request_datum('EVT_ID', '0'));
61
+		$DTT_ID   = absint($job_parameters->request_datum('DTT_ID', '0'));
62
+		if (! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
63
+			throw new BatchRequestException(
64
+				esc_html__('You do not have permission to view registrations', 'event_espresso')
65
+			);
66
+		}
67
+		$filepath = $this->create_file_from_job_with_name(
68
+			$job_parameters->job_id(),
69
+			$this->get_filename()
70
+		);
71
+		$job_parameters->add_extra_data('filepath', $filepath);
72
+
73
+		if ($job_parameters->request_datum('use_filters', false)) {
74
+			$query_params = maybe_unserialize($job_parameters->request_datum('filters', []));
75
+		} else {
76
+			$query_params = [
77
+				[
78
+					'OR'                 => [
79
+						// don't include registrations from failed or abandoned transactions...
80
+						'Transaction.STS_ID' => [
81
+							'NOT IN',
82
+							[
83
+								EEM_Transaction::failed_status_code,
84
+								EEM_Transaction::abandoned_status_code,
85
+							],
86
+						],
87
+						// unless the registration is approved,
88
+						// in which case include it regardless of transaction status
89
+						'STS_ID'             => EEM_Registration::status_id_approved,
90
+					],
91
+					'Ticket.TKT_deleted' => ['IN', [true, false]],
92
+				],
93
+				'order_by'   => ['Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'],
94
+				'force_join' => ['Transaction', 'Ticket', 'Attendee'],
95
+				'caps'       => EEM_Base::caps_read_admin,
96
+			];
97
+			if ($event_id) {
98
+				$query_params[0]['EVT_ID'] = $event_id;
99
+			} else {
100
+				$query_params['force_join'][] = 'Event';
101
+			}
102
+		}
103
+
104
+		if (! isset($query_params['force_join'])) {
105
+			$query_params['force_join'] = ['Event', 'Transaction', 'Ticket', 'Attendee'];
106
+		}
107
+
108
+		$query_params = apply_filters(
109
+			'FHEE__EE_Export__report_registration_for_event',
110
+			$query_params,
111
+			$event_id
112
+		);
113
+
114
+		$job_parameters->add_extra_data('query_params', $query_params);
115
+		$question_labels = $this->_get_question_labels($query_params);
116
+		$job_parameters->add_extra_data('question_labels', $question_labels);
117
+		$job_parameters->set_job_size($this->count_units_to_process($query_params));
118
+		// we need to set the header columns
119
+		// but to do that we need to process one row so that we can extract ALL of the column headers
120
+		$csv_data_for_row = $this->get_csv_data_for(
121
+			$event_id,
122
+			0,
123
+			1,
124
+			$question_labels,
125
+			$query_params,
126
+			$DTT_ID
127
+		);
128
+		// but we don't want to write any actual data yet...
129
+		// so let's blank out all of the values for that first row
130
+		array_walk(
131
+			$csv_data_for_row[0],
132
+			function (&$value) {
133
+				$value = null;
134
+			}
135
+		);
136
+
137
+		EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true, true);
138
+		$this->updateTextHeader(
139
+			esc_html__('Registrations report started successfully...', 'event_espresso')
140
+		);
141
+		return new JobStepResponse($job_parameters, $this->feedback);
142
+	}
143
+
144
+
145
+	/**
146
+	 * Gets the filename
147
+	 *
148
+	 * @return string
149
+	 */
150
+	protected function get_filename(): string
151
+	{
152
+		return apply_filters(
153
+			'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__get_filename',
154
+			sprintf(
155
+				'event-espresso-registrations-%s.csv',
156
+				str_replace([':', ' '], '-', current_time('mysql'))
157
+			)
158
+		);
159
+	}
160
+
161
+
162
+	/**
163
+	 * Gets the questions which are to be used for this report,
164
+	 * so they can be remembered for later
165
+	 *
166
+	 * @param array $registration_query_params
167
+	 * @return array question admin labels to be used for this report
168
+	 * @throws EE_Error
169
+	 * @throws ReflectionException
170
+	 */
171
+	protected function _get_question_labels(array $registration_query_params): array
172
+	{
173
+		$where                 = $registration_query_params[0] ?? null;
174
+		$question_query_params = [];
175
+		if ($where !== null) {
176
+			$question_query_params = [
177
+				$this->_change_registration_where_params_to_question_where_params($registration_query_params[0]),
178
+			];
179
+		}
180
+		// Make sure it's not a system question
181
+		$question_query_params[0]['OR*not-system-questions'] = [
182
+			'QST_system'      => '',
183
+			'QST_system*null' => ['IS_NULL']
184
+		];
185
+		if (
186
+			apply_filters(
187
+				'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport___get_question_labels__only_include_answered_questions',
188
+				false,
189
+				$registration_query_params
190
+			)
191
+		) {
192
+			$question_query_params[0]['Answer.ANS_ID'] = ['IS_NOT_NULL'];
193
+		}
194
+		$question_query_params['group_by'] = ['QST_ID'];
195
+		return array_unique(EEM_Question::instance()->get_col($question_query_params, 'QST_admin_label'));
196
+	}
197
+
198
+
199
+	/**
200
+	 * Takes where params meant for registrations and changes them to work for questions
201
+	 *
202
+	 * @param array $reg_where_params
203
+	 * @return array
204
+	 * @throws EE_Error
205
+	 * @throws ReflectionException
206
+	 */
207
+	protected function _change_registration_where_params_to_question_where_params(array $reg_where_params): array
208
+	{
209
+		$question_where_params = [];
210
+		foreach ($reg_where_params as $key => $val) {
211
+			if (EEM_Registration::instance()->is_logic_query_param_key($key)) {
212
+				$question_where_params[ $key ] =
213
+					$this->_change_registration_where_params_to_question_where_params($val);
214
+			} else {
215
+				// it's a normal where condition
216
+				$question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
217
+			}
218
+		}
219
+		return $question_where_params;
220
+	}
221
+
222
+
223
+	/**
224
+	 * Performs another step of the job
225
+	 *
226
+	 * @param JobParameters $job_parameters
227
+	 * @param int           $batch_size
228
+	 * @return JobStepResponse
229
+	 * @throws EE_Error
230
+	 * @throws ReflectionException
231
+	 */
232
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
233
+	{
234
+		if ($job_parameters->units_processed() < $job_parameters->job_size()) {
235
+			$csv_data = $this->get_csv_data_for(
236
+				(int) $job_parameters->request_datum('EVT_ID', '0'),
237
+				$job_parameters->units_processed(),
238
+				$batch_size,
239
+				$job_parameters->extra_datum('question_labels'),
240
+				$job_parameters->extra_datum('query_params'),
241
+				(int) $job_parameters->request_datum('DTT_ID', '0')
242
+			);
243
+			EEH_Export::write_data_array_to_csv(
244
+				$job_parameters->extra_datum('filepath'),
245
+				$csv_data,
246
+				false
247
+			);
248
+			$units_processed = count($csv_data);
249
+			if ($units_processed) {
250
+				$job_parameters->mark_processed($units_processed);
251
+				$this->updateText(
252
+					sprintf(
253
+						esc_html__('Wrote %1$s rows to report CSV file...', 'event_espresso'),
254
+						$units_processed
255
+					)
256
+				);
257
+			}
258
+		}
259
+		$extra_response_data = ['file_url' => ''];
260
+		if ($job_parameters->units_processed() >= $job_parameters->job_size()) {
261
+			$job_parameters->set_status(JobParameters::status_complete);
262
+			$extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
263
+			$this->displayJobFinalResults($job_parameters);
264
+		} else {
265
+			$job_parameters->set_status(JobParameters::status_continue);
266
+		}
267
+		return new JobStepResponse($job_parameters, $this->feedback, $extra_response_data);
268
+	}
269
+
270
+
271
+	/**
272
+	 * Gets the csv data for a batch of registrations
273
+	 *
274
+	 * @param int|null $event_id
275
+	 * @param int      $offset
276
+	 * @param int      $limit
277
+	 * @param array    $question_labels the IDs for all the questions which were answered by someone in this selection
278
+	 * @param array    $query_params    for using where querying the model
279
+	 * @param int      $DTT_ID
280
+	 * @return array top-level keys are numeric, next-level keys are column headers
281
+	 * @throws EE_Error
282
+	 * @throws ReflectionException
283
+	 */
284
+	public function get_csv_data_for(
285
+		?int $event_id,
286
+		int $offset,
287
+		int $limit,
288
+		array $question_labels,
289
+		array $query_params,
290
+		int $DTT_ID = 0
291
+	): array {
292
+		$reg_fields_to_include = [
293
+			'TXN_ID',
294
+			'ATT_ID',
295
+			'REG_ID',
296
+			'REG_date',
297
+			'REG_code',
298
+			'REG_count',
299
+			'REG_final_price',
300
+		];
301
+		$att_fields_to_include = [
302
+			'ATT_fname',
303
+			'ATT_lname',
304
+			'ATT_email',
305
+			'ATT_address',
306
+			'ATT_address2',
307
+			'ATT_city',
308
+			'STA_ID',
309
+			'CNT_ISO',
310
+			'ATT_zip',
311
+			'ATT_phone',
312
+		];
313
+
314
+		// get models
315
+		$event_model   = EEM_Event::instance();
316
+		$date_model    = EEM_Datetime::instance();
317
+		$ticket_model  = EEM_Ticket::instance();
318
+		$txn_model     = EEM_Transaction::instance();
319
+		$reg_model     = EEM_Registration::instance();
320
+		$pay_model     = EEM_Payment::instance();
321
+		$status_model  = EEM_Status::instance();
322
+
323
+		$registrations_csv_ready_array = [];
324
+		$query_params['limit']         = [$offset, $limit];
325
+		$registration_rows             = $reg_model->get_all_wpdb_results($query_params);
326
+
327
+		foreach ($registration_rows as $reg_row) {
328
+			if (! is_array($reg_row)) {
329
+				continue;
330
+			}
331
+			$reg_csv_array = [];
332
+			// registration ID
333
+			$reg_id_field = $reg_model->field_settings_for('REG_ID');
334
+			$reg_csv_array[ EEH_Export::get_column_name_for_field($reg_id_field) ] =
335
+				EEH_Export::prepare_value_from_db_for_display(
336
+					$reg_model,
337
+					'REG_ID',
338
+					$reg_row[ $reg_id_field->get_qualified_column() ]
339
+				);
340
+			// ALL registrations, or is list filtered to just one?
341
+			if (! $event_id) {
342
+				// ALL registrations, so get each event's name and ID
343
+				$reg_csv_array[ esc_html__('Event', 'event_espresso') ] = sprintf(
344
+					/* translators: 1: event name, 2: event ID */
345
+					esc_html__('%1$s (%2$s)', 'event_espresso'),
346
+					EEH_Export::prepare_value_from_db_for_display(
347
+						$event_model,
348
+						'EVT_name',
349
+						$reg_row['Event_CPT.post_title']
350
+					),
351
+					$reg_row['Event_CPT.ID']
352
+				);
353
+			}
354
+			// add attendee columns
355
+			$reg_csv_array = AttendeeCSV::addAttendeeColumns($att_fields_to_include, $reg_row, $reg_csv_array);
356
+			// add registration columns
357
+			$reg_csv_array = RegistrationCSV::addRegistrationColumns($reg_fields_to_include, $reg_row, $reg_csv_array);
358
+			// get pretty status
359
+			$stati = $status_model->localized_status(
360
+				[
361
+					$reg_row['Registration.STS_ID']     => esc_html__('unknown', 'event_espresso'),
362
+					$reg_row['TransactionTable.STS_ID'] => esc_html__('unknown', 'event_espresso'),
363
+				],
364
+				false,
365
+				'sentence'
366
+			);
367
+			$is_primary_reg = $reg_row['Registration.REG_count'] == '1';
368
+
369
+			$reg_csv_array[ esc_html__('Registration Status', 'event_espresso') ] =
370
+				$stati[ $reg_row['Registration.STS_ID'] ];
371
+			// get pretty transaction status
372
+			$reg_csv_array[ esc_html__('Transaction Status', 'event_espresso') ]     =
373
+				$stati[ $reg_row['TransactionTable.STS_ID'] ];
374
+			$reg_csv_array[ esc_html__('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
375
+				? EEH_Export::prepare_value_from_db_for_display(
376
+					$txn_model,
377
+					'TXN_total',
378
+					$reg_row['TransactionTable.TXN_total'],
379
+					'localized_float'
380
+				)
381
+				: '0.00';
382
+
383
+			$reg_csv_array[ esc_html__('Amount Paid', 'event_espresso') ]            = $is_primary_reg
384
+				? EEH_Export::prepare_value_from_db_for_display(
385
+					$txn_model,
386
+					'TXN_paid',
387
+					$reg_row['TransactionTable.TXN_paid'],
388
+					'localized_float'
389
+				)
390
+				: '0.00';
391
+
392
+			$payment_methods                                                                  = [];
393
+			$gateway_txn_ids_etc                                                              = [];
394
+			$payment_times                                                                    = [];
395
+			if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) {
396
+				$payments_info = $pay_model->get_all_wpdb_results(
397
+					[
398
+						[
399
+							'TXN_ID' => $reg_row['TransactionTable.TXN_ID'],
400
+							'STS_ID' => EEM_Payment::status_id_approved,
401
+						],
402
+						'force_join' => ['Payment_Method'],
403
+					],
404
+					ARRAY_A,
405
+					'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time'
406
+				);
407
+				[$payment_methods, $gateway_txn_ids_etc, $payment_times] = PaymentsInfoCSV::extractPaymentInfo(
408
+					$payments_info
409
+				);
410
+			}
411
+
412
+			$reg_csv_array[ esc_html__('Payment Date(s)', 'event_espresso') ] = implode(
413
+				',',
414
+				$payment_times
415
+			);
416
+
417
+			$reg_csv_array[ esc_html__('Payment Method(s)', 'event_espresso') ] = implode(
418
+				',',
419
+				$payment_methods
420
+			);
421
+
422
+			$reg_csv_array[ esc_html__('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
423
+				',',
424
+				$gateway_txn_ids_etc
425
+			);
426
+
427
+			$ticket_name      = esc_html__('Unknown', 'event_espresso');
428
+			$datetime_strings = [esc_html__('Unknown', 'event_espresso')];
429
+			if ($reg_row['Ticket.TKT_ID']) {
430
+				$ticket_name       = EEH_Export::prepare_value_from_db_for_display(
431
+					$ticket_model,
432
+					'TKT_name',
433
+					$reg_row['Ticket.TKT_name']
434
+				);
435
+				$datetime_strings = [];
436
+				$datetimes        = $date_model->get_all_wpdb_results(
437
+					[
438
+						['Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']],
439
+						'order_by'                 => ['DTT_EVT_start' => 'ASC'],
440
+						'default_where_conditions' => 'none',
441
+					]
442
+				);
443
+				foreach ($datetimes as $datetime) {
444
+					$datetime_strings[] = EEH_Export::prepare_value_from_db_for_display(
445
+						$date_model,
446
+						'DTT_EVT_start',
447
+						$datetime['Datetime.DTT_EVT_start']
448
+					);
449
+				}
450
+			}
451
+
452
+			$reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
453
+
454
+
455
+			$reg_csv_array[ esc_html__('Ticket Datetimes', 'event_espresso') ] = implode(
456
+				', ',
457
+				$datetime_strings
458
+			);
459
+
460
+			// add answer columns
461
+			$reg_csv_array = AnswersCSV::addAnswerColumns($reg_row, $reg_csv_array, $question_labels);
462
+			// Include check-in data
463
+			if ($event_id && $DTT_ID) {
464
+				// get whether or not the user has checked in
465
+				$reg_csv_array[ esc_html__('Datetime Check-ins #', 'event_espresso') ] =
466
+					$reg_model->count_related(
467
+						$reg_row['Registration.REG_ID'],
468
+						'Checkin',
469
+						[
470
+							[
471
+								'DTT_ID' => $DTT_ID
472
+							]
473
+						]
474
+					);
475
+				/** @var EE_Datetime $datetime */
476
+				$datetime     = $date_model->get_one_by_ID($DTT_ID);
477
+				$checkin_rows = EEM_Checkin::instance()->get_all(
478
+					[
479
+						[
480
+							'REG_ID' => $reg_row['Registration.REG_ID'],
481
+							'DTT_ID' => $datetime->get('DTT_ID'),
482
+						],
483
+					]
484
+				);
485
+				$checkins     = [];
486
+				foreach ($checkin_rows as $checkin_row) {
487
+					/** @var EE_Checkin $checkin_row */
488
+					$checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
489
+					if ($checkin_value) {
490
+						$checkins[] = $checkin_value;
491
+					}
492
+				}
493
+				$datetime_name                   = CheckinsCSV::getDatetimeLabel($datetime);
494
+				$reg_csv_array[ $datetime_name ] = implode(' --- ', $checkins);
495
+			} elseif ($event_id) {
496
+				// get whether or not the user has checked in
497
+				$reg_csv_array[ esc_html__('Event Check-ins #', 'event_espresso') ] =
498
+					$reg_model->count_related(
499
+						$reg_row['Registration.REG_ID'],
500
+						'Checkin'
501
+					);
502
+
503
+				$datetimes = $date_model->get_all(
504
+					[
505
+						[
506
+							'Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID'],
507
+						],
508
+						'order_by'                 => ['DTT_EVT_start' => 'ASC'],
509
+						'default_where_conditions' => 'none',
510
+					]
511
+				);
512
+				foreach ($datetimes as $datetime) {
513
+					if (! $datetime instanceof EE_Datetime) {
514
+						continue;
515
+					}
516
+
517
+					/** @var EE_Checkin $checkin_row */
518
+					$checkin_row = EEM_Checkin::instance()->get_one(
519
+						[
520
+							[
521
+								'REG_ID' => $reg_row['Registration.REG_ID'],
522
+								'DTT_ID' => $datetime->get('DTT_ID'),
523
+							],
524
+							'limit'    => 1,
525
+							'order_by' => [
526
+								'CHK_ID' => 'DESC'
527
+							]
528
+						]
529
+					);
530
+
531
+					$checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
532
+					$datetime_name = CheckinsCSV::getDatetimeLabel($datetime);
533
+
534
+					$reg_csv_array[ $datetime_name ] = $checkin_value;
535
+				}
536
+			}
537
+			/**
538
+			 * Filter to change the contents of each row of the registrations report CSV file.
539
+			 * This can be used to add or remote columns from the CSV file, or change their values.
540
+			 * Note when using: all rows in the CSV should have the same columns.
541
+			 *
542
+			 * @param array $reg_csv_array keys are the column names, values are their cell values
543
+			 * @param array $reg_row       one entry from EEM_Registration::get_all_wpdb_results()
544
+			 */
545
+			$registrations_csv_ready_array[] = apply_filters(
546
+				'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array',
547
+				$reg_csv_array,
548
+				$reg_row
549
+			);
550
+		}
551
+		// if we couldn't export anything, we want to at least show the column headers
552
+		if (empty($registrations_csv_ready_array)) {
553
+			$reg_csv_array               = [];
554
+			$model_and_fields_to_include = [
555
+				'Registration' => $reg_fields_to_include,
556
+				'Attendee'     => $att_fields_to_include,
557
+			];
558
+			foreach ($model_and_fields_to_include as $model_name => $field_list) {
559
+				$model = EE_Registry::instance()->load_model($model_name);
560
+				foreach ($field_list as $field_name) {
561
+					$field                                                          =
562
+						$model->field_settings_for($field_name);
563
+					$reg_csv_array[ EEH_Export::get_column_name_for_field($field) ] = null;
564
+				}
565
+			}
566
+			$registrations_csv_ready_array[] = $reg_csv_array;
567
+		}
568
+		return $registrations_csv_ready_array;
569
+	}
570
+
571
+
572
+	/**
573
+	 * Counts total unit to process
574
+	 *
575
+	 * @param array $query_params
576
+	 * @return int
577
+	 * @throws EE_Error
578
+	 * @throws ReflectionException
579
+	 */
580
+	public function count_units_to_process(array $query_params): int
581
+	{
582
+		return EEM_Registration::instance()->count(
583
+			array_diff_key(
584
+				$query_params,
585
+				array_flip(
586
+					['limit']
587
+				)
588
+			)
589
+		);
590
+	}
591
+
592
+
593
+	/**
594
+	 * Performs any clean-up logic when we know the job is completed.
595
+	 * In this case, we delete the temporary file
596
+	 *
597
+	 * @param JobParameters $job_parameters
598
+	 * @return JobStepResponse
599
+	 */
600
+	public function cleanup_job(JobParameters $job_parameters)
601
+	{
602
+		$this->updateText(esc_html__('File Generation complete and downloaded', 'event_espresso'));
603
+
604
+		$this->_file_helper->delete(
605
+			EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
606
+			true,
607
+			'd'
608
+		);
609
+		$this->updateText(esc_html__('Cleaned up temporary file', 'event_espresso'));
610
+		$this->updateText(
611
+			$this->infoWrapper(
612
+				sprintf(
613
+					esc_html__(
614
+						'If not automatically redirected in %1$s seconds, click here to return to the %2$sRegistrations List Table%3$s',
615
+						'event_espresso'
616
+					),
617
+					'<span id="ee-redirect-timer">10</span>',
618
+					'<a href="' . $job_parameters->request_datum('return_url') . '">',
619
+					'</a>'
620
+				)
621
+			)
622
+		);
623
+		return new JobStepResponse($job_parameters, $this->feedback);
624
+	}
625 625
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -59,7 +59,7 @@  discard block
 block discarded – undo
59 59
     {
60 60
         $event_id = absint($job_parameters->request_datum('EVT_ID', '0'));
61 61
         $DTT_ID   = absint($job_parameters->request_datum('DTT_ID', '0'));
62
-        if (! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
62
+        if ( ! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
63 63
             throw new BatchRequestException(
64 64
                 esc_html__('You do not have permission to view registrations', 'event_espresso')
65 65
             );
@@ -101,7 +101,7 @@  discard block
 block discarded – undo
101 101
             }
102 102
         }
103 103
 
104
-        if (! isset($query_params['force_join'])) {
104
+        if ( ! isset($query_params['force_join'])) {
105 105
             $query_params['force_join'] = ['Event', 'Transaction', 'Ticket', 'Attendee'];
106 106
         }
107 107
 
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
         // so let's blank out all of the values for that first row
130 130
         array_walk(
131 131
             $csv_data_for_row[0],
132
-            function (&$value) {
132
+            function(&$value) {
133 133
                 $value = null;
134 134
             }
135 135
         );
@@ -209,11 +209,11 @@  discard block
 block discarded – undo
209 209
         $question_where_params = [];
210 210
         foreach ($reg_where_params as $key => $val) {
211 211
             if (EEM_Registration::instance()->is_logic_query_param_key($key)) {
212
-                $question_where_params[ $key ] =
212
+                $question_where_params[$key] =
213 213
                     $this->_change_registration_where_params_to_question_where_params($val);
214 214
             } else {
215 215
                 // it's a normal where condition
216
-                $question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
216
+                $question_where_params['Question_Group.Event.Registration.'.$key] = $val;
217 217
             }
218 218
         }
219 219
         return $question_where_params;
@@ -325,22 +325,22 @@  discard block
 block discarded – undo
325 325
         $registration_rows             = $reg_model->get_all_wpdb_results($query_params);
326 326
 
327 327
         foreach ($registration_rows as $reg_row) {
328
-            if (! is_array($reg_row)) {
328
+            if ( ! is_array($reg_row)) {
329 329
                 continue;
330 330
             }
331 331
             $reg_csv_array = [];
332 332
             // registration ID
333 333
             $reg_id_field = $reg_model->field_settings_for('REG_ID');
334
-            $reg_csv_array[ EEH_Export::get_column_name_for_field($reg_id_field) ] =
334
+            $reg_csv_array[EEH_Export::get_column_name_for_field($reg_id_field)] =
335 335
                 EEH_Export::prepare_value_from_db_for_display(
336 336
                     $reg_model,
337 337
                     'REG_ID',
338
-                    $reg_row[ $reg_id_field->get_qualified_column() ]
338
+                    $reg_row[$reg_id_field->get_qualified_column()]
339 339
                 );
340 340
             // ALL registrations, or is list filtered to just one?
341
-            if (! $event_id) {
341
+            if ( ! $event_id) {
342 342
                 // ALL registrations, so get each event's name and ID
343
-                $reg_csv_array[ esc_html__('Event', 'event_espresso') ] = sprintf(
343
+                $reg_csv_array[esc_html__('Event', 'event_espresso')] = sprintf(
344 344
                     /* translators: 1: event name, 2: event ID */
345 345
                     esc_html__('%1$s (%2$s)', 'event_espresso'),
346 346
                     EEH_Export::prepare_value_from_db_for_display(
@@ -366,12 +366,12 @@  discard block
 block discarded – undo
366 366
             );
367 367
             $is_primary_reg = $reg_row['Registration.REG_count'] == '1';
368 368
 
369
-            $reg_csv_array[ esc_html__('Registration Status', 'event_espresso') ] =
370
-                $stati[ $reg_row['Registration.STS_ID'] ];
369
+            $reg_csv_array[esc_html__('Registration Status', 'event_espresso')] =
370
+                $stati[$reg_row['Registration.STS_ID']];
371 371
             // get pretty transaction status
372
-            $reg_csv_array[ esc_html__('Transaction Status', 'event_espresso') ]     =
373
-                $stati[ $reg_row['TransactionTable.STS_ID'] ];
374
-            $reg_csv_array[ esc_html__('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
372
+            $reg_csv_array[esc_html__('Transaction Status', 'event_espresso')]     =
373
+                $stati[$reg_row['TransactionTable.STS_ID']];
374
+            $reg_csv_array[esc_html__('Transaction Amount Due', 'event_espresso')] = $is_primary_reg
375 375
                 ? EEH_Export::prepare_value_from_db_for_display(
376 376
                     $txn_model,
377 377
                     'TXN_total',
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
                 )
381 381
                 : '0.00';
382 382
 
383
-            $reg_csv_array[ esc_html__('Amount Paid', 'event_espresso') ]            = $is_primary_reg
383
+            $reg_csv_array[esc_html__('Amount Paid', 'event_espresso')] = $is_primary_reg
384 384
                 ? EEH_Export::prepare_value_from_db_for_display(
385 385
                     $txn_model,
386 386
                     'TXN_paid',
@@ -409,17 +409,17 @@  discard block
 block discarded – undo
409 409
                 );
410 410
             }
411 411
 
412
-            $reg_csv_array[ esc_html__('Payment Date(s)', 'event_espresso') ] = implode(
412
+            $reg_csv_array[esc_html__('Payment Date(s)', 'event_espresso')] = implode(
413 413
                 ',',
414 414
                 $payment_times
415 415
             );
416 416
 
417
-            $reg_csv_array[ esc_html__('Payment Method(s)', 'event_espresso') ] = implode(
417
+            $reg_csv_array[esc_html__('Payment Method(s)', 'event_espresso')] = implode(
418 418
                 ',',
419 419
                 $payment_methods
420 420
             );
421 421
 
422
-            $reg_csv_array[ esc_html__('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
422
+            $reg_csv_array[esc_html__('Gateway Transaction ID(s)', 'event_espresso')] = implode(
423 423
                 ',',
424 424
                 $gateway_txn_ids_etc
425 425
             );
@@ -427,7 +427,7 @@  discard block
 block discarded – undo
427 427
             $ticket_name      = esc_html__('Unknown', 'event_espresso');
428 428
             $datetime_strings = [esc_html__('Unknown', 'event_espresso')];
429 429
             if ($reg_row['Ticket.TKT_ID']) {
430
-                $ticket_name       = EEH_Export::prepare_value_from_db_for_display(
430
+                $ticket_name = EEH_Export::prepare_value_from_db_for_display(
431 431
                     $ticket_model,
432 432
                     'TKT_name',
433 433
                     $reg_row['Ticket.TKT_name']
@@ -449,10 +449,10 @@  discard block
 block discarded – undo
449 449
                 }
450 450
             }
451 451
 
452
-            $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
452
+            $reg_csv_array[$ticket_model->field_settings_for('TKT_name')->get_nicename()] = $ticket_name;
453 453
 
454 454
 
455
-            $reg_csv_array[ esc_html__('Ticket Datetimes', 'event_espresso') ] = implode(
455
+            $reg_csv_array[esc_html__('Ticket Datetimes', 'event_espresso')] = implode(
456 456
                 ', ',
457 457
                 $datetime_strings
458 458
             );
@@ -462,7 +462,7 @@  discard block
 block discarded – undo
462 462
             // Include check-in data
463 463
             if ($event_id && $DTT_ID) {
464 464
                 // get whether or not the user has checked in
465
-                $reg_csv_array[ esc_html__('Datetime Check-ins #', 'event_espresso') ] =
465
+                $reg_csv_array[esc_html__('Datetime Check-ins #', 'event_espresso')] =
466 466
                     $reg_model->count_related(
467 467
                         $reg_row['Registration.REG_ID'],
468 468
                         'Checkin',
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
                         ],
483 483
                     ]
484 484
                 );
485
-                $checkins     = [];
485
+                $checkins = [];
486 486
                 foreach ($checkin_rows as $checkin_row) {
487 487
                     /** @var EE_Checkin $checkin_row */
488 488
                     $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
@@ -491,10 +491,10 @@  discard block
 block discarded – undo
491 491
                     }
492 492
                 }
493 493
                 $datetime_name                   = CheckinsCSV::getDatetimeLabel($datetime);
494
-                $reg_csv_array[ $datetime_name ] = implode(' --- ', $checkins);
494
+                $reg_csv_array[$datetime_name] = implode(' --- ', $checkins);
495 495
             } elseif ($event_id) {
496 496
                 // get whether or not the user has checked in
497
-                $reg_csv_array[ esc_html__('Event Check-ins #', 'event_espresso') ] =
497
+                $reg_csv_array[esc_html__('Event Check-ins #', 'event_espresso')] =
498 498
                     $reg_model->count_related(
499 499
                         $reg_row['Registration.REG_ID'],
500 500
                         'Checkin'
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
                     ]
511 511
                 );
512 512
                 foreach ($datetimes as $datetime) {
513
-                    if (! $datetime instanceof EE_Datetime) {
513
+                    if ( ! $datetime instanceof EE_Datetime) {
514 514
                         continue;
515 515
                     }
516 516
 
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
                     $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
532 532
                     $datetime_name = CheckinsCSV::getDatetimeLabel($datetime);
533 533
 
534
-                    $reg_csv_array[ $datetime_name ] = $checkin_value;
534
+                    $reg_csv_array[$datetime_name] = $checkin_value;
535 535
                 }
536 536
             }
537 537
             /**
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
                 foreach ($field_list as $field_name) {
561 561
                     $field                                                          =
562 562
                         $model->field_settings_for($field_name);
563
-                    $reg_csv_array[ EEH_Export::get_column_name_for_field($field) ] = null;
563
+                    $reg_csv_array[EEH_Export::get_column_name_for_field($field)] = null;
564 564
                 }
565 565
             }
566 566
             $registrations_csv_ready_array[] = $reg_csv_array;
@@ -615,7 +615,7 @@  discard block
 block discarded – undo
615 615
                         'event_espresso'
616 616
                     ),
617 617
                     '<span id="ee-redirect-timer">10</span>',
618
-                    '<a href="' . $job_parameters->request_datum('return_url') . '">',
618
+                    '<a href="'.$job_parameters->request_datum('return_url').'">',
619 619
                     '</a>'
620 620
                 )
621 621
             )
Please login to merge, or discard this patch.
core/services/request/ServerParams.php 2 patches
Indentation   +201 added lines, -201 removed lines patch added patch discarded remove patch
@@ -6,205 +6,205 @@
 block discarded – undo
6 6
 
7 7
 class ServerParams
8 8
 {
9
-    /**
10
-     * IP address for request
11
-     *
12
-     * @var string
13
-     */
14
-    protected $ip_address;
15
-
16
-
17
-    /**
18
-     * @var ServerSanitizer
19
-     */
20
-    protected $sanitizer;
21
-
22
-    /**
23
-     * sanitized $_SERVER parameters
24
-     *
25
-     * @var array
26
-     */
27
-    protected $server;
28
-
29
-    /**
30
-     * @var string
31
-     */
32
-    protected $request_uri;
33
-
34
-    /**
35
-     * @var string
36
-     */
37
-    protected $user_agent;
38
-
39
-
40
-    /**
41
-     * ServerParams constructor.
42
-     *
43
-     * @param ServerSanitizer $sanitizer
44
-     * @param array           $server
45
-     */
46
-    public function __construct(ServerSanitizer $sanitizer, array $server = [])
47
-    {
48
-        $this->sanitizer  = $sanitizer;
49
-        $this->server     = $this->cleanServerParams($server);
50
-        $this->ip_address = $this->setVisitorIp();
51
-    }
52
-
53
-
54
-    /**
55
-     * @return array
56
-     */
57
-    private function cleanServerParams(array $server)
58
-    {
59
-        $cleaned = [];
60
-        $server  = ! empty($server) ? $server : $_SERVER;
61
-        foreach ($server as $key => $value) {
62
-            $cleaned[ $key ] = $this->sanitizer->clean($key, $value);
63
-        }
64
-        return $cleaned;
65
-    }
66
-
67
-
68
-    /**
69
-     * @return array
70
-     */
71
-    public function getAllServerParams()
72
-    {
73
-        return $this->server;
74
-    }
75
-
76
-
77
-    /**
78
-     * @param string $key
79
-     * @param mixed|null $default
80
-     * @return array|int|float|string
81
-     */
82
-    public function getServerParam($key, $default = null)
83
-    {
84
-        return $this->serverParamIsSet($key) ? $this->server[ $key ] : $default;
85
-    }
86
-
87
-
88
-    /**
89
-     * @param string                 $key
90
-     * @param array|int|float|string $value
91
-     * @param bool                   $set_global_too
92
-     * @return void
93
-     */
94
-    public function setServerParam(string $key, $value, bool $set_global_too = false)
95
-    {
96
-        $value = $this->sanitizer->clean($key, $value);
97
-        $this->server[ $key ] = $value;
98
-        if ($set_global_too) {
99
-            $_SERVER[ $key ] = $value;
100
-        }
101
-    }
102
-
103
-
104
-    /**
105
-     * @param string $key
106
-     * @param bool   $unset_from_global_too
107
-     * @return void
108
-     */
109
-    public function unSetServerParam(string $key, bool $unset_from_global_too = false)
110
-    {
111
-        // because unset may not actually remove var
112
-        $this->server[ $key ] = null;
113
-        unset($this->server[ $key ]);
114
-        if ($unset_from_global_too) {
115
-            unset($_SERVER[ $key ]);
116
-        }
117
-    }
118
-
119
-
120
-    /**
121
-     * @return bool
122
-     */
123
-    public function serverParamIsSet($key)
124
-    {
125
-        return isset($this->server[ $key ]);
126
-    }
127
-
128
-
129
-    /**
130
-     * @return string
131
-     */
132
-    public function ipAddress()
133
-    {
134
-        return $this->ip_address;
135
-    }
136
-
137
-
138
-    /**
139
-     * attempt to get IP address of current visitor from server
140
-     * plz see: http://stackoverflow.com/a/2031935/1475279
141
-     *
142
-     * @access public
143
-     * @return string
144
-     */
145
-    private function setVisitorIp()
146
-    {
147
-        $visitor_ip  = '0.0.0.0';
148
-        $server_keys = [
149
-            'HTTP_CLIENT_IP',
150
-            'HTTP_FORWARDED',
151
-            'HTTP_FORWARDED_FOR',
152
-            'HTTP_X_CLUSTER_CLIENT_IP',
153
-            'HTTP_X_FORWARDED',
154
-            'HTTP_X_FORWARDED_FOR',
155
-            'REMOTE_ADDR',
156
-        ];
157
-        foreach ($server_keys as $key) {
158
-            if (isset($this->server[ $key ])) {
159
-                $potential_ip = array_map('trim', explode(',', $this->server[ $key ]));
160
-                foreach ($potential_ip as $ip) {
161
-                    if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
162
-                        $visitor_ip = $ip;
163
-                    }
164
-                }
165
-            }
166
-        }
167
-        return $visitor_ip;
168
-    }
169
-
170
-
171
-    /**
172
-     * Gets the request's literal URI. Related to `requestUriAfterSiteHomeUri`, see its description for a comparison.
173
-     *
174
-     * @param boolean $relativeToWpRoot If home_url() is "http://mysite.com/wp/", and a request comes to
175
-     *                                  "http://mysite.com/wp/wp-json", setting $relativeToWpRoot=true will return
176
-     *                                  "/wp-json", whereas $relativeToWpRoot=false will return "/wp/wp-json/".
177
-     * @return string
178
-     */
179
-    public function requestUri($relativeToWpRoot = false)
180
-    {
181
-        if ($relativeToWpRoot) {
182
-            $home_path = untrailingslashit(parse_url(home_url(), PHP_URL_PATH));
183
-            return str_replace($home_path, '', $this->server['REQUEST_URI']);
184
-        }
185
-        return $this->server['REQUEST_URI'];
186
-    }
187
-
188
-
189
-    /**
190
-     * @return string
191
-     */
192
-    public function userAgent()
193
-    {
194
-        if (empty($this->user_agent)) {
195
-            $this->setUserAgent();
196
-        }
197
-        return $this->user_agent;
198
-    }
199
-
200
-
201
-    /**
202
-     * @param string $user_agent
203
-     */
204
-    public function setUserAgent($user_agent = '')
205
-    {
206
-        $this->user_agent = $user_agent === '' || ! is_string($user_agent)
207
-            ? $this->getServerParam('HTTP_USER_AGENT')
208
-            : esc_attr($user_agent);
209
-    }
9
+	/**
10
+	 * IP address for request
11
+	 *
12
+	 * @var string
13
+	 */
14
+	protected $ip_address;
15
+
16
+
17
+	/**
18
+	 * @var ServerSanitizer
19
+	 */
20
+	protected $sanitizer;
21
+
22
+	/**
23
+	 * sanitized $_SERVER parameters
24
+	 *
25
+	 * @var array
26
+	 */
27
+	protected $server;
28
+
29
+	/**
30
+	 * @var string
31
+	 */
32
+	protected $request_uri;
33
+
34
+	/**
35
+	 * @var string
36
+	 */
37
+	protected $user_agent;
38
+
39
+
40
+	/**
41
+	 * ServerParams constructor.
42
+	 *
43
+	 * @param ServerSanitizer $sanitizer
44
+	 * @param array           $server
45
+	 */
46
+	public function __construct(ServerSanitizer $sanitizer, array $server = [])
47
+	{
48
+		$this->sanitizer  = $sanitizer;
49
+		$this->server     = $this->cleanServerParams($server);
50
+		$this->ip_address = $this->setVisitorIp();
51
+	}
52
+
53
+
54
+	/**
55
+	 * @return array
56
+	 */
57
+	private function cleanServerParams(array $server)
58
+	{
59
+		$cleaned = [];
60
+		$server  = ! empty($server) ? $server : $_SERVER;
61
+		foreach ($server as $key => $value) {
62
+			$cleaned[ $key ] = $this->sanitizer->clean($key, $value);
63
+		}
64
+		return $cleaned;
65
+	}
66
+
67
+
68
+	/**
69
+	 * @return array
70
+	 */
71
+	public function getAllServerParams()
72
+	{
73
+		return $this->server;
74
+	}
75
+
76
+
77
+	/**
78
+	 * @param string $key
79
+	 * @param mixed|null $default
80
+	 * @return array|int|float|string
81
+	 */
82
+	public function getServerParam($key, $default = null)
83
+	{
84
+		return $this->serverParamIsSet($key) ? $this->server[ $key ] : $default;
85
+	}
86
+
87
+
88
+	/**
89
+	 * @param string                 $key
90
+	 * @param array|int|float|string $value
91
+	 * @param bool                   $set_global_too
92
+	 * @return void
93
+	 */
94
+	public function setServerParam(string $key, $value, bool $set_global_too = false)
95
+	{
96
+		$value = $this->sanitizer->clean($key, $value);
97
+		$this->server[ $key ] = $value;
98
+		if ($set_global_too) {
99
+			$_SERVER[ $key ] = $value;
100
+		}
101
+	}
102
+
103
+
104
+	/**
105
+	 * @param string $key
106
+	 * @param bool   $unset_from_global_too
107
+	 * @return void
108
+	 */
109
+	public function unSetServerParam(string $key, bool $unset_from_global_too = false)
110
+	{
111
+		// because unset may not actually remove var
112
+		$this->server[ $key ] = null;
113
+		unset($this->server[ $key ]);
114
+		if ($unset_from_global_too) {
115
+			unset($_SERVER[ $key ]);
116
+		}
117
+	}
118
+
119
+
120
+	/**
121
+	 * @return bool
122
+	 */
123
+	public function serverParamIsSet($key)
124
+	{
125
+		return isset($this->server[ $key ]);
126
+	}
127
+
128
+
129
+	/**
130
+	 * @return string
131
+	 */
132
+	public function ipAddress()
133
+	{
134
+		return $this->ip_address;
135
+	}
136
+
137
+
138
+	/**
139
+	 * attempt to get IP address of current visitor from server
140
+	 * plz see: http://stackoverflow.com/a/2031935/1475279
141
+	 *
142
+	 * @access public
143
+	 * @return string
144
+	 */
145
+	private function setVisitorIp()
146
+	{
147
+		$visitor_ip  = '0.0.0.0';
148
+		$server_keys = [
149
+			'HTTP_CLIENT_IP',
150
+			'HTTP_FORWARDED',
151
+			'HTTP_FORWARDED_FOR',
152
+			'HTTP_X_CLUSTER_CLIENT_IP',
153
+			'HTTP_X_FORWARDED',
154
+			'HTTP_X_FORWARDED_FOR',
155
+			'REMOTE_ADDR',
156
+		];
157
+		foreach ($server_keys as $key) {
158
+			if (isset($this->server[ $key ])) {
159
+				$potential_ip = array_map('trim', explode(',', $this->server[ $key ]));
160
+				foreach ($potential_ip as $ip) {
161
+					if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
162
+						$visitor_ip = $ip;
163
+					}
164
+				}
165
+			}
166
+		}
167
+		return $visitor_ip;
168
+	}
169
+
170
+
171
+	/**
172
+	 * Gets the request's literal URI. Related to `requestUriAfterSiteHomeUri`, see its description for a comparison.
173
+	 *
174
+	 * @param boolean $relativeToWpRoot If home_url() is "http://mysite.com/wp/", and a request comes to
175
+	 *                                  "http://mysite.com/wp/wp-json", setting $relativeToWpRoot=true will return
176
+	 *                                  "/wp-json", whereas $relativeToWpRoot=false will return "/wp/wp-json/".
177
+	 * @return string
178
+	 */
179
+	public function requestUri($relativeToWpRoot = false)
180
+	{
181
+		if ($relativeToWpRoot) {
182
+			$home_path = untrailingslashit(parse_url(home_url(), PHP_URL_PATH));
183
+			return str_replace($home_path, '', $this->server['REQUEST_URI']);
184
+		}
185
+		return $this->server['REQUEST_URI'];
186
+	}
187
+
188
+
189
+	/**
190
+	 * @return string
191
+	 */
192
+	public function userAgent()
193
+	{
194
+		if (empty($this->user_agent)) {
195
+			$this->setUserAgent();
196
+		}
197
+		return $this->user_agent;
198
+	}
199
+
200
+
201
+	/**
202
+	 * @param string $user_agent
203
+	 */
204
+	public function setUserAgent($user_agent = '')
205
+	{
206
+		$this->user_agent = $user_agent === '' || ! is_string($user_agent)
207
+			? $this->getServerParam('HTTP_USER_AGENT')
208
+			: esc_attr($user_agent);
209
+	}
210 210
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -59,7 +59,7 @@  discard block
 block discarded – undo
59 59
         $cleaned = [];
60 60
         $server  = ! empty($server) ? $server : $_SERVER;
61 61
         foreach ($server as $key => $value) {
62
-            $cleaned[ $key ] = $this->sanitizer->clean($key, $value);
62
+            $cleaned[$key] = $this->sanitizer->clean($key, $value);
63 63
         }
64 64
         return $cleaned;
65 65
     }
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
      */
82 82
     public function getServerParam($key, $default = null)
83 83
     {
84
-        return $this->serverParamIsSet($key) ? $this->server[ $key ] : $default;
84
+        return $this->serverParamIsSet($key) ? $this->server[$key] : $default;
85 85
     }
86 86
 
87 87
 
@@ -94,9 +94,9 @@  discard block
 block discarded – undo
94 94
     public function setServerParam(string $key, $value, bool $set_global_too = false)
95 95
     {
96 96
         $value = $this->sanitizer->clean($key, $value);
97
-        $this->server[ $key ] = $value;
97
+        $this->server[$key] = $value;
98 98
         if ($set_global_too) {
99
-            $_SERVER[ $key ] = $value;
99
+            $_SERVER[$key] = $value;
100 100
         }
101 101
     }
102 102
 
@@ -109,10 +109,10 @@  discard block
 block discarded – undo
109 109
     public function unSetServerParam(string $key, bool $unset_from_global_too = false)
110 110
     {
111 111
         // because unset may not actually remove var
112
-        $this->server[ $key ] = null;
113
-        unset($this->server[ $key ]);
112
+        $this->server[$key] = null;
113
+        unset($this->server[$key]);
114 114
         if ($unset_from_global_too) {
115
-            unset($_SERVER[ $key ]);
115
+            unset($_SERVER[$key]);
116 116
         }
117 117
     }
118 118
 
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
      */
123 123
     public function serverParamIsSet($key)
124 124
     {
125
-        return isset($this->server[ $key ]);
125
+        return isset($this->server[$key]);
126 126
     }
127 127
 
128 128
 
@@ -155,8 +155,8 @@  discard block
 block discarded – undo
155 155
             'REMOTE_ADDR',
156 156
         ];
157 157
         foreach ($server_keys as $key) {
158
-            if (isset($this->server[ $key ])) {
159
-                $potential_ip = array_map('trim', explode(',', $this->server[ $key ]));
158
+            if (isset($this->server[$key])) {
159
+                $potential_ip = array_map('trim', explode(',', $this->server[$key]));
160 160
                 foreach ($potential_ip as $ip) {
161 161
                     if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
162 162
                         $visitor_ip = $ip;
Please login to merge, or discard this patch.
admin/extend/registrations/Extend_Registrations_Admin_Page.core.php 1 patch
Indentation   +1232 added lines, -1232 removed lines patch added patch discarded remove patch
@@ -14,1291 +14,1291 @@
 block discarded – undo
14 14
  */
15 15
 class Extend_Registrations_Admin_Page extends Registrations_Admin_Page
16 16
 {
17
-    /**
18
-     * This is used to hold the reports template data which is setup early in the request.
19
-     *
20
-     * @type array
21
-     */
22
-    protected $_reports_template_data = array();
17
+	/**
18
+	 * This is used to hold the reports template data which is setup early in the request.
19
+	 *
20
+	 * @type array
21
+	 */
22
+	protected $_reports_template_data = array();
23 23
 
24 24
 
25
-    /**
26
-     * Extend_Registrations_Admin_Page constructor.
27
-     *
28
-     * @param bool $routing
29
-     */
30
-    public function __construct($routing = true)
31
-    {
32
-        parent::__construct($routing);
33
-        if (! defined('REG_CAF_TEMPLATE_PATH')) {
34
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
35
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
36
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
37
-        }
38
-    }
25
+	/**
26
+	 * Extend_Registrations_Admin_Page constructor.
27
+	 *
28
+	 * @param bool $routing
29
+	 */
30
+	public function __construct($routing = true)
31
+	{
32
+		parent::__construct($routing);
33
+		if (! defined('REG_CAF_TEMPLATE_PATH')) {
34
+			define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
35
+			define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
36
+			define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
37
+		}
38
+	}
39 39
 
40 40
 
41
-    /**
42
-     * Extending page configuration.
43
-     */
44
-    protected function _extend_page_config()
45
-    {
46
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
47
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
48
-            ? $this->_req_data['_REG_ID']
49
-            : 0;
50
-        $new_page_routes = array(
51
-            'reports'                      => array(
52
-                'func'       => '_registration_reports',
53
-                'capability' => 'ee_read_registrations',
54
-            ),
55
-            'registration_checkins'        => array(
56
-                'func'       => '_registration_checkin_list_table',
57
-                'capability' => 'ee_read_checkins',
58
-            ),
59
-            'newsletter_selected_send'     => array(
60
-                'func'       => '_newsletter_selected_send',
61
-                'noheader'   => true,
62
-                'capability' => 'ee_send_message',
63
-            ),
64
-            'delete_checkin_rows'          => array(
65
-                'func'       => '_delete_checkin_rows',
66
-                'noheader'   => true,
67
-                'capability' => 'ee_delete_checkins',
68
-            ),
69
-            'delete_checkin_row'           => array(
70
-                'func'       => '_delete_checkin_row',
71
-                'noheader'   => true,
72
-                'capability' => 'ee_delete_checkin',
73
-                'obj_id'     => $reg_id,
74
-            ),
75
-            'toggle_checkin_status'        => array(
76
-                'func'       => '_toggle_checkin_status',
77
-                'noheader'   => true,
78
-                'capability' => 'ee_edit_checkin',
79
-                'obj_id'     => $reg_id,
80
-            ),
81
-            'toggle_checkin_status_bulk'   => array(
82
-                'func'       => '_toggle_checkin_status',
83
-                'noheader'   => true,
84
-                'capability' => 'ee_edit_checkins',
85
-            ),
86
-            'event_registrations'          => array(
87
-                'func'       => '_event_registrations_list_table',
88
-                'capability' => 'ee_read_checkins',
89
-            ),
90
-            'registrations_checkin_report' => array(
91
-                'func'       => '_registrations_checkin_report',
92
-                'noheader'   => true,
93
-                'capability' => 'ee_read_registrations',
94
-            ),
95
-        );
96
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
97
-        $new_page_config = array(
98
-            'reports'               => array(
99
-                'nav'           => array(
100
-                    'label' => esc_html__('Reports', 'event_espresso'),
101
-                    'icon' => 'dashicons-chart-bar',
102
-                    'order' => 30,
103
-                ),
104
-                'help_tabs'     => array(
105
-                    'registrations_reports_help_tab' => array(
106
-                        'title'    => esc_html__('Registration Reports', 'event_espresso'),
107
-                        'filename' => 'registrations_reports',
108
-                    ),
109
-                ),
110
-                'require_nonce' => false,
111
-            ),
112
-            'event_registrations'   => array(
113
-                'nav'           => array(
114
-                    'label'      => esc_html__('Event Check-In', 'event_espresso'),
115
-                    'icon' => 'dashicons-yes-alt',
116
-                    'order'      => 10,
117
-                    'persistent' => true,
118
-                ),
119
-                'help_tabs'     => array(
120
-                    'registrations_event_checkin_help_tab'                       => array(
121
-                        'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
122
-                        'filename' => 'registrations_event_checkin',
123
-                    ),
124
-                    'registrations_event_checkin_table_column_headings_help_tab' => array(
125
-                        'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
126
-                        'filename' => 'registrations_event_checkin_table_column_headings',
127
-                    ),
128
-                    'registrations_event_checkin_filters_help_tab'               => array(
129
-                        'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
130
-                        'filename' => 'registrations_event_checkin_filters',
131
-                    ),
132
-                    'registrations_event_checkin_views_help_tab'                 => array(
133
-                        'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
134
-                        'filename' => 'registrations_event_checkin_views',
135
-                    ),
136
-                    'registrations_event_checkin_other_help_tab'                 => array(
137
-                        'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
138
-                        'filename' => 'registrations_event_checkin_other',
139
-                    ),
140
-                ),
141
-                'list_table'    => 'EE_Event_Registrations_List_Table',
142
-                'metaboxes'     => array(),
143
-                'require_nonce' => false,
144
-            ),
145
-            'registration_checkins' => array(
146
-                'nav'           => array(
147
-                    'label'      => esc_html__('Check-In Records', 'event_espresso'),
148
-                    'icon' => 'dashicons-list-view',
149
-                    'order'      => 15,
150
-                    'persistent' => false,
151
-                    'url'        => '',
152
-                ),
153
-                'list_table'    => 'EE_Registration_CheckIn_List_Table',
154
-                'metaboxes'     => array(),
155
-                'require_nonce' => false,
156
-            ),
157
-        );
158
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
159
-        $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
160
-        $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
161
-    }
41
+	/**
42
+	 * Extending page configuration.
43
+	 */
44
+	protected function _extend_page_config()
45
+	{
46
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
47
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
48
+			? $this->_req_data['_REG_ID']
49
+			: 0;
50
+		$new_page_routes = array(
51
+			'reports'                      => array(
52
+				'func'       => '_registration_reports',
53
+				'capability' => 'ee_read_registrations',
54
+			),
55
+			'registration_checkins'        => array(
56
+				'func'       => '_registration_checkin_list_table',
57
+				'capability' => 'ee_read_checkins',
58
+			),
59
+			'newsletter_selected_send'     => array(
60
+				'func'       => '_newsletter_selected_send',
61
+				'noheader'   => true,
62
+				'capability' => 'ee_send_message',
63
+			),
64
+			'delete_checkin_rows'          => array(
65
+				'func'       => '_delete_checkin_rows',
66
+				'noheader'   => true,
67
+				'capability' => 'ee_delete_checkins',
68
+			),
69
+			'delete_checkin_row'           => array(
70
+				'func'       => '_delete_checkin_row',
71
+				'noheader'   => true,
72
+				'capability' => 'ee_delete_checkin',
73
+				'obj_id'     => $reg_id,
74
+			),
75
+			'toggle_checkin_status'        => array(
76
+				'func'       => '_toggle_checkin_status',
77
+				'noheader'   => true,
78
+				'capability' => 'ee_edit_checkin',
79
+				'obj_id'     => $reg_id,
80
+			),
81
+			'toggle_checkin_status_bulk'   => array(
82
+				'func'       => '_toggle_checkin_status',
83
+				'noheader'   => true,
84
+				'capability' => 'ee_edit_checkins',
85
+			),
86
+			'event_registrations'          => array(
87
+				'func'       => '_event_registrations_list_table',
88
+				'capability' => 'ee_read_checkins',
89
+			),
90
+			'registrations_checkin_report' => array(
91
+				'func'       => '_registrations_checkin_report',
92
+				'noheader'   => true,
93
+				'capability' => 'ee_read_registrations',
94
+			),
95
+		);
96
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
97
+		$new_page_config = array(
98
+			'reports'               => array(
99
+				'nav'           => array(
100
+					'label' => esc_html__('Reports', 'event_espresso'),
101
+					'icon' => 'dashicons-chart-bar',
102
+					'order' => 30,
103
+				),
104
+				'help_tabs'     => array(
105
+					'registrations_reports_help_tab' => array(
106
+						'title'    => esc_html__('Registration Reports', 'event_espresso'),
107
+						'filename' => 'registrations_reports',
108
+					),
109
+				),
110
+				'require_nonce' => false,
111
+			),
112
+			'event_registrations'   => array(
113
+				'nav'           => array(
114
+					'label'      => esc_html__('Event Check-In', 'event_espresso'),
115
+					'icon' => 'dashicons-yes-alt',
116
+					'order'      => 10,
117
+					'persistent' => true,
118
+				),
119
+				'help_tabs'     => array(
120
+					'registrations_event_checkin_help_tab'                       => array(
121
+						'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
122
+						'filename' => 'registrations_event_checkin',
123
+					),
124
+					'registrations_event_checkin_table_column_headings_help_tab' => array(
125
+						'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
126
+						'filename' => 'registrations_event_checkin_table_column_headings',
127
+					),
128
+					'registrations_event_checkin_filters_help_tab'               => array(
129
+						'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
130
+						'filename' => 'registrations_event_checkin_filters',
131
+					),
132
+					'registrations_event_checkin_views_help_tab'                 => array(
133
+						'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
134
+						'filename' => 'registrations_event_checkin_views',
135
+					),
136
+					'registrations_event_checkin_other_help_tab'                 => array(
137
+						'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
138
+						'filename' => 'registrations_event_checkin_other',
139
+					),
140
+				),
141
+				'list_table'    => 'EE_Event_Registrations_List_Table',
142
+				'metaboxes'     => array(),
143
+				'require_nonce' => false,
144
+			),
145
+			'registration_checkins' => array(
146
+				'nav'           => array(
147
+					'label'      => esc_html__('Check-In Records', 'event_espresso'),
148
+					'icon' => 'dashicons-list-view',
149
+					'order'      => 15,
150
+					'persistent' => false,
151
+					'url'        => '',
152
+				),
153
+				'list_table'    => 'EE_Registration_CheckIn_List_Table',
154
+				'metaboxes'     => array(),
155
+				'require_nonce' => false,
156
+			),
157
+		);
158
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
159
+		$this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
160
+		$this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
161
+	}
162 162
 
163 163
 
164
-    /**
165
-     * Ajax hooks for all routes in this page.
166
-     */
167
-    protected function _ajax_hooks()
168
-    {
169
-        parent::_ajax_hooks();
170
-        add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
171
-    }
164
+	/**
165
+	 * Ajax hooks for all routes in this page.
166
+	 */
167
+	protected function _ajax_hooks()
168
+	{
169
+		parent::_ajax_hooks();
170
+		add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
171
+	}
172 172
 
173 173
 
174
-    /**
175
-     * Global scripts for all routes in this page.
176
-     */
177
-    public function load_scripts_styles()
178
-    {
179
-        parent::load_scripts_styles();
180
-        // if newsletter message type is active then let's add filter and load js for it.
181
-        if (EEH_MSG_Template::is_mt_active('newsletter')) {
182
-            // enqueue newsletter js
183
-            wp_enqueue_script(
184
-                'ee-newsletter-trigger',
185
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
186
-                array('ee-dialog'),
187
-                EVENT_ESPRESSO_VERSION,
188
-                true
189
-            );
190
-            wp_enqueue_style(
191
-                'ee-newsletter-trigger-css',
192
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
193
-                array(),
194
-                EVENT_ESPRESSO_VERSION
195
-            );
196
-            // hook in buttons for newsletter message type trigger.
197
-            add_action(
198
-                'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
199
-                array($this, 'add_newsletter_action_buttons'),
200
-                10
201
-            );
202
-        }
203
-    }
174
+	/**
175
+	 * Global scripts for all routes in this page.
176
+	 */
177
+	public function load_scripts_styles()
178
+	{
179
+		parent::load_scripts_styles();
180
+		// if newsletter message type is active then let's add filter and load js for it.
181
+		if (EEH_MSG_Template::is_mt_active('newsletter')) {
182
+			// enqueue newsletter js
183
+			wp_enqueue_script(
184
+				'ee-newsletter-trigger',
185
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
186
+				array('ee-dialog'),
187
+				EVENT_ESPRESSO_VERSION,
188
+				true
189
+			);
190
+			wp_enqueue_style(
191
+				'ee-newsletter-trigger-css',
192
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
193
+				array(),
194
+				EVENT_ESPRESSO_VERSION
195
+			);
196
+			// hook in buttons for newsletter message type trigger.
197
+			add_action(
198
+				'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
199
+				array($this, 'add_newsletter_action_buttons'),
200
+				10
201
+			);
202
+		}
203
+	}
204 204
 
205 205
 
206
-    /**
207
-     * Scripts and styles for just the reports route.
208
-     */
209
-    public function load_scripts_styles_reports()
210
-    {
211
-        wp_register_script(
212
-            'ee-reg-reports-js',
213
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
214
-            array('google-charts'),
215
-            EVENT_ESPRESSO_VERSION,
216
-            true
217
-        );
218
-        wp_enqueue_script('ee-reg-reports-js');
219
-        $this->_registration_reports_js_setup();
220
-    }
206
+	/**
207
+	 * Scripts and styles for just the reports route.
208
+	 */
209
+	public function load_scripts_styles_reports()
210
+	{
211
+		wp_register_script(
212
+			'ee-reg-reports-js',
213
+			REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
214
+			array('google-charts'),
215
+			EVENT_ESPRESSO_VERSION,
216
+			true
217
+		);
218
+		wp_enqueue_script('ee-reg-reports-js');
219
+		$this->_registration_reports_js_setup();
220
+	}
221 221
 
222 222
 
223
-    /**
224
-     * Register screen options for event_registrations route.
225
-     */
226
-    protected function _add_screen_options_event_registrations()
227
-    {
228
-        $this->_per_page_screen_option();
229
-    }
223
+	/**
224
+	 * Register screen options for event_registrations route.
225
+	 */
226
+	protected function _add_screen_options_event_registrations()
227
+	{
228
+		$this->_per_page_screen_option();
229
+	}
230 230
 
231 231
 
232
-    /**
233
-     * Register screen options for registration_checkins route
234
-     */
235
-    protected function _add_screen_options_registration_checkins()
236
-    {
237
-        $page_title = $this->_admin_page_title;
238
-        $this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
239
-        $this->_per_page_screen_option();
240
-        $this->_admin_page_title = $page_title;
241
-    }
232
+	/**
233
+	 * Register screen options for registration_checkins route
234
+	 */
235
+	protected function _add_screen_options_registration_checkins()
236
+	{
237
+		$page_title = $this->_admin_page_title;
238
+		$this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
239
+		$this->_per_page_screen_option();
240
+		$this->_admin_page_title = $page_title;
241
+	}
242 242
 
243 243
 
244
-    /**
245
-     * Set views property for event_registrations route.
246
-     */
247
-    protected function _set_list_table_views_event_registrations()
248
-    {
249
-        $this->_views = array(
250
-            'all' => array(
251
-                'slug'        => 'all',
252
-                'label'       => esc_html__('All', 'event_espresso'),
253
-                'count'       => 0,
254
-                'bulk_action' => ! isset($this->_req_data['event_id'])
255
-                    ? array()
256
-                    : array(
257
-                        'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
258
-                    ),
259
-            ),
260
-        );
261
-    }
244
+	/**
245
+	 * Set views property for event_registrations route.
246
+	 */
247
+	protected function _set_list_table_views_event_registrations()
248
+	{
249
+		$this->_views = array(
250
+			'all' => array(
251
+				'slug'        => 'all',
252
+				'label'       => esc_html__('All', 'event_espresso'),
253
+				'count'       => 0,
254
+				'bulk_action' => ! isset($this->_req_data['event_id'])
255
+					? array()
256
+					: array(
257
+						'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
258
+					),
259
+			),
260
+		);
261
+	}
262 262
 
263 263
 
264
-    /**
265
-     * Set views property for registration_checkins route.
266
-     */
267
-    protected function _set_list_table_views_registration_checkins()
268
-    {
269
-        $this->_views = array(
270
-            'all' => array(
271
-                'slug'        => 'all',
272
-                'label'       => esc_html__('All', 'event_espresso'),
273
-                'count'       => 0,
274
-                'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
275
-            ),
276
-        );
277
-    }
264
+	/**
265
+	 * Set views property for registration_checkins route.
266
+	 */
267
+	protected function _set_list_table_views_registration_checkins()
268
+	{
269
+		$this->_views = array(
270
+			'all' => array(
271
+				'slug'        => 'all',
272
+				'label'       => esc_html__('All', 'event_espresso'),
273
+				'count'       => 0,
274
+				'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
275
+			),
276
+		);
277
+	}
278 278
 
279 279
 
280
-    /**
281
-     * callback for ajax action.
282
-     *
283
-     * @since 4.3.0
284
-     * @return void (JSON)
285
-     * @throws EE_Error
286
-     * @throws InvalidArgumentException
287
-     * @throws InvalidDataTypeException
288
-     * @throws InvalidInterfaceException
289
-     */
290
-    public function get_newsletter_form_content()
291
-    {
292
-        // do a nonce check cause we're not coming in from an normal route here.
293
-        $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
294
-            $this->_req_data['get_newsletter_form_content_nonce']
295
-        ) : '';
296
-        $nonce_ref = 'get_newsletter_form_content_nonce';
297
-        $this->_verify_nonce($nonce, $nonce_ref);
298
-        // let's get the mtp for the incoming MTP_ ID
299
-        if (! isset($this->_req_data['GRP_ID'])) {
300
-            EE_Error::add_error(
301
-                esc_html__(
302
-                    'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
303
-                    'event_espresso'
304
-                ),
305
-                __FILE__,
306
-                __FUNCTION__,
307
-                __LINE__
308
-            );
309
-            $this->_template_args['success'] = false;
310
-            $this->_template_args['error'] = true;
311
-            $this->_return_json();
312
-        }
313
-        $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
314
-        if (! $MTPG instanceof EE_Message_Template_Group) {
315
-            EE_Error::add_error(
316
-                sprintf(
317
-                    esc_html__(
318
-                        'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
319
-                        'event_espresso'
320
-                    ),
321
-                    $this->_req_data['GRP_ID']
322
-                ),
323
-                __FILE__,
324
-                __FUNCTION__,
325
-                __LINE__
326
-            );
327
-            $this->_template_args['success'] = false;
328
-            $this->_template_args['error'] = true;
329
-            $this->_return_json();
330
-        }
331
-        $MTPs = $MTPG->context_templates();
332
-        $MTPs = $MTPs['attendee'];
333
-        $template_fields = array();
334
-        /** @var EE_Message_Template $MTP */
335
-        foreach ($MTPs as $MTP) {
336
-            $field = $MTP->get('MTP_template_field');
337
-            if ($field === 'content') {
338
-                $content = $MTP->get('MTP_content');
339
-                if (! empty($content['newsletter_content'])) {
340
-                    $template_fields['newsletter_content'] = $content['newsletter_content'];
341
-                }
342
-                continue;
343
-            }
344
-            $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
345
-        }
346
-        $this->_template_args['success'] = true;
347
-        $this->_template_args['error'] = false;
348
-        $this->_template_args['data'] = array(
349
-            'batch_message_from'    => isset($template_fields['from'])
350
-                ? $template_fields['from']
351
-                : '',
352
-            'batch_message_subject' => isset($template_fields['subject'])
353
-                ? $template_fields['subject']
354
-                : '',
355
-            'batch_message_content' => isset($template_fields['newsletter_content'])
356
-                ? $template_fields['newsletter_content']
357
-                : '',
358
-        );
359
-        $this->_return_json();
360
-    }
280
+	/**
281
+	 * callback for ajax action.
282
+	 *
283
+	 * @since 4.3.0
284
+	 * @return void (JSON)
285
+	 * @throws EE_Error
286
+	 * @throws InvalidArgumentException
287
+	 * @throws InvalidDataTypeException
288
+	 * @throws InvalidInterfaceException
289
+	 */
290
+	public function get_newsletter_form_content()
291
+	{
292
+		// do a nonce check cause we're not coming in from an normal route here.
293
+		$nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
294
+			$this->_req_data['get_newsletter_form_content_nonce']
295
+		) : '';
296
+		$nonce_ref = 'get_newsletter_form_content_nonce';
297
+		$this->_verify_nonce($nonce, $nonce_ref);
298
+		// let's get the mtp for the incoming MTP_ ID
299
+		if (! isset($this->_req_data['GRP_ID'])) {
300
+			EE_Error::add_error(
301
+				esc_html__(
302
+					'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
303
+					'event_espresso'
304
+				),
305
+				__FILE__,
306
+				__FUNCTION__,
307
+				__LINE__
308
+			);
309
+			$this->_template_args['success'] = false;
310
+			$this->_template_args['error'] = true;
311
+			$this->_return_json();
312
+		}
313
+		$MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
314
+		if (! $MTPG instanceof EE_Message_Template_Group) {
315
+			EE_Error::add_error(
316
+				sprintf(
317
+					esc_html__(
318
+						'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
319
+						'event_espresso'
320
+					),
321
+					$this->_req_data['GRP_ID']
322
+				),
323
+				__FILE__,
324
+				__FUNCTION__,
325
+				__LINE__
326
+			);
327
+			$this->_template_args['success'] = false;
328
+			$this->_template_args['error'] = true;
329
+			$this->_return_json();
330
+		}
331
+		$MTPs = $MTPG->context_templates();
332
+		$MTPs = $MTPs['attendee'];
333
+		$template_fields = array();
334
+		/** @var EE_Message_Template $MTP */
335
+		foreach ($MTPs as $MTP) {
336
+			$field = $MTP->get('MTP_template_field');
337
+			if ($field === 'content') {
338
+				$content = $MTP->get('MTP_content');
339
+				if (! empty($content['newsletter_content'])) {
340
+					$template_fields['newsletter_content'] = $content['newsletter_content'];
341
+				}
342
+				continue;
343
+			}
344
+			$template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
345
+		}
346
+		$this->_template_args['success'] = true;
347
+		$this->_template_args['error'] = false;
348
+		$this->_template_args['data'] = array(
349
+			'batch_message_from'    => isset($template_fields['from'])
350
+				? $template_fields['from']
351
+				: '',
352
+			'batch_message_subject' => isset($template_fields['subject'])
353
+				? $template_fields['subject']
354
+				: '',
355
+			'batch_message_content' => isset($template_fields['newsletter_content'])
356
+				? $template_fields['newsletter_content']
357
+				: '',
358
+		);
359
+		$this->_return_json();
360
+	}
361 361
 
362 362
 
363
-    /**
364
-     * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
365
-     *
366
-     * @since 4.3.0
367
-     * @param EE_Admin_List_Table $list_table
368
-     * @return void
369
-     * @throws InvalidArgumentException
370
-     * @throws InvalidDataTypeException
371
-     * @throws InvalidInterfaceException
372
-     */
373
-    public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
374
-    {
375
-        if (
376
-            ! EE_Registry::instance()->CAP->current_user_can(
377
-                'ee_send_message',
378
-                'espresso_registrations_newsletter_selected_send'
379
-            )
380
-        ) {
381
-            return;
382
-        }
383
-        $routes_to_add_to = array(
384
-            'contact_list',
385
-            'event_registrations',
386
-            'default',
387
-        );
388
-        if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
389
-            if (
390
-                ($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
391
-                || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
392
-            ) {
393
-                echo '';
394
-            } else {
395
-                $button_text = sprintf(
396
-                    esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
397
-                    '<span class="send-selected-newsletter-count">0</span>'
398
-                );
399
-                echo '<button id="selected-batch-send-trigger" class="button button--secondary">'
400
-                     . '<span class="dashicons dashicons-email "></span>'
401
-                     . $button_text
402
-                     . '</button>';
403
-                add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
404
-            }
405
-        }
406
-    }
363
+	/**
364
+	 * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
365
+	 *
366
+	 * @since 4.3.0
367
+	 * @param EE_Admin_List_Table $list_table
368
+	 * @return void
369
+	 * @throws InvalidArgumentException
370
+	 * @throws InvalidDataTypeException
371
+	 * @throws InvalidInterfaceException
372
+	 */
373
+	public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
374
+	{
375
+		if (
376
+			! EE_Registry::instance()->CAP->current_user_can(
377
+				'ee_send_message',
378
+				'espresso_registrations_newsletter_selected_send'
379
+			)
380
+		) {
381
+			return;
382
+		}
383
+		$routes_to_add_to = array(
384
+			'contact_list',
385
+			'event_registrations',
386
+			'default',
387
+		);
388
+		if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
389
+			if (
390
+				($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
391
+				|| (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
392
+			) {
393
+				echo '';
394
+			} else {
395
+				$button_text = sprintf(
396
+					esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
397
+					'<span class="send-selected-newsletter-count">0</span>'
398
+				);
399
+				echo '<button id="selected-batch-send-trigger" class="button button--secondary">'
400
+					 . '<span class="dashicons dashicons-email "></span>'
401
+					 . $button_text
402
+					 . '</button>';
403
+				add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
404
+			}
405
+		}
406
+	}
407 407
 
408 408
 
409
-    /**
410
-     * @throws DomainException
411
-     * @throws EE_Error
412
-     * @throws InvalidArgumentException
413
-     * @throws InvalidDataTypeException
414
-     * @throws InvalidInterfaceException
415
-     */
416
-    public function newsletter_send_form_skeleton()
417
-    {
418
-        $list_table = $this->_list_table_object;
419
-        $codes = array();
420
-        // need to templates for the newsletter message type for the template selector.
421
-        $values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
422
-        $mtps = EEM_Message_Template_Group::instance()->get_all(
423
-            array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
424
-        );
425
-        foreach ($mtps as $mtp) {
426
-            $name = $mtp->name();
427
-            $values[] = array(
428
-                'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
429
-                'id'   => $mtp->ID(),
430
-            );
431
-        }
432
-        // need to get a list of shortcodes that are available for the newsletter message type.
433
-        $shortcodes = EEH_MSG_Template::get_shortcodes(
434
-            'newsletter',
435
-            'email',
436
-            array(),
437
-            'attendee',
438
-            false
439
-        );
440
-        foreach ($shortcodes as $field => $shortcode_array) {
441
-            $available_shortcodes = array();
442
-            foreach ($shortcode_array as $shortcode => $shortcode_details) {
443
-                $field_id = $field === '[NEWSLETTER_CONTENT]'
444
-                    ? 'content'
445
-                    : $field;
446
-                $field_id = 'batch-message-' . strtolower($field_id);
447
-                $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
448
-                                          . $shortcode
449
-                                          . '" data-linked-input-id="' . $field_id . '">'
450
-                                          . $shortcode
451
-                                          . '</span>';
452
-            }
453
-            $codes[ $field ] = implode(', ', $available_shortcodes);
454
-        }
455
-        $shortcodes = $codes;
456
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
457
-        $form_template_args = array(
458
-            'form_action'       => admin_url('admin.php?page=espresso_registrations'),
459
-            'form_route'        => 'newsletter_selected_send',
460
-            'form_nonce_name'   => 'newsletter_selected_send_nonce',
461
-            'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
462
-            'redirect_back_to'  => $this->_req_action,
463
-            'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
464
-            'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
465
-            'shortcodes'        => $shortcodes,
466
-            'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
467
-        );
468
-        EEH_Template::display_template($form_template, $form_template_args);
469
-    }
409
+	/**
410
+	 * @throws DomainException
411
+	 * @throws EE_Error
412
+	 * @throws InvalidArgumentException
413
+	 * @throws InvalidDataTypeException
414
+	 * @throws InvalidInterfaceException
415
+	 */
416
+	public function newsletter_send_form_skeleton()
417
+	{
418
+		$list_table = $this->_list_table_object;
419
+		$codes = array();
420
+		// need to templates for the newsletter message type for the template selector.
421
+		$values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
422
+		$mtps = EEM_Message_Template_Group::instance()->get_all(
423
+			array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
424
+		);
425
+		foreach ($mtps as $mtp) {
426
+			$name = $mtp->name();
427
+			$values[] = array(
428
+				'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
429
+				'id'   => $mtp->ID(),
430
+			);
431
+		}
432
+		// need to get a list of shortcodes that are available for the newsletter message type.
433
+		$shortcodes = EEH_MSG_Template::get_shortcodes(
434
+			'newsletter',
435
+			'email',
436
+			array(),
437
+			'attendee',
438
+			false
439
+		);
440
+		foreach ($shortcodes as $field => $shortcode_array) {
441
+			$available_shortcodes = array();
442
+			foreach ($shortcode_array as $shortcode => $shortcode_details) {
443
+				$field_id = $field === '[NEWSLETTER_CONTENT]'
444
+					? 'content'
445
+					: $field;
446
+				$field_id = 'batch-message-' . strtolower($field_id);
447
+				$available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
448
+										  . $shortcode
449
+										  . '" data-linked-input-id="' . $field_id . '">'
450
+										  . $shortcode
451
+										  . '</span>';
452
+			}
453
+			$codes[ $field ] = implode(', ', $available_shortcodes);
454
+		}
455
+		$shortcodes = $codes;
456
+		$form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
457
+		$form_template_args = array(
458
+			'form_action'       => admin_url('admin.php?page=espresso_registrations'),
459
+			'form_route'        => 'newsletter_selected_send',
460
+			'form_nonce_name'   => 'newsletter_selected_send_nonce',
461
+			'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
462
+			'redirect_back_to'  => $this->_req_action,
463
+			'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
464
+			'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
465
+			'shortcodes'        => $shortcodes,
466
+			'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
467
+		);
468
+		EEH_Template::display_template($form_template, $form_template_args);
469
+	}
470 470
 
471 471
 
472
-    /**
473
-     * Handles sending selected registrations/contacts a newsletter.
474
-     *
475
-     * @since  4.3.0
476
-     * @return void
477
-     * @throws EE_Error
478
-     * @throws InvalidArgumentException
479
-     * @throws InvalidDataTypeException
480
-     * @throws InvalidInterfaceException
481
-     */
482
-    protected function _newsletter_selected_send()
483
-    {
484
-        $success = true;
485
-        // first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
486
-        if (empty($this->_req_data['newsletter_mtp_selected'])) {
487
-            EE_Error::add_error(
488
-                esc_html__(
489
-                    'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
490
-                    'event_espresso'
491
-                ),
492
-                __FILE__,
493
-                __FUNCTION__,
494
-                __LINE__
495
-            );
496
-            $success = false;
497
-        }
498
-        if ($success) {
499
-            // update Message template in case there are any changes
500
-            $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
501
-                $this->_req_data['newsletter_mtp_selected']
502
-            );
503
-            $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
504
-                ? $Message_Template_Group->context_templates()
505
-                : array();
506
-            if (empty($Message_Templates)) {
507
-                EE_Error::add_error(
508
-                    esc_html__(
509
-                        'Unable to retrieve message template fields from the db. Messages not sent.',
510
-                        'event_espresso'
511
-                    ),
512
-                    __FILE__,
513
-                    __FUNCTION__,
514
-                    __LINE__
515
-                );
516
-            }
517
-            // let's just update the specific fields
518
-            foreach ($Message_Templates['attendee'] as $Message_Template) {
519
-                if ($Message_Template instanceof EE_Message_Template) {
520
-                    $field = $Message_Template->get('MTP_template_field');
521
-                    $content = $Message_Template->get('MTP_content');
522
-                    $new_content = $content;
523
-                    switch ($field) {
524
-                        case 'from':
525
-                            $new_content = ! empty($this->_req_data['batch_message']['from'])
526
-                                ? $this->_req_data['batch_message']['from']
527
-                                : $content;
528
-                            break;
529
-                        case 'subject':
530
-                            $new_content = ! empty($this->_req_data['batch_message']['subject'])
531
-                                ? $this->_req_data['batch_message']['subject']
532
-                                : $content;
533
-                            break;
534
-                        case 'content':
535
-                            $new_content = $content;
536
-                            $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
537
-                                ? $this->_req_data['batch_message']['content']
538
-                                : $content['newsletter_content'];
539
-                            break;
540
-                        default:
541
-                            // continue the foreach loop, we don't want to set $new_content nor save.
542
-                            continue 2;
543
-                    }
544
-                    $Message_Template->set('MTP_content', $new_content);
545
-                    $Message_Template->save();
546
-                }
547
-            }
548
-            // great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
549
-            $id_type = ! empty($this->_req_data['batch_message']['id_type'])
550
-                ? $this->_req_data['batch_message']['id_type']
551
-                : 'registration';
552
-            // id_type will affect how we assemble the ids.
553
-            $ids = ! empty($this->_req_data['batch_message']['ids'])
554
-                ? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
555
-                : array();
556
-            $registrations_used_for_contact_data = array();
557
-            // using switch because eventually we'll have other contexts that will be used for generating messages.
558
-            switch ($id_type) {
559
-                case 'registration':
560
-                    $registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
561
-                        array(
562
-                            array(
563
-                                'REG_ID' => array('IN', $ids),
564
-                            ),
565
-                        )
566
-                    );
567
-                    break;
568
-                case 'contact':
569
-                    $registrations_used_for_contact_data = EEM_Registration::instance()
570
-                                                                           ->get_latest_registration_for_each_of_given_contacts(
571
-                                                                               $ids
572
-                                                                           );
573
-                    break;
574
-            }
575
-            do_action_ref_array(
576
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
577
-                array(
578
-                    $registrations_used_for_contact_data,
579
-                    $Message_Template_Group->ID(),
580
-                )
581
-            );
582
-            // kept for backward compat, internally we no longer use this action.
583
-            // @deprecated 4.8.36.rc.002
584
-            $contacts = $id_type === 'registration'
585
-                ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
586
-                : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
587
-            do_action_ref_array(
588
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
589
-                array(
590
-                    $contacts,
591
-                    $Message_Template_Group->ID(),
592
-                )
593
-            );
594
-        }
595
-        $query_args = array(
596
-            'action' => ! empty($this->_req_data['redirect_back_to'])
597
-                ? $this->_req_data['redirect_back_to']
598
-                : 'default',
599
-        );
600
-        $this->_redirect_after_action(false, '', '', $query_args, true);
601
-    }
472
+	/**
473
+	 * Handles sending selected registrations/contacts a newsletter.
474
+	 *
475
+	 * @since  4.3.0
476
+	 * @return void
477
+	 * @throws EE_Error
478
+	 * @throws InvalidArgumentException
479
+	 * @throws InvalidDataTypeException
480
+	 * @throws InvalidInterfaceException
481
+	 */
482
+	protected function _newsletter_selected_send()
483
+	{
484
+		$success = true;
485
+		// first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
486
+		if (empty($this->_req_data['newsletter_mtp_selected'])) {
487
+			EE_Error::add_error(
488
+				esc_html__(
489
+					'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
490
+					'event_espresso'
491
+				),
492
+				__FILE__,
493
+				__FUNCTION__,
494
+				__LINE__
495
+			);
496
+			$success = false;
497
+		}
498
+		if ($success) {
499
+			// update Message template in case there are any changes
500
+			$Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
501
+				$this->_req_data['newsletter_mtp_selected']
502
+			);
503
+			$Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
504
+				? $Message_Template_Group->context_templates()
505
+				: array();
506
+			if (empty($Message_Templates)) {
507
+				EE_Error::add_error(
508
+					esc_html__(
509
+						'Unable to retrieve message template fields from the db. Messages not sent.',
510
+						'event_espresso'
511
+					),
512
+					__FILE__,
513
+					__FUNCTION__,
514
+					__LINE__
515
+				);
516
+			}
517
+			// let's just update the specific fields
518
+			foreach ($Message_Templates['attendee'] as $Message_Template) {
519
+				if ($Message_Template instanceof EE_Message_Template) {
520
+					$field = $Message_Template->get('MTP_template_field');
521
+					$content = $Message_Template->get('MTP_content');
522
+					$new_content = $content;
523
+					switch ($field) {
524
+						case 'from':
525
+							$new_content = ! empty($this->_req_data['batch_message']['from'])
526
+								? $this->_req_data['batch_message']['from']
527
+								: $content;
528
+							break;
529
+						case 'subject':
530
+							$new_content = ! empty($this->_req_data['batch_message']['subject'])
531
+								? $this->_req_data['batch_message']['subject']
532
+								: $content;
533
+							break;
534
+						case 'content':
535
+							$new_content = $content;
536
+							$new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
537
+								? $this->_req_data['batch_message']['content']
538
+								: $content['newsletter_content'];
539
+							break;
540
+						default:
541
+							// continue the foreach loop, we don't want to set $new_content nor save.
542
+							continue 2;
543
+					}
544
+					$Message_Template->set('MTP_content', $new_content);
545
+					$Message_Template->save();
546
+				}
547
+			}
548
+			// great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
549
+			$id_type = ! empty($this->_req_data['batch_message']['id_type'])
550
+				? $this->_req_data['batch_message']['id_type']
551
+				: 'registration';
552
+			// id_type will affect how we assemble the ids.
553
+			$ids = ! empty($this->_req_data['batch_message']['ids'])
554
+				? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
555
+				: array();
556
+			$registrations_used_for_contact_data = array();
557
+			// using switch because eventually we'll have other contexts that will be used for generating messages.
558
+			switch ($id_type) {
559
+				case 'registration':
560
+					$registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
561
+						array(
562
+							array(
563
+								'REG_ID' => array('IN', $ids),
564
+							),
565
+						)
566
+					);
567
+					break;
568
+				case 'contact':
569
+					$registrations_used_for_contact_data = EEM_Registration::instance()
570
+																		   ->get_latest_registration_for_each_of_given_contacts(
571
+																			   $ids
572
+																		   );
573
+					break;
574
+			}
575
+			do_action_ref_array(
576
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
577
+				array(
578
+					$registrations_used_for_contact_data,
579
+					$Message_Template_Group->ID(),
580
+				)
581
+			);
582
+			// kept for backward compat, internally we no longer use this action.
583
+			// @deprecated 4.8.36.rc.002
584
+			$contacts = $id_type === 'registration'
585
+				? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
586
+				: EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
587
+			do_action_ref_array(
588
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
589
+				array(
590
+					$contacts,
591
+					$Message_Template_Group->ID(),
592
+				)
593
+			);
594
+		}
595
+		$query_args = array(
596
+			'action' => ! empty($this->_req_data['redirect_back_to'])
597
+				? $this->_req_data['redirect_back_to']
598
+				: 'default',
599
+		);
600
+		$this->_redirect_after_action(false, '', '', $query_args, true);
601
+	}
602 602
 
603 603
 
604
-    /**
605
-     * This is called when javascript is being enqueued to setup the various data needed for the reports js.
606
-     * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
607
-     */
608
-    protected function _registration_reports_js_setup()
609
-    {
610
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
611
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
612
-    }
604
+	/**
605
+	 * This is called when javascript is being enqueued to setup the various data needed for the reports js.
606
+	 * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
607
+	 */
608
+	protected function _registration_reports_js_setup()
609
+	{
610
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
611
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
612
+	}
613 613
 
614 614
 
615
-    /**
616
-     *        generates Business Reports regarding Registrations
617
-     *
618
-     * @access protected
619
-     * @return void
620
-     * @throws DomainException
621
-     */
622
-    protected function _registration_reports()
623
-    {
624
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
625
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
626
-            $template_path,
627
-            $this->_reports_template_data,
628
-            true
629
-        );
630
-        // the final template wrapper
631
-        $this->display_admin_page_with_no_sidebar();
632
-    }
615
+	/**
616
+	 *        generates Business Reports regarding Registrations
617
+	 *
618
+	 * @access protected
619
+	 * @return void
620
+	 * @throws DomainException
621
+	 */
622
+	protected function _registration_reports()
623
+	{
624
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
625
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
626
+			$template_path,
627
+			$this->_reports_template_data,
628
+			true
629
+		);
630
+		// the final template wrapper
631
+		$this->display_admin_page_with_no_sidebar();
632
+	}
633 633
 
634 634
 
635
-    /**
636
-     * Generates Business Report showing total registrations per day.
637
-     *
638
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
639
-     * @return string
640
-     * @throws EE_Error
641
-     * @throws InvalidArgumentException
642
-     * @throws InvalidDataTypeException
643
-     * @throws InvalidInterfaceException
644
-     */
645
-    private function _registrations_per_day_report($period = '-1 month')
646
-    {
647
-        $report_ID = 'reg-admin-registrations-per-day-report-dv';
648
-        $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
649
-        $results = (array) $results;
650
-        $regs = array();
651
-        $subtitle = '';
652
-        if ($results) {
653
-            $column_titles = array();
654
-            $tracker = 0;
655
-            foreach ($results as $result) {
656
-                $report_column_values = array();
657
-                foreach ($result as $property_name => $property_value) {
658
-                    $property_value = $property_name === 'Registration_REG_date' ? $property_value
659
-                        : (int) $property_value;
660
-                    $report_column_values[] = $property_value;
661
-                    if ($tracker === 0) {
662
-                        if ($property_name === 'Registration_REG_date') {
663
-                            $column_titles[] = esc_html__(
664
-                                'Date (only days with registrations are shown)',
665
-                                'event_espresso'
666
-                            );
667
-                        } else {
668
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
669
-                        }
670
-                    }
671
-                }
672
-                $tracker++;
673
-                $regs[] = $report_column_values;
674
-            }
675
-            // make sure the column_titles is pushed to the beginning of the array
676
-            array_unshift($regs, $column_titles);
677
-            // setup the date range.
678
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
679
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
680
-            $ending_date = new DateTime("now", $DateTimeZone);
681
-            $subtitle = sprintf(
682
-                wp_strip_all_tags(
683
-                    _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
684
-                ),
685
-                $beginning_date->format('Y-m-d'),
686
-                $ending_date->format('Y-m-d')
687
-            );
688
-        }
689
-        $report_title = wp_strip_all_tags(__('Total Registrations per Day', 'event_espresso'));
690
-        $report_params = array(
691
-            'title'     => $report_title,
692
-            'subtitle'  => $subtitle,
693
-            'id'        => $report_ID,
694
-            'regs'      => $regs,
695
-            'noResults' => empty($regs),
696
-            'noRegsMsg' => sprintf(
697
-                wp_strip_all_tags(
698
-                    __(
699
-                        '%sThere are currently no registration records in the last month for this report.%s',
700
-                        'event_espresso'
701
-                    )
702
-                ),
703
-                '<h2>' . $report_title . '</h2><p>',
704
-                '</p>'
705
-            ),
706
-        );
707
-        wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
708
-        return $report_ID;
709
-    }
635
+	/**
636
+	 * Generates Business Report showing total registrations per day.
637
+	 *
638
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
639
+	 * @return string
640
+	 * @throws EE_Error
641
+	 * @throws InvalidArgumentException
642
+	 * @throws InvalidDataTypeException
643
+	 * @throws InvalidInterfaceException
644
+	 */
645
+	private function _registrations_per_day_report($period = '-1 month')
646
+	{
647
+		$report_ID = 'reg-admin-registrations-per-day-report-dv';
648
+		$results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
649
+		$results = (array) $results;
650
+		$regs = array();
651
+		$subtitle = '';
652
+		if ($results) {
653
+			$column_titles = array();
654
+			$tracker = 0;
655
+			foreach ($results as $result) {
656
+				$report_column_values = array();
657
+				foreach ($result as $property_name => $property_value) {
658
+					$property_value = $property_name === 'Registration_REG_date' ? $property_value
659
+						: (int) $property_value;
660
+					$report_column_values[] = $property_value;
661
+					if ($tracker === 0) {
662
+						if ($property_name === 'Registration_REG_date') {
663
+							$column_titles[] = esc_html__(
664
+								'Date (only days with registrations are shown)',
665
+								'event_espresso'
666
+							);
667
+						} else {
668
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
669
+						}
670
+					}
671
+				}
672
+				$tracker++;
673
+				$regs[] = $report_column_values;
674
+			}
675
+			// make sure the column_titles is pushed to the beginning of the array
676
+			array_unshift($regs, $column_titles);
677
+			// setup the date range.
678
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
679
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
680
+			$ending_date = new DateTime("now", $DateTimeZone);
681
+			$subtitle = sprintf(
682
+				wp_strip_all_tags(
683
+					_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
684
+				),
685
+				$beginning_date->format('Y-m-d'),
686
+				$ending_date->format('Y-m-d')
687
+			);
688
+		}
689
+		$report_title = wp_strip_all_tags(__('Total Registrations per Day', 'event_espresso'));
690
+		$report_params = array(
691
+			'title'     => $report_title,
692
+			'subtitle'  => $subtitle,
693
+			'id'        => $report_ID,
694
+			'regs'      => $regs,
695
+			'noResults' => empty($regs),
696
+			'noRegsMsg' => sprintf(
697
+				wp_strip_all_tags(
698
+					__(
699
+						'%sThere are currently no registration records in the last month for this report.%s',
700
+						'event_espresso'
701
+					)
702
+				),
703
+				'<h2>' . $report_title . '</h2><p>',
704
+				'</p>'
705
+			),
706
+		);
707
+		wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
708
+		return $report_ID;
709
+	}
710 710
 
711 711
 
712
-    /**
713
-     * Generates Business Report showing total registrations per event.
714
-     *
715
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
716
-     * @return string
717
-     * @throws EE_Error
718
-     * @throws InvalidArgumentException
719
-     * @throws InvalidDataTypeException
720
-     * @throws InvalidInterfaceException
721
-     */
722
-    private function _registrations_per_event_report($period = '-1 month')
723
-    {
724
-        $report_ID = 'reg-admin-registrations-per-event-report-dv';
725
-        $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
726
-        $results = (array) $results;
727
-        $regs = array();
728
-        $subtitle = '';
729
-        if ($results) {
730
-            $column_titles = array();
731
-            $tracker = 0;
732
-            foreach ($results as $result) {
733
-                $report_column_values = array();
734
-                foreach ($result as $property_name => $property_value) {
735
-                    $property_value = $property_name === 'Registration_Event' ? wp_trim_words(
736
-                        $property_value,
737
-                        4,
738
-                        '...'
739
-                    ) : (int) $property_value;
740
-                    $report_column_values[] = $property_value;
741
-                    if ($tracker === 0) {
742
-                        if ($property_name === 'Registration_Event') {
743
-                            $column_titles[] = esc_html__('Event', 'event_espresso');
744
-                        } else {
745
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
746
-                        }
747
-                    }
748
-                }
749
-                $tracker++;
750
-                $regs[] = $report_column_values;
751
-            }
752
-            // make sure the column_titles is pushed to the beginning of the array
753
-            array_unshift($regs, $column_titles);
754
-            // setup the date range.
755
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
756
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
757
-            $ending_date = new DateTime("now", $DateTimeZone);
758
-            $subtitle = sprintf(
759
-                wp_strip_all_tags(
760
-                    _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
761
-                ),
762
-                $beginning_date->format('Y-m-d'),
763
-                $ending_date->format('Y-m-d')
764
-            );
765
-        }
766
-        $report_title = wp_strip_all_tags(__('Total Registrations per Event', 'event_espresso'));
767
-        $report_params = array(
768
-            'title'     => $report_title,
769
-            'subtitle'  => $subtitle,
770
-            'id'        => $report_ID,
771
-            'regs'      => $regs,
772
-            'noResults' => empty($regs),
773
-            'noRegsMsg' => sprintf(
774
-                wp_strip_all_tags(
775
-                    __(
776
-                        '%sThere are currently no registration records in the last month for this report.%s',
777
-                        'event_espresso'
778
-                    )
779
-                ),
780
-                '<h2>' . $report_title . '</h2><p>',
781
-                '</p>'
782
-            ),
783
-        );
784
-        wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
785
-        return $report_ID;
786
-    }
712
+	/**
713
+	 * Generates Business Report showing total registrations per event.
714
+	 *
715
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
716
+	 * @return string
717
+	 * @throws EE_Error
718
+	 * @throws InvalidArgumentException
719
+	 * @throws InvalidDataTypeException
720
+	 * @throws InvalidInterfaceException
721
+	 */
722
+	private function _registrations_per_event_report($period = '-1 month')
723
+	{
724
+		$report_ID = 'reg-admin-registrations-per-event-report-dv';
725
+		$results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
726
+		$results = (array) $results;
727
+		$regs = array();
728
+		$subtitle = '';
729
+		if ($results) {
730
+			$column_titles = array();
731
+			$tracker = 0;
732
+			foreach ($results as $result) {
733
+				$report_column_values = array();
734
+				foreach ($result as $property_name => $property_value) {
735
+					$property_value = $property_name === 'Registration_Event' ? wp_trim_words(
736
+						$property_value,
737
+						4,
738
+						'...'
739
+					) : (int) $property_value;
740
+					$report_column_values[] = $property_value;
741
+					if ($tracker === 0) {
742
+						if ($property_name === 'Registration_Event') {
743
+							$column_titles[] = esc_html__('Event', 'event_espresso');
744
+						} else {
745
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
746
+						}
747
+					}
748
+				}
749
+				$tracker++;
750
+				$regs[] = $report_column_values;
751
+			}
752
+			// make sure the column_titles is pushed to the beginning of the array
753
+			array_unshift($regs, $column_titles);
754
+			// setup the date range.
755
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
756
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
757
+			$ending_date = new DateTime("now", $DateTimeZone);
758
+			$subtitle = sprintf(
759
+				wp_strip_all_tags(
760
+					_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
761
+				),
762
+				$beginning_date->format('Y-m-d'),
763
+				$ending_date->format('Y-m-d')
764
+			);
765
+		}
766
+		$report_title = wp_strip_all_tags(__('Total Registrations per Event', 'event_espresso'));
767
+		$report_params = array(
768
+			'title'     => $report_title,
769
+			'subtitle'  => $subtitle,
770
+			'id'        => $report_ID,
771
+			'regs'      => $regs,
772
+			'noResults' => empty($regs),
773
+			'noRegsMsg' => sprintf(
774
+				wp_strip_all_tags(
775
+					__(
776
+						'%sThere are currently no registration records in the last month for this report.%s',
777
+						'event_espresso'
778
+					)
779
+				),
780
+				'<h2>' . $report_title . '</h2><p>',
781
+				'</p>'
782
+			),
783
+		);
784
+		wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
785
+		return $report_ID;
786
+	}
787 787
 
788 788
 
789
-    /**
790
-     * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
791
-     *
792
-     * @access protected
793
-     * @return void
794
-     * @throws EE_Error
795
-     * @throws InvalidArgumentException
796
-     * @throws InvalidDataTypeException
797
-     * @throws InvalidInterfaceException
798
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
799
-     */
800
-    protected function _registration_checkin_list_table()
801
-    {
802
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
803
-        $reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
804
-        /** @var EE_Registration $registration */
805
-        $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
806
-        if (! $registration instanceof EE_Registration) {
807
-            throw new EE_Error(
808
-                sprintf(
809
-                    esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
810
-                    $reg_id
811
-                )
812
-            );
813
-        }
814
-        $attendee = $registration->attendee();
815
-        $this->_admin_page_title .= $this->get_action_link_or_button(
816
-            'new_registration',
817
-            'add-registrant',
818
-            array('event_id' => $registration->event_ID()),
819
-            'add-new-h2'
820
-        );
821
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
822
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
823
-        $legend_items = array(
824
-            'checkin'  => array(
825
-                'class' => $checked_in->cssClasses(),
826
-                'desc'  => $checked_in->legendLabel(),
827
-            ),
828
-            'checkout' => array(
829
-                'class' => $checked_out->cssClasses(),
830
-                'desc'  => $checked_out->legendLabel(),
831
-            ),
832
-        );
833
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
834
-        $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
835
-        /** @var EE_Datetime $datetime */
836
-        $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
837
-        $datetime_label = '';
838
-        if ($datetime instanceof EE_Datetime) {
839
-            $datetime_label = $datetime->get_dtt_display_name(true);
840
-            $datetime_label .= ! empty($datetime_label)
841
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
842
-                : $datetime->get_dtt_display_name();
843
-        }
844
-        $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
845
-            ? EE_Admin_Page::add_query_args_and_nonce(
846
-                array(
847
-                    'action'   => 'event_registrations',
848
-                    'event_id' => $registration->event_ID(),
849
-                    'DTT_ID'   => $dtt_id,
850
-                ),
851
-                $this->_admin_base_url
852
-            )
853
-            : '';
854
-        $datetime_link = ! empty($datetime_link)
855
-            ? '<a href="' . $datetime_link . '">'
856
-              . '<span id="checkin-dtt">'
857
-              . $datetime_label
858
-              . '</span></a>'
859
-            : $datetime_label;
860
-        $attendee_name = $attendee instanceof EE_Attendee
861
-            ? $attendee->full_name()
862
-            : '';
863
-        $attendee_link = $attendee instanceof EE_Attendee
864
-            ? $attendee->get_admin_details_link()
865
-            : '';
866
-        $attendee_link = ! empty($attendee_link)
867
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
868
-              . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
869
-              . '<span id="checkin-attendee-name">'
870
-              . $attendee_name
871
-              . '</span></a>'
872
-            : '';
873
-        $event_link = $registration->event() instanceof EE_Event
874
-            ? $registration->event()->get_admin_details_link()
875
-            : '';
876
-        $event_link = ! empty($event_link)
877
-            ? '<a href="' . $event_link . '"'
878
-              . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
879
-              . '<span id="checkin-event-name">'
880
-              . $registration->event_name()
881
-              . '</span>'
882
-              . '</a>'
883
-            : '';
884
-        $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
885
-            ? '<h2>' . sprintf(
886
-                esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
887
-                $attendee_link,
888
-                $datetime_link,
889
-                $event_link
890
-            ) . '</h2>'
891
-            : '';
892
-        $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
893
-            ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
894
-        $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
895
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
896
-        $this->display_admin_list_table_page_with_no_sidebar();
897
-    }
789
+	/**
790
+	 * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
791
+	 *
792
+	 * @access protected
793
+	 * @return void
794
+	 * @throws EE_Error
795
+	 * @throws InvalidArgumentException
796
+	 * @throws InvalidDataTypeException
797
+	 * @throws InvalidInterfaceException
798
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
799
+	 */
800
+	protected function _registration_checkin_list_table()
801
+	{
802
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
803
+		$reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
804
+		/** @var EE_Registration $registration */
805
+		$registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
806
+		if (! $registration instanceof EE_Registration) {
807
+			throw new EE_Error(
808
+				sprintf(
809
+					esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
810
+					$reg_id
811
+				)
812
+			);
813
+		}
814
+		$attendee = $registration->attendee();
815
+		$this->_admin_page_title .= $this->get_action_link_or_button(
816
+			'new_registration',
817
+			'add-registrant',
818
+			array('event_id' => $registration->event_ID()),
819
+			'add-new-h2'
820
+		);
821
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
822
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
823
+		$legend_items = array(
824
+			'checkin'  => array(
825
+				'class' => $checked_in->cssClasses(),
826
+				'desc'  => $checked_in->legendLabel(),
827
+			),
828
+			'checkout' => array(
829
+				'class' => $checked_out->cssClasses(),
830
+				'desc'  => $checked_out->legendLabel(),
831
+			),
832
+		);
833
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
834
+		$dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
835
+		/** @var EE_Datetime $datetime */
836
+		$datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
837
+		$datetime_label = '';
838
+		if ($datetime instanceof EE_Datetime) {
839
+			$datetime_label = $datetime->get_dtt_display_name(true);
840
+			$datetime_label .= ! empty($datetime_label)
841
+				? ' (' . $datetime->get_dtt_display_name() . ')'
842
+				: $datetime->get_dtt_display_name();
843
+		}
844
+		$datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
845
+			? EE_Admin_Page::add_query_args_and_nonce(
846
+				array(
847
+					'action'   => 'event_registrations',
848
+					'event_id' => $registration->event_ID(),
849
+					'DTT_ID'   => $dtt_id,
850
+				),
851
+				$this->_admin_base_url
852
+			)
853
+			: '';
854
+		$datetime_link = ! empty($datetime_link)
855
+			? '<a href="' . $datetime_link . '">'
856
+			  . '<span id="checkin-dtt">'
857
+			  . $datetime_label
858
+			  . '</span></a>'
859
+			: $datetime_label;
860
+		$attendee_name = $attendee instanceof EE_Attendee
861
+			? $attendee->full_name()
862
+			: '';
863
+		$attendee_link = $attendee instanceof EE_Attendee
864
+			? $attendee->get_admin_details_link()
865
+			: '';
866
+		$attendee_link = ! empty($attendee_link)
867
+			? '<a href="' . $attendee->get_admin_details_link() . '"'
868
+			  . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
869
+			  . '<span id="checkin-attendee-name">'
870
+			  . $attendee_name
871
+			  . '</span></a>'
872
+			: '';
873
+		$event_link = $registration->event() instanceof EE_Event
874
+			? $registration->event()->get_admin_details_link()
875
+			: '';
876
+		$event_link = ! empty($event_link)
877
+			? '<a href="' . $event_link . '"'
878
+			  . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
879
+			  . '<span id="checkin-event-name">'
880
+			  . $registration->event_name()
881
+			  . '</span>'
882
+			  . '</a>'
883
+			: '';
884
+		$this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
885
+			? '<h2>' . sprintf(
886
+				esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
887
+				$attendee_link,
888
+				$datetime_link,
889
+				$event_link
890
+			) . '</h2>'
891
+			: '';
892
+		$this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
893
+			? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
894
+		$this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
895
+			? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
896
+		$this->display_admin_list_table_page_with_no_sidebar();
897
+	}
898 898
 
899 899
 
900
-    /**
901
-     * toggle the Check-in status for the given registration (coming from ajax)
902
-     *
903
-     * @return void (JSON)
904
-     * @throws EE_Error
905
-     * @throws InvalidArgumentException
906
-     * @throws InvalidDataTypeException
907
-     * @throws InvalidInterfaceException
908
-     */
909
-    public function toggle_checkin_status()
910
-    {
911
-        // first make sure we have the necessary data
912
-        if (! isset($this->_req_data['_regid'])) {
913
-            EE_Error::add_error(
914
-                esc_html__(
915
-                    'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
916
-                    'event_espresso'
917
-                ),
918
-                __FILE__,
919
-                __FUNCTION__,
920
-                __LINE__
921
-            );
922
-            $this->_template_args['success'] = false;
923
-            $this->_template_args['error'] = true;
924
-            $this->_return_json();
925
-        };
926
-        // do a nonce check cause we're not coming in from an normal route here.
927
-        $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
928
-            : '';
929
-        $nonce_ref = 'checkin_nonce';
930
-        $this->_verify_nonce($nonce, $nonce_ref);
931
-        // beautiful! Made it this far so let's get the status.
932
-        $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
933
-        // setup new class to return via ajax
934
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
935
-        $this->_template_args['success'] = true;
936
-        $this->_return_json();
937
-    }
900
+	/**
901
+	 * toggle the Check-in status for the given registration (coming from ajax)
902
+	 *
903
+	 * @return void (JSON)
904
+	 * @throws EE_Error
905
+	 * @throws InvalidArgumentException
906
+	 * @throws InvalidDataTypeException
907
+	 * @throws InvalidInterfaceException
908
+	 */
909
+	public function toggle_checkin_status()
910
+	{
911
+		// first make sure we have the necessary data
912
+		if (! isset($this->_req_data['_regid'])) {
913
+			EE_Error::add_error(
914
+				esc_html__(
915
+					'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
916
+					'event_espresso'
917
+				),
918
+				__FILE__,
919
+				__FUNCTION__,
920
+				__LINE__
921
+			);
922
+			$this->_template_args['success'] = false;
923
+			$this->_template_args['error'] = true;
924
+			$this->_return_json();
925
+		};
926
+		// do a nonce check cause we're not coming in from an normal route here.
927
+		$nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
928
+			: '';
929
+		$nonce_ref = 'checkin_nonce';
930
+		$this->_verify_nonce($nonce, $nonce_ref);
931
+		// beautiful! Made it this far so let's get the status.
932
+		$new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
933
+		// setup new class to return via ajax
934
+		$this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
935
+		$this->_template_args['success'] = true;
936
+		$this->_return_json();
937
+	}
938 938
 
939 939
 
940
-    /**
941
-     * handles toggling the checkin status for the registration,
942
-     *
943
-     * @access protected
944
-     * @return int|void
945
-     * @throws EE_Error
946
-     * @throws InvalidArgumentException
947
-     * @throws InvalidDataTypeException
948
-     * @throws InvalidInterfaceException
949
-     */
950
-    protected function _toggle_checkin_status()
951
-    {
952
-        // first let's get the query args out of the way for the redirect
953
-        $query_args = array(
954
-            'action'   => 'event_registrations',
955
-            'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
956
-            'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
957
-        );
958
-        $new_status = false;
959
-        // bulk action check in toggle
960
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
961
-            // cycle thru checkboxes
962
-            while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
963
-                $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
964
-                $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
965
-            }
966
-        } elseif (isset($this->_req_data['_regid'])) {
967
-            // coming from ajax request
968
-            $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
969
-            $query_args['DTT_ID'] = $DTT_ID;
970
-            $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
971
-        } else {
972
-            EE_Error::add_error(
973
-                esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
974
-                __FILE__,
975
-                __FUNCTION__,
976
-                __LINE__
977
-            );
978
-        }
979
-        if (defined('DOING_AJAX')) {
980
-            return $new_status;
981
-        }
982
-        $this->_redirect_after_action(false, '', '', $query_args, true);
983
-    }
940
+	/**
941
+	 * handles toggling the checkin status for the registration,
942
+	 *
943
+	 * @access protected
944
+	 * @return int|void
945
+	 * @throws EE_Error
946
+	 * @throws InvalidArgumentException
947
+	 * @throws InvalidDataTypeException
948
+	 * @throws InvalidInterfaceException
949
+	 */
950
+	protected function _toggle_checkin_status()
951
+	{
952
+		// first let's get the query args out of the way for the redirect
953
+		$query_args = array(
954
+			'action'   => 'event_registrations',
955
+			'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
956
+			'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
957
+		);
958
+		$new_status = false;
959
+		// bulk action check in toggle
960
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
961
+			// cycle thru checkboxes
962
+			while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
963
+				$DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
964
+				$new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
965
+			}
966
+		} elseif (isset($this->_req_data['_regid'])) {
967
+			// coming from ajax request
968
+			$DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
969
+			$query_args['DTT_ID'] = $DTT_ID;
970
+			$new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
971
+		} else {
972
+			EE_Error::add_error(
973
+				esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
974
+				__FILE__,
975
+				__FUNCTION__,
976
+				__LINE__
977
+			);
978
+		}
979
+		if (defined('DOING_AJAX')) {
980
+			return $new_status;
981
+		}
982
+		$this->_redirect_after_action(false, '', '', $query_args, true);
983
+	}
984 984
 
985 985
 
986
-    /**
987
-     * This is toggles a single Check-in for the given registration and datetime.
988
-     *
989
-     * @param  int $REG_ID The registration we're toggling
990
-     * @param  int $DTT_ID The datetime we're toggling
991
-     * @return int The new status toggled to.
992
-     * @throws EE_Error
993
-     * @throws InvalidArgumentException
994
-     * @throws InvalidDataTypeException
995
-     * @throws InvalidInterfaceException
996
-     */
997
-    private function _toggle_checkin($REG_ID, $DTT_ID)
998
-    {
999
-        /** @var EE_Registration $REG */
1000
-        $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1001
-        $new_status = $REG->toggle_checkin_status($DTT_ID);
1002
-        if ($new_status !== false) {
1003
-            EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
1004
-        } else {
1005
-            EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
1006
-            $new_status = false;
1007
-        }
1008
-        return $new_status;
1009
-    }
986
+	/**
987
+	 * This is toggles a single Check-in for the given registration and datetime.
988
+	 *
989
+	 * @param  int $REG_ID The registration we're toggling
990
+	 * @param  int $DTT_ID The datetime we're toggling
991
+	 * @return int The new status toggled to.
992
+	 * @throws EE_Error
993
+	 * @throws InvalidArgumentException
994
+	 * @throws InvalidDataTypeException
995
+	 * @throws InvalidInterfaceException
996
+	 */
997
+	private function _toggle_checkin($REG_ID, $DTT_ID)
998
+	{
999
+		/** @var EE_Registration $REG */
1000
+		$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1001
+		$new_status = $REG->toggle_checkin_status($DTT_ID);
1002
+		if ($new_status !== false) {
1003
+			EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
1004
+		} else {
1005
+			EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
1006
+			$new_status = false;
1007
+		}
1008
+		return $new_status;
1009
+	}
1010 1010
 
1011 1011
 
1012
-    /**
1013
-     * Takes care of deleting multiple EE_Checkin table rows
1014
-     *
1015
-     * @access protected
1016
-     * @return void
1017
-     * @throws EE_Error
1018
-     * @throws InvalidArgumentException
1019
-     * @throws InvalidDataTypeException
1020
-     * @throws InvalidInterfaceException
1021
-     */
1022
-    protected function _delete_checkin_rows()
1023
-    {
1024
-        $query_args = array(
1025
-            'action'  => 'registration_checkins',
1026
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1027
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1028
-        );
1029
-        $errors = 0;
1030
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1031
-            while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1032
-                if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1033
-                    $errors++;
1034
-                }
1035
-            }
1036
-        } else {
1037
-            EE_Error::add_error(
1038
-                esc_html__(
1039
-                    'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1040
-                    'event_espresso'
1041
-                ),
1042
-                __FILE__,
1043
-                __FUNCTION__,
1044
-                __LINE__
1045
-            );
1046
-            $this->_redirect_after_action(false, '', '', $query_args, true);
1047
-        }
1048
-        if ($errors > 0) {
1049
-            EE_Error::add_error(
1050
-                sprintf(esc_html__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1051
-                __FILE__,
1052
-                __FUNCTION__,
1053
-                __LINE__
1054
-            );
1055
-        } else {
1056
-            EE_Error::add_success(esc_html__('Records were successfully deleted', 'event_espresso'));
1057
-        }
1058
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1059
-    }
1012
+	/**
1013
+	 * Takes care of deleting multiple EE_Checkin table rows
1014
+	 *
1015
+	 * @access protected
1016
+	 * @return void
1017
+	 * @throws EE_Error
1018
+	 * @throws InvalidArgumentException
1019
+	 * @throws InvalidDataTypeException
1020
+	 * @throws InvalidInterfaceException
1021
+	 */
1022
+	protected function _delete_checkin_rows()
1023
+	{
1024
+		$query_args = array(
1025
+			'action'  => 'registration_checkins',
1026
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1027
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1028
+		);
1029
+		$errors = 0;
1030
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1031
+			while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1032
+				if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1033
+					$errors++;
1034
+				}
1035
+			}
1036
+		} else {
1037
+			EE_Error::add_error(
1038
+				esc_html__(
1039
+					'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1040
+					'event_espresso'
1041
+				),
1042
+				__FILE__,
1043
+				__FUNCTION__,
1044
+				__LINE__
1045
+			);
1046
+			$this->_redirect_after_action(false, '', '', $query_args, true);
1047
+		}
1048
+		if ($errors > 0) {
1049
+			EE_Error::add_error(
1050
+				sprintf(esc_html__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1051
+				__FILE__,
1052
+				__FUNCTION__,
1053
+				__LINE__
1054
+			);
1055
+		} else {
1056
+			EE_Error::add_success(esc_html__('Records were successfully deleted', 'event_espresso'));
1057
+		}
1058
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1059
+	}
1060 1060
 
1061 1061
 
1062
-    /**
1063
-     * Deletes a single EE_Checkin row
1064
-     *
1065
-     * @return void
1066
-     * @throws EE_Error
1067
-     * @throws InvalidArgumentException
1068
-     * @throws InvalidDataTypeException
1069
-     * @throws InvalidInterfaceException
1070
-     */
1071
-    protected function _delete_checkin_row()
1072
-    {
1073
-        $query_args = array(
1074
-            'action'  => 'registration_checkins',
1075
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1076
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1077
-        );
1078
-        if (! empty($this->_req_data['CHK_ID'])) {
1079
-            if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1080
-                EE_Error::add_error(
1081
-                    esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1082
-                    __FILE__,
1083
-                    __FUNCTION__,
1084
-                    __LINE__
1085
-                );
1086
-            } else {
1087
-                EE_Error::add_success(esc_html__('Check-In record successfully deleted', 'event_espresso'));
1088
-            }
1089
-        } else {
1090
-            EE_Error::add_error(
1091
-                esc_html__(
1092
-                    'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1093
-                    'event_espresso'
1094
-                ),
1095
-                __FILE__,
1096
-                __FUNCTION__,
1097
-                __LINE__
1098
-            );
1099
-        }
1100
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1101
-    }
1062
+	/**
1063
+	 * Deletes a single EE_Checkin row
1064
+	 *
1065
+	 * @return void
1066
+	 * @throws EE_Error
1067
+	 * @throws InvalidArgumentException
1068
+	 * @throws InvalidDataTypeException
1069
+	 * @throws InvalidInterfaceException
1070
+	 */
1071
+	protected function _delete_checkin_row()
1072
+	{
1073
+		$query_args = array(
1074
+			'action'  => 'registration_checkins',
1075
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1076
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1077
+		);
1078
+		if (! empty($this->_req_data['CHK_ID'])) {
1079
+			if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1080
+				EE_Error::add_error(
1081
+					esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1082
+					__FILE__,
1083
+					__FUNCTION__,
1084
+					__LINE__
1085
+				);
1086
+			} else {
1087
+				EE_Error::add_success(esc_html__('Check-In record successfully deleted', 'event_espresso'));
1088
+			}
1089
+		} else {
1090
+			EE_Error::add_error(
1091
+				esc_html__(
1092
+					'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1093
+					'event_espresso'
1094
+				),
1095
+				__FILE__,
1096
+				__FUNCTION__,
1097
+				__LINE__
1098
+			);
1099
+		}
1100
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1101
+	}
1102 1102
 
1103 1103
 
1104
-    /**
1105
-     *        generates HTML for the Event Registrations List Table
1106
-     *
1107
-     * @access protected
1108
-     * @return void
1109
-     * @throws EE_Error
1110
-     * @throws InvalidArgumentException
1111
-     * @throws InvalidDataTypeException
1112
-     * @throws InvalidInterfaceException
1113
-     */
1114
-    protected function _event_registrations_list_table()
1115
-    {
1116
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1117
-        $this->_admin_page_title .= isset($this->_req_data['event_id'])
1118
-            ? $this->get_action_link_or_button(
1119
-                'new_registration',
1120
-                'add-registrant',
1121
-                array('event_id' => $this->_req_data['event_id']),
1122
-                'add-new-h2',
1123
-                '',
1124
-                false
1125
-            )
1126
-            : '';
1127
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1128
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1129
-        $checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1130
-        $checkin_invalid = new CheckinStatusDashicon(EE_Checkin::status_invalid);
1131
-        $legend_items = array(
1132
-            'star-icon'        => array(
1133
-                'class' => 'dashicons dashicons-star-filled gold-icon',
1134
-                'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1135
-            ),
1136
-            'checkin'          => array(
1137
-                'class' => $checked_in->cssClasses(),
1138
-                'desc'  => $checked_in->legendLabel(),
1139
-            ),
1140
-            'checkout'         => array(
1141
-                'class' => $checked_out->cssClasses(),
1142
-                'desc'  => $checked_out->legendLabel(),
1143
-            ),
1144
-            'nocheckinrecord'  => array(
1145
-                'class' => $checked_never->cssClasses(),
1146
-                'desc'  => $checked_never->legendLabel(),
1147
-            ),
1148
-            'canNotCheckin'  => array(
1149
-                'class' => $checkin_invalid->cssClasses(),
1150
-                'desc'  => $checkin_invalid->legendLabel(),
1151
-            ),
1152
-            'approved_status'  => array(
1153
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_approved,
1154
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1155
-            ),
1156
-            'cancelled_status' => array(
1157
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_cancelled,
1158
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1159
-            ),
1160
-            'declined_status'  => array(
1161
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_declined,
1162
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1163
-            ),
1164
-            'not_approved'     => array(
1165
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_not_approved,
1166
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1167
-            ),
1168
-            'pending_status'   => array(
1169
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_pending_payment,
1170
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1171
-            ),
1172
-            'wait_list'        => array(
1173
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_wait_list,
1174
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1175
-            ),
1176
-        );
1177
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1178
-        $event_id = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : 0;
1179
-        /** @var EE_Event $event */
1180
-        $event = EEM_Event::instance()->get_one_by_ID($event_id);
1181
-        $this->_template_args['before_list_table'] = $event instanceof EE_Event
1182
-            ? '<h2>
1104
+	/**
1105
+	 *        generates HTML for the Event Registrations List Table
1106
+	 *
1107
+	 * @access protected
1108
+	 * @return void
1109
+	 * @throws EE_Error
1110
+	 * @throws InvalidArgumentException
1111
+	 * @throws InvalidDataTypeException
1112
+	 * @throws InvalidInterfaceException
1113
+	 */
1114
+	protected function _event_registrations_list_table()
1115
+	{
1116
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1117
+		$this->_admin_page_title .= isset($this->_req_data['event_id'])
1118
+			? $this->get_action_link_or_button(
1119
+				'new_registration',
1120
+				'add-registrant',
1121
+				array('event_id' => $this->_req_data['event_id']),
1122
+				'add-new-h2',
1123
+				'',
1124
+				false
1125
+			)
1126
+			: '';
1127
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1128
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1129
+		$checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1130
+		$checkin_invalid = new CheckinStatusDashicon(EE_Checkin::status_invalid);
1131
+		$legend_items = array(
1132
+			'star-icon'        => array(
1133
+				'class' => 'dashicons dashicons-star-filled gold-icon',
1134
+				'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1135
+			),
1136
+			'checkin'          => array(
1137
+				'class' => $checked_in->cssClasses(),
1138
+				'desc'  => $checked_in->legendLabel(),
1139
+			),
1140
+			'checkout'         => array(
1141
+				'class' => $checked_out->cssClasses(),
1142
+				'desc'  => $checked_out->legendLabel(),
1143
+			),
1144
+			'nocheckinrecord'  => array(
1145
+				'class' => $checked_never->cssClasses(),
1146
+				'desc'  => $checked_never->legendLabel(),
1147
+			),
1148
+			'canNotCheckin'  => array(
1149
+				'class' => $checkin_invalid->cssClasses(),
1150
+				'desc'  => $checkin_invalid->legendLabel(),
1151
+			),
1152
+			'approved_status'  => array(
1153
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_approved,
1154
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1155
+			),
1156
+			'cancelled_status' => array(
1157
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_cancelled,
1158
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1159
+			),
1160
+			'declined_status'  => array(
1161
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_declined,
1162
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1163
+			),
1164
+			'not_approved'     => array(
1165
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_not_approved,
1166
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1167
+			),
1168
+			'pending_status'   => array(
1169
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_pending_payment,
1170
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1171
+			),
1172
+			'wait_list'        => array(
1173
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_wait_list,
1174
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1175
+			),
1176
+		);
1177
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1178
+		$event_id = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : 0;
1179
+		/** @var EE_Event $event */
1180
+		$event = EEM_Event::instance()->get_one_by_ID($event_id);
1181
+		$this->_template_args['before_list_table'] = $event instanceof EE_Event
1182
+			? '<h2>
1183 1183
                 ' . sprintf(
1184
-                esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1185
-                "<span class='ee-event-name'>{$event->name()}</span>"
1186
-            )
1187
-            : '';
1188
-        // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1189
-        // the event.
1190
-        $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1191
-        $datetime = null;
1192
-        if ($event instanceof EE_Event) {
1193
-            $datetimes_on_event = $event->datetimes();
1194
-            if (count($datetimes_on_event) === 1) {
1195
-                $datetime = reset($datetimes_on_event);
1196
-            }
1197
-        }
1198
-        $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1199
-        if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1200
-            $active_status   = $datetime->get_active_status();
1201
-            $datetime_status =
1202
-                '<span class="ee-status ee-status-bg--' . esc_attr($active_status) . ' event-active-status-' .
1203
-                esc_attr($active_status) . '">'
1204
-                . EEH_Template::pretty_status($active_status, false, 'sentence')
1205
-                . '</span>';
1206
-            $this->_template_args['before_list_table'] .= '<span class="ee-event-datetime-name">';
1207
-            $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar-alt"></span>';
1208
-            $this->_template_args['before_list_table'] .= $datetime->name();
1209
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1210
-            $this->_template_args['before_list_table'] .= $datetime_status;
1211
-            $this->_template_args['before_list_table'] .= '</span>';
1212
-        }
1213
-        $this->_template_args['before_list_table'] .= '</h2>';
1214
-        // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1215
-        // column represents
1216
-        if (! $datetime instanceof EE_Datetime) {
1217
-            $this->_template_args['before_list_table'] .= '<h3 class="description">'
1218
-                                                          . esc_html__(
1219
-                                                              'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1220
-                                                              'event_espresso'
1221
-                                                          )
1222
-                                                          . '</h3>';
1223
-        }
1224
-        $this->display_admin_list_table_page_with_no_sidebar();
1225
-    }
1184
+				esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1185
+				"<span class='ee-event-name'>{$event->name()}</span>"
1186
+			)
1187
+			: '';
1188
+		// need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1189
+		// the event.
1190
+		$DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1191
+		$datetime = null;
1192
+		if ($event instanceof EE_Event) {
1193
+			$datetimes_on_event = $event->datetimes();
1194
+			if (count($datetimes_on_event) === 1) {
1195
+				$datetime = reset($datetimes_on_event);
1196
+			}
1197
+		}
1198
+		$datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1199
+		if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1200
+			$active_status   = $datetime->get_active_status();
1201
+			$datetime_status =
1202
+				'<span class="ee-status ee-status-bg--' . esc_attr($active_status) . ' event-active-status-' .
1203
+				esc_attr($active_status) . '">'
1204
+				. EEH_Template::pretty_status($active_status, false, 'sentence')
1205
+				. '</span>';
1206
+			$this->_template_args['before_list_table'] .= '<span class="ee-event-datetime-name">';
1207
+			$this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar-alt"></span>';
1208
+			$this->_template_args['before_list_table'] .= $datetime->name();
1209
+			$this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1210
+			$this->_template_args['before_list_table'] .= $datetime_status;
1211
+			$this->_template_args['before_list_table'] .= '</span>';
1212
+		}
1213
+		$this->_template_args['before_list_table'] .= '</h2>';
1214
+		// if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1215
+		// column represents
1216
+		if (! $datetime instanceof EE_Datetime) {
1217
+			$this->_template_args['before_list_table'] .= '<h3 class="description">'
1218
+														  . esc_html__(
1219
+															  'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1220
+															  'event_espresso'
1221
+														  )
1222
+														  . '</h3>';
1223
+		}
1224
+		$this->display_admin_list_table_page_with_no_sidebar();
1225
+	}
1226 1226
 
1227
-    /**
1228
-     * Download the registrations check-in report (same as the normal registration report, but with different where
1229
-     * conditions)
1230
-     *
1231
-     * @return void ends the request by a redirect or download
1232
-     */
1233
-    public function _registrations_checkin_report()
1234
-    {
1235
-        $this->_registrations_report_base('_get_checkin_query_params_from_request');
1236
-    }
1227
+	/**
1228
+	 * Download the registrations check-in report (same as the normal registration report, but with different where
1229
+	 * conditions)
1230
+	 *
1231
+	 * @return void ends the request by a redirect or download
1232
+	 */
1233
+	public function _registrations_checkin_report()
1234
+	{
1235
+		$this->_registrations_report_base('_get_checkin_query_params_from_request');
1236
+	}
1237 1237
 
1238
-    /**
1239
-     * Gets the query params from the request, plus adds a where condition for the registration status,
1240
-     * because on the checkin page we only ever want to see approved and pending-approval registrations
1241
-     *
1242
-     * @param array $request
1243
-     * @param int   $per_page
1244
-     * @param bool  $count
1245
-     * @return array
1246
-     * @throws EE_Error
1247
-     */
1248
-    protected function _get_checkin_query_params_from_request(
1249
-        $request,
1250
-        $per_page = 10,
1251
-        $count = false
1252
-    ) {
1253
-        $query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1254
-        // unlike the regular registrations list table,
1255
-        $status_ids_array = apply_filters(
1256
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1257
-            array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1258
-        );
1259
-        $query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1260
-        return $query_params;
1261
-    }
1238
+	/**
1239
+	 * Gets the query params from the request, plus adds a where condition for the registration status,
1240
+	 * because on the checkin page we only ever want to see approved and pending-approval registrations
1241
+	 *
1242
+	 * @param array $request
1243
+	 * @param int   $per_page
1244
+	 * @param bool  $count
1245
+	 * @return array
1246
+	 * @throws EE_Error
1247
+	 */
1248
+	protected function _get_checkin_query_params_from_request(
1249
+		$request,
1250
+		$per_page = 10,
1251
+		$count = false
1252
+	) {
1253
+		$query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1254
+		// unlike the regular registrations list table,
1255
+		$status_ids_array = apply_filters(
1256
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1257
+			array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1258
+		);
1259
+		$query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1260
+		return $query_params;
1261
+	}
1262 1262
 
1263 1263
 
1264
-    /**
1265
-     * Gets registrations for an event
1266
-     *
1267
-     * @param int    $per_page
1268
-     * @param bool   $count whether to return count or data.
1269
-     * @param bool   $trash
1270
-     * @param string $orderby
1271
-     * @return EE_Registration[]|int
1272
-     * @throws EE_Error
1273
-     * @throws InvalidArgumentException
1274
-     * @throws InvalidDataTypeException
1275
-     * @throws InvalidInterfaceException
1276
-     */
1277
-    public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1278
-    {
1279
-        // set some defaults, these will get overridden if included in the actual request parameters
1280
-        $defaults = [
1281
-            'orderby' => $orderby,
1282
-            'order' => 'ASC',
1283
-        ];
1284
-        if ($trash) {
1285
-            $defaults['status'] = 'trash';
1286
-        }
1287
-        $query_params = $this->_get_checkin_query_params_from_request($defaults, $per_page, $count);
1264
+	/**
1265
+	 * Gets registrations for an event
1266
+	 *
1267
+	 * @param int    $per_page
1268
+	 * @param bool   $count whether to return count or data.
1269
+	 * @param bool   $trash
1270
+	 * @param string $orderby
1271
+	 * @return EE_Registration[]|int
1272
+	 * @throws EE_Error
1273
+	 * @throws InvalidArgumentException
1274
+	 * @throws InvalidDataTypeException
1275
+	 * @throws InvalidInterfaceException
1276
+	 */
1277
+	public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1278
+	{
1279
+		// set some defaults, these will get overridden if included in the actual request parameters
1280
+		$defaults = [
1281
+			'orderby' => $orderby,
1282
+			'order' => 'ASC',
1283
+		];
1284
+		if ($trash) {
1285
+			$defaults['status'] = 'trash';
1286
+		}
1287
+		$query_params = $this->_get_checkin_query_params_from_request($defaults, $per_page, $count);
1288 1288
 
1289
-        /**
1290
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1291
-         *
1292
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1293
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1294
-         *                             or if you have the development copy of EE you can view this at the path:
1295
-         *                             /docs/G--Model-System/model-query-params.md
1296
-         */
1297
-        $query_params['group_by'] = '';
1289
+		/**
1290
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1291
+		 *
1292
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1293
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1294
+		 *                             or if you have the development copy of EE you can view this at the path:
1295
+		 *                             /docs/G--Model-System/model-query-params.md
1296
+		 */
1297
+		$query_params['group_by'] = '';
1298 1298
 
1299
-        return $count
1300
-            ? EEM_Registration::instance()->count($query_params)
1301
-            /** @type EE_Registration[] */
1302
-            : EEM_Registration::instance()->get_all($query_params);
1303
-    }
1299
+		return $count
1300
+			? EEM_Registration::instance()->count($query_params)
1301
+			/** @type EE_Registration[] */
1302
+			: EEM_Registration::instance()->get_all($query_params);
1303
+	}
1304 1304
 }
Please login to merge, or discard this patch.
admin/extend/registrations/EE_Event_Registrations_List_Table.class.php 2 patches
Indentation   +641 added lines, -641 removed lines patch added patch discarded remove patch
@@ -16,689 +16,689 @@
 block discarded – undo
16 16
  */
17 17
 class EE_Event_Registrations_List_Table extends EE_Admin_List_Table
18 18
 {
19
-    /**
20
-     * @var RequestInterface
21
-     */
22
-    protected $request;
23
-
24
-    /**
25
-     * @var Extend_Registrations_Admin_Page
26
-     */
27
-    protected $_admin_page;
28
-
29
-    /**
30
-     * The event ID if one is specified in the request
31
-     *
32
-     * @var int
33
-     */
34
-    protected $event_id = 0;
35
-
36
-    /**
37
-     * This property will hold the related Datetimes on an event IF the event id is included in the request.
38
-     *
39
-     * @var DatetimesForEventCheckIn
40
-     */
41
-    protected $datetimes_for_event = [];
42
-
43
-    /**
44
-     * The DTT_ID if the current view has a specified datetime.
45
-     *
46
-     * @var int
47
-     */
48
-    protected $datetime_id = 0;
49
-
50
-    /**
51
-     * @var EE_Datetime
52
-     */
53
-    protected $datetime;
54
-
55
-    /**
56
-     * @var EE_Event
57
-     */
58
-    protected $event;
59
-
60
-    /**
61
-     * @var DatetimesForEventCheckIn
62
-     */
63
-    protected $datetimes_for_current_row;
64
-
65
-    /**
66
-     * @var bool
67
-     */
68
-    protected $hide_expired;
69
-
70
-    /**
71
-     * @var bool
72
-     */
73
-    protected $hide_upcoming;
74
-
75
-    /**
76
-     * @var   array
77
-     * @since $VID:$
78
-     */
79
-    protected $_status;
80
-
81
-
82
-    /**
83
-     * EE_Event_Registrations_List_Table constructor.
84
-     *
85
-     * @param Registrations_Admin_Page $admin_page
86
-     * @throws EE_Error
87
-     * @throws ReflectionException
88
-     */
89
-    public function __construct($admin_page)
90
-    {
91
-        $this->request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
92
-        $this->resolveRequestVars();
93
-        parent::__construct($admin_page);
94
-    }
95
-
96
-
97
-    /**
98
-     * @throws EE_Error
99
-     * @throws ReflectionException
100
-     * @since $VID:$
101
-     */
102
-    private function resolveRequestVars()
103
-    {
104
-        $this->event_id = $this->request->getRequestParam('event_id', 0, 'int');
105
-        $this->datetimes_for_event = DatetimesForEventCheckIn::fromEventID($this->event_id);
106
-        // if we're filtering for a specific event and it only has one datetime, then grab its ID
107
-        $datetime          = $this->datetimes_for_event->getOneDatetimeForEvent();
108
-        $this->datetime_id = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
109
-        // else check the request, but use the above as the default (and hope they match if BOTH exist, LOLZ)
110
-        $this->datetime_id = $this->request->getRequestParam(
111
-            'DTT_ID',
112
-            $this->datetime_id,
113
-            'int'
114
-        );
115
-    }
116
-
117
-
118
-    /**
119
-     * @throws EE_Error
120
-     */
121
-    protected function _setup_data()
122
-    {
123
-        $this->_data = $this->_view !== 'trash'
124
-            ? $this->_admin_page->get_event_attendees($this->_per_page)
125
-            : $this->_admin_page->get_event_attendees($this->_per_page, false, true);
126
-
127
-        $this->_all_data_count = $this->_view !== 'trash'
128
-            ? $this->_admin_page->get_event_attendees($this->_per_page, true)
129
-            : $this->_admin_page->get_event_attendees($this->_per_page, true, true);
130
-    }
131
-
132
-
133
-    /**
134
-     * @throws ReflectionException
135
-     * @throws EE_Error
136
-     */
137
-    protected function _set_properties()
138
-    {
139
-        $return_url = $this->getReturnUrl();
140
-
141
-        $EVT_ID = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : 0;
142
-        $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0;
143
-
144
-        $this->_wp_list_args = [
145
-            'singular' => esc_html__('registrant', 'event_espresso'),
146
-            'plural'   => esc_html__('registrants', 'event_espresso'),
147
-            'ajax'     => true,
148
-            'screen'   => $this->_admin_page->get_current_screen()->id,
149
-        ];
150
-        $columns             = [];
151
-
152
-        $this->_columns = [
153
-            '_REG_att_checked_in' => '<span class="dashicons dashicons-yes ee-icon-size-18"></span>',
154
-            'ATT_name'            => esc_html__('Registrant', 'event_espresso'),
155
-            'ATT_email'           => esc_html__('Email Address', 'event_espresso'),
156
-            'Event'               => esc_html__('Event', 'event_espresso'),
157
-            'PRC_name'            => esc_html__('TKT Option', 'event_espresso'),
158
-            '_REG_final_price'    => esc_html__('Price', 'event_espresso'),
159
-            'TXN_paid'            => esc_html__('Paid', 'event_espresso'),
160
-            'TXN_total'           => esc_html__('Total', 'event_espresso'),
161
-        ];
162
-        // Add/remove columns when an event has been selected
163
-        if (! empty($EVT_ID)) {
164
-            // Render a checkbox column
165
-            $columns['cb']              = '<input type="checkbox" />';
166
-            $this->_has_checkbox_column = true;
167
-            // Remove the 'Event' column
168
-            unset($this->_columns['Event']);
169
-            $this->setBottomButtons();
170
-        }
171
-        $this->_columns        = array_merge($columns, $this->_columns);
172
-        $this->_primary_column = '_REG_att_checked_in';
173
-
174
-        $csv_report = RegistrationsCsvReportParams::getRequestParams($return_url, $this->_req_data, $EVT_ID, $DTT_ID);
175
-        if (! empty($csv_report)) {
176
-            $this->_bottom_buttons['csv_reg_report'] = $csv_report;
177
-        }
178
-
179
-        $this->_sortable_columns = [
180
-            /**
181
-             * Allows users to change the default sort if they wish.
182
-             * Returning a falsey on this filter will result in the default sort to be by firstname rather than last name.
183
-             *
184
-             * Note: usual naming conventions for filters aren't followed here so that just one filter can be used to
185
-             * change the sorts on any list table involving registration contacts.  If you want to only change the filter
186
-             * for a specific list table you can use the provided reference to this object instance.
187
-             */
188
-            'ATT_name' => [
189
-                'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
190
-                true,
191
-                $this,
192
-            ]
193
-                ? ['ATT_lname' => true]
194
-                : ['ATT_fname' => true],
195
-            'Event'    => ['Event.EVT_name' => false],
196
-        ];
197
-        $this->_hidden_columns   = [];
198
-        $this->_evt              = EEM_Event::instance()->get_one_by_ID($EVT_ID);
199
-        $this->datetimes_for_event   = $this->_evt instanceof EE_Event ? $this->_evt->datetimes_ordered() : [];
200
-    }
201
-
202
-
203
-    /**
204
-     * @param EE_Registration $item
205
-     * @return string
206
-     */
207
-    protected function _get_row_class($item): string
208
-    {
209
-        $class = parent::_get_row_class($item);
210
-        if ($this->_has_checkbox_column) {
211
-            $class .= ' has-checkbox-column';
212
-        }
213
-        return $class;
214
-    }
215
-
216
-
217
-    /**
218
-     * @return array
219
-     * @throws EE_Error
220
-     * @throws ReflectionException
221
-     */
222
-    protected function _get_table_filters(): array
223
-    {
224
-        $filters = [];
225
-        $this->hide_expired = $this->request->getRequestParam('hide_expired', false, 'bool');
226
-        $this->hide_upcoming = $this->request->getRequestParam('hide_upcoming', false, 'bool');
227
-        $hide_expired_checked = $this->hide_expired ? 'checked' : '';
228
-        $hide_upcoming_checked = $this->hide_upcoming ? 'checked' : '';
229
-        // get datetimes for ALL active events (note possible capability restrictions)
230
-        $events   = $this->datetimes_for_event->getAllDatetimesForAllEvents();
231
-        $event_options[] = [
232
-            'id'   => 0,
233
-            'text' => esc_html__(' - select an event - ', 'event_espresso'),
234
-        ];
235
-        /** @var EE_Event $event */
236
-        foreach ($events as $event) {
237
-            // any registrations for this event?
238
-            if (! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
239
-                continue;
240
-            }
241
-            $expired_class = $event->is_expired() ? 'ee-expired-event' : '';
242
-            $upcoming_class  = $event->is_upcoming() ? ' ee-upcoming-event' : '';
243
-
244
-            $event_options[] = [
245
-                'id'    => $event->ID(),
246
-                'text'  => apply_filters(
247
-                    'FHEE__EE_Event_Registrations___get_table_filters__event_name',
248
-                    $event->name(),
249
-                    $event
250
-                ),
251
-                'class' => $expired_class . $upcoming_class,
252
-            ];
253
-            if ($event->ID() === $this->event_id) {
254
-                $this->hide_expired = $expired_class === '' ? $this->hide_expired : false;
255
-                $hide_expired_checked  = $expired_class === '' ? $hide_expired_checked : '';
256
-                $this->hide_upcoming = $upcoming_class === '' ? $this->hide_upcoming : false;
257
-                $hide_upcoming_checked = $upcoming_class === '' ? $hide_upcoming_checked : '';
258
-            }
259
-        }
260
-
261
-        $select_class = $this->hide_expired ? 'ee-hide-expired-events' : '';
262
-        $select_class .= $this->hide_upcoming ? ' ee-hide-upcoming-events' : '';
263
-
264
-        $filters[] = '
19
+	/**
20
+	 * @var RequestInterface
21
+	 */
22
+	protected $request;
23
+
24
+	/**
25
+	 * @var Extend_Registrations_Admin_Page
26
+	 */
27
+	protected $_admin_page;
28
+
29
+	/**
30
+	 * The event ID if one is specified in the request
31
+	 *
32
+	 * @var int
33
+	 */
34
+	protected $event_id = 0;
35
+
36
+	/**
37
+	 * This property will hold the related Datetimes on an event IF the event id is included in the request.
38
+	 *
39
+	 * @var DatetimesForEventCheckIn
40
+	 */
41
+	protected $datetimes_for_event = [];
42
+
43
+	/**
44
+	 * The DTT_ID if the current view has a specified datetime.
45
+	 *
46
+	 * @var int
47
+	 */
48
+	protected $datetime_id = 0;
49
+
50
+	/**
51
+	 * @var EE_Datetime
52
+	 */
53
+	protected $datetime;
54
+
55
+	/**
56
+	 * @var EE_Event
57
+	 */
58
+	protected $event;
59
+
60
+	/**
61
+	 * @var DatetimesForEventCheckIn
62
+	 */
63
+	protected $datetimes_for_current_row;
64
+
65
+	/**
66
+	 * @var bool
67
+	 */
68
+	protected $hide_expired;
69
+
70
+	/**
71
+	 * @var bool
72
+	 */
73
+	protected $hide_upcoming;
74
+
75
+	/**
76
+	 * @var   array
77
+	 * @since $VID:$
78
+	 */
79
+	protected $_status;
80
+
81
+
82
+	/**
83
+	 * EE_Event_Registrations_List_Table constructor.
84
+	 *
85
+	 * @param Registrations_Admin_Page $admin_page
86
+	 * @throws EE_Error
87
+	 * @throws ReflectionException
88
+	 */
89
+	public function __construct($admin_page)
90
+	{
91
+		$this->request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
92
+		$this->resolveRequestVars();
93
+		parent::__construct($admin_page);
94
+	}
95
+
96
+
97
+	/**
98
+	 * @throws EE_Error
99
+	 * @throws ReflectionException
100
+	 * @since $VID:$
101
+	 */
102
+	private function resolveRequestVars()
103
+	{
104
+		$this->event_id = $this->request->getRequestParam('event_id', 0, 'int');
105
+		$this->datetimes_for_event = DatetimesForEventCheckIn::fromEventID($this->event_id);
106
+		// if we're filtering for a specific event and it only has one datetime, then grab its ID
107
+		$datetime          = $this->datetimes_for_event->getOneDatetimeForEvent();
108
+		$this->datetime_id = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
109
+		// else check the request, but use the above as the default (and hope they match if BOTH exist, LOLZ)
110
+		$this->datetime_id = $this->request->getRequestParam(
111
+			'DTT_ID',
112
+			$this->datetime_id,
113
+			'int'
114
+		);
115
+	}
116
+
117
+
118
+	/**
119
+	 * @throws EE_Error
120
+	 */
121
+	protected function _setup_data()
122
+	{
123
+		$this->_data = $this->_view !== 'trash'
124
+			? $this->_admin_page->get_event_attendees($this->_per_page)
125
+			: $this->_admin_page->get_event_attendees($this->_per_page, false, true);
126
+
127
+		$this->_all_data_count = $this->_view !== 'trash'
128
+			? $this->_admin_page->get_event_attendees($this->_per_page, true)
129
+			: $this->_admin_page->get_event_attendees($this->_per_page, true, true);
130
+	}
131
+
132
+
133
+	/**
134
+	 * @throws ReflectionException
135
+	 * @throws EE_Error
136
+	 */
137
+	protected function _set_properties()
138
+	{
139
+		$return_url = $this->getReturnUrl();
140
+
141
+		$EVT_ID = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : 0;
142
+		$DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0;
143
+
144
+		$this->_wp_list_args = [
145
+			'singular' => esc_html__('registrant', 'event_espresso'),
146
+			'plural'   => esc_html__('registrants', 'event_espresso'),
147
+			'ajax'     => true,
148
+			'screen'   => $this->_admin_page->get_current_screen()->id,
149
+		];
150
+		$columns             = [];
151
+
152
+		$this->_columns = [
153
+			'_REG_att_checked_in' => '<span class="dashicons dashicons-yes ee-icon-size-18"></span>',
154
+			'ATT_name'            => esc_html__('Registrant', 'event_espresso'),
155
+			'ATT_email'           => esc_html__('Email Address', 'event_espresso'),
156
+			'Event'               => esc_html__('Event', 'event_espresso'),
157
+			'PRC_name'            => esc_html__('TKT Option', 'event_espresso'),
158
+			'_REG_final_price'    => esc_html__('Price', 'event_espresso'),
159
+			'TXN_paid'            => esc_html__('Paid', 'event_espresso'),
160
+			'TXN_total'           => esc_html__('Total', 'event_espresso'),
161
+		];
162
+		// Add/remove columns when an event has been selected
163
+		if (! empty($EVT_ID)) {
164
+			// Render a checkbox column
165
+			$columns['cb']              = '<input type="checkbox" />';
166
+			$this->_has_checkbox_column = true;
167
+			// Remove the 'Event' column
168
+			unset($this->_columns['Event']);
169
+			$this->setBottomButtons();
170
+		}
171
+		$this->_columns        = array_merge($columns, $this->_columns);
172
+		$this->_primary_column = '_REG_att_checked_in';
173
+
174
+		$csv_report = RegistrationsCsvReportParams::getRequestParams($return_url, $this->_req_data, $EVT_ID, $DTT_ID);
175
+		if (! empty($csv_report)) {
176
+			$this->_bottom_buttons['csv_reg_report'] = $csv_report;
177
+		}
178
+
179
+		$this->_sortable_columns = [
180
+			/**
181
+			 * Allows users to change the default sort if they wish.
182
+			 * Returning a falsey on this filter will result in the default sort to be by firstname rather than last name.
183
+			 *
184
+			 * Note: usual naming conventions for filters aren't followed here so that just one filter can be used to
185
+			 * change the sorts on any list table involving registration contacts.  If you want to only change the filter
186
+			 * for a specific list table you can use the provided reference to this object instance.
187
+			 */
188
+			'ATT_name' => [
189
+				'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
190
+				true,
191
+				$this,
192
+			]
193
+				? ['ATT_lname' => true]
194
+				: ['ATT_fname' => true],
195
+			'Event'    => ['Event.EVT_name' => false],
196
+		];
197
+		$this->_hidden_columns   = [];
198
+		$this->_evt              = EEM_Event::instance()->get_one_by_ID($EVT_ID);
199
+		$this->datetimes_for_event   = $this->_evt instanceof EE_Event ? $this->_evt->datetimes_ordered() : [];
200
+	}
201
+
202
+
203
+	/**
204
+	 * @param EE_Registration $item
205
+	 * @return string
206
+	 */
207
+	protected function _get_row_class($item): string
208
+	{
209
+		$class = parent::_get_row_class($item);
210
+		if ($this->_has_checkbox_column) {
211
+			$class .= ' has-checkbox-column';
212
+		}
213
+		return $class;
214
+	}
215
+
216
+
217
+	/**
218
+	 * @return array
219
+	 * @throws EE_Error
220
+	 * @throws ReflectionException
221
+	 */
222
+	protected function _get_table_filters(): array
223
+	{
224
+		$filters = [];
225
+		$this->hide_expired = $this->request->getRequestParam('hide_expired', false, 'bool');
226
+		$this->hide_upcoming = $this->request->getRequestParam('hide_upcoming', false, 'bool');
227
+		$hide_expired_checked = $this->hide_expired ? 'checked' : '';
228
+		$hide_upcoming_checked = $this->hide_upcoming ? 'checked' : '';
229
+		// get datetimes for ALL active events (note possible capability restrictions)
230
+		$events   = $this->datetimes_for_event->getAllDatetimesForAllEvents();
231
+		$event_options[] = [
232
+			'id'   => 0,
233
+			'text' => esc_html__(' - select an event - ', 'event_espresso'),
234
+		];
235
+		/** @var EE_Event $event */
236
+		foreach ($events as $event) {
237
+			// any registrations for this event?
238
+			if (! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
239
+				continue;
240
+			}
241
+			$expired_class = $event->is_expired() ? 'ee-expired-event' : '';
242
+			$upcoming_class  = $event->is_upcoming() ? ' ee-upcoming-event' : '';
243
+
244
+			$event_options[] = [
245
+				'id'    => $event->ID(),
246
+				'text'  => apply_filters(
247
+					'FHEE__EE_Event_Registrations___get_table_filters__event_name',
248
+					$event->name(),
249
+					$event
250
+				),
251
+				'class' => $expired_class . $upcoming_class,
252
+			];
253
+			if ($event->ID() === $this->event_id) {
254
+				$this->hide_expired = $expired_class === '' ? $this->hide_expired : false;
255
+				$hide_expired_checked  = $expired_class === '' ? $hide_expired_checked : '';
256
+				$this->hide_upcoming = $upcoming_class === '' ? $this->hide_upcoming : false;
257
+				$hide_upcoming_checked = $upcoming_class === '' ? $hide_upcoming_checked : '';
258
+			}
259
+		}
260
+
261
+		$select_class = $this->hide_expired ? 'ee-hide-expired-events' : '';
262
+		$select_class .= $this->hide_upcoming ? ' ee-hide-upcoming-events' : '';
263
+
264
+		$filters[] = '
265 265
         <div class="ee-event-filter__wrapper">
266 266
             <label class="ee-event-filter-main-label">' . esc_html__('Check-in Status for', 'event_espresso') . '</label>
267 267
             <div class="ee-event-filter">
268 268
                 <span class="ee-event-selector">
269 269
                     <label for="event_id">' . esc_html__('Event', 'event_espresso') . '</label>
270 270
                     ' . EEH_Form_Fields::select_input(
271
-                        'event_id',
272
-                        $event_options,
273
-                        $this->event_id,
274
-                        '',
275
-                        $select_class
276
-                    ) . '
271
+						'event_id',
272
+						$event_options,
273
+						$this->event_id,
274
+						'',
275
+						$select_class
276
+					) . '
277 277
                 </span>';
278
-        // DTT datetimes filter
279
-        $datetimes_for_event = $this->datetimes_for_event->getAllDatetimesForEvent($hide_upcoming_checked === 'checked');
280
-        if (count($datetimes_for_event) > 1) {
281
-            $datetimes[0] = esc_html__(' - select a datetime - ', 'event_espresso');
282
-            foreach ($datetimes_for_event as $datetime) {
283
-                if ($datetime instanceof EE_Datetime) {
284
-                    $datetime_string = $datetime->name();
285
-                    $datetime_string = ! empty($datetime_string) ? $datetime_string . ': ' : '';
286
-                    $datetime_string .= $datetime->date_and_time_range();
287
-                    $datetime_string .= $datetime->is_active() ? ' ∗' : '';
288
-                    $datetime_string .= $datetime->is_expired() ? ' «' : '';
289
-                    $datetime_string .= $datetime->is_upcoming() ? ' »' : '';
290
-                    // now put it all together
291
-                    $datetimes[ $datetime->ID() ] = $datetime_string;
292
-                }
293
-            }
294
-            $filters[] = '
278
+		// DTT datetimes filter
279
+		$datetimes_for_event = $this->datetimes_for_event->getAllDatetimesForEvent($hide_upcoming_checked === 'checked');
280
+		if (count($datetimes_for_event) > 1) {
281
+			$datetimes[0] = esc_html__(' - select a datetime - ', 'event_espresso');
282
+			foreach ($datetimes_for_event as $datetime) {
283
+				if ($datetime instanceof EE_Datetime) {
284
+					$datetime_string = $datetime->name();
285
+					$datetime_string = ! empty($datetime_string) ? $datetime_string . ': ' : '';
286
+					$datetime_string .= $datetime->date_and_time_range();
287
+					$datetime_string .= $datetime->is_active() ? ' ∗' : '';
288
+					$datetime_string .= $datetime->is_expired() ? ' «' : '';
289
+					$datetime_string .= $datetime->is_upcoming() ? ' »' : '';
290
+					// now put it all together
291
+					$datetimes[ $datetime->ID() ] = $datetime_string;
292
+				}
293
+			}
294
+			$filters[] = '
295 295
                 <span class="ee-datetime-selector">
296 296
                     <label for="DTT_ID">' . esc_html__('Datetime', 'event_espresso') . '</label>
297 297
                     ' . EEH_Form_Fields::select_input(
298
-                        'DTT_ID',
299
-                        $datetimes,
300
-                        $this->datetime_id
301
-                    ) . '
298
+						'DTT_ID',
299
+						$datetimes,
300
+						$this->datetime_id
301
+					) . '
302 302
                 </span>';
303
-        }
304
-        $filters[] = '
303
+		}
304
+		$filters[] = '
305 305
                 <span class="ee-hide-upcoming-check">
306 306
                     <label for="js-ee-hide-upcoming-events">
307 307
                         <input type="checkbox" id="js-ee-hide-upcoming-events" name="hide_upcoming" '
308
-                         . $hide_upcoming_checked
309
-                         . '>
308
+						 . $hide_upcoming_checked
309
+						 . '>
310 310
                         '
311
-                         . esc_html__('Hide Upcoming Events', 'event_espresso')
312
-                         . '
311
+						 . esc_html__('Hide Upcoming Events', 'event_espresso')
312
+						 . '
313 313
                     </label>
314 314
                     <span class="ee-help-btn dashicons dashicons-editor-help ee-aria-tooltip" aria-label="'
315
-                         . esc_html__(
316
-                             'Will not display events with start dates in the future (ie: have not yet begun)',
317
-                             'event_espresso'
318
-                         )
319
-                         . '"></span>
315
+						 . esc_html__(
316
+							 'Will not display events with start dates in the future (ie: have not yet begun)',
317
+							 'event_espresso'
318
+						 )
319
+						 . '"></span>
320 320
                 </span>
321 321
                 <span class="ee-hide-expired-check">
322 322
                     <label for="js-ee-hide-expired-events">
323 323
                         <input type="checkbox" id="js-ee-hide-expired-events" name="hide_expired" '
324
-                         . $hide_expired_checked
325
-                         . '>
324
+						 . $hide_expired_checked
325
+						 . '>
326 326
                         '
327
-                         . esc_html__('Hide Expired Events', 'event_espresso')
328
-                         . '
327
+						 . esc_html__('Hide Expired Events', 'event_espresso')
328
+						 . '
329 329
                     </label>
330 330
                     <span class="ee-help-btn dashicons dashicons-editor-help ee-aria-tooltip" aria-label="'
331
-                         . esc_html__(
332
-                             'Will not display events with end dates in the past (ie: have already finished)',
333
-                             'event_espresso'
334
-                         )
335
-                         . '"></span>
331
+						 . esc_html__(
332
+							 'Will not display events with end dates in the past (ie: have already finished)',
333
+							 'event_espresso'
334
+						 )
335
+						 . '"></span>
336 336
                 </span>
337 337
             </div>
338 338
         </div>';
339
-        return $filters;
340
-    }
341
-
342
-
343
-    /**
344
-     * @throws EE_Error
345
-     * @throws ReflectionException
346
-     */
347
-    protected function _add_view_counts()
348
-    {
349
-        $this->_views['all']['count'] = $this->_get_total_event_attendees();
350
-    }
351
-
352
-
353
-    /**
354
-     * @return int
355
-     * @throws EE_Error
356
-     * @throws ReflectionException
357
-     */
358
-    protected function _get_total_event_attendees(): int
359
-    {
360
-        $query_params      = [];
361
-        if ($this->event_id) {
362
-            $query_params[0]['EVT_ID'] = $this->event_id;
363
-        }
364
-        // if DTT is included we only show for that datetime.  Otherwise we're showing for all datetimes (the event).
365
-        if ($this->datetime_id) {
366
-            $query_params[0]['Ticket.Datetime.DTT_ID'] = $this->datetime_id;
367
-        }
368
-        $status_ids_array          = apply_filters(
369
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
370
-            [EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved]
371
-        );
372
-        $query_params[0]['STS_ID'] = ['IN', $status_ids_array];
373
-        return EEM_Registration::instance()->count($query_params);
374
-    }
375
-
376
-
377
-    /**
378
-     * @param EE_Registration $item
379
-     * @return string
380
-     * @throws EE_Error
381
-     * @throws ReflectionException
382
-     */
383
-    public function column_cb($item): string
384
-    {
385
-        return sprintf('<input type="checkbox" name="checkbox[%1$s]" value="%1$s" />', $item->ID());
386
-    }
387
-
388
-
389
-    /**
390
-     * column_REG_att_checked_in
391
-     *
392
-     * @param EE_Registration $registration
393
-     * @return string
394
-     * @throws EE_Error
395
-     * @throws InvalidArgumentException
396
-     * @throws InvalidDataTypeException
397
-     * @throws InvalidInterfaceException
398
-     * @throws ReflectionException
399
-     */
400
-    public function column__REG_att_checked_in(EE_Registration $registration): string
401
-    {
402
-        // we need a local variable for the datetime for each row
403
-        // (so that we don't pollute state for the entire table)
404
-        // so let's try to get it from the registration's event
405
-        $DTT_ID = $this->datetime_id;
406
-        if (! $DTT_ID) {
407
-            $reg_ticket_datetimes = $registration->ticket()->datetimes();
408
-            if (count($reg_ticket_datetimes) === 1) {
409
-                $reg_ticket_datetime = reset($reg_ticket_datetimes);
410
-                $DTT_ID = $reg_ticket_datetime instanceof EE_Datetime ? $reg_ticket_datetime->ID() : 0;
411
-            }
412
-        }
413
-
414
-        if (! $DTT_ID) {
415
-            $this->datetimes_for_current_row = DatetimesForEventCheckIn::fromRegistration($registration);
416
-            $datetime = $this->datetimes_for_current_row->getOneDatetimeForEvent($DTT_ID);
417
-            $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
418
-        }
419
-
420
-        $checkin_status_dashicon = CheckinStatusDashicon::fromRegistrationAndDatetimeId(
421
-            $registration,
422
-            $DTT_ID
423
-        );
424
-
425
-        $aria_label = $checkin_status_dashicon->ariaLabel();
426
-        $dashicon_class = $checkin_status_dashicon->cssClasses();
427
-        $attributes = ' onClick="return false"';
428
-        $button_class = 'button button--secondary button--icon-only ee-aria-tooltip ee-aria-tooltip--big-box';
429
-
430
-        if (
431
-            $DTT_ID
432
-            && EE_Registry::instance()->CAP->current_user_can(
433
-                'ee_edit_checkin',
434
-                'espresso_registrations_toggle_checkin_status',
435
-                $registration->ID()
436
-            )
437
-        ) {
438
-            // overwrite the disabled attribute with data attributes for performing checkin
439
-            $attributes = 'data-_regid="' . $registration->ID() . '"';
440
-            $attributes .= ' data-dttid="' . $DTT_ID . '"';
441
-            $attributes .= ' data-nonce="' . wp_create_nonce('checkin_nonce') . '"';
442
-            $button_class .= ' clickable trigger-checkin';
443
-        }
444
-
445
-        $content = '
339
+		return $filters;
340
+	}
341
+
342
+
343
+	/**
344
+	 * @throws EE_Error
345
+	 * @throws ReflectionException
346
+	 */
347
+	protected function _add_view_counts()
348
+	{
349
+		$this->_views['all']['count'] = $this->_get_total_event_attendees();
350
+	}
351
+
352
+
353
+	/**
354
+	 * @return int
355
+	 * @throws EE_Error
356
+	 * @throws ReflectionException
357
+	 */
358
+	protected function _get_total_event_attendees(): int
359
+	{
360
+		$query_params      = [];
361
+		if ($this->event_id) {
362
+			$query_params[0]['EVT_ID'] = $this->event_id;
363
+		}
364
+		// if DTT is included we only show for that datetime.  Otherwise we're showing for all datetimes (the event).
365
+		if ($this->datetime_id) {
366
+			$query_params[0]['Ticket.Datetime.DTT_ID'] = $this->datetime_id;
367
+		}
368
+		$status_ids_array          = apply_filters(
369
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
370
+			[EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved]
371
+		);
372
+		$query_params[0]['STS_ID'] = ['IN', $status_ids_array];
373
+		return EEM_Registration::instance()->count($query_params);
374
+	}
375
+
376
+
377
+	/**
378
+	 * @param EE_Registration $item
379
+	 * @return string
380
+	 * @throws EE_Error
381
+	 * @throws ReflectionException
382
+	 */
383
+	public function column_cb($item): string
384
+	{
385
+		return sprintf('<input type="checkbox" name="checkbox[%1$s]" value="%1$s" />', $item->ID());
386
+	}
387
+
388
+
389
+	/**
390
+	 * column_REG_att_checked_in
391
+	 *
392
+	 * @param EE_Registration $registration
393
+	 * @return string
394
+	 * @throws EE_Error
395
+	 * @throws InvalidArgumentException
396
+	 * @throws InvalidDataTypeException
397
+	 * @throws InvalidInterfaceException
398
+	 * @throws ReflectionException
399
+	 */
400
+	public function column__REG_att_checked_in(EE_Registration $registration): string
401
+	{
402
+		// we need a local variable for the datetime for each row
403
+		// (so that we don't pollute state for the entire table)
404
+		// so let's try to get it from the registration's event
405
+		$DTT_ID = $this->datetime_id;
406
+		if (! $DTT_ID) {
407
+			$reg_ticket_datetimes = $registration->ticket()->datetimes();
408
+			if (count($reg_ticket_datetimes) === 1) {
409
+				$reg_ticket_datetime = reset($reg_ticket_datetimes);
410
+				$DTT_ID = $reg_ticket_datetime instanceof EE_Datetime ? $reg_ticket_datetime->ID() : 0;
411
+			}
412
+		}
413
+
414
+		if (! $DTT_ID) {
415
+			$this->datetimes_for_current_row = DatetimesForEventCheckIn::fromRegistration($registration);
416
+			$datetime = $this->datetimes_for_current_row->getOneDatetimeForEvent($DTT_ID);
417
+			$DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
418
+		}
419
+
420
+		$checkin_status_dashicon = CheckinStatusDashicon::fromRegistrationAndDatetimeId(
421
+			$registration,
422
+			$DTT_ID
423
+		);
424
+
425
+		$aria_label = $checkin_status_dashicon->ariaLabel();
426
+		$dashicon_class = $checkin_status_dashicon->cssClasses();
427
+		$attributes = ' onClick="return false"';
428
+		$button_class = 'button button--secondary button--icon-only ee-aria-tooltip ee-aria-tooltip--big-box';
429
+
430
+		if (
431
+			$DTT_ID
432
+			&& EE_Registry::instance()->CAP->current_user_can(
433
+				'ee_edit_checkin',
434
+				'espresso_registrations_toggle_checkin_status',
435
+				$registration->ID()
436
+			)
437
+		) {
438
+			// overwrite the disabled attribute with data attributes for performing checkin
439
+			$attributes = 'data-_regid="' . $registration->ID() . '"';
440
+			$attributes .= ' data-dttid="' . $DTT_ID . '"';
441
+			$attributes .= ' data-nonce="' . wp_create_nonce('checkin_nonce') . '"';
442
+			$button_class .= ' clickable trigger-checkin';
443
+		}
444
+
445
+		$content = '
446 446
         <button aria-label="' . $aria_label . '" class="' . $button_class . '" ' . $attributes . '>
447 447
             <span class="' . $dashicon_class . '" ></span>
448 448
         </button>
449 449
         <span class="show-on-mobile-view-only">' . $this->column_ATT_name($registration) . '</span>';
450
-        return $this->columnContent('_REG_att_checked_in', $content, 'center');
451
-    }
452
-
453
-
454
-    /**
455
-     * @param EE_Registration $registration
456
-     * @return string
457
-     * @throws EE_Error
458
-     * @throws ReflectionException
459
-     */
460
-    public function column_ATT_name(EE_Registration $registration): string
461
-    {
462
-        $attendee = $registration->attendee();
463
-        if (! $attendee instanceof EE_Attendee) {
464
-            return esc_html__('No contact record for this registration.', 'event_espresso');
465
-        }
466
-        // edit attendee link
467
-        $edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
468
-            ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
469
-            REG_ADMIN_URL
470
-        );
471
-        $name_link    = '
450
+		return $this->columnContent('_REG_att_checked_in', $content, 'center');
451
+	}
452
+
453
+
454
+	/**
455
+	 * @param EE_Registration $registration
456
+	 * @return string
457
+	 * @throws EE_Error
458
+	 * @throws ReflectionException
459
+	 */
460
+	public function column_ATT_name(EE_Registration $registration): string
461
+	{
462
+		$attendee = $registration->attendee();
463
+		if (! $attendee instanceof EE_Attendee) {
464
+			return esc_html__('No contact record for this registration.', 'event_espresso');
465
+		}
466
+		// edit attendee link
467
+		$edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
468
+			['action' => 'view_registration', '_REG_ID' => $registration->ID()],
469
+			REG_ADMIN_URL
470
+		);
471
+		$name_link    = '
472 472
             <span class="ee-status-dot ee-status-bg--' . esc_attr($registration->status_ID()) . ' ee-aria-tooltip"
473 473
             aria-label="' . EEH_Template::pretty_status($registration->status_ID(), false, 'sentence') . '">
474 474
             </span>';
475
-        $name_link    .= EE_Registry::instance()->CAP->current_user_can(
476
-            'ee_edit_contacts',
477
-            'espresso_registrations_edit_attendee'
478
-        )
479
-            ? '<a class="ee-aria-tooltip" href="' . $edit_lnk_url . '" aria-label="' . esc_attr__(
480
-                'View Registration Details',
481
-                'event_espresso'
482
-            ) . '">'
483
-              . $registration->attendee()->full_name()
484
-              . '</a>'
485
-            : $registration->attendee()->full_name();
486
-        $name_link    .= $registration->count() === 1
487
-            ? '&nbsp;<sup><div class="dashicons dashicons-star-filled gold-icon"></div></sup>	'
488
-            : '';
489
-        // add group details
490
-        $name_link .= '&nbsp;' . sprintf(
491
-            esc_html__('(%s of %s)', 'event_espresso'),
492
-            $registration->count(),
493
-            $registration->group_size()
494
-        );
495
-        // add regcode
496
-        $link      = EE_Admin_Page::add_query_args_and_nonce(
497
-            ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
498
-            REG_ADMIN_URL
499
-        );
500
-        $name_link .= '<br>';
501
-        $name_link .= EE_Registry::instance()->instance()->CAP->current_user_can(
502
-            'ee_read_registration',
503
-            'view_registration',
504
-            $registration->ID()
505
-        )
506
-            ? '<a class="ee-aria-tooltip" href="' . $link . '" aria-label="' . esc_attr__(
507
-                'View Registration Details',
508
-                'event_espresso'
509
-            ) . '">'
510
-              . $registration->reg_code()
511
-              . '</a>'
512
-            : $registration->reg_code();
513
-
514
-        $actions                 = [];
515
-        if (
516
-            $this->datetime_id
517
-            && EE_Registry::instance()->CAP->current_user_can(
518
-                'ee_read_checkins',
519
-                'espresso_registrations_registration_checkins'
520
-            )
521
-        ) {
522
-            $checkin_list_url = EE_Admin_Page::add_query_args_and_nonce(
523
-                ['action' => 'registration_checkins', '_REG_ID' => $registration->ID(), 'DTT_ID' => $this->datetime_id],
524
-                REG_ADMIN_URL
525
-            );
526
-            // get the timestamps for this registration's checkins, related to the selected datetime
527
-            /** @var EE_Checkin[] $checkins */
528
-            $checkins = $registration->get_many_related('Checkin', [['DTT_ID' => $this->datetime_id]]);
529
-            if (! empty($checkins)) {
530
-                // get the last timestamp
531
-                $last_checkin = end($checkins);
532
-                // get timestamp string
533
-                $timestamp_string   = $last_checkin->get_datetime('CHK_timestamp');
534
-                $actions['checkin'] = '
475
+		$name_link    .= EE_Registry::instance()->CAP->current_user_can(
476
+			'ee_edit_contacts',
477
+			'espresso_registrations_edit_attendee'
478
+		)
479
+			? '<a class="ee-aria-tooltip" href="' . $edit_lnk_url . '" aria-label="' . esc_attr__(
480
+				'View Registration Details',
481
+				'event_espresso'
482
+			) . '">'
483
+			  . $registration->attendee()->full_name()
484
+			  . '</a>'
485
+			: $registration->attendee()->full_name();
486
+		$name_link    .= $registration->count() === 1
487
+			? '&nbsp;<sup><div class="dashicons dashicons-star-filled gold-icon"></div></sup>	'
488
+			: '';
489
+		// add group details
490
+		$name_link .= '&nbsp;' . sprintf(
491
+			esc_html__('(%s of %s)', 'event_espresso'),
492
+			$registration->count(),
493
+			$registration->group_size()
494
+		);
495
+		// add regcode
496
+		$link      = EE_Admin_Page::add_query_args_and_nonce(
497
+			['action' => 'view_registration', '_REG_ID' => $registration->ID()],
498
+			REG_ADMIN_URL
499
+		);
500
+		$name_link .= '<br>';
501
+		$name_link .= EE_Registry::instance()->instance()->CAP->current_user_can(
502
+			'ee_read_registration',
503
+			'view_registration',
504
+			$registration->ID()
505
+		)
506
+			? '<a class="ee-aria-tooltip" href="' . $link . '" aria-label="' . esc_attr__(
507
+				'View Registration Details',
508
+				'event_espresso'
509
+			) . '">'
510
+			  . $registration->reg_code()
511
+			  . '</a>'
512
+			: $registration->reg_code();
513
+
514
+		$actions                 = [];
515
+		if (
516
+			$this->datetime_id
517
+			&& EE_Registry::instance()->CAP->current_user_can(
518
+				'ee_read_checkins',
519
+				'espresso_registrations_registration_checkins'
520
+			)
521
+		) {
522
+			$checkin_list_url = EE_Admin_Page::add_query_args_and_nonce(
523
+				['action' => 'registration_checkins', '_REG_ID' => $registration->ID(), 'DTT_ID' => $this->datetime_id],
524
+				REG_ADMIN_URL
525
+			);
526
+			// get the timestamps for this registration's checkins, related to the selected datetime
527
+			/** @var EE_Checkin[] $checkins */
528
+			$checkins = $registration->get_many_related('Checkin', [['DTT_ID' => $this->datetime_id]]);
529
+			if (! empty($checkins)) {
530
+				// get the last timestamp
531
+				$last_checkin = end($checkins);
532
+				// get timestamp string
533
+				$timestamp_string   = $last_checkin->get_datetime('CHK_timestamp');
534
+				$actions['checkin'] = '
535 535
                     <a  class="ee-aria-tooltip"
536 536
                         href="' . $checkin_list_url . '"
537 537
                         aria-label="' . esc_attr__(
538
-                            'View this registrant\'s check-ins/checkouts for the datetime',
539
-                            'event_espresso'
540
-                        ) . '"
538
+							'View this registrant\'s check-ins/checkouts for the datetime',
539
+							'event_espresso'
540
+						) . '"
541 541
                     >
542 542
                         ' . $last_checkin->getCheckInText() . ': ' . $timestamp_string . '
543 543
                     </a>';
544
-            }
545
-        }
546
-        $content = (! empty($this->datetime_id) && ! empty($checkins))
547
-            ? sprintf('%1$s %2$s', $name_link, $this->row_actions($actions, true))
548
-            : $name_link;
549
-        return $this->columnContent('ATT_name', $content);
550
-    }
551
-
552
-
553
-    /**
554
-     * @param EE_Registration $registration
555
-     * @return string
556
-     * @throws EE_Error
557
-     * @throws EE_Error
558
-     * @throws ReflectionException
559
-     */
560
-    public function column_ATT_email(EE_Registration $registration): string
561
-    {
562
-        $attendee = $registration->attendee();
563
-        $content = $attendee instanceof EE_Attendee ? $attendee->email() : '';
564
-        return $this->columnContent('ATT_email', $content);
565
-    }
566
-
567
-
568
-    /**
569
-     * @param EE_Registration $registration
570
-     * @return string
571
-     * @throws EE_Error
572
-     * @throws ReflectionException
573
-     */
574
-    public function column_Event(EE_Registration $registration): string
575
-    {
576
-        try {
577
-            $event            = $this->event instanceof EE_Event ? $this->event : $registration->event();
578
-            $checkin_link_url = EE_Admin_Page::add_query_args_and_nonce(
579
-                ['action' => 'event_registrations', 'event_id' => $event->ID()],
580
-                REG_ADMIN_URL
581
-            );
582
-            $content      = EE_Registry::instance()->CAP->current_user_can(
583
-                'ee_read_checkins',
584
-                'espresso_registrations_registration_checkins'
585
-            ) ? '<a class="ee-aria-tooltip" href="' . $checkin_link_url . '" aria-label="'
586
-                . esc_attr__(
587
-                    'View Checkins for this Event',
588
-                    'event_espresso'
589
-                ) . '">' . $event->name() . '</a>' : $event->name();
590
-        } catch (EntityNotFoundException $e) {
591
-            $content = esc_html__('Unknown', 'event_espresso');
592
-        }
593
-        return $this->columnContent('Event', $content);
594
-    }
595
-
596
-
597
-    /**
598
-     * @param EE_Registration $registration
599
-     * @return string
600
-     * @throws EE_Error
601
-     * @throws ReflectionException
602
-     */
603
-    public function column_PRC_name(EE_Registration $registration): string
604
-    {
605
-        $content = $registration->ticket() instanceof EE_Ticket
606
-            ? $registration->ticket()->name()
607
-            : esc_html__(
608
-                "Unknown",
609
-                "event_espresso"
610
-            );
611
-        return $this->columnContent('PRC_name', $content);
612
-    }
613
-
614
-
615
-    /**
616
-     * column_REG_final_price
617
-     *
618
-     * @param EE_Registration $registration
619
-     * @return string
620
-     * @throws EE_Error
621
-     */
622
-    public function column__REG_final_price(EE_Registration $registration): string
623
-    {
624
-        return $this->columnContent('_REG_final_price', $registration->pretty_final_price(), 'end');
625
-    }
626
-
627
-
628
-    /**
629
-     * column_TXN_paid
630
-     *
631
-     * @param EE_Registration $registration
632
-     * @return string
633
-     * @throws EE_Error
634
-     * @throws ReflectionException
635
-     */
636
-    public function column_TXN_paid(EE_Registration $registration): string
637
-    {
638
-        $content = '';
639
-        if ($registration->count() === 1) {
640
-            if ($registration->transaction()->paid() >= $registration->transaction()->total()) {
641
-                return '<div class="dashicons dashicons-yes green-icon"></div>';
642
-            } else {
643
-                $view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
644
-                    ['action' => 'view_transaction', 'TXN_ID' => $registration->transaction_ID()],
645
-                    TXN_ADMIN_URL
646
-                );
647
-                $content = EE_Registry::instance()->CAP->current_user_can(
648
-                    'ee_read_transaction',
649
-                    'espresso_transactions_view_transaction'
650
-                ) ? '
544
+			}
545
+		}
546
+		$content = (! empty($this->datetime_id) && ! empty($checkins))
547
+			? sprintf('%1$s %2$s', $name_link, $this->row_actions($actions, true))
548
+			: $name_link;
549
+		return $this->columnContent('ATT_name', $content);
550
+	}
551
+
552
+
553
+	/**
554
+	 * @param EE_Registration $registration
555
+	 * @return string
556
+	 * @throws EE_Error
557
+	 * @throws EE_Error
558
+	 * @throws ReflectionException
559
+	 */
560
+	public function column_ATT_email(EE_Registration $registration): string
561
+	{
562
+		$attendee = $registration->attendee();
563
+		$content = $attendee instanceof EE_Attendee ? $attendee->email() : '';
564
+		return $this->columnContent('ATT_email', $content);
565
+	}
566
+
567
+
568
+	/**
569
+	 * @param EE_Registration $registration
570
+	 * @return string
571
+	 * @throws EE_Error
572
+	 * @throws ReflectionException
573
+	 */
574
+	public function column_Event(EE_Registration $registration): string
575
+	{
576
+		try {
577
+			$event            = $this->event instanceof EE_Event ? $this->event : $registration->event();
578
+			$checkin_link_url = EE_Admin_Page::add_query_args_and_nonce(
579
+				['action' => 'event_registrations', 'event_id' => $event->ID()],
580
+				REG_ADMIN_URL
581
+			);
582
+			$content      = EE_Registry::instance()->CAP->current_user_can(
583
+				'ee_read_checkins',
584
+				'espresso_registrations_registration_checkins'
585
+			) ? '<a class="ee-aria-tooltip" href="' . $checkin_link_url . '" aria-label="'
586
+				. esc_attr__(
587
+					'View Checkins for this Event',
588
+					'event_espresso'
589
+				) . '">' . $event->name() . '</a>' : $event->name();
590
+		} catch (EntityNotFoundException $e) {
591
+			$content = esc_html__('Unknown', 'event_espresso');
592
+		}
593
+		return $this->columnContent('Event', $content);
594
+	}
595
+
596
+
597
+	/**
598
+	 * @param EE_Registration $registration
599
+	 * @return string
600
+	 * @throws EE_Error
601
+	 * @throws ReflectionException
602
+	 */
603
+	public function column_PRC_name(EE_Registration $registration): string
604
+	{
605
+		$content = $registration->ticket() instanceof EE_Ticket
606
+			? $registration->ticket()->name()
607
+			: esc_html__(
608
+				"Unknown",
609
+				"event_espresso"
610
+			);
611
+		return $this->columnContent('PRC_name', $content);
612
+	}
613
+
614
+
615
+	/**
616
+	 * column_REG_final_price
617
+	 *
618
+	 * @param EE_Registration $registration
619
+	 * @return string
620
+	 * @throws EE_Error
621
+	 */
622
+	public function column__REG_final_price(EE_Registration $registration): string
623
+	{
624
+		return $this->columnContent('_REG_final_price', $registration->pretty_final_price(), 'end');
625
+	}
626
+
627
+
628
+	/**
629
+	 * column_TXN_paid
630
+	 *
631
+	 * @param EE_Registration $registration
632
+	 * @return string
633
+	 * @throws EE_Error
634
+	 * @throws ReflectionException
635
+	 */
636
+	public function column_TXN_paid(EE_Registration $registration): string
637
+	{
638
+		$content = '';
639
+		if ($registration->count() === 1) {
640
+			if ($registration->transaction()->paid() >= $registration->transaction()->total()) {
641
+				return '<div class="dashicons dashicons-yes green-icon"></div>';
642
+			} else {
643
+				$view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
644
+					['action' => 'view_transaction', 'TXN_ID' => $registration->transaction_ID()],
645
+					TXN_ADMIN_URL
646
+				);
647
+				$content = EE_Registry::instance()->CAP->current_user_can(
648
+					'ee_read_transaction',
649
+					'espresso_transactions_view_transaction'
650
+				) ? '
651 651
 				<a class="ee-aria-tooltip ee-status-color--'
652
-                    . $registration->transaction()->status_ID()
653
-                    . '" href="'
654
-                    . $view_txn_lnk_url
655
-                    . '"  aria-label="'
656
-                    . esc_attr__('View Transaction', 'event_espresso')
657
-                    . '">
652
+					. $registration->transaction()->status_ID()
653
+					. '" href="'
654
+					. $view_txn_lnk_url
655
+					. '"  aria-label="'
656
+					. esc_attr__('View Transaction', 'event_espresso')
657
+					. '">
658 658
 						'
659
-                    . $registration->transaction()->pretty_paid()
660
-                    . '
659
+					. $registration->transaction()->pretty_paid()
660
+					. '
661 661
 					</a>
662 662
 				' : $registration->transaction()->pretty_paid();
663
-            }
664
-        }
665
-        return $this->columnContent('TXN_paid', $content, 'end');
666
-    }
667
-
668
-
669
-    /**
670
-     *        column_TXN_total
671
-     *
672
-     * @param EE_Registration $registration
673
-     * @return string
674
-     * @throws EE_Error
675
-     * @throws ReflectionException
676
-     */
677
-    public function column_TXN_total(EE_Registration $registration): string
678
-    {
679
-        $content = '';
680
-        $txn = $registration->transaction();
681
-        $view_txn_url = add_query_arg(['action' => 'view_transaction', 'TXN_ID' => $txn->ID()], TXN_ADMIN_URL);
682
-        if ($registration->get('REG_count') === 1) {
683
-            $line_total_obj = $txn->total_line_item();
684
-            $txn_total      = $line_total_obj instanceof EE_Line_Item
685
-                ? $line_total_obj->get_pretty('LIN_total')
686
-                : esc_html__(
687
-                    'View Transaction',
688
-                    'event_espresso'
689
-                );
690
-            $content = EE_Registry::instance()->CAP->current_user_can(
691
-                'ee_read_transaction',
692
-                'espresso_transactions_view_transaction'
693
-            ) ? '<a class="ee-aria-tooltip" href="'
694
-                . $view_txn_url
695
-                . '" aria-label="'
696
-                . esc_attr__('View Transaction', 'event_espresso')
697
-                . '">'
698
-                . $txn_total
699
-                . '</a>'
700
-                : $txn_total;
701
-        }
702
-        return $this->columnContent('TXN_total', $content, 'end');
703
-    }
663
+			}
664
+		}
665
+		return $this->columnContent('TXN_paid', $content, 'end');
666
+	}
667
+
668
+
669
+	/**
670
+	 *        column_TXN_total
671
+	 *
672
+	 * @param EE_Registration $registration
673
+	 * @return string
674
+	 * @throws EE_Error
675
+	 * @throws ReflectionException
676
+	 */
677
+	public function column_TXN_total(EE_Registration $registration): string
678
+	{
679
+		$content = '';
680
+		$txn = $registration->transaction();
681
+		$view_txn_url = add_query_arg(['action' => 'view_transaction', 'TXN_ID' => $txn->ID()], TXN_ADMIN_URL);
682
+		if ($registration->get('REG_count') === 1) {
683
+			$line_total_obj = $txn->total_line_item();
684
+			$txn_total      = $line_total_obj instanceof EE_Line_Item
685
+				? $line_total_obj->get_pretty('LIN_total')
686
+				: esc_html__(
687
+					'View Transaction',
688
+					'event_espresso'
689
+				);
690
+			$content = EE_Registry::instance()->CAP->current_user_can(
691
+				'ee_read_transaction',
692
+				'espresso_transactions_view_transaction'
693
+			) ? '<a class="ee-aria-tooltip" href="'
694
+				. $view_txn_url
695
+				. '" aria-label="'
696
+				. esc_attr__('View Transaction', 'event_espresso')
697
+				. '">'
698
+				. $txn_total
699
+				. '</a>'
700
+				: $txn_total;
701
+		}
702
+		return $this->columnContent('TXN_total', $content, 'end');
703
+	}
704 704
 }
Please login to merge, or discard this patch.
Spacing   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -147,7 +147,7 @@  discard block
 block discarded – undo
147 147
             'ajax'     => true,
148 148
             'screen'   => $this->_admin_page->get_current_screen()->id,
149 149
         ];
150
-        $columns             = [];
150
+        $columns = [];
151 151
 
152 152
         $this->_columns = [
153 153
             '_REG_att_checked_in' => '<span class="dashicons dashicons-yes ee-icon-size-18"></span>',
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
             'TXN_total'           => esc_html__('Total', 'event_espresso'),
161 161
         ];
162 162
         // Add/remove columns when an event has been selected
163
-        if (! empty($EVT_ID)) {
163
+        if ( ! empty($EVT_ID)) {
164 164
             // Render a checkbox column
165 165
             $columns['cb']              = '<input type="checkbox" />';
166 166
             $this->_has_checkbox_column = true;
@@ -172,7 +172,7 @@  discard block
 block discarded – undo
172 172
         $this->_primary_column = '_REG_att_checked_in';
173 173
 
174 174
         $csv_report = RegistrationsCsvReportParams::getRequestParams($return_url, $this->_req_data, $EVT_ID, $DTT_ID);
175
-        if (! empty($csv_report)) {
175
+        if ( ! empty($csv_report)) {
176 176
             $this->_bottom_buttons['csv_reg_report'] = $csv_report;
177 177
         }
178 178
 
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
         ];
197 197
         $this->_hidden_columns   = [];
198 198
         $this->_evt              = EEM_Event::instance()->get_one_by_ID($EVT_ID);
199
-        $this->datetimes_for_event   = $this->_evt instanceof EE_Event ? $this->_evt->datetimes_ordered() : [];
199
+        $this->datetimes_for_event = $this->_evt instanceof EE_Event ? $this->_evt->datetimes_ordered() : [];
200 200
     }
201 201
 
202 202
 
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
         $hide_expired_checked = $this->hide_expired ? 'checked' : '';
228 228
         $hide_upcoming_checked = $this->hide_upcoming ? 'checked' : '';
229 229
         // get datetimes for ALL active events (note possible capability restrictions)
230
-        $events   = $this->datetimes_for_event->getAllDatetimesForAllEvents();
230
+        $events = $this->datetimes_for_event->getAllDatetimesForAllEvents();
231 231
         $event_options[] = [
232 232
             'id'   => 0,
233 233
             'text' => esc_html__(' - select an event - ', 'event_espresso'),
@@ -235,7 +235,7 @@  discard block
 block discarded – undo
235 235
         /** @var EE_Event $event */
236 236
         foreach ($events as $event) {
237 237
             // any registrations for this event?
238
-            if (! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
238
+            if ( ! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
239 239
                 continue;
240 240
             }
241 241
             $expired_class = $event->is_expired() ? 'ee-expired-event' : '';
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
                     $event->name(),
249 249
                     $event
250 250
                 ),
251
-                'class' => $expired_class . $upcoming_class,
251
+                'class' => $expired_class.$upcoming_class,
252 252
             ];
253 253
             if ($event->ID() === $this->event_id) {
254 254
                 $this->hide_expired = $expired_class === '' ? $this->hide_expired : false;
@@ -263,17 +263,17 @@  discard block
 block discarded – undo
263 263
 
264 264
         $filters[] = '
265 265
         <div class="ee-event-filter__wrapper">
266
-            <label class="ee-event-filter-main-label">' . esc_html__('Check-in Status for', 'event_espresso') . '</label>
266
+            <label class="ee-event-filter-main-label">' . esc_html__('Check-in Status for', 'event_espresso').'</label>
267 267
             <div class="ee-event-filter">
268 268
                 <span class="ee-event-selector">
269
-                    <label for="event_id">' . esc_html__('Event', 'event_espresso') . '</label>
269
+                    <label for="event_id">' . esc_html__('Event', 'event_espresso').'</label>
270 270
                     ' . EEH_Form_Fields::select_input(
271 271
                         'event_id',
272 272
                         $event_options,
273 273
                         $this->event_id,
274 274
                         '',
275 275
                         $select_class
276
-                    ) . '
276
+                    ).'
277 277
                 </span>';
278 278
         // DTT datetimes filter
279 279
         $datetimes_for_event = $this->datetimes_for_event->getAllDatetimesForEvent($hide_upcoming_checked === 'checked');
@@ -282,23 +282,23 @@  discard block
 block discarded – undo
282 282
             foreach ($datetimes_for_event as $datetime) {
283 283
                 if ($datetime instanceof EE_Datetime) {
284 284
                     $datetime_string = $datetime->name();
285
-                    $datetime_string = ! empty($datetime_string) ? $datetime_string . ': ' : '';
285
+                    $datetime_string = ! empty($datetime_string) ? $datetime_string.': ' : '';
286 286
                     $datetime_string .= $datetime->date_and_time_range();
287 287
                     $datetime_string .= $datetime->is_active() ? ' ∗' : '';
288 288
                     $datetime_string .= $datetime->is_expired() ? ' «' : '';
289 289
                     $datetime_string .= $datetime->is_upcoming() ? ' »' : '';
290 290
                     // now put it all together
291
-                    $datetimes[ $datetime->ID() ] = $datetime_string;
291
+                    $datetimes[$datetime->ID()] = $datetime_string;
292 292
                 }
293 293
             }
294 294
             $filters[] = '
295 295
                 <span class="ee-datetime-selector">
296
-                    <label for="DTT_ID">' . esc_html__('Datetime', 'event_espresso') . '</label>
296
+                    <label for="DTT_ID">' . esc_html__('Datetime', 'event_espresso').'</label>
297 297
                     ' . EEH_Form_Fields::select_input(
298 298
                         'DTT_ID',
299 299
                         $datetimes,
300 300
                         $this->datetime_id
301
-                    ) . '
301
+                    ).'
302 302
                 </span>';
303 303
         }
304 304
         $filters[] = '
@@ -357,7 +357,7 @@  discard block
 block discarded – undo
357 357
      */
358 358
     protected function _get_total_event_attendees(): int
359 359
     {
360
-        $query_params      = [];
360
+        $query_params = [];
361 361
         if ($this->event_id) {
362 362
             $query_params[0]['EVT_ID'] = $this->event_id;
363 363
         }
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
         if ($this->datetime_id) {
366 366
             $query_params[0]['Ticket.Datetime.DTT_ID'] = $this->datetime_id;
367 367
         }
368
-        $status_ids_array          = apply_filters(
368
+        $status_ids_array = apply_filters(
369 369
             'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
370 370
             [EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved]
371 371
         );
@@ -403,7 +403,7 @@  discard block
 block discarded – undo
403 403
         // (so that we don't pollute state for the entire table)
404 404
         // so let's try to get it from the registration's event
405 405
         $DTT_ID = $this->datetime_id;
406
-        if (! $DTT_ID) {
406
+        if ( ! $DTT_ID) {
407 407
             $reg_ticket_datetimes = $registration->ticket()->datetimes();
408 408
             if (count($reg_ticket_datetimes) === 1) {
409 409
                 $reg_ticket_datetime = reset($reg_ticket_datetimes);
@@ -411,7 +411,7 @@  discard block
 block discarded – undo
411 411
             }
412 412
         }
413 413
 
414
-        if (! $DTT_ID) {
414
+        if ( ! $DTT_ID) {
415 415
             $this->datetimes_for_current_row = DatetimesForEventCheckIn::fromRegistration($registration);
416 416
             $datetime = $this->datetimes_for_current_row->getOneDatetimeForEvent($DTT_ID);
417 417
             $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
@@ -436,17 +436,17 @@  discard block
 block discarded – undo
436 436
             )
437 437
         ) {
438 438
             // overwrite the disabled attribute with data attributes for performing checkin
439
-            $attributes = 'data-_regid="' . $registration->ID() . '"';
440
-            $attributes .= ' data-dttid="' . $DTT_ID . '"';
441
-            $attributes .= ' data-nonce="' . wp_create_nonce('checkin_nonce') . '"';
439
+            $attributes = 'data-_regid="'.$registration->ID().'"';
440
+            $attributes .= ' data-dttid="'.$DTT_ID.'"';
441
+            $attributes .= ' data-nonce="'.wp_create_nonce('checkin_nonce').'"';
442 442
             $button_class .= ' clickable trigger-checkin';
443 443
         }
444 444
 
445 445
         $content = '
446
-        <button aria-label="' . $aria_label . '" class="' . $button_class . '" ' . $attributes . '>
447
-            <span class="' . $dashicon_class . '" ></span>
446
+        <button aria-label="' . $aria_label.'" class="'.$button_class.'" '.$attributes.'>
447
+            <span class="' . $dashicon_class.'" ></span>
448 448
         </button>
449
-        <span class="show-on-mobile-view-only">' . $this->column_ATT_name($registration) . '</span>';
449
+        <span class="show-on-mobile-view-only">' . $this->column_ATT_name($registration).'</span>';
450 450
         return $this->columnContent('_REG_att_checked_in', $content, 'center');
451 451
     }
452 452
 
@@ -460,7 +460,7 @@  discard block
 block discarded – undo
460 460
     public function column_ATT_name(EE_Registration $registration): string
461 461
     {
462 462
         $attendee = $registration->attendee();
463
-        if (! $attendee instanceof EE_Attendee) {
463
+        if ( ! $attendee instanceof EE_Attendee) {
464 464
             return esc_html__('No contact record for this registration.', 'event_espresso');
465 465
         }
466 466
         // edit attendee link
@@ -468,32 +468,32 @@  discard block
 block discarded – undo
468 468
             ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
469 469
             REG_ADMIN_URL
470 470
         );
471
-        $name_link    = '
472
-            <span class="ee-status-dot ee-status-bg--' . esc_attr($registration->status_ID()) . ' ee-aria-tooltip"
473
-            aria-label="' . EEH_Template::pretty_status($registration->status_ID(), false, 'sentence') . '">
471
+        $name_link = '
472
+            <span class="ee-status-dot ee-status-bg--' . esc_attr($registration->status_ID()).' ee-aria-tooltip"
473
+            aria-label="' . EEH_Template::pretty_status($registration->status_ID(), false, 'sentence').'">
474 474
             </span>';
475
-        $name_link    .= EE_Registry::instance()->CAP->current_user_can(
475
+        $name_link .= EE_Registry::instance()->CAP->current_user_can(
476 476
             'ee_edit_contacts',
477 477
             'espresso_registrations_edit_attendee'
478 478
         )
479
-            ? '<a class="ee-aria-tooltip" href="' . $edit_lnk_url . '" aria-label="' . esc_attr__(
479
+            ? '<a class="ee-aria-tooltip" href="'.$edit_lnk_url.'" aria-label="'.esc_attr__(
480 480
                 'View Registration Details',
481 481
                 'event_espresso'
482
-            ) . '">'
482
+            ).'">'
483 483
               . $registration->attendee()->full_name()
484 484
               . '</a>'
485 485
             : $registration->attendee()->full_name();
486
-        $name_link    .= $registration->count() === 1
486
+        $name_link .= $registration->count() === 1
487 487
             ? '&nbsp;<sup><div class="dashicons dashicons-star-filled gold-icon"></div></sup>	'
488 488
             : '';
489 489
         // add group details
490
-        $name_link .= '&nbsp;' . sprintf(
490
+        $name_link .= '&nbsp;'.sprintf(
491 491
             esc_html__('(%s of %s)', 'event_espresso'),
492 492
             $registration->count(),
493 493
             $registration->group_size()
494 494
         );
495 495
         // add regcode
496
-        $link      = EE_Admin_Page::add_query_args_and_nonce(
496
+        $link = EE_Admin_Page::add_query_args_and_nonce(
497 497
             ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
498 498
             REG_ADMIN_URL
499 499
         );
@@ -503,15 +503,15 @@  discard block
 block discarded – undo
503 503
             'view_registration',
504 504
             $registration->ID()
505 505
         )
506
-            ? '<a class="ee-aria-tooltip" href="' . $link . '" aria-label="' . esc_attr__(
506
+            ? '<a class="ee-aria-tooltip" href="'.$link.'" aria-label="'.esc_attr__(
507 507
                 'View Registration Details',
508 508
                 'event_espresso'
509
-            ) . '">'
509
+            ).'">'
510 510
               . $registration->reg_code()
511 511
               . '</a>'
512 512
             : $registration->reg_code();
513 513
 
514
-        $actions                 = [];
514
+        $actions = [];
515 515
         if (
516 516
             $this->datetime_id
517 517
             && EE_Registry::instance()->CAP->current_user_can(
@@ -526,24 +526,24 @@  discard block
 block discarded – undo
526 526
             // get the timestamps for this registration's checkins, related to the selected datetime
527 527
             /** @var EE_Checkin[] $checkins */
528 528
             $checkins = $registration->get_many_related('Checkin', [['DTT_ID' => $this->datetime_id]]);
529
-            if (! empty($checkins)) {
529
+            if ( ! empty($checkins)) {
530 530
                 // get the last timestamp
531 531
                 $last_checkin = end($checkins);
532 532
                 // get timestamp string
533 533
                 $timestamp_string   = $last_checkin->get_datetime('CHK_timestamp');
534 534
                 $actions['checkin'] = '
535 535
                     <a  class="ee-aria-tooltip"
536
-                        href="' . $checkin_list_url . '"
536
+                        href="' . $checkin_list_url.'"
537 537
                         aria-label="' . esc_attr__(
538 538
                             'View this registrant\'s check-ins/checkouts for the datetime',
539 539
                             'event_espresso'
540
-                        ) . '"
540
+                        ).'"
541 541
                     >
542
-                        ' . $last_checkin->getCheckInText() . ': ' . $timestamp_string . '
542
+                        ' . $last_checkin->getCheckInText().': '.$timestamp_string.'
543 543
                     </a>';
544 544
             }
545 545
         }
546
-        $content = (! empty($this->datetime_id) && ! empty($checkins))
546
+        $content = ( ! empty($this->datetime_id) && ! empty($checkins))
547 547
             ? sprintf('%1$s %2$s', $name_link, $this->row_actions($actions, true))
548 548
             : $name_link;
549 549
         return $this->columnContent('ATT_name', $content);
@@ -579,14 +579,14 @@  discard block
 block discarded – undo
579 579
                 ['action' => 'event_registrations', 'event_id' => $event->ID()],
580 580
                 REG_ADMIN_URL
581 581
             );
582
-            $content      = EE_Registry::instance()->CAP->current_user_can(
582
+            $content = EE_Registry::instance()->CAP->current_user_can(
583 583
                 'ee_read_checkins',
584 584
                 'espresso_registrations_registration_checkins'
585
-            ) ? '<a class="ee-aria-tooltip" href="' . $checkin_link_url . '" aria-label="'
585
+            ) ? '<a class="ee-aria-tooltip" href="'.$checkin_link_url.'" aria-label="'
586 586
                 . esc_attr__(
587 587
                     'View Checkins for this Event',
588 588
                     'event_espresso'
589
-                ) . '">' . $event->name() . '</a>' : $event->name();
589
+                ).'">'.$event->name().'</a>' : $event->name();
590 590
         } catch (EntityNotFoundException $e) {
591 591
             $content = esc_html__('Unknown', 'event_espresso');
592 592
         }
Please login to merge, or discard this patch.
admin_pages/general_settings/General_Settings_Admin_Page.core.php 1 patch
Indentation   +1419 added lines, -1419 removed lines patch added patch discarded remove patch
@@ -19,1436 +19,1436 @@
 block discarded – undo
19 19
  */
20 20
 class General_Settings_Admin_Page extends EE_Admin_Page
21 21
 {
22
-    /**
23
-     * @var EE_Core_Config
24
-     */
25
-    public $core_config;
26
-
27
-
28
-    /**
29
-     * Initialize basic properties.
30
-     */
31
-    protected function _init_page_props()
32
-    {
33
-        $this->page_slug        = GEN_SET_PG_SLUG;
34
-        $this->page_label       = GEN_SET_LABEL;
35
-        $this->_admin_base_url  = GEN_SET_ADMIN_URL;
36
-        $this->_admin_base_path = GEN_SET_ADMIN;
37
-    }
38
-
39
-
40
-    /**
41
-     * Set ajax hooks
42
-     */
43
-    protected function _ajax_hooks()
44
-    {
45
-        add_action('wp_ajax_espresso_display_country_settings', [$this, 'display_country_settings']);
46
-        add_action('wp_ajax_espresso_display_country_states', [$this, 'display_country_states']);
47
-        add_action('wp_ajax_espresso_delete_state', [$this, 'delete_state'], 10, 3);
48
-        add_action('wp_ajax_espresso_add_new_state', [$this, 'add_new_state']);
49
-    }
50
-
51
-
52
-    /**
53
-     * More page properties initialization.
54
-     */
55
-    protected function _define_page_props()
56
-    {
57
-        $this->_admin_page_title = GEN_SET_LABEL;
58
-        $this->_labels           = ['publishbox' => esc_html__('Update Settings', 'event_espresso')];
59
-    }
60
-
61
-
62
-    /**
63
-     * Set page routes property.
64
-     */
65
-    protected function _set_page_routes()
66
-    {
67
-        $this->_page_routes = [
68
-            'critical_pages'                => [
69
-                'func'       => '_espresso_page_settings',
70
-                'capability' => 'manage_options',
71
-            ],
72
-            'update_espresso_page_settings' => [
73
-                'func'       => '_update_espresso_page_settings',
74
-                'capability' => 'manage_options',
75
-                'noheader'   => true,
76
-            ],
77
-            'default'                       => [
78
-                'func'       => '_your_organization_settings',
79
-                'capability' => 'manage_options',
80
-            ],
81
-
82
-            'update_your_organization_settings' => [
83
-                'func'       => '_update_your_organization_settings',
84
-                'capability' => 'manage_options',
85
-                'noheader'   => true,
86
-            ],
87
-
88
-            'admin_option_settings' => [
89
-                'func'       => '_admin_option_settings',
90
-                'capability' => 'manage_options',
91
-            ],
92
-
93
-            'update_admin_option_settings' => [
94
-                'func'       => '_update_admin_option_settings',
95
-                'capability' => 'manage_options',
96
-                'noheader'   => true,
97
-            ],
98
-
99
-            'country_settings' => [
100
-                'func'       => '_country_settings',
101
-                'capability' => 'manage_options',
102
-            ],
103
-
104
-            'update_country_settings' => [
105
-                'func'       => '_update_country_settings',
106
-                'capability' => 'manage_options',
107
-                'noheader'   => true,
108
-            ],
109
-
110
-            'display_country_settings' => [
111
-                'func'       => 'display_country_settings',
112
-                'capability' => 'manage_options',
113
-                'noheader'   => true,
114
-            ],
115
-
116
-            'add_new_state' => [
117
-                'func'       => 'add_new_state',
118
-                'capability' => 'manage_options',
119
-                'noheader'   => true,
120
-            ],
121
-
122
-            'delete_state'            => [
123
-                'func'       => 'delete_state',
124
-                'capability' => 'manage_options',
125
-                'noheader'   => true,
126
-            ],
127
-            'privacy_settings'        => [
128
-                'func'       => 'privacySettings',
129
-                'capability' => 'manage_options',
130
-            ],
131
-            'update_privacy_settings' => [
132
-                'func'               => 'updatePrivacySettings',
133
-                'capability'         => 'manage_options',
134
-                'noheader'           => true,
135
-                'headers_sent_route' => 'privacy_settings',
136
-            ],
137
-        ];
138
-    }
139
-
140
-
141
-    /**
142
-     * Set page configuration property
143
-     */
144
-    protected function _set_page_config()
145
-    {
146
-        $this->_page_config = [
147
-            'critical_pages'        => [
148
-                'nav'           => [
149
-                    'label' => esc_html__('Critical Pages', 'event_espresso'),
150
-                    'icon' => 'dashicons-warning',
151
-                    'order' => 50,
152
-                ],
153
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
154
-                'help_tabs'     => [
155
-                    'general_settings_critical_pages_help_tab' => [
156
-                        'title'    => esc_html__('Critical Pages', 'event_espresso'),
157
-                        'filename' => 'general_settings_critical_pages',
158
-                    ],
159
-                ],
160
-                'require_nonce' => false,
161
-            ],
162
-            'default'               => [
163
-                'nav'           => [
164
-                    'label' => esc_html__('Your Organization', 'event_espresso'),
165
-                    'icon' => 'dashicons-admin-home',
166
-                    'order' => 20,
167
-                ],
168
-                'help_tabs'     => [
169
-                    'general_settings_your_organization_help_tab' => [
170
-                        'title'    => esc_html__('Your Organization', 'event_espresso'),
171
-                        'filename' => 'general_settings_your_organization',
172
-                    ],
173
-                ],
174
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
175
-                'require_nonce' => false,
176
-            ],
177
-            'admin_option_settings' => [
178
-                'nav'           => [
179
-                    'label' => esc_html__('Admin Options', 'event_espresso'),
180
-                    'icon' => 'dashicons-admin-settings',
181
-                    'order' => 60,
182
-                ],
183
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
184
-                'help_tabs'     => [
185
-                    'general_settings_admin_options_help_tab' => [
186
-                        'title'    => esc_html__('Admin Options', 'event_espresso'),
187
-                        'filename' => 'general_settings_admin_options',
188
-                    ],
189
-                ],
190
-                'require_nonce' => false,
191
-            ],
192
-            'country_settings'      => [
193
-                'nav'           => [
194
-                    'label' => esc_html__('Countries', 'event_espresso'),
195
-                    'icon' => 'dashicons-admin-site',
196
-                    'order' => 70,
197
-                ],
198
-                'help_tabs'     => [
199
-                    'general_settings_countries_help_tab' => [
200
-                        'title'    => esc_html__('Countries', 'event_espresso'),
201
-                        'filename' => 'general_settings_countries',
202
-                    ],
203
-                ],
204
-                'require_nonce' => false,
205
-            ],
206
-            'privacy_settings'      => [
207
-                'nav'           => [
208
-                    'label' => esc_html__('Privacy', 'event_espresso'),
209
-                    'icon' => 'dashicons-privacy',
210
-                    'order' => 80,
211
-                ],
212
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
213
-                'require_nonce' => false,
214
-            ],
215
-        ];
216
-    }
217
-
218
-
219
-    protected function _add_screen_options()
220
-    {
221
-    }
222
-
223
-
224
-    protected function _add_feature_pointers()
225
-    {
226
-    }
227
-
228
-
229
-    /**
230
-     * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
231
-     */
232
-    public function load_scripts_styles()
233
-    {
234
-        // styles
235
-        wp_enqueue_style('espresso-ui-theme');
236
-        // scripts
237
-        wp_enqueue_script('ee_admin_js');
238
-    }
239
-
240
-
241
-    /**
242
-     * Execute logic running on `admin_init`
243
-     */
244
-    public function admin_init()
245
-    {
246
-        $this->core_config = EE_Registry::instance()->CFG->core;
247
-
248
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(
249
-            esc_html__(
250
-                '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.',
251
-                'event_espresso'
252
-            )
253
-        );
254
-        EE_Registry::$i18n_js_strings['error_occurred']          = wp_strip_all_tags(
255
-            esc_html__(
256
-                'An error occurred! Please refresh the page and try again.',
257
-                'event_espresso'
258
-            )
259
-        );
260
-        EE_Registry::$i18n_js_strings['confirm_delete_state']    = wp_strip_all_tags(
261
-            esc_html__(
262
-                'Are you sure you want to delete this State / Province?',
263
-                'event_espresso'
264
-            )
265
-        );
266
-        EE_Registry::$i18n_js_strings['ajax_url']                = admin_url(
267
-            'admin-ajax.php?page=espresso_general_settings',
268
-            is_ssl() ? 'https://' : 'http://'
269
-        );
270
-    }
271
-
272
-
273
-    public function admin_notices()
274
-    {
275
-    }
276
-
277
-
278
-    public function admin_footer_scripts()
279
-    {
280
-    }
281
-
282
-
283
-    /**
284
-     * Enqueue scripts and styles for the default route.
285
-     */
286
-    public function load_scripts_styles_default()
287
-    {
288
-        // styles
289
-        wp_enqueue_style('thickbox');
290
-        // scripts
291
-        wp_enqueue_script('media-upload');
292
-        wp_enqueue_script('thickbox');
293
-        wp_register_script(
294
-            'organization_settings',
295
-            GEN_SET_ASSETS_URL . 'your_organization_settings.js',
296
-            ['jquery', 'media-upload', 'thickbox'],
297
-            EVENT_ESPRESSO_VERSION,
298
-            true
299
-        );
300
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
301
-        wp_enqueue_script('organization_settings');
302
-        wp_enqueue_style('organization-css');
303
-        $confirm_image_delete = [
304
-            'text' => wp_strip_all_tags(
305
-                esc_html__(
306
-                    'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
307
-                    'event_espresso'
308
-                )
309
-            ),
310
-        ];
311
-        wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
312
-    }
313
-
314
-
315
-    /**
316
-     * Enqueue scripts and styles for the country settings route.
317
-     */
318
-    public function load_scripts_styles_country_settings()
319
-    {
320
-        // scripts
321
-        wp_register_script(
322
-            'gen_settings_countries',
323
-            GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
324
-            ['ee_admin_js'],
325
-            EVENT_ESPRESSO_VERSION,
326
-            true
327
-        );
328
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
329
-        wp_enqueue_script('gen_settings_countries');
330
-        wp_enqueue_style('organization-css');
331
-    }
332
-
333
-
334
-    /*************        Espresso Pages        *************/
335
-    /**
336
-     * _espresso_page_settings
337
-     *
338
-     * @throws EE_Error
339
-     * @throws DomainException
340
-     * @throws DomainException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidArgumentException
343
-     */
344
-    protected function _espresso_page_settings()
345
-    {
346
-        // Check to make sure all of the main pages are set up properly,
347
-        // if not create the default pages and display an admin notice
348
-        EEH_Activation::verify_default_pages_exist();
349
-        $this->_transient_garbage_collection();
350
-
351
-        $this->_template_args['values'] = $this->_yes_no_values;
352
-
353
-        $this->_template_args['reg_page_id']  = $this->core_config->reg_page_id ?? null;
354
-        $this->_template_args['reg_page_obj'] = isset($this->core_config->reg_page_id)
355
-            ? get_post($this->core_config->reg_page_id)
356
-            : false;
357
-
358
-        $this->_template_args['txn_page_id']  = $this->core_config->txn_page_id ?? null;
359
-        $this->_template_args['txn_page_obj'] = isset($this->core_config->txn_page_id)
360
-            ? get_post($this->core_config->txn_page_id)
361
-            : false;
362
-
363
-        $this->_template_args['thank_you_page_id']  = $this->core_config->thank_you_page_id ?? null;
364
-        $this->_template_args['thank_you_page_obj'] = isset($this->core_config->thank_you_page_id)
365
-            ? get_post($this->core_config->thank_you_page_id)
366
-            : false;
367
-
368
-        $this->_template_args['cancel_page_id']  = $this->core_config->cancel_page_id ?? null;
369
-        $this->_template_args['cancel_page_obj'] = isset($this->core_config->cancel_page_id)
370
-            ? get_post($this->core_config->cancel_page_id)
371
-            : false;
372
-
373
-        $this->_set_add_edit_form_tags('update_espresso_page_settings');
374
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
375
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
376
-            GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
377
-            $this->_template_args,
378
-            true
379
-        );
380
-        $this->display_admin_page_with_sidebar();
381
-    }
382
-
383
-
384
-    /**
385
-     * Handler for updating espresso page settings.
386
-     *
387
-     * @throws EE_Error
388
-     */
389
-    protected function _update_espresso_page_settings()
390
-    {
391
-        $this->core_config = EE_Registry::instance()->CFG->core;
392
-        // capture incoming request data && set page IDs
393
-        $this->core_config->reg_page_id       = $this->request->getRequestParam(
394
-            'reg_page_id',
395
-            $this->core_config->reg_page_id,
396
-            DataType::INT
397
-        );
398
-        $this->core_config->txn_page_id       = $this->request->getRequestParam(
399
-            'txn_page_id',
400
-            $this->core_config->txn_page_id,
401
-            DataType::INT
402
-        );
403
-        $this->core_config->thank_you_page_id = $this->request->getRequestParam(
404
-            'thank_you_page_id',
405
-            $this->core_config->thank_you_page_id,
406
-            DataType::INT
407
-        );
408
-        $this->core_config->cancel_page_id    = $this->request->getRequestParam(
409
-            'cancel_page_id',
410
-            $this->core_config->cancel_page_id,
411
-            DataType::INT
412
-        );
413
-
414
-        $this->core_config = apply_filters(
415
-            'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
416
-            $this->core_config,
417
-            $this->request->requestParams()
418
-        );
419
-
420
-        $what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
421
-        $this->_redirect_after_action(
422
-            $this->_update_espresso_configuration(
423
-                $what,
424
-                $this->core_config,
425
-                __FILE__,
426
-                __FUNCTION__,
427
-                __LINE__
428
-            ),
429
-            $what,
430
-            '',
431
-            [
432
-                'action' => 'critical_pages',
433
-            ],
434
-            true
435
-        );
436
-    }
437
-
438
-
439
-    /*************        Your Organization        *************/
440
-
441
-
442
-    /**
443
-     * @throws DomainException
444
-     * @throws EE_Error
445
-     * @throws InvalidArgumentException
446
-     * @throws InvalidDataTypeException
447
-     * @throws InvalidInterfaceException
448
-     */
449
-    protected function _your_organization_settings()
450
-    {
451
-        $this->_template_args['admin_page_content'] = '';
452
-        try {
453
-            /** @var OrganizationSettings $organization_settings_form */
454
-            $organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
455
-
456
-            $this->_template_args['admin_page_content'] = EEH_HTML::div(
457
-                $organization_settings_form->display(),
458
-                '',
459
-                'padding'
460
-            );
461
-        } catch (Exception $e) {
462
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
463
-        }
464
-        $this->_set_add_edit_form_tags('update_your_organization_settings');
465
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
466
-        $this->display_admin_page_with_sidebar();
467
-    }
468
-
469
-
470
-    /**
471
-     * Handler for updating organization settings.
472
-     *
473
-     * @throws EE_Error
474
-     */
475
-    protected function _update_your_organization_settings()
476
-    {
477
-        try {
478
-            /** @var OrganizationSettings $organization_settings_form */
479
-            $organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
480
-
481
-            $success = $organization_settings_form->process($this->request->requestParams());
482
-
483
-            EE_Registry::instance()->CFG = apply_filters(
484
-                'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
485
-                EE_Registry::instance()->CFG
486
-            );
487
-        } catch (Exception $e) {
488
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
489
-            $success = false;
490
-        }
491
-
492
-        if ($success) {
493
-            $success = $this->_update_espresso_configuration(
494
-                esc_html__('Your Organization Settings', 'event_espresso'),
495
-                EE_Registry::instance()->CFG,
496
-                __FILE__,
497
-                __FUNCTION__,
498
-                __LINE__
499
-            );
500
-        }
501
-
502
-        $this->_redirect_after_action($success, '', '', ['action' => 'default'], true);
503
-    }
504
-
505
-
506
-
507
-    /*************        Admin Options        *************/
508
-
509
-
510
-    /**
511
-     * _admin_option_settings
512
-     *
513
-     * @throws EE_Error
514
-     * @throws LogicException
515
-     */
516
-    protected function _admin_option_settings()
517
-    {
518
-        $this->_template_args['admin_page_content'] = '';
519
-        try {
520
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
521
-            // still need this for the old school form in Extend_General_Settings_Admin_Page
522
-            $this->_template_args['values'] = $this->_yes_no_values;
523
-            // also need to account for the do_action that was in the old template
524
-            $admin_options_settings_form->setTemplateArgs($this->_template_args);
525
-            $this->_template_args['admin_page_content'] = EEH_HTML::div(
526
-                $admin_options_settings_form->display(),
527
-                '',
528
-                'padding'
529
-            );
530
-        } catch (Exception $e) {
531
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
532
-        }
533
-        $this->_set_add_edit_form_tags('update_admin_option_settings');
534
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
535
-        $this->display_admin_page_with_sidebar();
536
-    }
537
-
538
-
539
-    /**
540
-     * _update_admin_option_settings
541
-     *
542
-     * @throws EE_Error
543
-     * @throws InvalidDataTypeException
544
-     * @throws InvalidFormSubmissionException
545
-     * @throws InvalidArgumentException
546
-     * @throws LogicException
547
-     */
548
-    protected function _update_admin_option_settings()
549
-    {
550
-        try {
551
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
552
-            $admin_options_settings_form->process(
553
-                $this->request->getRequestParam(
554
-                    $admin_options_settings_form->slug(),
555
-                    [],
556
-                    DataType::STRING,
557
-                    true
558
-                )
559
-            );
560
-            EE_Registry::instance()->CFG->admin = apply_filters(
561
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
562
-                EE_Registry::instance()->CFG->admin
563
-            );
564
-        } catch (Exception $e) {
565
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
566
-        }
567
-        $this->_redirect_after_action(
568
-            apply_filters(
569
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
570
-                $this->_update_espresso_configuration(
571
-                    esc_html__('Admin Options', 'event_espresso'),
572
-                    EE_Registry::instance()->CFG->admin,
573
-                    __FILE__,
574
-                    __FUNCTION__,
575
-                    __LINE__
576
-                )
577
-            ),
578
-            esc_html__('Admin Options', 'event_espresso'),
579
-            'updated',
580
-            ['action' => 'admin_option_settings']
581
-        );
582
-    }
583
-
584
-
585
-    /*************        Countries        *************/
586
-
587
-
588
-    /**
589
-     * @param string|null $default
590
-     * @return string
591
-     */
592
-    protected function getCountryISO(?string $default = null): string
593
-    {
594
-        $default = $default ?? $this->getCountryIsoForSite();
595
-        $CNT_ISO = $this->request->getRequestParam('country', $default);
596
-        $CNT_ISO = $this->request->getRequestParam('CNT_ISO', $CNT_ISO);
597
-        return strtoupper($CNT_ISO);
598
-    }
599
-
600
-
601
-    /**
602
-     * @return string
603
-     */
604
-    protected function getCountryIsoForSite(): string
605
-    {
606
-        return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
607
-            ? EE_Registry::instance()->CFG->organization->CNT_ISO
608
-            : 'US';
609
-    }
610
-
611
-
612
-    /**
613
-     * @param string          $CNT_ISO
614
-     * @param EE_Country|null $country
615
-     * @return EE_Base_Class|EE_Country
616
-     * @throws EE_Error
617
-     * @throws InvalidArgumentException
618
-     * @throws InvalidDataTypeException
619
-     * @throws InvalidInterfaceException
620
-     * @throws ReflectionException
621
-     */
622
-    protected function verifyOrGetCountryFromIso(string $CNT_ISO, ?EE_Country $country = null)
623
-    {
624
-        /** @var EE_Country $country */
625
-        return $country instanceof EE_Country && $country->ID() === $CNT_ISO
626
-            ? $country
627
-            : EEM_Country::instance()->get_one_by_ID($CNT_ISO);
628
-    }
629
-
630
-
631
-    /**
632
-     * Output Country Settings view.
633
-     *
634
-     * @throws DomainException
635
-     * @throws EE_Error
636
-     * @throws InvalidArgumentException
637
-     * @throws InvalidDataTypeException
638
-     * @throws InvalidInterfaceException
639
-     * @throws ReflectionException
640
-     */
641
-    protected function _country_settings()
642
-    {
643
-        $CNT_ISO = $this->getCountryISO();
644
-
645
-        $this->_template_args['values']    = $this->_yes_no_values;
646
-        $this->_template_args['countries'] = new EE_Question_Form_Input(
647
-            EE_Question::new_instance(
648
-                [
649
-                  'QST_ID'           => 0,
650
-                  'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
651
-                  'QST_system'       => 'admin-country',
652
-                ]
653
-            ),
654
-            EE_Answer::new_instance(
655
-                [
656
-                    'ANS_ID'    => 0,
657
-                    'ANS_value' => $CNT_ISO,
658
-                ]
659
-            ),
660
-            [
661
-                'input_id'       => 'country',
662
-                'input_name'     => 'country',
663
-                'input_prefix'   => '',
664
-                'append_qstn_id' => false,
665
-            ]
666
-        );
667
-
668
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO);
669
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10);
670
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10);
671
-        $this->_template_args['country_details_settings'] = $this->display_country_settings(
672
-            $country->ID(),
673
-            $country
674
-        );
675
-        $this->_template_args['country_states_settings']  = $this->display_country_states(
676
-            $country->ID(),
677
-            $country
678
-        );
679
-        $this->_template_args['CNT_name_for_site']        = $country->name();
680
-
681
-        $this->_set_add_edit_form_tags('update_country_settings');
682
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
683
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
684
-            GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
685
-            $this->_template_args,
686
-            true
687
-        );
688
-        $this->display_admin_page_with_no_sidebar();
689
-    }
690
-
691
-
692
-    /**
693
-     * @param string          $CNT_ISO
694
-     * @param EE_Country|null $country
695
-     * @return string
696
-     * @throws DomainException
697
-     * @throws EE_Error
698
-     * @throws InvalidArgumentException
699
-     * @throws InvalidDataTypeException
700
-     * @throws InvalidInterfaceException
701
-     * @throws ReflectionException
702
-     */
703
-    public function display_country_settings(string $CNT_ISO = '', ?EE_Country $country = null): string
704
-    {
705
-        $CNT_ISO          = $this->getCountryISO($CNT_ISO);
706
-        $CNT_ISO_for_site = $this->getCountryIsoForSite();
707
-
708
-        if (! $CNT_ISO) {
709
-            return '';
710
-        }
711
-
712
-        // for ajax
713
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
714
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
715
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10, 2);
716
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10, 2);
717
-        $country                                  = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
718
-        $CNT_cur_disabled                         = $CNT_ISO !== $CNT_ISO_for_site;
719
-        $this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
720
-
721
-        $country_input_types            = [
722
-            'CNT_active'      => [
723
-                'type'             => 'RADIO_BTN',
724
-                'input_name'       => "cntry[$CNT_ISO]",
725
-                'class'            => '',
726
-                'options'          => $this->_yes_no_values,
727
-                'use_desc_4_label' => true,
728
-            ],
729
-            'CNT_ISO'         => [
730
-                'type'       => 'TEXT',
731
-                'input_name' => "cntry[$CNT_ISO]",
732
-                'class'      => 'ee-input-width--small',
733
-            ],
734
-            'CNT_ISO3'        => [
735
-                'type'       => 'TEXT',
736
-                'input_name' => "cntry[$CNT_ISO]",
737
-                'class'      => 'ee-input-width--small',
738
-            ],
739
-            // 'RGN_ID'          => [
740
-            //     'type'       => 'TEXT',
741
-            //     'input_name' => "cntry[$CNT_ISO]",
742
-            //     'class'      => 'ee-input-width--small',
743
-            // ],
744
-            'CNT_name'        => [
745
-                'type'       => 'TEXT',
746
-                'input_name' => "cntry[$CNT_ISO]",
747
-                'class'      => 'ee-input-width--big',
748
-            ],
749
-            'CNT_cur_code'    => [
750
-                'type'       => 'TEXT',
751
-                'input_name' => "cntry[$CNT_ISO]",
752
-                'class'      => 'ee-input-width--small',
753
-                'disabled'   => $CNT_cur_disabled,
754
-            ],
755
-            'CNT_cur_single'  => [
756
-                'type'       => 'TEXT',
757
-                'input_name' => "cntry[$CNT_ISO]",
758
-                'class'      => 'ee-input-width--reg',
759
-                'disabled'   => $CNT_cur_disabled,
760
-            ],
761
-            'CNT_cur_plural'  => [
762
-                'type'       => 'TEXT',
763
-                'input_name' => "cntry[$CNT_ISO]",
764
-                'class'      => 'ee-input-width--reg',
765
-                'disabled'   => $CNT_cur_disabled,
766
-            ],
767
-            'CNT_cur_sign'    => [
768
-                'type'         => 'TEXT',
769
-                'input_name'   => "cntry[$CNT_ISO]",
770
-                'class'        => 'ee-input-width--small',
771
-                'htmlentities' => false,
772
-                'disabled'     => $CNT_cur_disabled,
773
-            ],
774
-            'CNT_cur_sign_b4' => [
775
-                'type'             => 'RADIO_BTN',
776
-                'input_name'       => "cntry[$CNT_ISO]",
777
-                'class'            => '',
778
-                'options'          => $this->_yes_no_values,
779
-                'use_desc_4_label' => true,
780
-                'disabled'         => $CNT_cur_disabled,
781
-            ],
782
-            'CNT_cur_dec_plc' => [
783
-                'type'       => 'RADIO_BTN',
784
-                'input_name' => "cntry[$CNT_ISO]",
785
-                'class'      => '',
786
-                'options'    => [
787
-                    ['id' => 0, 'text' => ''],
788
-                    ['id' => 1, 'text' => ''],
789
-                    ['id' => 2, 'text' => ''],
790
-                    ['id' => 3, 'text' => ''],
791
-                ],
792
-                'disabled'   => $CNT_cur_disabled,
793
-            ],
794
-            'CNT_cur_dec_mrk' => [
795
-                'type'             => 'RADIO_BTN',
796
-                'input_name'       => "cntry[$CNT_ISO]",
797
-                'class'            => '',
798
-                'options'          => [
799
-                    [
800
-                        'id'   => ',',
801
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
802
-                    ],
803
-                    ['id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')],
804
-                ],
805
-                'use_desc_4_label' => true,
806
-                'disabled'         => $CNT_cur_disabled,
807
-            ],
808
-            'CNT_cur_thsnds'  => [
809
-                'type'             => 'RADIO_BTN',
810
-                'input_name'       => "cntry[$CNT_ISO]",
811
-                'class'            => '',
812
-                'options'          => [
813
-                    [
814
-                        'id'   => ',',
815
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
816
-                    ],
817
-                    [
818
-                        'id'   => '.',
819
-                        'text' => esc_html__('. (decimal)', 'event_espresso'),
820
-                    ],
821
-                    [
822
-                        'id'   => '&nbsp;',
823
-                        'text' => esc_html__('(space)', 'event_espresso'),
824
-                    ],
825
-                ],
826
-                'use_desc_4_label' => true,
827
-                'disabled'         => $CNT_cur_disabled,
828
-            ],
829
-            'CNT_tel_code'    => [
830
-                'type'       => 'TEXT',
831
-                'input_name' => "cntry[$CNT_ISO]",
832
-                'class'      => 'ee-input-width--small',
833
-            ],
834
-            'CNT_is_EU'       => [
835
-                'type'             => 'RADIO_BTN',
836
-                'input_name'       => "cntry[$CNT_ISO]",
837
-                'class'            => '',
838
-                'options'          => $this->_yes_no_values,
839
-                'use_desc_4_label' => true,
840
-            ],
841
-        ];
842
-        $this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
843
-            $country,
844
-            $country_input_types
845
-        );
846
-        $country_details_settings       = EEH_Template::display_template(
847
-            GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
848
-            $this->_template_args,
849
-            true
850
-        );
851
-
852
-        if (defined('DOING_AJAX')) {
853
-            $notices = EE_Error::get_notices(false, false, false);
854
-            echo wp_json_encode(
855
-                [
856
-                    'return_data' => $country_details_settings,
857
-                    'success'     => $notices['success'],
858
-                    'errors'      => $notices['errors'],
859
-                ]
860
-            );
861
-            die();
862
-        }
863
-        return $country_details_settings;
864
-    }
865
-
866
-
867
-    /**
868
-     * @param string          $CNT_ISO
869
-     * @param EE_Country|null $country
870
-     * @return string
871
-     * @throws DomainException
872
-     * @throws EE_Error
873
-     * @throws InvalidArgumentException
874
-     * @throws InvalidDataTypeException
875
-     * @throws InvalidInterfaceException
876
-     * @throws ReflectionException
877
-     */
878
-    public function display_country_states(string $CNT_ISO = '', ?EE_Country $country = null): string
879
-    {
880
-        $CNT_ISO = $this->getCountryISO($CNT_ISO);
881
-        if (! $CNT_ISO) {
882
-            return '';
883
-        }
884
-        // for ajax
885
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
886
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
887
-        add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'state_form_field_label_wrap'], 10, 2);
888
-        add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'state_form_field_input__wrap'], 10);
889
-        $states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
890
-        if (empty($states)) {
891
-            /** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
892
-            $countrySubRegionDao = $this->loader->getShared(
893
-                'EventEspresso\core\services\address\CountrySubRegionDao'
894
-            );
895
-            if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
896
-                $country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
897
-                if ($countrySubRegionDao->saveCountrySubRegions($country)) {
898
-                    $states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
899
-                }
900
-            }
901
-        }
902
-        if (is_array($states)) {
903
-            foreach ($states as $STA_ID => $state) {
904
-                if ($state instanceof EE_State) {
905
-                    $inputs = EE_Question_Form_Input::generate_question_form_inputs_for_object(
906
-                        $state,
907
-                        [
908
-                            'STA_abbrev' => [
909
-                                'type'             => 'TEXT',
910
-                                'label'            => esc_html__('Code', 'event_espresso'),
911
-                                'input_name'       => "states[$STA_ID]",
912
-                                'class'            => 'ee-input-width--tiny',
913
-                                'add_mobile_label' => true,
914
-                            ],
915
-                            'STA_name'   => [
916
-                                'type'             => 'TEXT',
917
-                                'label'            => esc_html__('Name', 'event_espresso'),
918
-                                'input_name'       => "states[$STA_ID]",
919
-                                'class'            => 'ee-input-width--big',
920
-                                'add_mobile_label' => true,
921
-                            ],
922
-                            'STA_active' => [
923
-                                'type'             => 'RADIO_BTN',
924
-                                'label'            => esc_html__(
925
-                                    'State Appears in Dropdown Select Lists',
926
-                                    'event_espresso'
927
-                                ),
928
-                                'input_name'       => "states[$STA_ID]",
929
-                                'options'          => $this->_yes_no_values,
930
-                                'use_desc_4_label' => true,
931
-                                'add_mobile_label' => true,
932
-                            ],
933
-                        ]
934
-                    );
935
-
936
-                    $delete_state_url = EE_Admin_Page::add_query_args_and_nonce(
937
-                        [
938
-                            'action'     => 'delete_state',
939
-                            'STA_ID'     => $STA_ID,
940
-                            'CNT_ISO'    => $CNT_ISO,
941
-                            'STA_abbrev' => $state->abbrev(),
942
-                        ],
943
-                        GEN_SET_ADMIN_URL
944
-                    );
945
-
946
-                    $this->_template_args['states'][ $STA_ID ]['inputs']           = $inputs;
947
-                    $this->_template_args['states'][ $STA_ID ]['delete_state_url'] = $delete_state_url;
948
-                }
949
-            }
950
-        } else {
951
-            $this->_template_args['states'] = false;
952
-        }
953
-
954
-        $this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
955
-            ['action' => 'add_new_state'],
956
-            GEN_SET_ADMIN_URL
957
-        );
958
-
959
-        $state_details_settings = EEH_Template::display_template(
960
-            GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
961
-            $this->_template_args,
962
-            true
963
-        );
964
-
965
-        if (defined('DOING_AJAX')) {
966
-            $notices = EE_Error::get_notices(false, false, false);
967
-            echo wp_json_encode(
968
-                [
969
-                    'return_data' => $state_details_settings,
970
-                    'success'     => $notices['success'],
971
-                    'errors'      => $notices['errors'],
972
-                ]
973
-            );
974
-            die();
975
-        }
976
-        return $state_details_settings;
977
-    }
978
-
979
-
980
-    /**
981
-     * @return void
982
-     * @throws EE_Error
983
-     * @throws InvalidArgumentException
984
-     * @throws InvalidDataTypeException
985
-     * @throws InvalidInterfaceException
986
-     * @throws ReflectionException
987
-     */
988
-    public function add_new_state()
989
-    {
990
-        $success = true;
991
-        $CNT_ISO = $this->getCountryISO('');
992
-        if (! $CNT_ISO) {
993
-            EE_Error::add_error(
994
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
995
-                __FILE__,
996
-                __FUNCTION__,
997
-                __LINE__
998
-            );
999
-            $success = false;
1000
-        }
1001
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1002
-        if (! $STA_abbrev) {
1003
-            EE_Error::add_error(
1004
-                esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1005
-                __FILE__,
1006
-                __FUNCTION__,
1007
-                __LINE__
1008
-            );
1009
-            $success = false;
1010
-        }
1011
-        $STA_name = $this->request->getRequestParam('STA_name');
1012
-        if (! $STA_name) {
1013
-            EE_Error::add_error(
1014
-                esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1015
-                __FILE__,
1016
-                __FUNCTION__,
1017
-                __LINE__
1018
-            );
1019
-            $success = false;
1020
-        }
1021
-
1022
-        if ($success) {
1023
-            $cols_n_values = [
1024
-                'CNT_ISO'    => $CNT_ISO,
1025
-                'STA_abbrev' => $STA_abbrev,
1026
-                'STA_name'   => $STA_name,
1027
-                'STA_active' => true,
1028
-            ];
1029
-            $success       = EEM_State::instance()->insert($cols_n_values);
1030
-            EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1031
-        }
1032
-
1033
-        if (defined('DOING_AJAX')) {
1034
-            $notices = EE_Error::get_notices(false, false, false);
1035
-            echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1036
-            die();
1037
-        }
1038
-        $this->_redirect_after_action(
1039
-            $success,
1040
-            esc_html__('State', 'event_espresso'),
1041
-            'added',
1042
-            ['action' => 'country_settings']
1043
-        );
1044
-    }
1045
-
1046
-
1047
-    /**
1048
-     * @return void
1049
-     * @throws EE_Error
1050
-     * @throws InvalidArgumentException
1051
-     * @throws InvalidDataTypeException
1052
-     * @throws InvalidInterfaceException
1053
-     * @throws ReflectionException
1054
-     */
1055
-    public function delete_state()
1056
-    {
1057
-        $CNT_ISO    = $this->getCountryISO();
1058
-        $STA_ID     = $this->request->getRequestParam('STA_ID');
1059
-        $STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1060
-
1061
-        if (! $STA_ID) {
1062
-            EE_Error::add_error(
1063
-                esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1064
-                __FILE__,
1065
-                __FUNCTION__,
1066
-                __LINE__
1067
-            );
1068
-            return;
1069
-        }
1070
-
1071
-        $success = EEM_State::instance()->delete_by_ID($STA_ID);
1072
-        if ($success !== false) {
1073
-            do_action(
1074
-                'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1075
-                $CNT_ISO,
1076
-                $STA_ID,
1077
-                ['STA_abbrev' => $STA_abbrev]
1078
-            );
1079
-            EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1080
-        }
1081
-        if (defined('DOING_AJAX')) {
1082
-            $notices                = EE_Error::get_notices(false);
1083
-            $notices['return_data'] = true;
1084
-            echo wp_json_encode($notices);
1085
-            die();
1086
-        }
1087
-        $this->_redirect_after_action(
1088
-            $success,
1089
-            esc_html__('State', 'event_espresso'),
1090
-            'deleted',
1091
-            ['action' => 'country_settings']
1092
-        );
1093
-    }
1094
-
1095
-
1096
-    /**
1097
-     * @return void
1098
-     * @throws EE_Error
1099
-     * @throws InvalidArgumentException
1100
-     * @throws InvalidDataTypeException
1101
-     * @throws InvalidInterfaceException
1102
-     * @throws ReflectionException
1103
-     */
1104
-    protected function _update_country_settings()
1105
-    {
1106
-        $CNT_ISO = $this->getCountryISO();
1107
-        if (! $CNT_ISO) {
1108
-            EE_Error::add_error(
1109
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1110
-                __FILE__,
1111
-                __FUNCTION__,
1112
-                __LINE__
1113
-            );
1114
-            return;
1115
-        }
1116
-
1117
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1118
-
1119
-        $cols_n_values                    = [];
1120
-        $cols_n_values['CNT_ISO3']        = strtoupper(
1121
-            $this->request->getRequestParam('cntry', $country->ISO3())
1122
-        );
1123
-        $cols_n_values['CNT_name']        = $this->request->getRequestParam(
1124
-            "cntry[$CNT_ISO][CNT_name]",
1125
-            $country->name()
1126
-        );
1127
-        $cols_n_values['CNT_cur_code']    = strtoupper(
1128
-            $this->request->getRequestParam(
1129
-                "cntry[$CNT_ISO][CNT_cur_code]",
1130
-                $country->currency_code()
1131
-            )
1132
-        );
1133
-        $cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1134
-            "cntry[$CNT_ISO][CNT_cur_single]",
1135
-            $country->currency_name_single()
1136
-        );
1137
-        $cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1138
-            "cntry[$CNT_ISO][CNT_cur_plural]",
1139
-            $country->currency_name_plural()
1140
-        );
1141
-        $cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1142
-            "cntry[$CNT_ISO][CNT_cur_sign]",
1143
-            $country->currency_sign()
1144
-        );
1145
-        $cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1146
-            "cntry[$CNT_ISO][CNT_cur_sign_b4]",
1147
-            $country->currency_sign_before(),
1148
-            DataType::BOOL
1149
-        );
1150
-        $cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1151
-            "cntry[$CNT_ISO][CNT_cur_dec_plc]",
1152
-            $country->currency_decimal_places()
1153
-        );
1154
-        $cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1155
-            "cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1156
-            $country->currency_decimal_mark()
1157
-        );
1158
-        $cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1159
-            "cntry[$CNT_ISO][CNT_cur_thsnds]",
1160
-            $country->currency_thousands_separator()
1161
-        );
1162
-        $cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1163
-            "cntry[$CNT_ISO][CNT_tel_code]",
1164
-            $country->telephoneCode()
1165
-        );
1166
-        $cols_n_values['CNT_active']      = $this->request->getRequestParam(
1167
-            "cntry[$CNT_ISO][CNT_active]",
1168
-            $country->isActive(),
1169
-            DataType::BOOL
1170
-        );
1171
-
1172
-        // allow filtering of country data
1173
-        $cols_n_values = apply_filters(
1174
-            'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1175
-            $cols_n_values
1176
-        );
1177
-
1178
-        // where values
1179
-        $where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1180
-        // run the update
1181
-        $success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1182
-
1183
-        // allow filtering of states data
1184
-        $states = apply_filters(
1185
-            'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1186
-            $this->request->getRequestParam('states', [], DataType::STRING, true)
1187
-        );
1188
-
1189
-        if (! empty($states) && $success !== false) {
1190
-            // loop thru state data ( looks like : states[75][STA_name] )
1191
-            foreach ($states as $STA_ID => $state) {
1192
-                $cols_n_values = [
1193
-                    'CNT_ISO'    => $CNT_ISO,
1194
-                    'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1195
-                    'STA_name'   => sanitize_text_field($state['STA_name']),
1196
-                    'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1197
-                ];
1198
-                // where values
1199
-                $where_cols_n_values = [['STA_ID' => $STA_ID]];
1200
-                // run the update
1201
-                $success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1202
-                if ($success !== false) {
1203
-                    do_action(
1204
-                        'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1205
-                        $CNT_ISO,
1206
-                        $STA_ID,
1207
-                        $cols_n_values
1208
-                    );
1209
-                }
1210
-            }
1211
-        }
1212
-        // check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1213
-        if (
1214
-            isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1215
-            && $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1216
-        ) {
1217
-            EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1218
-            EE_Registry::instance()->CFG->update_espresso_config();
1219
-        }
1220
-
1221
-        if ($success !== false) {
1222
-            EE_Error::add_success(
1223
-                esc_html__('Country Settings updated successfully.', 'event_espresso')
1224
-            );
1225
-        }
1226
-        $this->_redirect_after_action(
1227
-            $success,
1228
-            '',
1229
-            '',
1230
-            ['action' => 'country_settings', 'country' => $CNT_ISO],
1231
-            true
1232
-        );
1233
-    }
1234
-
1235
-
1236
-    /**
1237
-     * form_form_field_label_wrap
1238
-     *
1239
-     * @param string $label
1240
-     * @return string
1241
-     */
1242
-    public function country_form_field_label_wrap(string $label): string
1243
-    {
1244
-        return '
22
+	/**
23
+	 * @var EE_Core_Config
24
+	 */
25
+	public $core_config;
26
+
27
+
28
+	/**
29
+	 * Initialize basic properties.
30
+	 */
31
+	protected function _init_page_props()
32
+	{
33
+		$this->page_slug        = GEN_SET_PG_SLUG;
34
+		$this->page_label       = GEN_SET_LABEL;
35
+		$this->_admin_base_url  = GEN_SET_ADMIN_URL;
36
+		$this->_admin_base_path = GEN_SET_ADMIN;
37
+	}
38
+
39
+
40
+	/**
41
+	 * Set ajax hooks
42
+	 */
43
+	protected function _ajax_hooks()
44
+	{
45
+		add_action('wp_ajax_espresso_display_country_settings', [$this, 'display_country_settings']);
46
+		add_action('wp_ajax_espresso_display_country_states', [$this, 'display_country_states']);
47
+		add_action('wp_ajax_espresso_delete_state', [$this, 'delete_state'], 10, 3);
48
+		add_action('wp_ajax_espresso_add_new_state', [$this, 'add_new_state']);
49
+	}
50
+
51
+
52
+	/**
53
+	 * More page properties initialization.
54
+	 */
55
+	protected function _define_page_props()
56
+	{
57
+		$this->_admin_page_title = GEN_SET_LABEL;
58
+		$this->_labels           = ['publishbox' => esc_html__('Update Settings', 'event_espresso')];
59
+	}
60
+
61
+
62
+	/**
63
+	 * Set page routes property.
64
+	 */
65
+	protected function _set_page_routes()
66
+	{
67
+		$this->_page_routes = [
68
+			'critical_pages'                => [
69
+				'func'       => '_espresso_page_settings',
70
+				'capability' => 'manage_options',
71
+			],
72
+			'update_espresso_page_settings' => [
73
+				'func'       => '_update_espresso_page_settings',
74
+				'capability' => 'manage_options',
75
+				'noheader'   => true,
76
+			],
77
+			'default'                       => [
78
+				'func'       => '_your_organization_settings',
79
+				'capability' => 'manage_options',
80
+			],
81
+
82
+			'update_your_organization_settings' => [
83
+				'func'       => '_update_your_organization_settings',
84
+				'capability' => 'manage_options',
85
+				'noheader'   => true,
86
+			],
87
+
88
+			'admin_option_settings' => [
89
+				'func'       => '_admin_option_settings',
90
+				'capability' => 'manage_options',
91
+			],
92
+
93
+			'update_admin_option_settings' => [
94
+				'func'       => '_update_admin_option_settings',
95
+				'capability' => 'manage_options',
96
+				'noheader'   => true,
97
+			],
98
+
99
+			'country_settings' => [
100
+				'func'       => '_country_settings',
101
+				'capability' => 'manage_options',
102
+			],
103
+
104
+			'update_country_settings' => [
105
+				'func'       => '_update_country_settings',
106
+				'capability' => 'manage_options',
107
+				'noheader'   => true,
108
+			],
109
+
110
+			'display_country_settings' => [
111
+				'func'       => 'display_country_settings',
112
+				'capability' => 'manage_options',
113
+				'noheader'   => true,
114
+			],
115
+
116
+			'add_new_state' => [
117
+				'func'       => 'add_new_state',
118
+				'capability' => 'manage_options',
119
+				'noheader'   => true,
120
+			],
121
+
122
+			'delete_state'            => [
123
+				'func'       => 'delete_state',
124
+				'capability' => 'manage_options',
125
+				'noheader'   => true,
126
+			],
127
+			'privacy_settings'        => [
128
+				'func'       => 'privacySettings',
129
+				'capability' => 'manage_options',
130
+			],
131
+			'update_privacy_settings' => [
132
+				'func'               => 'updatePrivacySettings',
133
+				'capability'         => 'manage_options',
134
+				'noheader'           => true,
135
+				'headers_sent_route' => 'privacy_settings',
136
+			],
137
+		];
138
+	}
139
+
140
+
141
+	/**
142
+	 * Set page configuration property
143
+	 */
144
+	protected function _set_page_config()
145
+	{
146
+		$this->_page_config = [
147
+			'critical_pages'        => [
148
+				'nav'           => [
149
+					'label' => esc_html__('Critical Pages', 'event_espresso'),
150
+					'icon' => 'dashicons-warning',
151
+					'order' => 50,
152
+				],
153
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
154
+				'help_tabs'     => [
155
+					'general_settings_critical_pages_help_tab' => [
156
+						'title'    => esc_html__('Critical Pages', 'event_espresso'),
157
+						'filename' => 'general_settings_critical_pages',
158
+					],
159
+				],
160
+				'require_nonce' => false,
161
+			],
162
+			'default'               => [
163
+				'nav'           => [
164
+					'label' => esc_html__('Your Organization', 'event_espresso'),
165
+					'icon' => 'dashicons-admin-home',
166
+					'order' => 20,
167
+				],
168
+				'help_tabs'     => [
169
+					'general_settings_your_organization_help_tab' => [
170
+						'title'    => esc_html__('Your Organization', 'event_espresso'),
171
+						'filename' => 'general_settings_your_organization',
172
+					],
173
+				],
174
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
175
+				'require_nonce' => false,
176
+			],
177
+			'admin_option_settings' => [
178
+				'nav'           => [
179
+					'label' => esc_html__('Admin Options', 'event_espresso'),
180
+					'icon' => 'dashicons-admin-settings',
181
+					'order' => 60,
182
+				],
183
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
184
+				'help_tabs'     => [
185
+					'general_settings_admin_options_help_tab' => [
186
+						'title'    => esc_html__('Admin Options', 'event_espresso'),
187
+						'filename' => 'general_settings_admin_options',
188
+					],
189
+				],
190
+				'require_nonce' => false,
191
+			],
192
+			'country_settings'      => [
193
+				'nav'           => [
194
+					'label' => esc_html__('Countries', 'event_espresso'),
195
+					'icon' => 'dashicons-admin-site',
196
+					'order' => 70,
197
+				],
198
+				'help_tabs'     => [
199
+					'general_settings_countries_help_tab' => [
200
+						'title'    => esc_html__('Countries', 'event_espresso'),
201
+						'filename' => 'general_settings_countries',
202
+					],
203
+				],
204
+				'require_nonce' => false,
205
+			],
206
+			'privacy_settings'      => [
207
+				'nav'           => [
208
+					'label' => esc_html__('Privacy', 'event_espresso'),
209
+					'icon' => 'dashicons-privacy',
210
+					'order' => 80,
211
+				],
212
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
213
+				'require_nonce' => false,
214
+			],
215
+		];
216
+	}
217
+
218
+
219
+	protected function _add_screen_options()
220
+	{
221
+	}
222
+
223
+
224
+	protected function _add_feature_pointers()
225
+	{
226
+	}
227
+
228
+
229
+	/**
230
+	 * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
231
+	 */
232
+	public function load_scripts_styles()
233
+	{
234
+		// styles
235
+		wp_enqueue_style('espresso-ui-theme');
236
+		// scripts
237
+		wp_enqueue_script('ee_admin_js');
238
+	}
239
+
240
+
241
+	/**
242
+	 * Execute logic running on `admin_init`
243
+	 */
244
+	public function admin_init()
245
+	{
246
+		$this->core_config = EE_Registry::instance()->CFG->core;
247
+
248
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(
249
+			esc_html__(
250
+				'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.',
251
+				'event_espresso'
252
+			)
253
+		);
254
+		EE_Registry::$i18n_js_strings['error_occurred']          = wp_strip_all_tags(
255
+			esc_html__(
256
+				'An error occurred! Please refresh the page and try again.',
257
+				'event_espresso'
258
+			)
259
+		);
260
+		EE_Registry::$i18n_js_strings['confirm_delete_state']    = wp_strip_all_tags(
261
+			esc_html__(
262
+				'Are you sure you want to delete this State / Province?',
263
+				'event_espresso'
264
+			)
265
+		);
266
+		EE_Registry::$i18n_js_strings['ajax_url']                = admin_url(
267
+			'admin-ajax.php?page=espresso_general_settings',
268
+			is_ssl() ? 'https://' : 'http://'
269
+		);
270
+	}
271
+
272
+
273
+	public function admin_notices()
274
+	{
275
+	}
276
+
277
+
278
+	public function admin_footer_scripts()
279
+	{
280
+	}
281
+
282
+
283
+	/**
284
+	 * Enqueue scripts and styles for the default route.
285
+	 */
286
+	public function load_scripts_styles_default()
287
+	{
288
+		// styles
289
+		wp_enqueue_style('thickbox');
290
+		// scripts
291
+		wp_enqueue_script('media-upload');
292
+		wp_enqueue_script('thickbox');
293
+		wp_register_script(
294
+			'organization_settings',
295
+			GEN_SET_ASSETS_URL . 'your_organization_settings.js',
296
+			['jquery', 'media-upload', 'thickbox'],
297
+			EVENT_ESPRESSO_VERSION,
298
+			true
299
+		);
300
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
301
+		wp_enqueue_script('organization_settings');
302
+		wp_enqueue_style('organization-css');
303
+		$confirm_image_delete = [
304
+			'text' => wp_strip_all_tags(
305
+				esc_html__(
306
+					'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
307
+					'event_espresso'
308
+				)
309
+			),
310
+		];
311
+		wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
312
+	}
313
+
314
+
315
+	/**
316
+	 * Enqueue scripts and styles for the country settings route.
317
+	 */
318
+	public function load_scripts_styles_country_settings()
319
+	{
320
+		// scripts
321
+		wp_register_script(
322
+			'gen_settings_countries',
323
+			GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
324
+			['ee_admin_js'],
325
+			EVENT_ESPRESSO_VERSION,
326
+			true
327
+		);
328
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', [], EVENT_ESPRESSO_VERSION);
329
+		wp_enqueue_script('gen_settings_countries');
330
+		wp_enqueue_style('organization-css');
331
+	}
332
+
333
+
334
+	/*************        Espresso Pages        *************/
335
+	/**
336
+	 * _espresso_page_settings
337
+	 *
338
+	 * @throws EE_Error
339
+	 * @throws DomainException
340
+	 * @throws DomainException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidArgumentException
343
+	 */
344
+	protected function _espresso_page_settings()
345
+	{
346
+		// Check to make sure all of the main pages are set up properly,
347
+		// if not create the default pages and display an admin notice
348
+		EEH_Activation::verify_default_pages_exist();
349
+		$this->_transient_garbage_collection();
350
+
351
+		$this->_template_args['values'] = $this->_yes_no_values;
352
+
353
+		$this->_template_args['reg_page_id']  = $this->core_config->reg_page_id ?? null;
354
+		$this->_template_args['reg_page_obj'] = isset($this->core_config->reg_page_id)
355
+			? get_post($this->core_config->reg_page_id)
356
+			: false;
357
+
358
+		$this->_template_args['txn_page_id']  = $this->core_config->txn_page_id ?? null;
359
+		$this->_template_args['txn_page_obj'] = isset($this->core_config->txn_page_id)
360
+			? get_post($this->core_config->txn_page_id)
361
+			: false;
362
+
363
+		$this->_template_args['thank_you_page_id']  = $this->core_config->thank_you_page_id ?? null;
364
+		$this->_template_args['thank_you_page_obj'] = isset($this->core_config->thank_you_page_id)
365
+			? get_post($this->core_config->thank_you_page_id)
366
+			: false;
367
+
368
+		$this->_template_args['cancel_page_id']  = $this->core_config->cancel_page_id ?? null;
369
+		$this->_template_args['cancel_page_obj'] = isset($this->core_config->cancel_page_id)
370
+			? get_post($this->core_config->cancel_page_id)
371
+			: false;
372
+
373
+		$this->_set_add_edit_form_tags('update_espresso_page_settings');
374
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
375
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
376
+			GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
377
+			$this->_template_args,
378
+			true
379
+		);
380
+		$this->display_admin_page_with_sidebar();
381
+	}
382
+
383
+
384
+	/**
385
+	 * Handler for updating espresso page settings.
386
+	 *
387
+	 * @throws EE_Error
388
+	 */
389
+	protected function _update_espresso_page_settings()
390
+	{
391
+		$this->core_config = EE_Registry::instance()->CFG->core;
392
+		// capture incoming request data && set page IDs
393
+		$this->core_config->reg_page_id       = $this->request->getRequestParam(
394
+			'reg_page_id',
395
+			$this->core_config->reg_page_id,
396
+			DataType::INT
397
+		);
398
+		$this->core_config->txn_page_id       = $this->request->getRequestParam(
399
+			'txn_page_id',
400
+			$this->core_config->txn_page_id,
401
+			DataType::INT
402
+		);
403
+		$this->core_config->thank_you_page_id = $this->request->getRequestParam(
404
+			'thank_you_page_id',
405
+			$this->core_config->thank_you_page_id,
406
+			DataType::INT
407
+		);
408
+		$this->core_config->cancel_page_id    = $this->request->getRequestParam(
409
+			'cancel_page_id',
410
+			$this->core_config->cancel_page_id,
411
+			DataType::INT
412
+		);
413
+
414
+		$this->core_config = apply_filters(
415
+			'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
416
+			$this->core_config,
417
+			$this->request->requestParams()
418
+		);
419
+
420
+		$what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
421
+		$this->_redirect_after_action(
422
+			$this->_update_espresso_configuration(
423
+				$what,
424
+				$this->core_config,
425
+				__FILE__,
426
+				__FUNCTION__,
427
+				__LINE__
428
+			),
429
+			$what,
430
+			'',
431
+			[
432
+				'action' => 'critical_pages',
433
+			],
434
+			true
435
+		);
436
+	}
437
+
438
+
439
+	/*************        Your Organization        *************/
440
+
441
+
442
+	/**
443
+	 * @throws DomainException
444
+	 * @throws EE_Error
445
+	 * @throws InvalidArgumentException
446
+	 * @throws InvalidDataTypeException
447
+	 * @throws InvalidInterfaceException
448
+	 */
449
+	protected function _your_organization_settings()
450
+	{
451
+		$this->_template_args['admin_page_content'] = '';
452
+		try {
453
+			/** @var OrganizationSettings $organization_settings_form */
454
+			$organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
455
+
456
+			$this->_template_args['admin_page_content'] = EEH_HTML::div(
457
+				$organization_settings_form->display(),
458
+				'',
459
+				'padding'
460
+			);
461
+		} catch (Exception $e) {
462
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
463
+		}
464
+		$this->_set_add_edit_form_tags('update_your_organization_settings');
465
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
466
+		$this->display_admin_page_with_sidebar();
467
+	}
468
+
469
+
470
+	/**
471
+	 * Handler for updating organization settings.
472
+	 *
473
+	 * @throws EE_Error
474
+	 */
475
+	protected function _update_your_organization_settings()
476
+	{
477
+		try {
478
+			/** @var OrganizationSettings $organization_settings_form */
479
+			$organization_settings_form = $this->loader->getShared(OrganizationSettings::class);
480
+
481
+			$success = $organization_settings_form->process($this->request->requestParams());
482
+
483
+			EE_Registry::instance()->CFG = apply_filters(
484
+				'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
485
+				EE_Registry::instance()->CFG
486
+			);
487
+		} catch (Exception $e) {
488
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
489
+			$success = false;
490
+		}
491
+
492
+		if ($success) {
493
+			$success = $this->_update_espresso_configuration(
494
+				esc_html__('Your Organization Settings', 'event_espresso'),
495
+				EE_Registry::instance()->CFG,
496
+				__FILE__,
497
+				__FUNCTION__,
498
+				__LINE__
499
+			);
500
+		}
501
+
502
+		$this->_redirect_after_action($success, '', '', ['action' => 'default'], true);
503
+	}
504
+
505
+
506
+
507
+	/*************        Admin Options        *************/
508
+
509
+
510
+	/**
511
+	 * _admin_option_settings
512
+	 *
513
+	 * @throws EE_Error
514
+	 * @throws LogicException
515
+	 */
516
+	protected function _admin_option_settings()
517
+	{
518
+		$this->_template_args['admin_page_content'] = '';
519
+		try {
520
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
521
+			// still need this for the old school form in Extend_General_Settings_Admin_Page
522
+			$this->_template_args['values'] = $this->_yes_no_values;
523
+			// also need to account for the do_action that was in the old template
524
+			$admin_options_settings_form->setTemplateArgs($this->_template_args);
525
+			$this->_template_args['admin_page_content'] = EEH_HTML::div(
526
+				$admin_options_settings_form->display(),
527
+				'',
528
+				'padding'
529
+			);
530
+		} catch (Exception $e) {
531
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
532
+		}
533
+		$this->_set_add_edit_form_tags('update_admin_option_settings');
534
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
535
+		$this->display_admin_page_with_sidebar();
536
+	}
537
+
538
+
539
+	/**
540
+	 * _update_admin_option_settings
541
+	 *
542
+	 * @throws EE_Error
543
+	 * @throws InvalidDataTypeException
544
+	 * @throws InvalidFormSubmissionException
545
+	 * @throws InvalidArgumentException
546
+	 * @throws LogicException
547
+	 */
548
+	protected function _update_admin_option_settings()
549
+	{
550
+		try {
551
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
552
+			$admin_options_settings_form->process(
553
+				$this->request->getRequestParam(
554
+					$admin_options_settings_form->slug(),
555
+					[],
556
+					DataType::STRING,
557
+					true
558
+				)
559
+			);
560
+			EE_Registry::instance()->CFG->admin = apply_filters(
561
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
562
+				EE_Registry::instance()->CFG->admin
563
+			);
564
+		} catch (Exception $e) {
565
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
566
+		}
567
+		$this->_redirect_after_action(
568
+			apply_filters(
569
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
570
+				$this->_update_espresso_configuration(
571
+					esc_html__('Admin Options', 'event_espresso'),
572
+					EE_Registry::instance()->CFG->admin,
573
+					__FILE__,
574
+					__FUNCTION__,
575
+					__LINE__
576
+				)
577
+			),
578
+			esc_html__('Admin Options', 'event_espresso'),
579
+			'updated',
580
+			['action' => 'admin_option_settings']
581
+		);
582
+	}
583
+
584
+
585
+	/*************        Countries        *************/
586
+
587
+
588
+	/**
589
+	 * @param string|null $default
590
+	 * @return string
591
+	 */
592
+	protected function getCountryISO(?string $default = null): string
593
+	{
594
+		$default = $default ?? $this->getCountryIsoForSite();
595
+		$CNT_ISO = $this->request->getRequestParam('country', $default);
596
+		$CNT_ISO = $this->request->getRequestParam('CNT_ISO', $CNT_ISO);
597
+		return strtoupper($CNT_ISO);
598
+	}
599
+
600
+
601
+	/**
602
+	 * @return string
603
+	 */
604
+	protected function getCountryIsoForSite(): string
605
+	{
606
+		return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
607
+			? EE_Registry::instance()->CFG->organization->CNT_ISO
608
+			: 'US';
609
+	}
610
+
611
+
612
+	/**
613
+	 * @param string          $CNT_ISO
614
+	 * @param EE_Country|null $country
615
+	 * @return EE_Base_Class|EE_Country
616
+	 * @throws EE_Error
617
+	 * @throws InvalidArgumentException
618
+	 * @throws InvalidDataTypeException
619
+	 * @throws InvalidInterfaceException
620
+	 * @throws ReflectionException
621
+	 */
622
+	protected function verifyOrGetCountryFromIso(string $CNT_ISO, ?EE_Country $country = null)
623
+	{
624
+		/** @var EE_Country $country */
625
+		return $country instanceof EE_Country && $country->ID() === $CNT_ISO
626
+			? $country
627
+			: EEM_Country::instance()->get_one_by_ID($CNT_ISO);
628
+	}
629
+
630
+
631
+	/**
632
+	 * Output Country Settings view.
633
+	 *
634
+	 * @throws DomainException
635
+	 * @throws EE_Error
636
+	 * @throws InvalidArgumentException
637
+	 * @throws InvalidDataTypeException
638
+	 * @throws InvalidInterfaceException
639
+	 * @throws ReflectionException
640
+	 */
641
+	protected function _country_settings()
642
+	{
643
+		$CNT_ISO = $this->getCountryISO();
644
+
645
+		$this->_template_args['values']    = $this->_yes_no_values;
646
+		$this->_template_args['countries'] = new EE_Question_Form_Input(
647
+			EE_Question::new_instance(
648
+				[
649
+				  'QST_ID'           => 0,
650
+				  'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
651
+				  'QST_system'       => 'admin-country',
652
+				]
653
+			),
654
+			EE_Answer::new_instance(
655
+				[
656
+					'ANS_ID'    => 0,
657
+					'ANS_value' => $CNT_ISO,
658
+				]
659
+			),
660
+			[
661
+				'input_id'       => 'country',
662
+				'input_name'     => 'country',
663
+				'input_prefix'   => '',
664
+				'append_qstn_id' => false,
665
+			]
666
+		);
667
+
668
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO);
669
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10);
670
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10);
671
+		$this->_template_args['country_details_settings'] = $this->display_country_settings(
672
+			$country->ID(),
673
+			$country
674
+		);
675
+		$this->_template_args['country_states_settings']  = $this->display_country_states(
676
+			$country->ID(),
677
+			$country
678
+		);
679
+		$this->_template_args['CNT_name_for_site']        = $country->name();
680
+
681
+		$this->_set_add_edit_form_tags('update_country_settings');
682
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
683
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
684
+			GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
685
+			$this->_template_args,
686
+			true
687
+		);
688
+		$this->display_admin_page_with_no_sidebar();
689
+	}
690
+
691
+
692
+	/**
693
+	 * @param string          $CNT_ISO
694
+	 * @param EE_Country|null $country
695
+	 * @return string
696
+	 * @throws DomainException
697
+	 * @throws EE_Error
698
+	 * @throws InvalidArgumentException
699
+	 * @throws InvalidDataTypeException
700
+	 * @throws InvalidInterfaceException
701
+	 * @throws ReflectionException
702
+	 */
703
+	public function display_country_settings(string $CNT_ISO = '', ?EE_Country $country = null): string
704
+	{
705
+		$CNT_ISO          = $this->getCountryISO($CNT_ISO);
706
+		$CNT_ISO_for_site = $this->getCountryIsoForSite();
707
+
708
+		if (! $CNT_ISO) {
709
+			return '';
710
+		}
711
+
712
+		// for ajax
713
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
714
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
715
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'country_form_field_label_wrap'], 10, 2);
716
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'country_form_field_input__wrap'], 10, 2);
717
+		$country                                  = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
718
+		$CNT_cur_disabled                         = $CNT_ISO !== $CNT_ISO_for_site;
719
+		$this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
720
+
721
+		$country_input_types            = [
722
+			'CNT_active'      => [
723
+				'type'             => 'RADIO_BTN',
724
+				'input_name'       => "cntry[$CNT_ISO]",
725
+				'class'            => '',
726
+				'options'          => $this->_yes_no_values,
727
+				'use_desc_4_label' => true,
728
+			],
729
+			'CNT_ISO'         => [
730
+				'type'       => 'TEXT',
731
+				'input_name' => "cntry[$CNT_ISO]",
732
+				'class'      => 'ee-input-width--small',
733
+			],
734
+			'CNT_ISO3'        => [
735
+				'type'       => 'TEXT',
736
+				'input_name' => "cntry[$CNT_ISO]",
737
+				'class'      => 'ee-input-width--small',
738
+			],
739
+			// 'RGN_ID'          => [
740
+			//     'type'       => 'TEXT',
741
+			//     'input_name' => "cntry[$CNT_ISO]",
742
+			//     'class'      => 'ee-input-width--small',
743
+			// ],
744
+			'CNT_name'        => [
745
+				'type'       => 'TEXT',
746
+				'input_name' => "cntry[$CNT_ISO]",
747
+				'class'      => 'ee-input-width--big',
748
+			],
749
+			'CNT_cur_code'    => [
750
+				'type'       => 'TEXT',
751
+				'input_name' => "cntry[$CNT_ISO]",
752
+				'class'      => 'ee-input-width--small',
753
+				'disabled'   => $CNT_cur_disabled,
754
+			],
755
+			'CNT_cur_single'  => [
756
+				'type'       => 'TEXT',
757
+				'input_name' => "cntry[$CNT_ISO]",
758
+				'class'      => 'ee-input-width--reg',
759
+				'disabled'   => $CNT_cur_disabled,
760
+			],
761
+			'CNT_cur_plural'  => [
762
+				'type'       => 'TEXT',
763
+				'input_name' => "cntry[$CNT_ISO]",
764
+				'class'      => 'ee-input-width--reg',
765
+				'disabled'   => $CNT_cur_disabled,
766
+			],
767
+			'CNT_cur_sign'    => [
768
+				'type'         => 'TEXT',
769
+				'input_name'   => "cntry[$CNT_ISO]",
770
+				'class'        => 'ee-input-width--small',
771
+				'htmlentities' => false,
772
+				'disabled'     => $CNT_cur_disabled,
773
+			],
774
+			'CNT_cur_sign_b4' => [
775
+				'type'             => 'RADIO_BTN',
776
+				'input_name'       => "cntry[$CNT_ISO]",
777
+				'class'            => '',
778
+				'options'          => $this->_yes_no_values,
779
+				'use_desc_4_label' => true,
780
+				'disabled'         => $CNT_cur_disabled,
781
+			],
782
+			'CNT_cur_dec_plc' => [
783
+				'type'       => 'RADIO_BTN',
784
+				'input_name' => "cntry[$CNT_ISO]",
785
+				'class'      => '',
786
+				'options'    => [
787
+					['id' => 0, 'text' => ''],
788
+					['id' => 1, 'text' => ''],
789
+					['id' => 2, 'text' => ''],
790
+					['id' => 3, 'text' => ''],
791
+				],
792
+				'disabled'   => $CNT_cur_disabled,
793
+			],
794
+			'CNT_cur_dec_mrk' => [
795
+				'type'             => 'RADIO_BTN',
796
+				'input_name'       => "cntry[$CNT_ISO]",
797
+				'class'            => '',
798
+				'options'          => [
799
+					[
800
+						'id'   => ',',
801
+						'text' => esc_html__(', (comma)', 'event_espresso'),
802
+					],
803
+					['id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')],
804
+				],
805
+				'use_desc_4_label' => true,
806
+				'disabled'         => $CNT_cur_disabled,
807
+			],
808
+			'CNT_cur_thsnds'  => [
809
+				'type'             => 'RADIO_BTN',
810
+				'input_name'       => "cntry[$CNT_ISO]",
811
+				'class'            => '',
812
+				'options'          => [
813
+					[
814
+						'id'   => ',',
815
+						'text' => esc_html__(', (comma)', 'event_espresso'),
816
+					],
817
+					[
818
+						'id'   => '.',
819
+						'text' => esc_html__('. (decimal)', 'event_espresso'),
820
+					],
821
+					[
822
+						'id'   => '&nbsp;',
823
+						'text' => esc_html__('(space)', 'event_espresso'),
824
+					],
825
+				],
826
+				'use_desc_4_label' => true,
827
+				'disabled'         => $CNT_cur_disabled,
828
+			],
829
+			'CNT_tel_code'    => [
830
+				'type'       => 'TEXT',
831
+				'input_name' => "cntry[$CNT_ISO]",
832
+				'class'      => 'ee-input-width--small',
833
+			],
834
+			'CNT_is_EU'       => [
835
+				'type'             => 'RADIO_BTN',
836
+				'input_name'       => "cntry[$CNT_ISO]",
837
+				'class'            => '',
838
+				'options'          => $this->_yes_no_values,
839
+				'use_desc_4_label' => true,
840
+			],
841
+		];
842
+		$this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
843
+			$country,
844
+			$country_input_types
845
+		);
846
+		$country_details_settings       = EEH_Template::display_template(
847
+			GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
848
+			$this->_template_args,
849
+			true
850
+		);
851
+
852
+		if (defined('DOING_AJAX')) {
853
+			$notices = EE_Error::get_notices(false, false, false);
854
+			echo wp_json_encode(
855
+				[
856
+					'return_data' => $country_details_settings,
857
+					'success'     => $notices['success'],
858
+					'errors'      => $notices['errors'],
859
+				]
860
+			);
861
+			die();
862
+		}
863
+		return $country_details_settings;
864
+	}
865
+
866
+
867
+	/**
868
+	 * @param string          $CNT_ISO
869
+	 * @param EE_Country|null $country
870
+	 * @return string
871
+	 * @throws DomainException
872
+	 * @throws EE_Error
873
+	 * @throws InvalidArgumentException
874
+	 * @throws InvalidDataTypeException
875
+	 * @throws InvalidInterfaceException
876
+	 * @throws ReflectionException
877
+	 */
878
+	public function display_country_states(string $CNT_ISO = '', ?EE_Country $country = null): string
879
+	{
880
+		$CNT_ISO = $this->getCountryISO($CNT_ISO);
881
+		if (! $CNT_ISO) {
882
+			return '';
883
+		}
884
+		// for ajax
885
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
886
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
887
+		add_filter('FHEE__EEH_Form_Fields__label_html', [$this, 'state_form_field_label_wrap'], 10, 2);
888
+		add_filter('FHEE__EEH_Form_Fields__input_html', [$this, 'state_form_field_input__wrap'], 10);
889
+		$states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
890
+		if (empty($states)) {
891
+			/** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
892
+			$countrySubRegionDao = $this->loader->getShared(
893
+				'EventEspresso\core\services\address\CountrySubRegionDao'
894
+			);
895
+			if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
896
+				$country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
897
+				if ($countrySubRegionDao->saveCountrySubRegions($country)) {
898
+					$states = EEM_State::instance()->get_all_states_for_these_countries([$CNT_ISO => $CNT_ISO]);
899
+				}
900
+			}
901
+		}
902
+		if (is_array($states)) {
903
+			foreach ($states as $STA_ID => $state) {
904
+				if ($state instanceof EE_State) {
905
+					$inputs = EE_Question_Form_Input::generate_question_form_inputs_for_object(
906
+						$state,
907
+						[
908
+							'STA_abbrev' => [
909
+								'type'             => 'TEXT',
910
+								'label'            => esc_html__('Code', 'event_espresso'),
911
+								'input_name'       => "states[$STA_ID]",
912
+								'class'            => 'ee-input-width--tiny',
913
+								'add_mobile_label' => true,
914
+							],
915
+							'STA_name'   => [
916
+								'type'             => 'TEXT',
917
+								'label'            => esc_html__('Name', 'event_espresso'),
918
+								'input_name'       => "states[$STA_ID]",
919
+								'class'            => 'ee-input-width--big',
920
+								'add_mobile_label' => true,
921
+							],
922
+							'STA_active' => [
923
+								'type'             => 'RADIO_BTN',
924
+								'label'            => esc_html__(
925
+									'State Appears in Dropdown Select Lists',
926
+									'event_espresso'
927
+								),
928
+								'input_name'       => "states[$STA_ID]",
929
+								'options'          => $this->_yes_no_values,
930
+								'use_desc_4_label' => true,
931
+								'add_mobile_label' => true,
932
+							],
933
+						]
934
+					);
935
+
936
+					$delete_state_url = EE_Admin_Page::add_query_args_and_nonce(
937
+						[
938
+							'action'     => 'delete_state',
939
+							'STA_ID'     => $STA_ID,
940
+							'CNT_ISO'    => $CNT_ISO,
941
+							'STA_abbrev' => $state->abbrev(),
942
+						],
943
+						GEN_SET_ADMIN_URL
944
+					);
945
+
946
+					$this->_template_args['states'][ $STA_ID ]['inputs']           = $inputs;
947
+					$this->_template_args['states'][ $STA_ID ]['delete_state_url'] = $delete_state_url;
948
+				}
949
+			}
950
+		} else {
951
+			$this->_template_args['states'] = false;
952
+		}
953
+
954
+		$this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
955
+			['action' => 'add_new_state'],
956
+			GEN_SET_ADMIN_URL
957
+		);
958
+
959
+		$state_details_settings = EEH_Template::display_template(
960
+			GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
961
+			$this->_template_args,
962
+			true
963
+		);
964
+
965
+		if (defined('DOING_AJAX')) {
966
+			$notices = EE_Error::get_notices(false, false, false);
967
+			echo wp_json_encode(
968
+				[
969
+					'return_data' => $state_details_settings,
970
+					'success'     => $notices['success'],
971
+					'errors'      => $notices['errors'],
972
+				]
973
+			);
974
+			die();
975
+		}
976
+		return $state_details_settings;
977
+	}
978
+
979
+
980
+	/**
981
+	 * @return void
982
+	 * @throws EE_Error
983
+	 * @throws InvalidArgumentException
984
+	 * @throws InvalidDataTypeException
985
+	 * @throws InvalidInterfaceException
986
+	 * @throws ReflectionException
987
+	 */
988
+	public function add_new_state()
989
+	{
990
+		$success = true;
991
+		$CNT_ISO = $this->getCountryISO('');
992
+		if (! $CNT_ISO) {
993
+			EE_Error::add_error(
994
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
995
+				__FILE__,
996
+				__FUNCTION__,
997
+				__LINE__
998
+			);
999
+			$success = false;
1000
+		}
1001
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1002
+		if (! $STA_abbrev) {
1003
+			EE_Error::add_error(
1004
+				esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
1005
+				__FILE__,
1006
+				__FUNCTION__,
1007
+				__LINE__
1008
+			);
1009
+			$success = false;
1010
+		}
1011
+		$STA_name = $this->request->getRequestParam('STA_name');
1012
+		if (! $STA_name) {
1013
+			EE_Error::add_error(
1014
+				esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1015
+				__FILE__,
1016
+				__FUNCTION__,
1017
+				__LINE__
1018
+			);
1019
+			$success = false;
1020
+		}
1021
+
1022
+		if ($success) {
1023
+			$cols_n_values = [
1024
+				'CNT_ISO'    => $CNT_ISO,
1025
+				'STA_abbrev' => $STA_abbrev,
1026
+				'STA_name'   => $STA_name,
1027
+				'STA_active' => true,
1028
+			];
1029
+			$success       = EEM_State::instance()->insert($cols_n_values);
1030
+			EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1031
+		}
1032
+
1033
+		if (defined('DOING_AJAX')) {
1034
+			$notices = EE_Error::get_notices(false, false, false);
1035
+			echo wp_json_encode(array_merge($notices, ['return_data' => $CNT_ISO]));
1036
+			die();
1037
+		}
1038
+		$this->_redirect_after_action(
1039
+			$success,
1040
+			esc_html__('State', 'event_espresso'),
1041
+			'added',
1042
+			['action' => 'country_settings']
1043
+		);
1044
+	}
1045
+
1046
+
1047
+	/**
1048
+	 * @return void
1049
+	 * @throws EE_Error
1050
+	 * @throws InvalidArgumentException
1051
+	 * @throws InvalidDataTypeException
1052
+	 * @throws InvalidInterfaceException
1053
+	 * @throws ReflectionException
1054
+	 */
1055
+	public function delete_state()
1056
+	{
1057
+		$CNT_ISO    = $this->getCountryISO();
1058
+		$STA_ID     = $this->request->getRequestParam('STA_ID');
1059
+		$STA_abbrev = $this->request->getRequestParam('STA_abbrev');
1060
+
1061
+		if (! $STA_ID) {
1062
+			EE_Error::add_error(
1063
+				esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1064
+				__FILE__,
1065
+				__FUNCTION__,
1066
+				__LINE__
1067
+			);
1068
+			return;
1069
+		}
1070
+
1071
+		$success = EEM_State::instance()->delete_by_ID($STA_ID);
1072
+		if ($success !== false) {
1073
+			do_action(
1074
+				'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1075
+				$CNT_ISO,
1076
+				$STA_ID,
1077
+				['STA_abbrev' => $STA_abbrev]
1078
+			);
1079
+			EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1080
+		}
1081
+		if (defined('DOING_AJAX')) {
1082
+			$notices                = EE_Error::get_notices(false);
1083
+			$notices['return_data'] = true;
1084
+			echo wp_json_encode($notices);
1085
+			die();
1086
+		}
1087
+		$this->_redirect_after_action(
1088
+			$success,
1089
+			esc_html__('State', 'event_espresso'),
1090
+			'deleted',
1091
+			['action' => 'country_settings']
1092
+		);
1093
+	}
1094
+
1095
+
1096
+	/**
1097
+	 * @return void
1098
+	 * @throws EE_Error
1099
+	 * @throws InvalidArgumentException
1100
+	 * @throws InvalidDataTypeException
1101
+	 * @throws InvalidInterfaceException
1102
+	 * @throws ReflectionException
1103
+	 */
1104
+	protected function _update_country_settings()
1105
+	{
1106
+		$CNT_ISO = $this->getCountryISO();
1107
+		if (! $CNT_ISO) {
1108
+			EE_Error::add_error(
1109
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1110
+				__FILE__,
1111
+				__FUNCTION__,
1112
+				__LINE__
1113
+			);
1114
+			return;
1115
+		}
1116
+
1117
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO);
1118
+
1119
+		$cols_n_values                    = [];
1120
+		$cols_n_values['CNT_ISO3']        = strtoupper(
1121
+			$this->request->getRequestParam('cntry', $country->ISO3())
1122
+		);
1123
+		$cols_n_values['CNT_name']        = $this->request->getRequestParam(
1124
+			"cntry[$CNT_ISO][CNT_name]",
1125
+			$country->name()
1126
+		);
1127
+		$cols_n_values['CNT_cur_code']    = strtoupper(
1128
+			$this->request->getRequestParam(
1129
+				"cntry[$CNT_ISO][CNT_cur_code]",
1130
+				$country->currency_code()
1131
+			)
1132
+		);
1133
+		$cols_n_values['CNT_cur_single']  = $this->request->getRequestParam(
1134
+			"cntry[$CNT_ISO][CNT_cur_single]",
1135
+			$country->currency_name_single()
1136
+		);
1137
+		$cols_n_values['CNT_cur_plural']  = $this->request->getRequestParam(
1138
+			"cntry[$CNT_ISO][CNT_cur_plural]",
1139
+			$country->currency_name_plural()
1140
+		);
1141
+		$cols_n_values['CNT_cur_sign']    = $this->request->getRequestParam(
1142
+			"cntry[$CNT_ISO][CNT_cur_sign]",
1143
+			$country->currency_sign()
1144
+		);
1145
+		$cols_n_values['CNT_cur_sign_b4'] = $this->request->getRequestParam(
1146
+			"cntry[$CNT_ISO][CNT_cur_sign_b4]",
1147
+			$country->currency_sign_before(),
1148
+			DataType::BOOL
1149
+		);
1150
+		$cols_n_values['CNT_cur_dec_plc'] = $this->request->getRequestParam(
1151
+			"cntry[$CNT_ISO][CNT_cur_dec_plc]",
1152
+			$country->currency_decimal_places()
1153
+		);
1154
+		$cols_n_values['CNT_cur_dec_mrk'] = $this->request->getRequestParam(
1155
+			"cntry[$CNT_ISO][CNT_cur_dec_mrk]",
1156
+			$country->currency_decimal_mark()
1157
+		);
1158
+		$cols_n_values['CNT_cur_thsnds']  = $this->request->getRequestParam(
1159
+			"cntry[$CNT_ISO][CNT_cur_thsnds]",
1160
+			$country->currency_thousands_separator()
1161
+		);
1162
+		$cols_n_values['CNT_tel_code']    = $this->request->getRequestParam(
1163
+			"cntry[$CNT_ISO][CNT_tel_code]",
1164
+			$country->telephoneCode()
1165
+		);
1166
+		$cols_n_values['CNT_active']      = $this->request->getRequestParam(
1167
+			"cntry[$CNT_ISO][CNT_active]",
1168
+			$country->isActive(),
1169
+			DataType::BOOL
1170
+		);
1171
+
1172
+		// allow filtering of country data
1173
+		$cols_n_values = apply_filters(
1174
+			'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1175
+			$cols_n_values
1176
+		);
1177
+
1178
+		// where values
1179
+		$where_cols_n_values = [['CNT_ISO' => $CNT_ISO]];
1180
+		// run the update
1181
+		$success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1182
+
1183
+		// allow filtering of states data
1184
+		$states = apply_filters(
1185
+			'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1186
+			$this->request->getRequestParam('states', [], DataType::STRING, true)
1187
+		);
1188
+
1189
+		if (! empty($states) && $success !== false) {
1190
+			// loop thru state data ( looks like : states[75][STA_name] )
1191
+			foreach ($states as $STA_ID => $state) {
1192
+				$cols_n_values = [
1193
+					'CNT_ISO'    => $CNT_ISO,
1194
+					'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1195
+					'STA_name'   => sanitize_text_field($state['STA_name']),
1196
+					'STA_active' => filter_var($state['STA_active'], FILTER_VALIDATE_BOOLEAN),
1197
+				];
1198
+				// where values
1199
+				$where_cols_n_values = [['STA_ID' => $STA_ID]];
1200
+				// run the update
1201
+				$success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1202
+				if ($success !== false) {
1203
+					do_action(
1204
+						'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1205
+						$CNT_ISO,
1206
+						$STA_ID,
1207
+						$cols_n_values
1208
+					);
1209
+				}
1210
+			}
1211
+		}
1212
+		// check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1213
+		if (
1214
+			isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1215
+			&& $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1216
+		) {
1217
+			EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1218
+			EE_Registry::instance()->CFG->update_espresso_config();
1219
+		}
1220
+
1221
+		if ($success !== false) {
1222
+			EE_Error::add_success(
1223
+				esc_html__('Country Settings updated successfully.', 'event_espresso')
1224
+			);
1225
+		}
1226
+		$this->_redirect_after_action(
1227
+			$success,
1228
+			'',
1229
+			'',
1230
+			['action' => 'country_settings', 'country' => $CNT_ISO],
1231
+			true
1232
+		);
1233
+	}
1234
+
1235
+
1236
+	/**
1237
+	 * form_form_field_label_wrap
1238
+	 *
1239
+	 * @param string $label
1240
+	 * @return string
1241
+	 */
1242
+	public function country_form_field_label_wrap(string $label): string
1243
+	{
1244
+		return '
1245 1245
 			<tr>
1246 1246
 				<th>
1247 1247
 					' . $label . '
1248 1248
 				</th>';
1249
-    }
1250
-
1251
-
1252
-    /**
1253
-     * form_form_field_input__wrap
1254
-     *
1255
-     * @param string $input
1256
-     * @return string
1257
-     */
1258
-    public function country_form_field_input__wrap(string $input): string
1259
-    {
1260
-        return '
1249
+	}
1250
+
1251
+
1252
+	/**
1253
+	 * form_form_field_input__wrap
1254
+	 *
1255
+	 * @param string $input
1256
+	 * @return string
1257
+	 */
1258
+	public function country_form_field_input__wrap(string $input): string
1259
+	{
1260
+		return '
1261 1261
 				<td class="general-settings-country-input-td">
1262 1262
 					' . $input . '
1263 1263
 				</td>
1264 1264
 			</tr>';
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     * form_form_field_label_wrap
1270
-     *
1271
-     * @param string $label
1272
-     * @param string $required_text
1273
-     * @return string
1274
-     */
1275
-    public function state_form_field_label_wrap(string $label, string $required_text): string
1276
-    {
1277
-        return $required_text;
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * form_form_field_input__wrap
1283
-     *
1284
-     * @param string $input
1285
-     * @return string
1286
-     */
1287
-    public function state_form_field_input__wrap(string $input): string
1288
-    {
1289
-        return '
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 * form_form_field_label_wrap
1270
+	 *
1271
+	 * @param string $label
1272
+	 * @param string $required_text
1273
+	 * @return string
1274
+	 */
1275
+	public function state_form_field_label_wrap(string $label, string $required_text): string
1276
+	{
1277
+		return $required_text;
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * form_form_field_input__wrap
1283
+	 *
1284
+	 * @param string $input
1285
+	 * @return string
1286
+	 */
1287
+	public function state_form_field_input__wrap(string $input): string
1288
+	{
1289
+		return '
1290 1290
 				<td class="general-settings-country-state-input-td">
1291 1291
 					' . $input . '
1292 1292
 				</td>';
1293
-    }
1294
-
1295
-
1296
-    /***********/
1297
-
1298
-
1299
-    /**
1300
-     * displays edit and view links for critical EE pages
1301
-     *
1302
-     * @param int $ee_page_id
1303
-     * @return string
1304
-     */
1305
-    public static function edit_view_links(int $ee_page_id): string
1306
-    {
1307
-        $edit_url = add_query_arg(
1308
-            ['post' => $ee_page_id, 'action' => 'edit'],
1309
-            admin_url('post.php')
1310
-        );
1311
-        $links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1312
-        $links    .= ' &nbsp;|&nbsp; ';
1313
-        $links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1314
-
1315
-        return $links;
1316
-    }
1317
-
1318
-
1319
-    /**
1320
-     * displays page and shortcode status for critical EE pages
1321
-     *
1322
-     * @param WP_Post $ee_page
1323
-     * @param string  $shortcode
1324
-     * @return string
1325
-     */
1326
-    public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1327
-    {
1328
-        // page status
1329
-        if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1330
-            $pg_class  = 'ee-status-bg--success';
1331
-            $pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1332
-        } else {
1333
-            $pg_class  = 'ee-status-bg--error';
1334
-            $pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1335
-        }
1336
-
1337
-        // shortcode status
1338
-        if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1339
-            $sc_class  = 'ee-status-bg--success';
1340
-            $sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1341
-        } else {
1342
-            $sc_class  = 'ee-status-bg--error';
1343
-            $sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1344
-        }
1345
-
1346
-        return '
1293
+	}
1294
+
1295
+
1296
+	/***********/
1297
+
1298
+
1299
+	/**
1300
+	 * displays edit and view links for critical EE pages
1301
+	 *
1302
+	 * @param int $ee_page_id
1303
+	 * @return string
1304
+	 */
1305
+	public static function edit_view_links(int $ee_page_id): string
1306
+	{
1307
+		$edit_url = add_query_arg(
1308
+			['post' => $ee_page_id, 'action' => 'edit'],
1309
+			admin_url('post.php')
1310
+		);
1311
+		$links    = '<a href="' . esc_url_raw($edit_url) . '" >' . esc_html__('Edit', 'event_espresso') . '</a>';
1312
+		$links    .= ' &nbsp;|&nbsp; ';
1313
+		$links    .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1314
+
1315
+		return $links;
1316
+	}
1317
+
1318
+
1319
+	/**
1320
+	 * displays page and shortcode status for critical EE pages
1321
+	 *
1322
+	 * @param WP_Post $ee_page
1323
+	 * @param string  $shortcode
1324
+	 * @return string
1325
+	 */
1326
+	public static function page_and_shortcode_status(WP_Post $ee_page, string $shortcode): string
1327
+	{
1328
+		// page status
1329
+		if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1330
+			$pg_class  = 'ee-status-bg--success';
1331
+			$pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1332
+		} else {
1333
+			$pg_class  = 'ee-status-bg--error';
1334
+			$pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1335
+		}
1336
+
1337
+		// shortcode status
1338
+		if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1339
+			$sc_class  = 'ee-status-bg--success';
1340
+			$sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1341
+		} else {
1342
+			$sc_class  = 'ee-status-bg--error';
1343
+			$sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1344
+		}
1345
+
1346
+		return '
1347 1347
         <span class="ee-page-status ' . $pg_class . '"><strong>' . $pg_status . '</strong></span>
1348 1348
         <span class="ee-page-status ' . $sc_class . '"><strong>' . $sc_status . '</strong></span>';
1349
-    }
1350
-
1351
-
1352
-    /**
1353
-     * generates a dropdown of all parent pages - copied from WP core
1354
-     *
1355
-     * @param int  $default
1356
-     * @param int  $parent
1357
-     * @param int  $level
1358
-     * @param bool $echo
1359
-     * @return string;
1360
-     */
1361
-    public static function page_settings_dropdown(
1362
-        int $default = 0,
1363
-        int $parent = 0,
1364
-        int $level = 0,
1365
-        bool $echo = true
1366
-    ): string {
1367
-        global $wpdb;
1368
-        $items  = $wpdb->get_results(
1369
-            $wpdb->prepare(
1370
-                "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",
1371
-                $parent
1372
-            )
1373
-        );
1374
-        $output = '';
1375
-
1376
-        if ($items) {
1377
-            $level = absint($level);
1378
-            foreach ($items as $item) {
1379
-                $ID         = absint($item->ID);
1380
-                $post_title = wp_strip_all_tags($item->post_title);
1381
-                $pad        = str_repeat('&nbsp;', $level * 3);
1382
-                $option     = "\n\t";
1383
-                $option     .= '<option class="level-' . $level . '" ';
1384
-                $option     .= 'value="' . $ID . '" ';
1385
-                $option     .= $ID === absint($default) ? ' selected' : '';
1386
-                $option     .= '>';
1387
-                $option     .= "$pad {$post_title}";
1388
-                $option     .= '</option>';
1389
-                $output     .= $option;
1390
-                ob_start();
1391
-                parent_dropdown($default, $item->ID, $level + 1);
1392
-                $output .= ob_get_clean();
1393
-            }
1394
-        }
1395
-        if ($echo) {
1396
-            echo wp_kses($output, AllowedTags::getWithFormTags());
1397
-            return '';
1398
-        }
1399
-        return $output;
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     * Loads the scripts for the privacy settings form
1405
-     */
1406
-    public function load_scripts_styles_privacy_settings()
1407
-    {
1408
-        $form_handler = $this->loader->getShared(
1409
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1410
-        );
1411
-        $form_handler->enqueueStylesAndScripts();
1412
-    }
1413
-
1414
-
1415
-    /**
1416
-     * display the privacy settings form
1417
-     *
1418
-     * @throws EE_Error
1419
-     */
1420
-    public function privacySettings()
1421
-    {
1422
-        $this->_set_add_edit_form_tags('update_privacy_settings');
1423
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
1424
-        $form_handler                               = $this->loader->getShared(
1425
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1426
-        );
1427
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
1428
-            $form_handler->display(),
1429
-            '',
1430
-            'padding'
1431
-        );
1432
-        $this->display_admin_page_with_sidebar();
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * Update the privacy settings from form data
1438
-     *
1439
-     * @throws EE_Error
1440
-     */
1441
-    public function updatePrivacySettings()
1442
-    {
1443
-        $form_handler = $this->loader->getShared(
1444
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1445
-        );
1446
-        $success      = $form_handler->process($this->get_request_data());
1447
-        $this->_redirect_after_action(
1448
-            $success,
1449
-            esc_html__('Registration Form Options', 'event_espresso'),
1450
-            'updated',
1451
-            ['action' => 'privacy_settings']
1452
-        );
1453
-    }
1349
+	}
1350
+
1351
+
1352
+	/**
1353
+	 * generates a dropdown of all parent pages - copied from WP core
1354
+	 *
1355
+	 * @param int  $default
1356
+	 * @param int  $parent
1357
+	 * @param int  $level
1358
+	 * @param bool $echo
1359
+	 * @return string;
1360
+	 */
1361
+	public static function page_settings_dropdown(
1362
+		int $default = 0,
1363
+		int $parent = 0,
1364
+		int $level = 0,
1365
+		bool $echo = true
1366
+	): string {
1367
+		global $wpdb;
1368
+		$items  = $wpdb->get_results(
1369
+			$wpdb->prepare(
1370
+				"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",
1371
+				$parent
1372
+			)
1373
+		);
1374
+		$output = '';
1375
+
1376
+		if ($items) {
1377
+			$level = absint($level);
1378
+			foreach ($items as $item) {
1379
+				$ID         = absint($item->ID);
1380
+				$post_title = wp_strip_all_tags($item->post_title);
1381
+				$pad        = str_repeat('&nbsp;', $level * 3);
1382
+				$option     = "\n\t";
1383
+				$option     .= '<option class="level-' . $level . '" ';
1384
+				$option     .= 'value="' . $ID . '" ';
1385
+				$option     .= $ID === absint($default) ? ' selected' : '';
1386
+				$option     .= '>';
1387
+				$option     .= "$pad {$post_title}";
1388
+				$option     .= '</option>';
1389
+				$output     .= $option;
1390
+				ob_start();
1391
+				parent_dropdown($default, $item->ID, $level + 1);
1392
+				$output .= ob_get_clean();
1393
+			}
1394
+		}
1395
+		if ($echo) {
1396
+			echo wp_kses($output, AllowedTags::getWithFormTags());
1397
+			return '';
1398
+		}
1399
+		return $output;
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 * Loads the scripts for the privacy settings form
1405
+	 */
1406
+	public function load_scripts_styles_privacy_settings()
1407
+	{
1408
+		$form_handler = $this->loader->getShared(
1409
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1410
+		);
1411
+		$form_handler->enqueueStylesAndScripts();
1412
+	}
1413
+
1414
+
1415
+	/**
1416
+	 * display the privacy settings form
1417
+	 *
1418
+	 * @throws EE_Error
1419
+	 */
1420
+	public function privacySettings()
1421
+	{
1422
+		$this->_set_add_edit_form_tags('update_privacy_settings');
1423
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
1424
+		$form_handler                               = $this->loader->getShared(
1425
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1426
+		);
1427
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
1428
+			$form_handler->display(),
1429
+			'',
1430
+			'padding'
1431
+		);
1432
+		$this->display_admin_page_with_sidebar();
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * Update the privacy settings from form data
1438
+	 *
1439
+	 * @throws EE_Error
1440
+	 */
1441
+	public function updatePrivacySettings()
1442
+	{
1443
+		$form_handler = $this->loader->getShared(
1444
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler'
1445
+		);
1446
+		$success      = $form_handler->process($this->get_request_data());
1447
+		$this->_redirect_after_action(
1448
+			$success,
1449
+			esc_html__('Registration Form Options', 'event_espresso'),
1450
+			'updated',
1451
+			['action' => 'privacy_settings']
1452
+		);
1453
+	}
1454 1454
 }
Please login to merge, or discard this patch.