Completed
Branch master (59af22)
by
unknown
07:35 queued 03:06
created
widgets/upcoming_events/EEW_Upcoming_Events.widget.php 2 patches
Indentation   +623 added lines, -623 removed lines patch added patch discarded remove patch
@@ -14,109 +14,109 @@  discard block
 block discarded – undo
14 14
  */
15 15
 class EEW_Upcoming_Events extends EspressoWidget
16 16
 {
17
-    /**
18
-     * @var string
19
-     */
20
-    private $title;
21
-    /**
22
-     * @var string
23
-     */
24
-    private $events_category;
25
-
26
-    /**
27
-     * @var bool
28
-     */
29
-    private $show_expired;
30
-
31
-    /**
32
-     * @var string
33
-     */
34
-    private $image_size;
35
-
36
-    /**
37
-     * @var bool
38
-     */
39
-    private $show_desc;
40
-
41
-    /**
42
-     * @var bool
43
-     */
44
-    private $show_dates;
45
-
46
-    /**
47
-     * @var string
48
-     */
49
-    private $date_limit;
50
-
51
-    /**
52
-     * @var string
53
-     */
54
-    private $date_range;
55
-
56
-    /**
57
-     * @var string
58
-     */
59
-    private $limit;
60
-
61
-    /**
62
-     * @var string
63
-     */
64
-    private $order;
65
-
66
-
67
-    /**
68
-     * Register widget with WordPress.
69
-     */
70
-    public function __construct()
71
-    {
72
-        parent::__construct(
73
-            esc_html__('Event Espresso Upcoming Events', 'event_espresso'),
74
-            ['description' => esc_html__('A widget to display your upcoming events.', 'event_espresso')]
75
-        );
76
-    }
77
-
78
-
79
-    /**
80
-     * Back-end widget form.
81
-     *
82
-     * @param array $instance Previously saved values from database.
83
-     * @return void
84
-     * @throws EE_Error
85
-     * @throws ReflectionException
86
-     * @see WP_Widget::form()
87
-     */
88
-    public function form($instance)
89
-    {
90
-
91
-        EE_Registry::instance()->load_class('Question_Option', [], false, false, true);
92
-        // Set up some default widget settings.
93
-        $defaults = [
94
-            'title'           => esc_html__('Upcoming Events', 'event_espresso'),
95
-            'category_name'   => '',
96
-            'show_expired'    => 0,
97
-            'show_desc'       => true,
98
-            'show_dates'      => true,
99
-            'show_everywhere' => false,
100
-            'date_limit'      => 2,
101
-            'limit'           => 10,
102
-            'sort'            => 'ASC',
103
-            'date_range'      => false,
104
-            'image_size'      => 'medium',
105
-        ];
106
-
107
-        $instance = wp_parse_args((array) $instance, $defaults);
108
-        // don't add HTML labels for EE_Form_Fields generated inputs
109
-        add_filter('FHEE__EEH_Form_Fields__label_html', '__return_empty_string');
110
-        $yes_no_values = [
111
-            EE_Question_Option::new_instance(['QSO_value' => false, 'QSO_desc' => esc_html__('No', 'event_espresso')]),
112
-            EE_Question_Option::new_instance(['QSO_value' => true, 'QSO_desc' => esc_html__('Yes', 'event_espresso')]),
113
-        ];
114
-        $sort_values   = [
115
-            EE_Question_Option::new_instance(['QSO_value' => 'ASC', 'QSO_desc' => esc_html__('ASC', 'event_espresso')]),
116
-            EE_Question_Option::new_instance(['QSO_value' => 'DESC', 'QSO_desc' => esc_html__('DESC', 'event_espresso')]),
117
-        ];
118
-
119
-        ?>
17
+	/**
18
+	 * @var string
19
+	 */
20
+	private $title;
21
+	/**
22
+	 * @var string
23
+	 */
24
+	private $events_category;
25
+
26
+	/**
27
+	 * @var bool
28
+	 */
29
+	private $show_expired;
30
+
31
+	/**
32
+	 * @var string
33
+	 */
34
+	private $image_size;
35
+
36
+	/**
37
+	 * @var bool
38
+	 */
39
+	private $show_desc;
40
+
41
+	/**
42
+	 * @var bool
43
+	 */
44
+	private $show_dates;
45
+
46
+	/**
47
+	 * @var string
48
+	 */
49
+	private $date_limit;
50
+
51
+	/**
52
+	 * @var string
53
+	 */
54
+	private $date_range;
55
+
56
+	/**
57
+	 * @var string
58
+	 */
59
+	private $limit;
60
+
61
+	/**
62
+	 * @var string
63
+	 */
64
+	private $order;
65
+
66
+
67
+	/**
68
+	 * Register widget with WordPress.
69
+	 */
70
+	public function __construct()
71
+	{
72
+		parent::__construct(
73
+			esc_html__('Event Espresso Upcoming Events', 'event_espresso'),
74
+			['description' => esc_html__('A widget to display your upcoming events.', 'event_espresso')]
75
+		);
76
+	}
77
+
78
+
79
+	/**
80
+	 * Back-end widget form.
81
+	 *
82
+	 * @param array $instance Previously saved values from database.
83
+	 * @return void
84
+	 * @throws EE_Error
85
+	 * @throws ReflectionException
86
+	 * @see WP_Widget::form()
87
+	 */
88
+	public function form($instance)
89
+	{
90
+
91
+		EE_Registry::instance()->load_class('Question_Option', [], false, false, true);
92
+		// Set up some default widget settings.
93
+		$defaults = [
94
+			'title'           => esc_html__('Upcoming Events', 'event_espresso'),
95
+			'category_name'   => '',
96
+			'show_expired'    => 0,
97
+			'show_desc'       => true,
98
+			'show_dates'      => true,
99
+			'show_everywhere' => false,
100
+			'date_limit'      => 2,
101
+			'limit'           => 10,
102
+			'sort'            => 'ASC',
103
+			'date_range'      => false,
104
+			'image_size'      => 'medium',
105
+		];
106
+
107
+		$instance = wp_parse_args((array) $instance, $defaults);
108
+		// don't add HTML labels for EE_Form_Fields generated inputs
109
+		add_filter('FHEE__EEH_Form_Fields__label_html', '__return_empty_string');
110
+		$yes_no_values = [
111
+			EE_Question_Option::new_instance(['QSO_value' => false, 'QSO_desc' => esc_html__('No', 'event_espresso')]),
112
+			EE_Question_Option::new_instance(['QSO_value' => true, 'QSO_desc' => esc_html__('Yes', 'event_espresso')]),
113
+		];
114
+		$sort_values   = [
115
+			EE_Question_Option::new_instance(['QSO_value' => 'ASC', 'QSO_desc' => esc_html__('ASC', 'event_espresso')]),
116
+			EE_Question_Option::new_instance(['QSO_value' => 'DESC', 'QSO_desc' => esc_html__('DESC', 'event_espresso')]),
117
+		];
118
+
119
+		?>
120 120
 
121 121
         <!-- Widget Title: Text Input -->
122 122
 
@@ -153,38 +153,38 @@  discard block
 block discarded – undo
153 153
                 <?php esc_html_e('Show Expired Events:', 'event_espresso'); ?>
154 154
             </label>
155 155
             <?php
156
-            $show_expired_options   = $yes_no_values;
157
-            $show_expired_options[] = EE_Question_Option::new_instance(
158
-                ['QSO_value' => 2, 'QSO_desc' => esc_html__('Show Only Expired', 'event_espresso')]
159
-            );
160
-            echo wp_kses(
161
-                EEH_Form_Fields::select(
162
-                    esc_html__('Show Expired Events:', 'event_espresso'),
163
-                    $instance['show_expired'],
164
-                    $show_expired_options,
165
-                    $this->fieldName('show_expired'),
166
-                    $this->fieldID('show_expired')
167
-                ),
168
-                AllowedTags::getWithFormTags()
169
-            );
170
-            ?>
156
+			$show_expired_options   = $yes_no_values;
157
+			$show_expired_options[] = EE_Question_Option::new_instance(
158
+				['QSO_value' => 2, 'QSO_desc' => esc_html__('Show Only Expired', 'event_espresso')]
159
+			);
160
+			echo wp_kses(
161
+				EEH_Form_Fields::select(
162
+					esc_html__('Show Expired Events:', 'event_espresso'),
163
+					$instance['show_expired'],
164
+					$show_expired_options,
165
+					$this->fieldName('show_expired'),
166
+					$this->fieldID('show_expired')
167
+				),
168
+				AllowedTags::getWithFormTags()
169
+			);
170
+			?>
171 171
         </p>
172 172
         <p>
173 173
             <label for="<?php echo esc_attr($this->fieldID('sort')); ?>">
174 174
                 <?php esc_html_e('Sort Events:', 'event_espresso'); ?>
175 175
             </label>
176 176
             <?php
177
-            echo wp_kses(
178
-                EEH_Form_Fields::select(
179
-                    esc_html__('Sort Events:', 'event_espresso'),
180
-                    $instance['sort'],
181
-                    $sort_values,
182
-                    $this->fieldName('sort'),
183
-                    $this->fieldID('sort')
184
-                ),
185
-                AllowedTags::getWithFormTags()
186
-            );
187
-            ?>
177
+			echo wp_kses(
178
+				EEH_Form_Fields::select(
179
+					esc_html__('Sort Events:', 'event_espresso'),
180
+					$instance['sort'],
181
+					$sort_values,
182
+					$this->fieldName('sort'),
183
+					$this->fieldID('sort')
184
+				),
185
+				AllowedTags::getWithFormTags()
186
+			);
187
+			?>
188 188
         </p>
189 189
         <p>
190 190
             <label for="<?php echo esc_attr($this->fieldID('image_size')); ?>">
@@ -198,51 +198,51 @@  discard block
 block discarded – undo
198 198
                 <?php esc_html_e('Show Description:', 'event_espresso'); ?>
199 199
             </label>
200 200
             <?php
201
-            echo wp_kses(
202
-                EEH_Form_Fields::select(
203
-                    esc_html__('Show Description:', 'event_espresso'),
204
-                    $instance['show_desc'],
205
-                    $yes_no_values,
206
-                    $this->fieldName('show_desc'),
207
-                    $this->fieldID('show_desc')
208
-                ),
209
-                AllowedTags::getWithFormTags()
210
-            );
211
-            ?>
201
+			echo wp_kses(
202
+				EEH_Form_Fields::select(
203
+					esc_html__('Show Description:', 'event_espresso'),
204
+					$instance['show_desc'],
205
+					$yes_no_values,
206
+					$this->fieldName('show_desc'),
207
+					$this->fieldID('show_desc')
208
+				),
209
+				AllowedTags::getWithFormTags()
210
+			);
211
+			?>
212 212
         </p>
213 213
         <p>
214 214
             <label for="<?php echo esc_attr($this->fieldID('show_dates')); ?>">
215 215
                 <?php esc_html_e('Show Dates:', 'event_espresso'); ?>
216 216
             </label>
217 217
             <?php
218
-            echo wp_kses(
219
-                EEH_Form_Fields::select(
220
-                    esc_html__('Show Dates:', 'event_espresso'),
221
-                    $instance['show_dates'],
222
-                    $yes_no_values,
223
-                    $this->fieldName('show_dates'),
224
-                    $this->fieldID('show_dates')
225
-                ),
226
-                AllowedTags::getWithFormTags()
227
-            );
228
-            ?>
218
+			echo wp_kses(
219
+				EEH_Form_Fields::select(
220
+					esc_html__('Show Dates:', 'event_espresso'),
221
+					$instance['show_dates'],
222
+					$yes_no_values,
223
+					$this->fieldName('show_dates'),
224
+					$this->fieldID('show_dates')
225
+				),
226
+				AllowedTags::getWithFormTags()
227
+			);
228
+			?>
229 229
         </p>
230 230
         <p>
231 231
             <label for="<?php echo esc_attr($this->fieldID('show_everywhere')); ?>">
232 232
                 <?php esc_html_e('Show on all Pages:', 'event_espresso'); ?>
233 233
             </label>
234 234
             <?php
235
-            echo wp_kses(
236
-                EEH_Form_Fields::select(
237
-                    esc_html__('Show on all Pages:', 'event_espresso'),
238
-                    $instance['show_everywhere'],
239
-                    $yes_no_values,
240
-                    $this->fieldName('show_everywhere'),
241
-                    $this->fieldID('show_everywhere')
242
-                ),
243
-                AllowedTags::getWithFormTags()
244
-            );
245
-            ?>
235
+			echo wp_kses(
236
+				EEH_Form_Fields::select(
237
+					esc_html__('Show on all Pages:', 'event_espresso'),
238
+					$instance['show_everywhere'],
239
+					$yes_no_values,
240
+					$this->fieldName('show_everywhere'),
241
+					$this->fieldID('show_everywhere')
242
+				),
243
+				AllowedTags::getWithFormTags()
244
+			);
245
+			?>
246 246
         </p>
247 247
         <p>
248 248
             <label for="<?php echo esc_attr($this->fieldID('date_limit')); ?>">
@@ -260,292 +260,292 @@  discard block
 block discarded – undo
260 260
                 <?php esc_html_e('Show Date Range:', 'event_espresso'); ?>
261 261
             </label>
262 262
             <?php
263
-            echo wp_kses(
264
-                EEH_Form_Fields::select(
265
-                    esc_html__('Show Date Range:', 'event_espresso'),
266
-                    $instance['date_range'],
267
-                    $yes_no_values,
268
-                    $this->fieldName('date_range'),
269
-                    $this->fieldID('date_range')
270
-                ),
271
-                AllowedTags::getWithFormTags()
272
-            );
273
-            ?>
263
+			echo wp_kses(
264
+				EEH_Form_Fields::select(
265
+					esc_html__('Show Date Range:', 'event_espresso'),
266
+					$instance['date_range'],
267
+					$yes_no_values,
268
+					$this->fieldName('date_range'),
269
+					$this->fieldID('date_range')
270
+				),
271
+				AllowedTags::getWithFormTags()
272
+			);
273
+			?>
274 274
             <span class="description">
275 275
                 <br />
276 276
                 <?php esc_html_e(
277
-                    'This setting will replace the list of dates in the widget.',
278
-                    'event_espresso'
279
-                ); ?>
277
+					'This setting will replace the list of dates in the widget.',
278
+					'event_espresso'
279
+				); ?>
280 280
             </span>
281 281
         </p>
282 282
 
283 283
         <?php
284
-    }
285
-
286
-
287
-    /**
288
-     * Sanitize widget form values as they are saved.
289
-     *
290
-     * @param array $new_instance Values just sent to be saved.
291
-     * @param array $old_instance Previously saved values from database.
292
-     *
293
-     * @return array Updated safe values to be saved.
294
-     * @see WP_Widget::update()
295
-     *
296
-     */
297
-    public function update($new_instance, $old_instance)
298
-    {
299
-        /** @var EE_Capabilities $capabilities */
300
-        $capabilities = LoaderFactory::getLoader()->getShared(EE_Capabilities::class);
301
-        if (! $capabilities->current_user_can('manage_options', 'update-espresso-widget')) {
302
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
303
-        }
304
-        $instance                    = $old_instance;
305
-        $instance['title']           = ! empty($new_instance['title']) ? strip_tags((string) $new_instance['title']) : '';
306
-        $instance['category_name']   = $new_instance['category_name'];
307
-        $instance['show_expired']    = $new_instance['show_expired'];
308
-        $instance['limit']           = $new_instance['limit'];
309
-        $instance['sort']            = $new_instance['sort'];
310
-        $instance['image_size']      = $new_instance['image_size'];
311
-        $instance['show_desc']       = $new_instance['show_desc'];
312
-        $instance['show_dates']      = $new_instance['show_dates'];
313
-        $instance['show_everywhere'] = $new_instance['show_everywhere'];
314
-        $instance['date_limit']      = $new_instance['date_limit'];
315
-        $instance['date_range']      = $new_instance['date_range'];
316
-        return $instance;
317
-    }
318
-
319
-
320
-    /**
321
-     * Front-end display of widget.
322
-     *
323
-     * @param array $args     Widget arguments.
324
-     * @param array $instance Saved values from database.
325
-     * @throws EE_Error
326
-     * @throws ReflectionException
327
-     * @see WP_Widget::widget()
328
-     *
329
-     */
330
-    public function widget($args, $instance)
331
-    {
332
-
333
-        global $post;
334
-        // make sure there is some kinda post object
335
-        if ($post instanceof WP_Post) {
336
-            $before_widget = '';
337
-            $before_title  = '';
338
-            $after_title   = '';
339
-            $after_widget  = '';
340
-            // but NOT an events archives page, cuz that would be like two event lists on the same page
341
-            $show_everywhere = ! isset($instance['show_everywhere']) || absint($instance['show_everywhere']);
342
-            if ($show_everywhere || ! ($post->post_type == EspressoPostType::EVENTS && is_archive())) {
343
-                // let's use some of the event helper functions'
344
-                // make separate vars out of attributes
345
-                extract($args);
346
-
347
-                // grab widget settings
348
-                $this->parseWidgetSettings($instance);
349
-                $title = $this->widgetTitle();
350
-
351
-                // Before widget (defined by themes).
352
-                echo wp_kses($before_widget, AllowedTags::getAllowedTags());
353
-                // Display the widget title if one was input (before and after defined by themes).
354
-                if (! empty($title)) {
355
-                    echo wp_kses($before_title . $title . $after_title, AllowedTags::getAllowedTags());
356
-                }
357
-                echo wp_kses($this->widgetContent($post), AllowedTags::getWithFormTags());
358
-                // After widget (defined by themes).
359
-                echo wp_kses($after_widget, AllowedTags::getAllowedTags());
360
-            }
361
-        }
362
-    }
363
-
364
-
365
-    /**
366
-     * make_the_title_a_link
367
-     * callback for widget_title filter
368
-     *
369
-     * @param $title
370
-     * @return string
371
-     */
372
-    public function make_the_title_a_link($title)
373
-    {
374
-        return '<a href="' . EEH_Event_View::event_archive_url() . '">' . $title . '</a>';
375
-    }
376
-
377
-
378
-    /**
379
-     * @param string $field_name
380
-     * @return string
381
-     * @since   4.10.14.p
382
-     */
383
-    public function fieldID($field_name)
384
-    {
385
-        return parent::get_field_id($field_name);
386
-    }
387
-
388
-
389
-    /**
390
-     * @param string $field_name
391
-     * @return string
392
-     * @since   4.10.14.p
393
-     */
394
-    public function fieldName($field_name)
395
-    {
396
-        return parent::get_field_name($field_name);
397
-    }
398
-
399
-
400
-    /**
401
-     * @param array $instance
402
-     * @throws EE_Error
403
-     * @throws ReflectionException
404
-     * @since   4.10.14.p
405
-     */
406
-    private function eventCategoriesSelector(array $instance)
407
-    {
408
-        $event_categories = [];
409
-        $categories       = EEM_Term::instance()->get_all_ee_categories(true);
410
-        if ($categories) {
411
-            foreach ($categories as $category) {
412
-                if ($category instanceof EE_Term) {
413
-                    $event_categories[] =
414
-                        EE_Question_Option::new_instance(
415
-                            [
416
-                                'QSO_value' => $category->get('slug'),
417
-                                'QSO_desc'  => $category->get('name'),
418
-                            ]
419
-                        );
420
-                }
421
-            }
422
-        }
423
-        array_unshift(
424
-            $event_categories,
425
-            EE_Question_Option::new_instance(
426
-                [
427
-                    'QSO_value' => '',
428
-                    'QSO_desc'  => esc_html__(' - display all - ', 'event_espresso'),
429
-                ]
430
-            )
431
-        );
432
-        echo wp_kses(
433
-            EEH_Form_Fields::select(
434
-                esc_html__('Event Category:', 'event_espresso'),
435
-                $instance['category_name'],
436
-                $event_categories,
437
-                $this->fieldName('category_name'),
438
-                $this->fieldID('category_name')
439
-            ),
440
-            AllowedTags::getWithFormTags()
441
-        );
442
-    }
443
-
444
-
445
-    /**
446
-     * @param array $instance
447
-     * @since   4.10.14.p
448
-     */
449
-    private function imageSizeSelector(array $instance)
450
-    {
451
-        $image_sizes = [];
452
-        $sizes       = get_intermediate_image_sizes();
453
-        if ($sizes) {
454
-            // loop thru images and create option objects out of them
455
-            foreach ($sizes as $image_size) {
456
-                $image_size = trim($image_size);
457
-                // no big images plz
458
-                if (! in_array($image_size, ['large', 'post-thumbnail'])) {
459
-                    $image_sizes[] =
460
-                        EE_Question_Option::new_instance(['QSO_value' => $image_size, 'QSO_desc' => $image_size]);
461
-                }
462
-            }
463
-            $image_sizes[] =
464
-                EE_Question_Option::new_instance(
465
-                    ['QSO_value' => 'none', 'QSO_desc' => esc_html__('don\'t show images', 'event_espresso')]
466
-                );
467
-        }
468
-        echo wp_kses(
469
-            EEH_Form_Fields::select(
470
-                esc_html__('Image Size:', 'event_espresso'),
471
-                $instance['image_size'],
472
-                $image_sizes,
473
-                $this->fieldName('image_size'),
474
-                $this->fieldID('image_size')
475
-            ),
476
-            AllowedTags::getWithFormTags()
477
-        );
478
-    }
479
-
480
-
481
-    /**
482
-     * @param array $instance
483
-     * @since   4.10.14.p
484
-     */
485
-    private function parseWidgetSettings(array $instance)
486
-    {
487
-        $this->title = isset($instance['title']) && ! empty($instance['title']) ? $instance['title'] : '';
488
-        $this->events_category     = isset($instance['category_name']) && ! empty($instance['category_name'])
489
-            ? $instance['category_name']
490
-            : false;
491
-        $this->show_expired = isset($instance['show_expired'])
492
-            ? filter_var($instance['show_expired'], FILTER_VALIDATE_BOOLEAN)
493
-            : 0;
494
-        $this->image_size   = isset($instance['image_size']) && ! empty($instance['image_size'])
495
-            ? $instance['image_size']
496
-            : 'medium';
497
-        $this->show_desc    = ! isset($instance['show_desc'])
498
-                              || filter_var($instance['show_desc'], FILTER_VALIDATE_BOOLEAN);
499
-        $this->show_dates   = ! isset($instance['show_dates'])
500
-                              || filter_var($instance['show_dates'], FILTER_VALIDATE_BOOLEAN);
501
-        $this->date_limit   = isset($instance['date_limit']) && ! empty($instance['date_limit'])
502
-            ? $instance['date_limit']
503
-            : null;
504
-        $this->date_range   = isset($instance['date_range']) && ! empty($instance['date_range'])
505
-            ? $instance['date_range']
506
-            : false;
507
-        $this->limit        = isset($instance['limit']) ? absint($instance['limit']) : 10;
508
-        $this->order        = isset($instance['sort']) && $instance['sort'] === 'DESC'
509
-            ? 'DESC'
510
-            : 'ASC';
511
-    }
512
-
513
-
514
-    /**
515
-     * @return mixed|void
516
-     * @since   4.10.14.p
517
-     */
518
-    private function widgetTitle()
519
-    {
520
-        // add function to make the title a link
521
-        add_filter('widget_title', [$this, 'make_the_title_a_link'], 15);
522
-        // filter the title
523
-        $title = apply_filters('widget_title', $this->title);
524
-        // remove the function from the filter, so it does not affect other widgets
525
-        remove_filter('widget_title', [$this, 'make_the_title_a_link'], 15);
526
-        return $title;
527
-    }
528
-
529
-
530
-    /**
531
-     * @param WP_Post $post
532
-     * @return string
533
-     * @throws EE_Error
534
-     * @throws ReflectionException
535
-     * @since   4.10.14.p
536
-     */
537
-    private function widgetContent(WP_Post $post)
538
-    {
539
-        // run the query
540
-        $events = $this->getUpcomingEvents();
541
-        if (empty($events)) {
542
-            return '';
543
-        }
544
-        $list_items = '';
545
-        foreach ($events as $event) {
546
-            if ($event instanceof EE_Event && (! is_single() || $post->ID != $event->ID())) {
547
-                $event_url = $this->eventUrl($event);
548
-                $list_items .= '
284
+	}
285
+
286
+
287
+	/**
288
+	 * Sanitize widget form values as they are saved.
289
+	 *
290
+	 * @param array $new_instance Values just sent to be saved.
291
+	 * @param array $old_instance Previously saved values from database.
292
+	 *
293
+	 * @return array Updated safe values to be saved.
294
+	 * @see WP_Widget::update()
295
+	 *
296
+	 */
297
+	public function update($new_instance, $old_instance)
298
+	{
299
+		/** @var EE_Capabilities $capabilities */
300
+		$capabilities = LoaderFactory::getLoader()->getShared(EE_Capabilities::class);
301
+		if (! $capabilities->current_user_can('manage_options', 'update-espresso-widget')) {
302
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
303
+		}
304
+		$instance                    = $old_instance;
305
+		$instance['title']           = ! empty($new_instance['title']) ? strip_tags((string) $new_instance['title']) : '';
306
+		$instance['category_name']   = $new_instance['category_name'];
307
+		$instance['show_expired']    = $new_instance['show_expired'];
308
+		$instance['limit']           = $new_instance['limit'];
309
+		$instance['sort']            = $new_instance['sort'];
310
+		$instance['image_size']      = $new_instance['image_size'];
311
+		$instance['show_desc']       = $new_instance['show_desc'];
312
+		$instance['show_dates']      = $new_instance['show_dates'];
313
+		$instance['show_everywhere'] = $new_instance['show_everywhere'];
314
+		$instance['date_limit']      = $new_instance['date_limit'];
315
+		$instance['date_range']      = $new_instance['date_range'];
316
+		return $instance;
317
+	}
318
+
319
+
320
+	/**
321
+	 * Front-end display of widget.
322
+	 *
323
+	 * @param array $args     Widget arguments.
324
+	 * @param array $instance Saved values from database.
325
+	 * @throws EE_Error
326
+	 * @throws ReflectionException
327
+	 * @see WP_Widget::widget()
328
+	 *
329
+	 */
330
+	public function widget($args, $instance)
331
+	{
332
+
333
+		global $post;
334
+		// make sure there is some kinda post object
335
+		if ($post instanceof WP_Post) {
336
+			$before_widget = '';
337
+			$before_title  = '';
338
+			$after_title   = '';
339
+			$after_widget  = '';
340
+			// but NOT an events archives page, cuz that would be like two event lists on the same page
341
+			$show_everywhere = ! isset($instance['show_everywhere']) || absint($instance['show_everywhere']);
342
+			if ($show_everywhere || ! ($post->post_type == EspressoPostType::EVENTS && is_archive())) {
343
+				// let's use some of the event helper functions'
344
+				// make separate vars out of attributes
345
+				extract($args);
346
+
347
+				// grab widget settings
348
+				$this->parseWidgetSettings($instance);
349
+				$title = $this->widgetTitle();
350
+
351
+				// Before widget (defined by themes).
352
+				echo wp_kses($before_widget, AllowedTags::getAllowedTags());
353
+				// Display the widget title if one was input (before and after defined by themes).
354
+				if (! empty($title)) {
355
+					echo wp_kses($before_title . $title . $after_title, AllowedTags::getAllowedTags());
356
+				}
357
+				echo wp_kses($this->widgetContent($post), AllowedTags::getWithFormTags());
358
+				// After widget (defined by themes).
359
+				echo wp_kses($after_widget, AllowedTags::getAllowedTags());
360
+			}
361
+		}
362
+	}
363
+
364
+
365
+	/**
366
+	 * make_the_title_a_link
367
+	 * callback for widget_title filter
368
+	 *
369
+	 * @param $title
370
+	 * @return string
371
+	 */
372
+	public function make_the_title_a_link($title)
373
+	{
374
+		return '<a href="' . EEH_Event_View::event_archive_url() . '">' . $title . '</a>';
375
+	}
376
+
377
+
378
+	/**
379
+	 * @param string $field_name
380
+	 * @return string
381
+	 * @since   4.10.14.p
382
+	 */
383
+	public function fieldID($field_name)
384
+	{
385
+		return parent::get_field_id($field_name);
386
+	}
387
+
388
+
389
+	/**
390
+	 * @param string $field_name
391
+	 * @return string
392
+	 * @since   4.10.14.p
393
+	 */
394
+	public function fieldName($field_name)
395
+	{
396
+		return parent::get_field_name($field_name);
397
+	}
398
+
399
+
400
+	/**
401
+	 * @param array $instance
402
+	 * @throws EE_Error
403
+	 * @throws ReflectionException
404
+	 * @since   4.10.14.p
405
+	 */
406
+	private function eventCategoriesSelector(array $instance)
407
+	{
408
+		$event_categories = [];
409
+		$categories       = EEM_Term::instance()->get_all_ee_categories(true);
410
+		if ($categories) {
411
+			foreach ($categories as $category) {
412
+				if ($category instanceof EE_Term) {
413
+					$event_categories[] =
414
+						EE_Question_Option::new_instance(
415
+							[
416
+								'QSO_value' => $category->get('slug'),
417
+								'QSO_desc'  => $category->get('name'),
418
+							]
419
+						);
420
+				}
421
+			}
422
+		}
423
+		array_unshift(
424
+			$event_categories,
425
+			EE_Question_Option::new_instance(
426
+				[
427
+					'QSO_value' => '',
428
+					'QSO_desc'  => esc_html__(' - display all - ', 'event_espresso'),
429
+				]
430
+			)
431
+		);
432
+		echo wp_kses(
433
+			EEH_Form_Fields::select(
434
+				esc_html__('Event Category:', 'event_espresso'),
435
+				$instance['category_name'],
436
+				$event_categories,
437
+				$this->fieldName('category_name'),
438
+				$this->fieldID('category_name')
439
+			),
440
+			AllowedTags::getWithFormTags()
441
+		);
442
+	}
443
+
444
+
445
+	/**
446
+	 * @param array $instance
447
+	 * @since   4.10.14.p
448
+	 */
449
+	private function imageSizeSelector(array $instance)
450
+	{
451
+		$image_sizes = [];
452
+		$sizes       = get_intermediate_image_sizes();
453
+		if ($sizes) {
454
+			// loop thru images and create option objects out of them
455
+			foreach ($sizes as $image_size) {
456
+				$image_size = trim($image_size);
457
+				// no big images plz
458
+				if (! in_array($image_size, ['large', 'post-thumbnail'])) {
459
+					$image_sizes[] =
460
+						EE_Question_Option::new_instance(['QSO_value' => $image_size, 'QSO_desc' => $image_size]);
461
+				}
462
+			}
463
+			$image_sizes[] =
464
+				EE_Question_Option::new_instance(
465
+					['QSO_value' => 'none', 'QSO_desc' => esc_html__('don\'t show images', 'event_espresso')]
466
+				);
467
+		}
468
+		echo wp_kses(
469
+			EEH_Form_Fields::select(
470
+				esc_html__('Image Size:', 'event_espresso'),
471
+				$instance['image_size'],
472
+				$image_sizes,
473
+				$this->fieldName('image_size'),
474
+				$this->fieldID('image_size')
475
+			),
476
+			AllowedTags::getWithFormTags()
477
+		);
478
+	}
479
+
480
+
481
+	/**
482
+	 * @param array $instance
483
+	 * @since   4.10.14.p
484
+	 */
485
+	private function parseWidgetSettings(array $instance)
486
+	{
487
+		$this->title = isset($instance['title']) && ! empty($instance['title']) ? $instance['title'] : '';
488
+		$this->events_category     = isset($instance['category_name']) && ! empty($instance['category_name'])
489
+			? $instance['category_name']
490
+			: false;
491
+		$this->show_expired = isset($instance['show_expired'])
492
+			? filter_var($instance['show_expired'], FILTER_VALIDATE_BOOLEAN)
493
+			: 0;
494
+		$this->image_size   = isset($instance['image_size']) && ! empty($instance['image_size'])
495
+			? $instance['image_size']
496
+			: 'medium';
497
+		$this->show_desc    = ! isset($instance['show_desc'])
498
+							  || filter_var($instance['show_desc'], FILTER_VALIDATE_BOOLEAN);
499
+		$this->show_dates   = ! isset($instance['show_dates'])
500
+							  || filter_var($instance['show_dates'], FILTER_VALIDATE_BOOLEAN);
501
+		$this->date_limit   = isset($instance['date_limit']) && ! empty($instance['date_limit'])
502
+			? $instance['date_limit']
503
+			: null;
504
+		$this->date_range   = isset($instance['date_range']) && ! empty($instance['date_range'])
505
+			? $instance['date_range']
506
+			: false;
507
+		$this->limit        = isset($instance['limit']) ? absint($instance['limit']) : 10;
508
+		$this->order        = isset($instance['sort']) && $instance['sort'] === 'DESC'
509
+			? 'DESC'
510
+			: 'ASC';
511
+	}
512
+
513
+
514
+	/**
515
+	 * @return mixed|void
516
+	 * @since   4.10.14.p
517
+	 */
518
+	private function widgetTitle()
519
+	{
520
+		// add function to make the title a link
521
+		add_filter('widget_title', [$this, 'make_the_title_a_link'], 15);
522
+		// filter the title
523
+		$title = apply_filters('widget_title', $this->title);
524
+		// remove the function from the filter, so it does not affect other widgets
525
+		remove_filter('widget_title', [$this, 'make_the_title_a_link'], 15);
526
+		return $title;
527
+	}
528
+
529
+
530
+	/**
531
+	 * @param WP_Post $post
532
+	 * @return string
533
+	 * @throws EE_Error
534
+	 * @throws ReflectionException
535
+	 * @since   4.10.14.p
536
+	 */
537
+	private function widgetContent(WP_Post $post)
538
+	{
539
+		// run the query
540
+		$events = $this->getUpcomingEvents();
541
+		if (empty($events)) {
542
+			return '';
543
+		}
544
+		$list_items = '';
545
+		foreach ($events as $event) {
546
+			if ($event instanceof EE_Event && (! is_single() || $post->ID != $event->ID())) {
547
+				$event_url = $this->eventUrl($event);
548
+				$list_items .= '
549 549
                 <li id="ee-upcoming-events-widget-li-' . absint($event->ID()) . '"
550 550
                     class="ee-upcoming-events-widget-li"
551 551
                 >
@@ -556,194 +556,194 @@  discard block
 block discarded – undo
556 556
                     </h5>
557 557
                     ' . $this->eventWidgetContent($event, $event_url) . '
558 558
                 </li>';
559
-            }
560
-        }
561
-        return '
559
+			}
560
+		}
561
+		return '
562 562
             <ul class="ee-upcoming-events-widget-ul">
563 563
                 ' . $list_items . '
564 564
             </ul>';
565
-    }
566
-
567
-
568
-    /**
569
-     * @param EE_Event $event
570
-     * @return string|null
571
-     * @throws EE_Error
572
-     * @since   4.10.14.p
573
-     */
574
-    private function eventUrl(EE_Event $event)
575
-    {
576
-        return esc_url_raw(
577
-            apply_filters(
578
-                'FHEE_EEW_Upcoming_Events__widget__event_url',
579
-                $event->get_permalink(),
580
-                $event
581
-            )
582
-        );
583
-    }
584
-
585
-
586
-    /**
587
-     * @return EE_Base_Class[]
588
-     * @throws EE_Error
589
-     */
590
-    private function getUpcomingEvents()
591
-    {
592
-        return EEM_Event::instance()->get_all(
593
-            [
594
-                $this->queryWhereParams(),
595
-                'limit'    => '0,' . $this->limit,
596
-                'order_by' => 'Datetime.DTT_EVT_start',
597
-                'order'    => $this->order,
598
-                'group_by' => 'EVT_ID',
599
-            ]
600
-        );
601
-    }
602
-
603
-
604
-    /**
605
-     * @return mixed|void
606
-     * @throws EE_Error
607
-     * @since   4.10.14.p
608
-     */
609
-    private function queryWhereParams()
610
-    {
611
-        // start to build our where clause
612
-        $where = [
613
-            'status' => ['IN', ['publish', 'sold_out']],
614
-        ];
615
-        // add category
616
-        if ($this->events_category) {
617
-            $where['Term_Taxonomy.taxonomy']  = 'espresso_event_categories';
618
-            $where['Term_Taxonomy.Term.slug'] = $this->events_category;
619
-        }
620
-        // if NOT expired then we want events that start today or in the future
621
-        // if NOT show expired then we want events that start today or in the future
622
-        if ($this->show_expired == 0) {
623
-            $where['Datetime.DTT_EVT_end'] = [
624
-                '>=',
625
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
626
-            ];
627
-        }
628
-        // if show ONLY expired we want events that ended prior to today
629
-        if ($this->show_expired == 2) {
630
-            $where['Datetime.DTT_EVT_end'] = [
631
-                '<=',
632
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
633
-            ];
634
-        }
635
-        // allow $where to be filtered
636
-        return apply_filters('FHEE__EEW_Upcoming_Events__widget__where', $where, $this->events_category, $this->show_expired);
637
-    }
638
-
639
-
640
-    /**
641
-     * @param EE_Event $event
642
-     * @return string
643
-     * @throws EE_Error
644
-     * @throws ReflectionException
645
-     * @since   4.10.14.p
646
-     */
647
-    private function linkClass(EE_Event $event)
648
-    {
649
-        // how big is the event name ?
650
-        $name_length = strlen($event->name());
651
-        switch ($name_length) {
652
-            case $name_length > 70:
653
-                return ' three-line';
654
-            case $name_length > 35:
655
-                return ' two-line';
656
-        }
657
-        return ' one-line';
658
-    }
659
-
660
-
661
-    /**
662
-     * @param EE_Event $event
663
-     * @param string   $event_url
664
-     * @return mixed|string|void
665
-     * @throws EE_Error
666
-     * @throws ReflectionException
667
-     * @since   4.10.14.p
668
-     */
669
-    private function eventWidgetContent(EE_Event $event, $event_url = '')
670
-    {
671
-        if (post_password_required($event->ID())) {
672
-            return apply_filters(
673
-                'FHEE_EEW_Upcoming_Events__widget__password_form',
674
-                get_the_password_form($event->ID()),
675
-                $event
676
-            );
677
-        }
678
-
679
-        $content = '';
680
-        if (has_post_thumbnail($event->ID()) && $this->image_size != 'none') {
681
-            $content .= '
565
+	}
566
+
567
+
568
+	/**
569
+	 * @param EE_Event $event
570
+	 * @return string|null
571
+	 * @throws EE_Error
572
+	 * @since   4.10.14.p
573
+	 */
574
+	private function eventUrl(EE_Event $event)
575
+	{
576
+		return esc_url_raw(
577
+			apply_filters(
578
+				'FHEE_EEW_Upcoming_Events__widget__event_url',
579
+				$event->get_permalink(),
580
+				$event
581
+			)
582
+		);
583
+	}
584
+
585
+
586
+	/**
587
+	 * @return EE_Base_Class[]
588
+	 * @throws EE_Error
589
+	 */
590
+	private function getUpcomingEvents()
591
+	{
592
+		return EEM_Event::instance()->get_all(
593
+			[
594
+				$this->queryWhereParams(),
595
+				'limit'    => '0,' . $this->limit,
596
+				'order_by' => 'Datetime.DTT_EVT_start',
597
+				'order'    => $this->order,
598
+				'group_by' => 'EVT_ID',
599
+			]
600
+		);
601
+	}
602
+
603
+
604
+	/**
605
+	 * @return mixed|void
606
+	 * @throws EE_Error
607
+	 * @since   4.10.14.p
608
+	 */
609
+	private function queryWhereParams()
610
+	{
611
+		// start to build our where clause
612
+		$where = [
613
+			'status' => ['IN', ['publish', 'sold_out']],
614
+		];
615
+		// add category
616
+		if ($this->events_category) {
617
+			$where['Term_Taxonomy.taxonomy']  = 'espresso_event_categories';
618
+			$where['Term_Taxonomy.Term.slug'] = $this->events_category;
619
+		}
620
+		// if NOT expired then we want events that start today or in the future
621
+		// if NOT show expired then we want events that start today or in the future
622
+		if ($this->show_expired == 0) {
623
+			$where['Datetime.DTT_EVT_end'] = [
624
+				'>=',
625
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
626
+			];
627
+		}
628
+		// if show ONLY expired we want events that ended prior to today
629
+		if ($this->show_expired == 2) {
630
+			$where['Datetime.DTT_EVT_end'] = [
631
+				'<=',
632
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
633
+			];
634
+		}
635
+		// allow $where to be filtered
636
+		return apply_filters('FHEE__EEW_Upcoming_Events__widget__where', $where, $this->events_category, $this->show_expired);
637
+	}
638
+
639
+
640
+	/**
641
+	 * @param EE_Event $event
642
+	 * @return string
643
+	 * @throws EE_Error
644
+	 * @throws ReflectionException
645
+	 * @since   4.10.14.p
646
+	 */
647
+	private function linkClass(EE_Event $event)
648
+	{
649
+		// how big is the event name ?
650
+		$name_length = strlen($event->name());
651
+		switch ($name_length) {
652
+			case $name_length > 70:
653
+				return ' three-line';
654
+			case $name_length > 35:
655
+				return ' two-line';
656
+		}
657
+		return ' one-line';
658
+	}
659
+
660
+
661
+	/**
662
+	 * @param EE_Event $event
663
+	 * @param string   $event_url
664
+	 * @return mixed|string|void
665
+	 * @throws EE_Error
666
+	 * @throws ReflectionException
667
+	 * @since   4.10.14.p
668
+	 */
669
+	private function eventWidgetContent(EE_Event $event, $event_url = '')
670
+	{
671
+		if (post_password_required($event->ID())) {
672
+			return apply_filters(
673
+				'FHEE_EEW_Upcoming_Events__widget__password_form',
674
+				get_the_password_form($event->ID()),
675
+				$event
676
+			);
677
+		}
678
+
679
+		$content = '';
680
+		if (has_post_thumbnail($event->ID()) && $this->image_size != 'none') {
681
+			$content .= '
682 682
                 <div class="ee-upcoming-events-widget-img-dv">
683 683
                     <a class="ee-upcoming-events-widget-img" href="' . $event_url . '">
684 684
                         ' . get_the_post_thumbnail($event->ID(), $this->image_size) . '
685 685
                     </a>
686 686
                 </div>';
687
-        }
688
-
689
-        if ($this->show_dates) {
690
-            $content .= $this->eventDates($event);
691
-        }
692
-
693
-        if ($this->show_desc) {
694
-            $allowedtags = AllowedTags::getAllowedTags();
695
-            $desc    = $event->short_description(25);
696
-            $content .= $desc ? '<p style="margin-top: .5em">' . wp_kses($desc, $allowedtags) . '</p>' : '';
697
-        }
698
-
699
-        return $content;
700
-    }
701
-
702
-
703
-    /**
704
-     * @param EE_Event $event
705
-     * @return string
706
-     * @throws EE_Error
707
-     * @throws ReflectionException
708
-     * @since   4.10.14.p
709
-     */
710
-    private function eventDates(EE_Event $event)
711
-    {
712
-        $date_format        = apply_filters(
713
-            'FHEE__espresso_event_date_range__date_format',
714
-            get_option('date_format')
715
-        );
716
-        $time_format        = apply_filters(
717
-            'FHEE__espresso_event_date_range__time_format',
718
-            get_option('time_format')
719
-        );
720
-        $single_date_format = apply_filters(
721
-            'FHEE__espresso_event_date_range__single_date_format',
722
-            get_option('date_format')
723
-        );
724
-        $single_time_format = apply_filters(
725
-            'FHEE__espresso_event_date_range__single_time_format',
726
-            get_option('time_format')
727
-        );
728
-        if ($this->date_range == true) {
729
-            return espresso_event_date_range(
730
-                $date_format,
731
-                $time_format,
732
-                $single_date_format,
733
-                $single_time_format,
734
-                $event->ID(),
735
-                false
736
-            );
737
-        }
738
-        return espresso_list_of_event_dates(
739
-            $event->ID(),
740
-            $date_format,
741
-            $time_format,
742
-            false,
743
-            null,
744
-            true,
745
-            true,
746
-            $this->date_limit
747
-        );
748
-    }
687
+		}
688
+
689
+		if ($this->show_dates) {
690
+			$content .= $this->eventDates($event);
691
+		}
692
+
693
+		if ($this->show_desc) {
694
+			$allowedtags = AllowedTags::getAllowedTags();
695
+			$desc    = $event->short_description(25);
696
+			$content .= $desc ? '<p style="margin-top: .5em">' . wp_kses($desc, $allowedtags) . '</p>' : '';
697
+		}
698
+
699
+		return $content;
700
+	}
701
+
702
+
703
+	/**
704
+	 * @param EE_Event $event
705
+	 * @return string
706
+	 * @throws EE_Error
707
+	 * @throws ReflectionException
708
+	 * @since   4.10.14.p
709
+	 */
710
+	private function eventDates(EE_Event $event)
711
+	{
712
+		$date_format        = apply_filters(
713
+			'FHEE__espresso_event_date_range__date_format',
714
+			get_option('date_format')
715
+		);
716
+		$time_format        = apply_filters(
717
+			'FHEE__espresso_event_date_range__time_format',
718
+			get_option('time_format')
719
+		);
720
+		$single_date_format = apply_filters(
721
+			'FHEE__espresso_event_date_range__single_date_format',
722
+			get_option('date_format')
723
+		);
724
+		$single_time_format = apply_filters(
725
+			'FHEE__espresso_event_date_range__single_time_format',
726
+			get_option('time_format')
727
+		);
728
+		if ($this->date_range == true) {
729
+			return espresso_event_date_range(
730
+				$date_format,
731
+				$time_format,
732
+				$single_date_format,
733
+				$single_time_format,
734
+				$event->ID(),
735
+				false
736
+			);
737
+		}
738
+		return espresso_list_of_event_dates(
739
+			$event->ID(),
740
+			$date_format,
741
+			$time_format,
742
+			false,
743
+			null,
744
+			true,
745
+			true,
746
+			$this->date_limit
747
+		);
748
+	}
749 749
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
             EE_Question_Option::new_instance(['QSO_value' => false, 'QSO_desc' => esc_html__('No', 'event_espresso')]),
112 112
             EE_Question_Option::new_instance(['QSO_value' => true, 'QSO_desc' => esc_html__('Yes', 'event_espresso')]),
113 113
         ];
114
-        $sort_values   = [
114
+        $sort_values = [
115 115
             EE_Question_Option::new_instance(['QSO_value' => 'ASC', 'QSO_desc' => esc_html__('ASC', 'event_espresso')]),
116 116
             EE_Question_Option::new_instance(['QSO_value' => 'DESC', 'QSO_desc' => esc_html__('DESC', 'event_espresso')]),
117 117
         ];
@@ -298,7 +298,7 @@  discard block
 block discarded – undo
298 298
     {
299 299
         /** @var EE_Capabilities $capabilities */
300 300
         $capabilities = LoaderFactory::getLoader()->getShared(EE_Capabilities::class);
301
-        if (! $capabilities->current_user_can('manage_options', 'update-espresso-widget')) {
301
+        if ( ! $capabilities->current_user_can('manage_options', 'update-espresso-widget')) {
302 302
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
303 303
         }
304 304
         $instance                    = $old_instance;
@@ -351,8 +351,8 @@  discard block
 block discarded – undo
351 351
                 // Before widget (defined by themes).
352 352
                 echo wp_kses($before_widget, AllowedTags::getAllowedTags());
353 353
                 // Display the widget title if one was input (before and after defined by themes).
354
-                if (! empty($title)) {
355
-                    echo wp_kses($before_title . $title . $after_title, AllowedTags::getAllowedTags());
354
+                if ( ! empty($title)) {
355
+                    echo wp_kses($before_title.$title.$after_title, AllowedTags::getAllowedTags());
356 356
                 }
357 357
                 echo wp_kses($this->widgetContent($post), AllowedTags::getWithFormTags());
358 358
                 // After widget (defined by themes).
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
      */
372 372
     public function make_the_title_a_link($title)
373 373
     {
374
-        return '<a href="' . EEH_Event_View::event_archive_url() . '">' . $title . '</a>';
374
+        return '<a href="'.EEH_Event_View::event_archive_url().'">'.$title.'</a>';
375 375
     }
376 376
 
377 377
 
@@ -455,7 +455,7 @@  discard block
 block discarded – undo
455 455
             foreach ($sizes as $image_size) {
456 456
                 $image_size = trim($image_size);
457 457
                 // no big images plz
458
-                if (! in_array($image_size, ['large', 'post-thumbnail'])) {
458
+                if ( ! in_array($image_size, ['large', 'post-thumbnail'])) {
459 459
                     $image_sizes[] =
460 460
                         EE_Question_Option::new_instance(['QSO_value' => $image_size, 'QSO_desc' => $image_size]);
461 461
                 }
@@ -485,7 +485,7 @@  discard block
 block discarded – undo
485 485
     private function parseWidgetSettings(array $instance)
486 486
     {
487 487
         $this->title = isset($instance['title']) && ! empty($instance['title']) ? $instance['title'] : '';
488
-        $this->events_category     = isset($instance['category_name']) && ! empty($instance['category_name'])
488
+        $this->events_category = isset($instance['category_name']) && ! empty($instance['category_name'])
489 489
             ? $instance['category_name']
490 490
             : false;
491 491
         $this->show_expired = isset($instance['show_expired'])
@@ -543,24 +543,24 @@  discard block
 block discarded – undo
543 543
         }
544 544
         $list_items = '';
545 545
         foreach ($events as $event) {
546
-            if ($event instanceof EE_Event && (! is_single() || $post->ID != $event->ID())) {
546
+            if ($event instanceof EE_Event && ( ! is_single() || $post->ID != $event->ID())) {
547 547
                 $event_url = $this->eventUrl($event);
548 548
                 $list_items .= '
549
-                <li id="ee-upcoming-events-widget-li-' . absint($event->ID()) . '"
549
+                <li id="ee-upcoming-events-widget-li-' . absint($event->ID()).'"
550 550
                     class="ee-upcoming-events-widget-li"
551 551
                 >
552 552
                     <h5 class="ee-upcoming-events-widget-title-h5">
553
-                        <a class="ee-widget-event-name-a' . $this->linkClass($event) . '" href="' . $event_url . '">
554
-                            ' . esc_html($event->name()) . '
553
+                        <a class="ee-widget-event-name-a' . $this->linkClass($event).'" href="'.$event_url.'">
554
+                            ' . esc_html($event->name()).'
555 555
                         </a>
556 556
                     </h5>
557
-                    ' . $this->eventWidgetContent($event, $event_url) . '
557
+                    ' . $this->eventWidgetContent($event, $event_url).'
558 558
                 </li>';
559 559
             }
560 560
         }
561 561
         return '
562 562
             <ul class="ee-upcoming-events-widget-ul">
563
-                ' . $list_items . '
563
+                ' . $list_items.'
564 564
             </ul>';
565 565
     }
566 566
 
@@ -592,7 +592,7 @@  discard block
 block discarded – undo
592 592
         return EEM_Event::instance()->get_all(
593 593
             [
594 594
                 $this->queryWhereParams(),
595
-                'limit'    => '0,' . $this->limit,
595
+                'limit'    => '0,'.$this->limit,
596 596
                 'order_by' => 'Datetime.DTT_EVT_start',
597 597
                 'order'    => $this->order,
598 598
                 'group_by' => 'EVT_ID',
@@ -680,8 +680,8 @@  discard block
 block discarded – undo
680 680
         if (has_post_thumbnail($event->ID()) && $this->image_size != 'none') {
681 681
             $content .= '
682 682
                 <div class="ee-upcoming-events-widget-img-dv">
683
-                    <a class="ee-upcoming-events-widget-img" href="' . $event_url . '">
684
-                        ' . get_the_post_thumbnail($event->ID(), $this->image_size) . '
683
+                    <a class="ee-upcoming-events-widget-img" href="' . $event_url.'">
684
+                        ' . get_the_post_thumbnail($event->ID(), $this->image_size).'
685 685
                     </a>
686 686
                 </div>';
687 687
         }
@@ -692,8 +692,8 @@  discard block
 block discarded – undo
692 692
 
693 693
         if ($this->show_desc) {
694 694
             $allowedtags = AllowedTags::getAllowedTags();
695
-            $desc    = $event->short_description(25);
696
-            $content .= $desc ? '<p style="margin-top: .5em">' . wp_kses($desc, $allowedtags) . '</p>' : '';
695
+            $desc = $event->short_description(25);
696
+            $content .= $desc ? '<p style="margin-top: .5em">'.wp_kses($desc, $allowedtags).'</p>' : '';
697 697
         }
698 698
 
699 699
         return $content;
@@ -709,11 +709,11 @@  discard block
 block discarded – undo
709 709
      */
710 710
     private function eventDates(EE_Event $event)
711 711
     {
712
-        $date_format        = apply_filters(
712
+        $date_format = apply_filters(
713 713
             'FHEE__espresso_event_date_range__date_format',
714 714
             get_option('date_format')
715 715
         );
716
-        $time_format        = apply_filters(
716
+        $time_format = apply_filters(
717 717
             'FHEE__espresso_event_date_range__time_format',
718 718
             get_option('time_format')
719 719
         );
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +107 added lines, -107 removed lines patch added patch discarded remove patch
@@ -37,138 +37,138 @@
 block discarded – undo
37 37
  * @since           4.0
38 38
  */
39 39
 if (function_exists('espresso_version')) {
40
-    if (! function_exists('espresso_duplicate_plugin_error')) {
41
-        /**
42
-         *    espresso_duplicate_plugin_error
43
-         *    displays if more than one version of EE is activated at the same time.
44
-         */
45
-        function espresso_duplicate_plugin_error()
46
-        {
47
-            ?>
40
+	if (! function_exists('espresso_duplicate_plugin_error')) {
41
+		/**
42
+		 *    espresso_duplicate_plugin_error
43
+		 *    displays if more than one version of EE is activated at the same time.
44
+		 */
45
+		function espresso_duplicate_plugin_error()
46
+		{
47
+			?>
48 48
 <div class="error">
49 49
 	<p>
50 50
 		<?php
51
-                    echo esc_html__(
52
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
-                        'event_espresso'
54
-                    ); ?>
51
+					echo esc_html__(
52
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
+						'event_espresso'
54
+					); ?>
55 55
 	</p>
56 56
 </div>
57 57
 <?php
58
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
59
-        }
60
-    }
61
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
58
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
59
+		}
60
+	}
61
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62 62
 } else {
63
-    define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
-        /**
66
-         * espresso_minimum_php_version_error
67
-         *
68
-         * @return void
69
-         */
70
-        function espresso_minimum_php_version_error()
71
-        {
72
-            ?>
63
+	define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
+		/**
66
+		 * espresso_minimum_php_version_error
67
+		 *
68
+		 * @return void
69
+		 */
70
+		function espresso_minimum_php_version_error()
71
+		{
72
+			?>
73 73
 <div class="error">
74 74
 	<p>
75 75
 		<?php
76
-                    printf(
77
-                        esc_html__(
78
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
-                            'event_espresso'
80
-                        ),
81
-                        EE_MIN_PHP_VER_REQUIRED,
82
-                        PHP_VERSION,
83
-                        '<br/>',
84
-                        '<a href="https://www.php.net/downloads.php">https://php.net/downloads.php</a>'
85
-                    );
86
-                    ?>
76
+					printf(
77
+						esc_html__(
78
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
+							'event_espresso'
80
+						),
81
+						EE_MIN_PHP_VER_REQUIRED,
82
+						PHP_VERSION,
83
+						'<br/>',
84
+						'<a href="https://www.php.net/downloads.php">https://php.net/downloads.php</a>'
85
+					);
86
+					?>
87 87
 	</p>
88 88
 </div>
89 89
 <?php
90
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
91
-        }
90
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
91
+		}
92 92
 
93
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
-    } else {
95
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
93
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
+	} else {
95
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
96 96
 
97
-        require_once __DIR__ . '/vendor/autoload.php';
97
+		require_once __DIR__ . '/vendor/autoload.php';
98 98
 
99
-        /**
100
-         * espresso_version
101
-         * Returns the plugin version
102
-         *
103
-         * @return string
104
-         */
105
-        function espresso_version(): string
106
-        {
107
-            return apply_filters('FHEE__espresso__espresso_version', '5.0.25.rc.000');
108
-        }
99
+		/**
100
+		 * espresso_version
101
+		 * Returns the plugin version
102
+		 *
103
+		 * @return string
104
+		 */
105
+		function espresso_version(): string
106
+		{
107
+			return apply_filters('FHEE__espresso__espresso_version', '5.0.25.rc.000');
108
+		}
109 109
 
110
-        /**
111
-         * espresso_plugin_activation
112
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
113
-         */
114
-        function espresso_plugin_activation()
115
-        {
116
-            update_option('ee_espresso_activation', true);
117
-            update_option('event-espresso-core_allow_tracking', 'no');
118
-            update_option('event-espresso-core_tracking_notice', 'hide');
119
-            // Run WP GraphQL activation callback
120
-            espressoLoadWpGraphQL();
121
-            graphql_activation_callback();
122
-        }
110
+		/**
111
+		 * espresso_plugin_activation
112
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
113
+		 */
114
+		function espresso_plugin_activation()
115
+		{
116
+			update_option('ee_espresso_activation', true);
117
+			update_option('event-espresso-core_allow_tracking', 'no');
118
+			update_option('event-espresso-core_tracking_notice', 'hide');
119
+			// Run WP GraphQL activation callback
120
+			espressoLoadWpGraphQL();
121
+			graphql_activation_callback();
122
+		}
123 123
 
124
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
124
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
125 125
 
126
-        /**
127
-         * espresso_plugin_deactivation
128
-         */
129
-        function espresso_plugin_deactivation()
130
-        {
131
-            // Run WP GraphQL deactivation callback
132
-            espressoLoadWpGraphQL();
133
-            graphql_deactivation_callback();
134
-            delete_option('event-espresso-core_allow_tracking');
135
-            delete_option('event-espresso-core_tracking_notice');
136
-        }
137
-        register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
126
+		/**
127
+		 * espresso_plugin_deactivation
128
+		 */
129
+		function espresso_plugin_deactivation()
130
+		{
131
+			// Run WP GraphQL deactivation callback
132
+			espressoLoadWpGraphQL();
133
+			graphql_deactivation_callback();
134
+			delete_option('event-espresso-core_allow_tracking');
135
+			delete_option('event-espresso-core_tracking_notice');
136
+		}
137
+		register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
138 138
 
139
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
140
-        bootstrap_espresso();
141
-    }
139
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
140
+		bootstrap_espresso();
141
+	}
142 142
 }
143 143
 
144 144
 if (! function_exists('espresso_deactivate_plugin')) {
145
-    /**
146
-     *    deactivate_plugin
147
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
148
-     *
149
-     * @access public
150
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
151
-     * @return    void
152
-     */
153
-    function espresso_deactivate_plugin(string $plugin_basename = '')
154
-    {
155
-        if (! function_exists('deactivate_plugins')) {
156
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
157
-        }
158
-        unset($_GET['activate'], $_REQUEST['activate']);
159
-        deactivate_plugins($plugin_basename);
160
-    }
145
+	/**
146
+	 *    deactivate_plugin
147
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
148
+	 *
149
+	 * @access public
150
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
151
+	 * @return    void
152
+	 */
153
+	function espresso_deactivate_plugin(string $plugin_basename = '')
154
+	{
155
+		if (! function_exists('deactivate_plugins')) {
156
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
157
+		}
158
+		unset($_GET['activate'], $_REQUEST['activate']);
159
+		deactivate_plugins($plugin_basename);
160
+	}
161 161
 }
162 162
 
163 163
 
164 164
 if (! function_exists('espressoLoadWpGraphQL')) {
165
-    function espressoLoadWpGraphQL()
166
-    {
167
-        if (
168
-            ! class_exists('WPGraphQL')
169
-            && is_readable(__DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php')
170
-        ) {
171
-            require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
172
-        }
173
-    }
165
+	function espressoLoadWpGraphQL()
166
+	{
167
+		if (
168
+			! class_exists('WPGraphQL')
169
+			&& is_readable(__DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php')
170
+		) {
171
+			require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
172
+		}
173
+	}
174 174
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Form_Fields.helper.php 2 patches
Indentation   +2059 added lines, -2059 removed lines patch added patch discarded remove patch
@@ -27,1056 +27,1056 @@  discard block
 block discarded – undo
27 27
  */
28 28
 class EEH_Form_Fields
29 29
 {
30
-    /**
31
-     *  Generates HTML for the forms used on admin pages
32
-     *
33
-     *
34
-     * @static
35
-     * @access public
36
-     * @param array $input_vars - array of input field details
37
-     *                          format:
38
-     *                          $template_form_fields['field-id'] = array(
39
-     *                          'name' => 'name_attribute',
40
-     *                          'label' => esc_html__('Field Label', 'event_espresso'), //or false
41
-     *                          'input' => 'hidden', //field input type can be 'text', 'select', 'textarea', 'hidden',
42
-     *                          'checkbox', 'wp_editor'
43
-     *                          'type' => 'int', //what "type" the value is (i.e. string, int etc)
44
-     *                          'required' => false, //boolean for whether the field is required
45
-     *                          'validation' => true, //boolean, whether to validate the field (todo)
46
-     *                          'value' => 'some_value_for_field', //what value is used for field
47
-     *                          'format' => '%d', //what format the value is (%d, %f, or %s)
48
-     *                          'db-col' => 'column_in_db' //used to indicate which column the field corresponds with
49
-     *                          in the db
50
-     *                          'options' => optiona, optionb || array('value' => 'label', '') //if the input type is
51
-     *                          "select", this allows you to set the args for the different <option> tags.
52
-     *                          'tabindex' => 1 //this allows you to set the tabindex for the field.
53
-     *                          'append_content' => '' //this allows you to send in html content to append to the
54
-     *                          field.
55
-     *                          )
56
-     * @param array $form_id    - used for defining unique identifiers for the form.
57
-     * @return string
58
-     * @todo   : at some point we can break this down into other static methods to abstract it a bit better.
59
-     */
60
-    public static function get_form_fields($input_vars = [], $form_id = false)
61
-    {
62
-
63
-        if (empty($input_vars)) {
64
-            EE_Error::add_error(
65
-                esc_html__('missing required variables for the form field generator', 'event_espresso'),
66
-                __FILE__,
67
-                __FUNCTION__,
68
-                __LINE__
69
-            );
70
-            return false;
71
-        }
72
-
73
-        $output        = "";
74
-        $inputs        = [];
75
-        $hidden_inputs = [];
76
-
77
-        // cycle thru inputs
78
-        foreach ($input_vars as $input_key => $input_value) {
79
-            $defaults = [
80
-                'append_content' => '',
81
-                'css_class'      => '',
82
-                'cols'           => 80,
83
-                'db-col'         => 'column_in_db',
84
-                'format'         => '%d',
85
-                'input'          => 'hidden',
86
-                'label'          => esc_html__('No label', 'event_espresso'),
87
-                'name'           => $input_key,
88
-                'options'        => [],
89
-                'required'       => false,
90
-                'tabindex'       => 0,
91
-                'rows'           => 10,
92
-                'type'           => 'int',
93
-                'validation'     => true,
94
-                'value'          => 'some_value_for_field',
95
-            ];
96
-
97
-            $input_value = wp_parse_args($input_value, $defaults);
98
-
99
-            $append_content = $input_value['append_content'];
100
-            $css_class      = $input_value['css_class'];
101
-            $cols           = $input_value['cols'];
102
-            $label          = $input_value['label'];
103
-            $name           = $input_value['name'];
104
-            $options        = $input_value['options'];
105
-            $required       = $input_value['required'];
106
-            $tab_index      = $input_value['tabindex'];
107
-            $rows           = $input_value['rows'];
108
-            $type           = $input_value['input'];
109
-            $value          = $input_value['value'];
110
-
111
-            $id    = $form_id ? $form_id . '-' . $input_key : $input_key;
112
-            $class = $required ? 'required ' . $css_class : $css_class;
113
-
114
-            // what type of input are we dealing with ?
115
-            switch ($type) {
116
-                case 'checkbox':
117
-                case 'radio':
118
-                    $field = self::adminMulti($value, $class, $id, $name, $required, $tab_index, $type, 1, $label);
119
-                    $field .= $append_content ?: '';
120
-                    break;
121
-
122
-                case 'hidden':
123
-                    $field           = null;
124
-                    $hidden_inputs[] = self::adminHidden($css_class, $id, $name, $value);
125
-                    break;
126
-
127
-                case 'select':
128
-                    $options = is_array($options) ? $options : explode(',', $options);
129
-                    $field   = self::adminLabel($id, $label, $required);
130
-                    $field   .= self::adminSelect($value, $class, $id, $name, $required, $tab_index, $options);
131
-                    $field   .= $append_content ?: '';
132
-                    break;
133
-
134
-                case 'textarea':
135
-                    $field = self::adminLabel($id, $label, $required);
136
-                    $field .= self::adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value);
137
-                    $field .= $append_content ?: '';
138
-                    break;
139
-
140
-                case 'wp_editor':
141
-                    $label = esc_html($label);
142
-                    $field = "<h4>{$label}</h4>";
143
-                    $field .= $append_content ?: '';
144
-                    $field .= self::adminWpEditor(
145
-                        $class,
146
-                        $id,
147
-                        $name,
148
-                        $rows,
149
-                        $tab_index,
150
-                        $value
151
-                    );
152
-                    break;
153
-
154
-                default:
155
-                    $field = self::adminLabel($id, $label, $required);
156
-                    $field .= self::adminText($class, $id, $name, $required, $tab_index, $value);
157
-                    $field .= $append_content ?: '';
158
-            }
159
-            if ($field) {
160
-                $inputs[] = $field;
161
-            }
162
-        } // end foreach( $input_vars as $input_key => $input_value )
163
-
164
-        if (! empty($inputs)) {
165
-            $glue   = "
30
+	/**
31
+	 *  Generates HTML for the forms used on admin pages
32
+	 *
33
+	 *
34
+	 * @static
35
+	 * @access public
36
+	 * @param array $input_vars - array of input field details
37
+	 *                          format:
38
+	 *                          $template_form_fields['field-id'] = array(
39
+	 *                          'name' => 'name_attribute',
40
+	 *                          'label' => esc_html__('Field Label', 'event_espresso'), //or false
41
+	 *                          'input' => 'hidden', //field input type can be 'text', 'select', 'textarea', 'hidden',
42
+	 *                          'checkbox', 'wp_editor'
43
+	 *                          'type' => 'int', //what "type" the value is (i.e. string, int etc)
44
+	 *                          'required' => false, //boolean for whether the field is required
45
+	 *                          'validation' => true, //boolean, whether to validate the field (todo)
46
+	 *                          'value' => 'some_value_for_field', //what value is used for field
47
+	 *                          'format' => '%d', //what format the value is (%d, %f, or %s)
48
+	 *                          'db-col' => 'column_in_db' //used to indicate which column the field corresponds with
49
+	 *                          in the db
50
+	 *                          'options' => optiona, optionb || array('value' => 'label', '') //if the input type is
51
+	 *                          "select", this allows you to set the args for the different <option> tags.
52
+	 *                          'tabindex' => 1 //this allows you to set the tabindex for the field.
53
+	 *                          'append_content' => '' //this allows you to send in html content to append to the
54
+	 *                          field.
55
+	 *                          )
56
+	 * @param array $form_id    - used for defining unique identifiers for the form.
57
+	 * @return string
58
+	 * @todo   : at some point we can break this down into other static methods to abstract it a bit better.
59
+	 */
60
+	public static function get_form_fields($input_vars = [], $form_id = false)
61
+	{
62
+
63
+		if (empty($input_vars)) {
64
+			EE_Error::add_error(
65
+				esc_html__('missing required variables for the form field generator', 'event_espresso'),
66
+				__FILE__,
67
+				__FUNCTION__,
68
+				__LINE__
69
+			);
70
+			return false;
71
+		}
72
+
73
+		$output        = "";
74
+		$inputs        = [];
75
+		$hidden_inputs = [];
76
+
77
+		// cycle thru inputs
78
+		foreach ($input_vars as $input_key => $input_value) {
79
+			$defaults = [
80
+				'append_content' => '',
81
+				'css_class'      => '',
82
+				'cols'           => 80,
83
+				'db-col'         => 'column_in_db',
84
+				'format'         => '%d',
85
+				'input'          => 'hidden',
86
+				'label'          => esc_html__('No label', 'event_espresso'),
87
+				'name'           => $input_key,
88
+				'options'        => [],
89
+				'required'       => false,
90
+				'tabindex'       => 0,
91
+				'rows'           => 10,
92
+				'type'           => 'int',
93
+				'validation'     => true,
94
+				'value'          => 'some_value_for_field',
95
+			];
96
+
97
+			$input_value = wp_parse_args($input_value, $defaults);
98
+
99
+			$append_content = $input_value['append_content'];
100
+			$css_class      = $input_value['css_class'];
101
+			$cols           = $input_value['cols'];
102
+			$label          = $input_value['label'];
103
+			$name           = $input_value['name'];
104
+			$options        = $input_value['options'];
105
+			$required       = $input_value['required'];
106
+			$tab_index      = $input_value['tabindex'];
107
+			$rows           = $input_value['rows'];
108
+			$type           = $input_value['input'];
109
+			$value          = $input_value['value'];
110
+
111
+			$id    = $form_id ? $form_id . '-' . $input_key : $input_key;
112
+			$class = $required ? 'required ' . $css_class : $css_class;
113
+
114
+			// what type of input are we dealing with ?
115
+			switch ($type) {
116
+				case 'checkbox':
117
+				case 'radio':
118
+					$field = self::adminMulti($value, $class, $id, $name, $required, $tab_index, $type, 1, $label);
119
+					$field .= $append_content ?: '';
120
+					break;
121
+
122
+				case 'hidden':
123
+					$field           = null;
124
+					$hidden_inputs[] = self::adminHidden($css_class, $id, $name, $value);
125
+					break;
126
+
127
+				case 'select':
128
+					$options = is_array($options) ? $options : explode(',', $options);
129
+					$field   = self::adminLabel($id, $label, $required);
130
+					$field   .= self::adminSelect($value, $class, $id, $name, $required, $tab_index, $options);
131
+					$field   .= $append_content ?: '';
132
+					break;
133
+
134
+				case 'textarea':
135
+					$field = self::adminLabel($id, $label, $required);
136
+					$field .= self::adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value);
137
+					$field .= $append_content ?: '';
138
+					break;
139
+
140
+				case 'wp_editor':
141
+					$label = esc_html($label);
142
+					$field = "<h4>{$label}</h4>";
143
+					$field .= $append_content ?: '';
144
+					$field .= self::adminWpEditor(
145
+						$class,
146
+						$id,
147
+						$name,
148
+						$rows,
149
+						$tab_index,
150
+						$value
151
+					);
152
+					break;
153
+
154
+				default:
155
+					$field = self::adminLabel($id, $label, $required);
156
+					$field .= self::adminText($class, $id, $name, $required, $tab_index, $value);
157
+					$field .= $append_content ?: '';
158
+			}
159
+			if ($field) {
160
+				$inputs[] = $field;
161
+			}
162
+		} // end foreach( $input_vars as $input_key => $input_value )
163
+
164
+		if (! empty($inputs)) {
165
+			$glue   = "
166 166
                 </li>
167 167
                 <li>
168 168
                     ";
169
-            $inputs = implode($glue, $inputs);
170
-            $output = "
169
+			$inputs = implode($glue, $inputs);
170
+			$output = "
171 171
             <ul>
172 172
                 <li>
173 173
                 {$inputs}
174 174
                 </li>
175 175
             </ul>
176 176
             ";
177
-        }
178
-        return $output . implode("\n", $hidden_inputs);
179
-    }
180
-
181
-
182
-    /**
183
-     * form_fields_array
184
-     * This utility function assembles form fields from a given structured array with field information.
185
-     * //TODO: This is an alternate generator that we may want to use instead.
186
-     *
187
-     * @param array $fields structured array of fields to assemble in the following format:
188
-     *                      [field_name] => array(
189
-     *                      ['label'] => 'label for field',
190
-     *                      ['labels'] => array('label_1', 'label_2'); //optional - if the field type is a multi select
191
-     *                      type of field you can indicated the labels for each option via this index
192
-     *                      ['extra_desc'] => 'extra description for the field', //optional
193
-     *                      ['type'] => 'textarea'|'text'|'wp_editor'|'checkbox'|'radio'|'hidden'|'select', //defaults
194
-     *                      to text
195
-     *                      ['value'] => 'value that goes in the field', //(if multi then this is an array of values
196
-     *                      and the 'default' paramater will be used for what is selected)
197
-     *                      ['default'] => 'default if the field type is multi (i.e. select or radios or checkboxes)',
198
-     *                      ['class'] => 'name-of-class(es)-for-input',
199
-     *                      ['classes'] => array('class_1', 'class_2'); //optional - if the field type is a multi
200
-     *                      select type of field you can indicate the css class for each option via this index.
201
-     *                      ['id'] => 'css-id-for-input') //defaults to 'field_name'
202
-     *                      ['unique_id'] => 1 //defaults to empty string.  This is useful for when the fields
203
-     *                      generated are going to be used in a loop and you want to make sure that the field
204
-     *                      identifiers are unique from each other.
205
-     *                      ['dimensions'] => array(100,300), //defaults to empty array.  This is used by field types
206
-     *                      such as textarea to indicate cols/rows.
207
-     *                      ['tabindex'] => '' //this allows you to set the tabindex for the field.
208
-     *                      ['wpeditor_args'] => array() //if the type of field is wpeditor then this can optionally
209
-     *                      contain an array of arguments for the editor setup.
210
-     *
211
-     * @return array         an array of inputs for form indexed by field name, and in the following structure:
212
-     *     [field_name] => array( 'label' => '{label_html}', 'field' => '{input_html}'
213
-     */
214
-    public static function get_form_fields_array($fields)
215
-    {
216
-
217
-        $form_fields = [];
218
-        $fields      = (array) $fields;
219
-
220
-        foreach ($fields as $field_name => $field_atts) {
221
-            // defaults:
222
-            $defaults = [
223
-                'class'         => '',
224
-                'classes'       => '',
225
-                'default'       => '',
226
-                'dimensions'    => ['10', '5'],
227
-                'extra_desc'    => '',
228
-                'id'            => $field_name,
229
-                'label'         => '',
230
-                'labels'        => '',
231
-                'required'      => false,
232
-                'tabindex'      => 0,
233
-                'type'          => 'text',
234
-                'unique_id'     => '',
235
-                'value'         => '',
236
-                'wpeditor_args' => [],
237
-            ];
238
-            // merge defaults with passed arguments
239
-            $_fields = wp_parse_args($field_atts, $defaults);
240
-
241
-            $class          = $_fields['class'];
242
-            $classes        = $_fields['classes'];
243
-            $default        = $_fields['default'];
244
-            $dims           = $_fields['dimensions'];
245
-            $extra_desc     = $_fields['extra_desc'];
246
-            $id             = $_fields['id'];
247
-            $label          = $_fields['label'];
248
-            $labels         = $_fields['labels'];
249
-            $required       = $_fields['required'];
250
-            $tab_index      = $_fields['tabindex'];
251
-            $type           = $_fields['type'];
252
-            $unique_id      = $_fields['unique_id'];
253
-            $value          = $_fields['value'];
254
-            $wp_editor_args = $_fields['wpeditor_args'];
255
-
256
-            // generate label
257
-            $label = ! empty($label) ? self::adminLabel($id, $label, $required) : '';
258
-            // generate field name
259
-            $name = ! empty($unique_id) ? $field_name . '[' . $unique_id . ']' : $field_name;
260
-
261
-            // we determine what we're building based on the type
262
-            switch ($type) {
263
-                case 'checkbox':
264
-                case 'radio':
265
-                    if (is_array($value)) {
266
-                        $c_input = '';
267
-                        foreach ($value as $key => $val) {
268
-                            $c_input .= self::adminMulti(
269
-                                $default,
270
-                                isset($classes[ $key ]) ? $classes[ $key ] : '',
271
-                                $field_name . '_' . $value,
272
-                                $name,
273
-                                $required,
274
-                                $tab_index,
275
-                                $type,
276
-                                $val,
277
-                                isset($labels[ $key ]) ? $labels[ $key ] : ''
278
-                            );
279
-                        }
280
-                        $field = $c_input;
281
-                    } else {
282
-                        $field = self::adminMulti(
283
-                            $default,
284
-                            $class,
285
-                            $id,
286
-                            $name,
287
-                            $required,
288
-                            $tab_index,
289
-                            $type,
290
-                            $value,
291
-                            $_fields['label']
292
-                        );
293
-                    }
294
-                    break;
295
-
296
-                case 'hidden':
297
-                    $field = self::adminHidden($class, $id, $name, $value);
298
-                    break;
299
-
300
-                case 'select':
301
-                    $options = [];
302
-                    foreach ($value as $key => $val) {
303
-                        $options[ $val ] = isset($labels[ $key ]) ? $labels[ $key ] : '';
304
-                    }
305
-                    $field = self::adminSelect($default, $class, $id, $name, $required, $tab_index, $options);
306
-                    break;
307
-
308
-                case 'textarea':
309
-                    $field =
310
-                        self::adminTextarea($class, $dims[0], $id, $name, $required, $dims[1], $tab_index, $value);
311
-                    break;
312
-
313
-                case 'wp_editor':
314
-                    $field = self::adminWpEditor(
315
-                        $class,
316
-                        $_fields['id'],
317
-                        $name,
318
-                        $dims[1],
319
-                        $tab_index,
320
-                        $value,
321
-                        $wp_editor_args
322
-                    );
323
-                    break;
324
-
325
-                default:
326
-                    $field = self::adminText($class, $id, $name, $required, $tab_index, $value);
327
-            }
328
-
329
-            $form_fields[ $field_name ] = ['label' => $label, 'field' => $field . $extra_desc];
330
-        }
331
-
332
-        return $form_fields;
333
-    }
334
-
335
-
336
-    /**
337
-     * @param string $class
338
-     * @param string $id
339
-     * @param string $name
340
-     * @param string $value
341
-     * @return string
342
-     * @since   4.10.14.p
343
-     */
344
-    private static function adminHidden($class, $id, $name, $value)
345
-    {
346
-        $id    = esc_attr($id);
347
-        $name  = esc_attr($name);
348
-        $class = esc_attr($class);
349
-        return "
177
+		}
178
+		return $output . implode("\n", $hidden_inputs);
179
+	}
180
+
181
+
182
+	/**
183
+	 * form_fields_array
184
+	 * This utility function assembles form fields from a given structured array with field information.
185
+	 * //TODO: This is an alternate generator that we may want to use instead.
186
+	 *
187
+	 * @param array $fields structured array of fields to assemble in the following format:
188
+	 *                      [field_name] => array(
189
+	 *                      ['label'] => 'label for field',
190
+	 *                      ['labels'] => array('label_1', 'label_2'); //optional - if the field type is a multi select
191
+	 *                      type of field you can indicated the labels for each option via this index
192
+	 *                      ['extra_desc'] => 'extra description for the field', //optional
193
+	 *                      ['type'] => 'textarea'|'text'|'wp_editor'|'checkbox'|'radio'|'hidden'|'select', //defaults
194
+	 *                      to text
195
+	 *                      ['value'] => 'value that goes in the field', //(if multi then this is an array of values
196
+	 *                      and the 'default' paramater will be used for what is selected)
197
+	 *                      ['default'] => 'default if the field type is multi (i.e. select or radios or checkboxes)',
198
+	 *                      ['class'] => 'name-of-class(es)-for-input',
199
+	 *                      ['classes'] => array('class_1', 'class_2'); //optional - if the field type is a multi
200
+	 *                      select type of field you can indicate the css class for each option via this index.
201
+	 *                      ['id'] => 'css-id-for-input') //defaults to 'field_name'
202
+	 *                      ['unique_id'] => 1 //defaults to empty string.  This is useful for when the fields
203
+	 *                      generated are going to be used in a loop and you want to make sure that the field
204
+	 *                      identifiers are unique from each other.
205
+	 *                      ['dimensions'] => array(100,300), //defaults to empty array.  This is used by field types
206
+	 *                      such as textarea to indicate cols/rows.
207
+	 *                      ['tabindex'] => '' //this allows you to set the tabindex for the field.
208
+	 *                      ['wpeditor_args'] => array() //if the type of field is wpeditor then this can optionally
209
+	 *                      contain an array of arguments for the editor setup.
210
+	 *
211
+	 * @return array         an array of inputs for form indexed by field name, and in the following structure:
212
+	 *     [field_name] => array( 'label' => '{label_html}', 'field' => '{input_html}'
213
+	 */
214
+	public static function get_form_fields_array($fields)
215
+	{
216
+
217
+		$form_fields = [];
218
+		$fields      = (array) $fields;
219
+
220
+		foreach ($fields as $field_name => $field_atts) {
221
+			// defaults:
222
+			$defaults = [
223
+				'class'         => '',
224
+				'classes'       => '',
225
+				'default'       => '',
226
+				'dimensions'    => ['10', '5'],
227
+				'extra_desc'    => '',
228
+				'id'            => $field_name,
229
+				'label'         => '',
230
+				'labels'        => '',
231
+				'required'      => false,
232
+				'tabindex'      => 0,
233
+				'type'          => 'text',
234
+				'unique_id'     => '',
235
+				'value'         => '',
236
+				'wpeditor_args' => [],
237
+			];
238
+			// merge defaults with passed arguments
239
+			$_fields = wp_parse_args($field_atts, $defaults);
240
+
241
+			$class          = $_fields['class'];
242
+			$classes        = $_fields['classes'];
243
+			$default        = $_fields['default'];
244
+			$dims           = $_fields['dimensions'];
245
+			$extra_desc     = $_fields['extra_desc'];
246
+			$id             = $_fields['id'];
247
+			$label          = $_fields['label'];
248
+			$labels         = $_fields['labels'];
249
+			$required       = $_fields['required'];
250
+			$tab_index      = $_fields['tabindex'];
251
+			$type           = $_fields['type'];
252
+			$unique_id      = $_fields['unique_id'];
253
+			$value          = $_fields['value'];
254
+			$wp_editor_args = $_fields['wpeditor_args'];
255
+
256
+			// generate label
257
+			$label = ! empty($label) ? self::adminLabel($id, $label, $required) : '';
258
+			// generate field name
259
+			$name = ! empty($unique_id) ? $field_name . '[' . $unique_id . ']' : $field_name;
260
+
261
+			// we determine what we're building based on the type
262
+			switch ($type) {
263
+				case 'checkbox':
264
+				case 'radio':
265
+					if (is_array($value)) {
266
+						$c_input = '';
267
+						foreach ($value as $key => $val) {
268
+							$c_input .= self::adminMulti(
269
+								$default,
270
+								isset($classes[ $key ]) ? $classes[ $key ] : '',
271
+								$field_name . '_' . $value,
272
+								$name,
273
+								$required,
274
+								$tab_index,
275
+								$type,
276
+								$val,
277
+								isset($labels[ $key ]) ? $labels[ $key ] : ''
278
+							);
279
+						}
280
+						$field = $c_input;
281
+					} else {
282
+						$field = self::adminMulti(
283
+							$default,
284
+							$class,
285
+							$id,
286
+							$name,
287
+							$required,
288
+							$tab_index,
289
+							$type,
290
+							$value,
291
+							$_fields['label']
292
+						);
293
+					}
294
+					break;
295
+
296
+				case 'hidden':
297
+					$field = self::adminHidden($class, $id, $name, $value);
298
+					break;
299
+
300
+				case 'select':
301
+					$options = [];
302
+					foreach ($value as $key => $val) {
303
+						$options[ $val ] = isset($labels[ $key ]) ? $labels[ $key ] : '';
304
+					}
305
+					$field = self::adminSelect($default, $class, $id, $name, $required, $tab_index, $options);
306
+					break;
307
+
308
+				case 'textarea':
309
+					$field =
310
+						self::adminTextarea($class, $dims[0], $id, $name, $required, $dims[1], $tab_index, $value);
311
+					break;
312
+
313
+				case 'wp_editor':
314
+					$field = self::adminWpEditor(
315
+						$class,
316
+						$_fields['id'],
317
+						$name,
318
+						$dims[1],
319
+						$tab_index,
320
+						$value,
321
+						$wp_editor_args
322
+					);
323
+					break;
324
+
325
+				default:
326
+					$field = self::adminText($class, $id, $name, $required, $tab_index, $value);
327
+			}
328
+
329
+			$form_fields[ $field_name ] = ['label' => $label, 'field' => $field . $extra_desc];
330
+		}
331
+
332
+		return $form_fields;
333
+	}
334
+
335
+
336
+	/**
337
+	 * @param string $class
338
+	 * @param string $id
339
+	 * @param string $name
340
+	 * @param string $value
341
+	 * @return string
342
+	 * @since   4.10.14.p
343
+	 */
344
+	private static function adminHidden($class, $id, $name, $value)
345
+	{
346
+		$id    = esc_attr($id);
347
+		$name  = esc_attr($name);
348
+		$class = esc_attr($class);
349
+		return "
350 350
         <input name='{$name}' type='hidden' id='{$id}' class='{$class}' value='{$value}' />";
351
-    }
352
-
353
-
354
-    /**
355
-     * @param string $id
356
-     * @param string $label
357
-     * @param string $required
358
-     * @return string
359
-     * @since   4.10.14.p
360
-     */
361
-    private static function adminLabel($id, $label, $required)
362
-    {
363
-        $id       = esc_attr($id);
364
-        $label    = esc_html($label);
365
-        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? " <span>*</span>" : '';
366
-        return "<label for='{$id}'>{$label}{$required}</label>";
367
-    }
368
-
369
-
370
-    /**
371
-     * @param string $default
372
-     * @param string $class
373
-     * @param string $id
374
-     * @param string $name
375
-     * @param string $required
376
-     * @param int    $tab_index
377
-     * @param string $type
378
-     * @param string $value
379
-     * @param string $label
380
-     * @return string
381
-     * @since   4.10.14.p
382
-     */
383
-    private static function adminMulti($default, $class, $id, $name, $required, $tab_index, $type, $value, $label = '')
384
-    {
385
-        $id        = esc_attr($id);
386
-        $name      = esc_attr($name);
387
-        $class     = esc_attr($class);
388
-        $tab_index = absint($tab_index);
389
-        $checked   = ! empty($default) && $default == $value ? 'checked ' : '';
390
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
391
-        $input     = "
351
+	}
352
+
353
+
354
+	/**
355
+	 * @param string $id
356
+	 * @param string $label
357
+	 * @param string $required
358
+	 * @return string
359
+	 * @since   4.10.14.p
360
+	 */
361
+	private static function adminLabel($id, $label, $required)
362
+	{
363
+		$id       = esc_attr($id);
364
+		$label    = esc_html($label);
365
+		$required = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? " <span>*</span>" : '';
366
+		return "<label for='{$id}'>{$label}{$required}</label>";
367
+	}
368
+
369
+
370
+	/**
371
+	 * @param string $default
372
+	 * @param string $class
373
+	 * @param string $id
374
+	 * @param string $name
375
+	 * @param string $required
376
+	 * @param int    $tab_index
377
+	 * @param string $type
378
+	 * @param string $value
379
+	 * @param string $label
380
+	 * @return string
381
+	 * @since   4.10.14.p
382
+	 */
383
+	private static function adminMulti($default, $class, $id, $name, $required, $tab_index, $type, $value, $label = '')
384
+	{
385
+		$id        = esc_attr($id);
386
+		$name      = esc_attr($name);
387
+		$class     = esc_attr($class);
388
+		$tab_index = absint($tab_index);
389
+		$checked   = ! empty($default) && $default == $value ? 'checked ' : '';
390
+		$required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
391
+		$input     = "
392 392
         <input name='{$name}[]' type='{$type}' id='{$id}' class='{$class}' value='{$value}' {$checked} {$required} tabindex='{$tab_index}'/>";
393
-        if ($label === '') {
394
-            return $input;
395
-        }
396
-        $label = esc_html($label);
397
-        $label_class = self::appendInputSizeClass('', $label);
398
-        $label_class = $label_class ? ' class="' . $label_class . '"' : '';
399
-        return "
393
+		if ($label === '') {
394
+			return $input;
395
+		}
396
+		$label = esc_html($label);
397
+		$label_class = self::appendInputSizeClass('', $label);
398
+		$label_class = $label_class ? ' class="' . $label_class . '"' : '';
399
+		return "
400 400
         <label for='$id'{$label_class}>
401 401
             {$input}
402 402
             {$label}
403 403
         </label>";
404
-    }
405
-
406
-
407
-    /**
408
-     * @param string $default
409
-     * @param string $class
410
-     * @param string $id
411
-     * @param string $name
412
-     * @param string $required
413
-     * @param int    $tab_index
414
-     * @param array  $options
415
-     * @return string
416
-     * @since   4.10.14.p
417
-     */
418
-    private static function adminSelect($default, $class, $id, $name, $required, $tab_index, $options = [])
419
-    {
420
-        $options_array = [];
421
-        foreach ($options as $value => $label) {
422
-            $selected        = ! empty($default) && $default == $value ? 'selected' : '';
423
-            $value           = esc_attr($value);
424
-            $label           = wp_strip_all_tags($label);
425
-            $options_array[] = "<option value='{$value}' {$selected}>{$label}</option>";
426
-        }
427
-        $options_html = implode("\n", $options_array);
428
-        $id           = esc_attr($id);
429
-        $name         = esc_attr($name);
430
-        $class        = esc_attr($class);
431
-        $tab_index    = absint($tab_index);
432
-        $required     = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
433
-
434
-        $class = self::appendInputSizeClass($class, $options);
435
-
436
-        return "
404
+	}
405
+
406
+
407
+	/**
408
+	 * @param string $default
409
+	 * @param string $class
410
+	 * @param string $id
411
+	 * @param string $name
412
+	 * @param string $required
413
+	 * @param int    $tab_index
414
+	 * @param array  $options
415
+	 * @return string
416
+	 * @since   4.10.14.p
417
+	 */
418
+	private static function adminSelect($default, $class, $id, $name, $required, $tab_index, $options = [])
419
+	{
420
+		$options_array = [];
421
+		foreach ($options as $value => $label) {
422
+			$selected        = ! empty($default) && $default == $value ? 'selected' : '';
423
+			$value           = esc_attr($value);
424
+			$label           = wp_strip_all_tags($label);
425
+			$options_array[] = "<option value='{$value}' {$selected}>{$label}</option>";
426
+		}
427
+		$options_html = implode("\n", $options_array);
428
+		$id           = esc_attr($id);
429
+		$name         = esc_attr($name);
430
+		$class        = esc_attr($class);
431
+		$tab_index    = absint($tab_index);
432
+		$required     = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
433
+
434
+		$class = self::appendInputSizeClass($class, $options);
435
+
436
+		return "
437 437
         <select name='{$name}' id='{$id}' class='{$class}' {$required} tabindex='{$tab_index}'>
438 438
             {$options_html}
439 439
         </select>";
440
-    }
441
-
442
-
443
-    /**
444
-     * @param string $class
445
-     * @param string $id
446
-     * @param string $name
447
-     * @param string $required
448
-     * @param int    $tab_index
449
-     * @param string $value
450
-     * @return string
451
-     * @since   4.10.14.p
452
-     */
453
-    private static function adminText($class, $id, $name, $required, $tab_index, $value)
454
-    {
455
-        $id        = esc_attr($id);
456
-        $name      = esc_attr($name);
457
-        $class     = esc_attr($class);
458
-        $tab_index = absint($tab_index);
459
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
460
-        $class     = self::appendInputSizeClass($class, $value);
461
-        $value     = esc_attr($value);
462
-        return "
440
+	}
441
+
442
+
443
+	/**
444
+	 * @param string $class
445
+	 * @param string $id
446
+	 * @param string $name
447
+	 * @param string $required
448
+	 * @param int    $tab_index
449
+	 * @param string $value
450
+	 * @return string
451
+	 * @since   4.10.14.p
452
+	 */
453
+	private static function adminText($class, $id, $name, $required, $tab_index, $value)
454
+	{
455
+		$id        = esc_attr($id);
456
+		$name      = esc_attr($name);
457
+		$class     = esc_attr($class);
458
+		$tab_index = absint($tab_index);
459
+		$required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
460
+		$class     = self::appendInputSizeClass($class, $value);
461
+		$value     = esc_attr($value);
462
+		return "
463 463
         <input name='{$name}' type='text' id='{$id}' class='{$class}' value='{$value}' {$required} tabindex='{$tab_index}'/>";
464
-    }
465
-
466
-
467
-    /**
468
-     * @param string $class
469
-     * @param int    $cols
470
-     * @param string $id
471
-     * @param string $name
472
-     * @param string $required
473
-     * @param int    $rows
474
-     * @param int    $tab_index
475
-     * @param string $value
476
-     * @return string
477
-     * @since   4.10.14.p
478
-     */
479
-    private static function adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value)
480
-    {
481
-        $id        = esc_attr($id);
482
-        $name      = esc_attr($name);
483
-        $class     = esc_attr($class);
484
-        $cols      = absint($cols);
485
-        $rows      = absint($rows);
486
-        $value     = esc_textarea($value);
487
-        $tab_index = absint($tab_index);
488
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
489
-        return "
464
+	}
465
+
466
+
467
+	/**
468
+	 * @param string $class
469
+	 * @param int    $cols
470
+	 * @param string $id
471
+	 * @param string $name
472
+	 * @param string $required
473
+	 * @param int    $rows
474
+	 * @param int    $tab_index
475
+	 * @param string $value
476
+	 * @return string
477
+	 * @since   4.10.14.p
478
+	 */
479
+	private static function adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value)
480
+	{
481
+		$id        = esc_attr($id);
482
+		$name      = esc_attr($name);
483
+		$class     = esc_attr($class);
484
+		$cols      = absint($cols);
485
+		$rows      = absint($rows);
486
+		$value     = esc_textarea($value);
487
+		$tab_index = absint($tab_index);
488
+		$required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
489
+		return "
490 490
         <textarea name='{$name}' id='{$id}' class='{$class}' rows='{$rows}' cols='{$cols}' {$required} tabindex='{$tab_index}'>{$value}</textarea>";
491
-    }
492
-
493
-
494
-    /**
495
-     * @param string $class
496
-     * @param string $id
497
-     * @param string $name
498
-     * @param int    $rows
499
-     * @param int    $tab_index
500
-     * @param string $value
501
-     * @param array  $wp_editor_args
502
-     * @return false|string
503
-     * @since   4.10.14.p
504
-     */
505
-    private static function adminWpEditor($class, $id, $name, $rows, $tab_index, $value, $wp_editor_args = [])
506
-    {
507
-        $editor_settings = $wp_editor_args + [
508
-                'textarea_name' => esc_attr($name),
509
-                'textarea_rows' => absint($rows),
510
-                'editor_class'  => esc_attr($class),
511
-                'tabindex'      => absint($tab_index),
512
-            ];
513
-        ob_start();
514
-        wp_editor($value, esc_attr($id), $editor_settings);
515
-        return ob_get_clean();
516
-    }
517
-
518
-
519
-    /**
520
-     * espresso admin page select_input
521
-     * Turns an array into a select fields
522
-     *
523
-     * @static
524
-     * @access public
525
-     * @param string  $name       field name
526
-     * @param array   $values     option values, numbered array starting at 0, where each value is an array with a key
527
-     *                            'text' (meaning text to display' and 'id' (meaning the internal value) eg:
528
-     *                            array(1=>array('text'=>'Monday','id'=>1),2=>array('text'=>'Tuesday','id'=>2)...). or
529
-     *                            as an array of key-value pairs, where the key is to be used for the select input's
530
-     *                            name, and the value will be the text shown to the user.  Optionally you can also
531
-     *                            include an additional key of "class" which will add a specific class to the option
532
-     *                            for that value.
533
-     * @param string  $default    default value
534
-     * @param string  $parameters extra parameters
535
-     * @param string  $class      css class
536
-     * @param boolean $autosize   whether to autosize the select or not
537
-     * @return string              html string for the select input
538
-     */
539
-    public static function select_input(
540
-        $name,
541
-        $values,
542
-        $default = '',
543
-        $parameters = '',
544
-        $class = '',
545
-        $autosize = true
546
-    ) {
547
-        // if $values was submitted in the wrong format, convert it over
548
-        if (! empty($values) && (! array_key_exists(0, $values) || ! is_array($values[0]))) {
549
-            $converted_values = [];
550
-            foreach ($values as $id => $text) {
551
-                $converted_values[] = ['id' => $id, 'text' => $text];
552
-            }
553
-            $values = $converted_values;
554
-        }
555
-
556
-        $field =
557
-            '<select id="' . EEH_Formatter::ee_tep_output_string($name)
558
-            . '" name="' . EEH_Formatter::ee_tep_output_string($name)
559
-            . '"';
560
-
561
-        if (EEH_Formatter::ee_tep_not_null($parameters)) {
562
-            $field .= ' ' . $parameters;
563
-        }
564
-        $class = $autosize ? self::appendInputSizeClass($class, $values) : '';
565
-
566
-        $field .= ' class="' . $class . '">';
567
-
568
-        if (empty($default) && isset($GLOBALS[ $name ])) {
569
-            $default = stripslashes($GLOBALS[ $name ]);
570
-        }
571
-
572
-        $field .= self::selectInputOption($values, $default);
573
-        $field .= '</select>';
574
-
575
-        return $field;
576
-    }
577
-
578
-
579
-    private static function selectInputOption(array $values, $default): string
580
-    {
581
-        if (isset($values['id'], $values['text'])) {
582
-            $id = is_scalar($values['id']) ? $values['id'] : '';
583
-            $text = is_scalar($values['text']) ? $values['text'] : '';
584
-            $selected = $default == $values['id'] ? ' selected = "selected"' : '';
585
-            $html_class = isset($values['class']) ? ' class="' . $values['class'] . '"' : '';
586
-            return "<option value='{$id}'{$selected}{$html_class}>{$text}</option>";
587
-        }
588
-        $options = '';
589
-        foreach ($values as $value) {
590
-            $options .= self::selectInputOption($value, $default);
591
-        }
592
-        return $options;
593
-    }
594
-
595
-
596
-    /**
597
-     * @param mixed $value
598
-     * @return int
599
-     * @since   5.0.0.p
600
-     */
601
-    private static function getInputValueLength($value): int
602
-    {
603
-        if ($value instanceof EE_Question_Option) {
604
-            return self::getInputValueLength($value->desc());
605
-        }
606
-        if (is_array($value)) {
607
-            $chars = 0;
608
-            foreach ($value as $val) {
609
-                $length = self::getInputValueLength($val);
610
-                $chars = max($length, $chars);
611
-            }
612
-            return $chars;
613
-        }
614
-        // not a primitive? return something big
615
-        if (! is_scalar($value)) {
616
-            return 500;
617
-        }
618
-        return strlen((string) $value);
619
-    }
620
-
621
-
622
-    /**
623
-     * @param string $class
624
-     * @param mixed $value
625
-     * @return string
626
-     * @since   5.0.0.p
627
-     */
628
-    private static function appendInputSizeClass(string $class, $value): string
629
-    {
630
-        if (strpos($class, 'ee-input-width--') !== false) {
631
-            return $class;
632
-        }
633
-        $chars = self::getInputValueLength($value);
634
-        if ($chars && $chars < 5) {
635
-            return "{$class} ee-input-width--tiny";
636
-        }
637
-        if ($chars && $chars < 25) {
638
-            return "{$class} ee-input-width--small";
639
-        }
640
-        if ($chars && $chars > 100) {
641
-            return "{$class} ee-input-width--big";
642
-        }
643
-        return "{$class} ee-input-width--reg";
644
-    }
645
-
646
-
647
-    /**
648
-     * generate_question_groups_html
649
-     *
650
-     * @param array  $question_groups
651
-     * @param string $group_wrapper
652
-     * @return string HTML
653
-     * @throws EE_Error
654
-     * @throws ReflectionException
655
-     */
656
-    public static function generate_question_groups_html($question_groups = [], $group_wrapper = 'fieldset')
657
-    {
658
-
659
-        $html                            = '';
660
-        $before_question_group_questions =
661
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
662
-        $after_question_group_questions  =
663
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
664
-
665
-        if (! empty($question_groups)) {
666
-            // loop thru question groups
667
-            foreach ($question_groups as $QSG) {
668
-                // check that questions exist
669
-                if (! empty($QSG['QSG_questions'])) {
670
-                    // use fieldsets
671
-                    $html .= "\n\t"
672
-                             . '<'
673
-                             . $group_wrapper
674
-                             . ' class="espresso-question-group-wrap" id="'
675
-                             . $QSG['QSG_identifier']
676
-                             . '">';
677
-                    // group_name
678
-                    $html .= $QSG['QSG_show_group_name']
679
-                        ? "\n\t\t"
680
-                          . '<h5 class="espresso-question-group-title-h5 section-title">'
681
-                          . self::prep_answer($QSG['QSG_name'])
682
-                          . '</h5>'
683
-                        : '';
684
-                    // group_desc
685
-                    $html .= $QSG['QSG_show_group_desc'] && ! empty($QSG['QSG_desc'])
686
-                        ? '<div class="espresso-question-group-desc-pg">'
687
-                          . self::prep_answer($QSG['QSG_desc'])
688
-                          . '</div>'
689
-                        : '';
690
-
691
-                    $html .= $before_question_group_questions;
692
-                    // loop thru questions
693
-                    foreach ($QSG['QSG_questions'] as $question) {
694
-                        $QFI  = new EE_Question_Form_Input(
695
-                            $question['qst_obj'],
696
-                            $question['ans_obj'],
697
-                            $question
698
-                        );
699
-                        $html .= self::generate_form_input($QFI);
700
-                    }
701
-                    $html .= $after_question_group_questions;
702
-                    $html .= "\n\t" . '</' . $group_wrapper . '>';
703
-                }
704
-            }
705
-        }
706
-
707
-        return $html;
708
-    }
709
-
710
-
711
-    /**
712
-     * generate_question_groups_html
713
-     *
714
-     * @param array  $question_groups
715
-     * @param array  $q_meta
716
-     * @param bool   $from_admin
717
-     * @param string $group_wrapper
718
-     * @return string HTML
719
-     * @throws EE_Error
720
-     * @throws ReflectionException
721
-     */
722
-    public static function generate_question_groups_html2(
723
-        $question_groups = [],
724
-        $q_meta = [],
725
-        $from_admin = false,
726
-        $group_wrapper = 'fieldset'
727
-    ) {
728
-
729
-        $html                            = '';
730
-        $before_question_group_questions =
731
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
732
-        $after_question_group_questions  =
733
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
734
-
735
-        $default_q_meta = [
736
-            'att_nmbr'    => 1,
737
-            'ticket_id'   => '',
738
-            'input_name'  => '',
739
-            'input_id'    => '',
740
-            'input_class' => '',
741
-        ];
742
-        $q_meta         = array_merge($default_q_meta, $q_meta);
743
-
744
-        if (! empty($question_groups)) {
745
-            // loop thru question groups
746
-            foreach ($question_groups as $QSG) {
747
-                if ($QSG instanceof EE_Question_Group) {
748
-                    // check that questions exist
749
-
750
-                    $where = ['QST_deleted' => 0];
751
-                    if (! $from_admin) {
752
-                        $where['QST_admin_only'] = 0;
753
-                    }
754
-                    $questions =
755
-                        $QSG->questions([$where, 'order_by' => ['Question_Group_Question.QGQ_order' => 'ASC']]);
756
-                    if (! empty($questions)) {
757
-                        // use fieldsets
758
-                        $html .= "\n\t"
759
-                                 . '<' . $group_wrapper . ' class="espresso-question-group-wrap" '
760
-                                 . 'id="' . $QSG->get('QSG_identifier') . '">';
761
-                        // group_name
762
-                        if ($QSG->show_group_name()) {
763
-                            $html .= "\n\t\t"
764
-                                     . '<h5 class="espresso-question-group-title-h5 section-title">'
765
-                                     . $QSG->get_pretty('QSG_name')
766
-                                     . '</h5>';
767
-                        }
768
-                        // group_desc
769
-                        if ($QSG->show_group_desc()) {
770
-                            $html .= '<div class="espresso-question-group-desc-pg">'
771
-                                     . $QSG->get_pretty('QSG_desc')
772
-                                     . '</div>';
773
-                        }
774
-
775
-                        $html .= $before_question_group_questions;
776
-                        // loop thru questions
777
-                        foreach ($questions as $QST) {
778
-                            $qstn_id = $QST->is_system_question() ? $QST->system_ID() : $QST->ID();
779
-
780
-                            $answer = null;
781
-
782
-                            /** @var RequestInterface $request */
783
-                            $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
784
-                            $request_qstn = $request->getRequestParam('qstn', [], 'string', true);
785
-                            if (! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
786
-                                // check for answer in $request_qstn in case we are reprocessing a form after an error
787
-                                if (isset($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])) {
788
-                                    $answer = is_array($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])
789
-                                        ? $request_qstn[ $q_meta['input_id'] ][ $qstn_id ]
790
-                                        : sanitize_text_field($request_qstn[ $q_meta['input_id'] ][ $qstn_id ]);
791
-                                }
792
-                            } elseif (isset($q_meta['attendee']) && $q_meta['attendee']) {
793
-                                // attendee data from the session
794
-                                $answer =
795
-                                    isset($q_meta['attendee'][ $qstn_id ]) ? $q_meta['attendee'][ $qstn_id ] : null;
796
-                            }
797
-
798
-
799
-                            $QFI  = new EE_Question_Form_Input(
800
-                                $QST,
801
-                                EE_Answer::new_instance(
802
-                                    [
803
-                                        'ANS_ID'    => 0,
804
-                                        'QST_ID'    => 0,
805
-                                        'REG_ID'    => 0,
806
-                                        'ANS_value' => $answer,
807
-                                    ]
808
-                                ),
809
-                                $q_meta
810
-                            );
811
-                            $html .= self::generate_form_input($QFI);
812
-                        }
813
-                        $html .= $after_question_group_questions;
814
-                        $html .= "\n\t" . '</' . $group_wrapper . '>';
815
-                    }
816
-                }
817
-            }
818
-        }
819
-        return $html;
820
-    }
821
-
822
-
823
-    /**
824
-     * generate_form_input
825
-     *
826
-     * @param EE_Question_Form_Input $QFI
827
-     * @return string HTML
828
-     * @throws EE_Error
829
-     * @throws ReflectionException
830
-     */
831
-    public static function generate_form_input(EE_Question_Form_Input $QFI)
832
-    {
833
-        if (isset($QFI->QST_admin_only) && $QFI->QST_admin_only && ! is_admin()) {
834
-            return '';
835
-        }
836
-        /** @var RequestInterface $request */
837
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
838
-
839
-        $QFI = self::_load_system_dropdowns($QFI);
840
-        $QFI = self::_load_specialized_dropdowns($QFI);
841
-
842
-        // we also need to verify
843
-
844
-        $display_text = (string) $QFI->get('QST_display_text');
845
-        $input_name   = (string) $QFI->get('QST_input_name');
846
-        $answer       = $request->getRequestParam($input_name, $QFI->get('ANS_value'));
847
-        $input_id     = (string) $QFI->get('QST_input_id');
848
-        $input_class  = (string) $QFI->get('QST_input_class');
849
-        //      $disabled = $QFI->get('QST_disabled') ? ' disabled="disabled"' : '';
850
-        $disabled          = (bool) $QFI->get('QST_disabled');
851
-        $required_label    = apply_filters(' FHEE__EEH_Form_Fields__generate_form_input__required_label', '<em>*</em>');
852
-        $QST_required      = (bool) $QFI->get('QST_required');
853
-        $required          = $QST_required
854
-            ? ['label' => $required_label, 'class' => 'required needs-value', 'title' => $QST_required]
855
-            : [];
856
-        $use_html_entities = $QFI->get_meta('htmlentities');
857
-        $required_text     = (string) $QFI->get('QST_required_text') !== ''
858
-            ? (string) $QFI->get('QST_required_text')
859
-            : esc_html__('This field is required', 'event_espresso');
860
-        $required_text     = $QST_required
861
-            ? "\n\t\t\t"
862
-              . '<div class="required-text hidden">'
863
-              . self::prep_answer($required_text, $use_html_entities)
864
-              . '</div>'
865
-            : '';
866
-        $label_class       = (string) $QFI->get('label_class');
867
-        $label_class       = $label_class ? "{$label_class} espresso-form-input-lbl" : 'espresso-form-input-lbl';
868
-        $QST_options       = $QFI->options(true, $answer);
869
-        $options           = is_array($QST_options) ? self::prep_answer_options($QST_options) : [];
870
-        $system_ID         = (string) $QFI->get('QST_system');
871
-        $label_b4          = (bool) $QFI->get_meta('label_b4');
872
-        $use_desc_4_label  = (bool) $QFI->get_meta('use_desc_4_label');
873
-        $add_mobile_label  = (bool) $QFI->get_meta('add_mobile_label');
874
-
875
-
876
-        switch ($QFI->get('QST_type')) {
877
-            case 'TEXTAREA':
878
-                return EEH_Form_Fields::textarea(
879
-                    $display_text,
880
-                    $answer,
881
-                    $input_name,
882
-                    $input_id,
883
-                    $input_class,
884
-                    [],
885
-                    $required,
886
-                    $required_text,
887
-                    $label_class,
888
-                    $disabled,
889
-                    $system_ID,
890
-                    $use_html_entities,
891
-                    $add_mobile_label
892
-                );
893
-
894
-            case 'DROPDOWN':
895
-                return EEH_Form_Fields::select(
896
-                    $display_text,
897
-                    $answer,
898
-                    $options,
899
-                    $input_name,
900
-                    $input_id,
901
-                    $input_class,
902
-                    $required,
903
-                    $required_text,
904
-                    $label_class,
905
-                    $disabled,
906
-                    $system_ID,
907
-                    $use_html_entities,
908
-                    true,
909
-                    $add_mobile_label
910
-                );
911
-
912
-
913
-            case 'RADIO_BTN':
914
-                return EEH_Form_Fields::radio(
915
-                    $display_text,
916
-                    $answer,
917
-                    $options,
918
-                    $input_name,
919
-                    $input_id,
920
-                    $input_class,
921
-                    $required,
922
-                    $required_text,
923
-                    $label_class,
924
-                    $disabled,
925
-                    $system_ID,
926
-                    $use_html_entities,
927
-                    $label_b4,
928
-                    $use_desc_4_label,
929
-                    $add_mobile_label
930
-                );
931
-
932
-            case 'CHECKBOX':
933
-                return EEH_Form_Fields::checkbox(
934
-                    $display_text,
935
-                    $answer,
936
-                    $options,
937
-                    $input_name,
938
-                    $input_id,
939
-                    $input_class,
940
-                    $required,
941
-                    $required_text,
942
-                    $label_class,
943
-                    $disabled,
944
-                    $label_b4,
945
-                    $system_ID,
946
-                    $use_html_entities,
947
-                    $add_mobile_label
948
-                );
949
-
950
-            case 'DATE':
951
-                return EEH_Form_Fields::datepicker(
952
-                    $display_text,
953
-                    $answer,
954
-                    $input_name,
955
-                    $input_id,
956
-                    $input_class,
957
-                    $required,
958
-                    $required_text,
959
-                    $label_class,
960
-                    $disabled,
961
-                    $system_ID,
962
-                    $use_html_entities,
963
-                    $add_mobile_label
964
-                );
965
-
966
-            case 'TEXT':
967
-            default:
968
-                return EEH_Form_Fields::text(
969
-                    $display_text,
970
-                    $answer,
971
-                    $input_name,
972
-                    $input_id,
973
-                    $input_class,
974
-                    $required,
975
-                    $required_text,
976
-                    $label_class,
977
-                    $disabled,
978
-                    $system_ID,
979
-                    $use_html_entities,
980
-                    $add_mobile_label
981
-                );
982
-        }
983
-    }
984
-
985
-
986
-    public static function label(
987
-        string $question,
988
-        string $required_text = '',
989
-        string $required_label = '',
990
-        string $name = '',
991
-        string $label_class = '',
992
-        bool $filter = true
993
-    ): string {
994
-        $for   = ! empty($name) ? " for='{$name}'" : '';
995
-        $class = ! empty($label_class) ? " class='{$label_class}'" : '';
996
-        $label = self::prep_question($question) . $required_label;
997
-        $label_html = "
491
+	}
492
+
493
+
494
+	/**
495
+	 * @param string $class
496
+	 * @param string $id
497
+	 * @param string $name
498
+	 * @param int    $rows
499
+	 * @param int    $tab_index
500
+	 * @param string $value
501
+	 * @param array  $wp_editor_args
502
+	 * @return false|string
503
+	 * @since   4.10.14.p
504
+	 */
505
+	private static function adminWpEditor($class, $id, $name, $rows, $tab_index, $value, $wp_editor_args = [])
506
+	{
507
+		$editor_settings = $wp_editor_args + [
508
+				'textarea_name' => esc_attr($name),
509
+				'textarea_rows' => absint($rows),
510
+				'editor_class'  => esc_attr($class),
511
+				'tabindex'      => absint($tab_index),
512
+			];
513
+		ob_start();
514
+		wp_editor($value, esc_attr($id), $editor_settings);
515
+		return ob_get_clean();
516
+	}
517
+
518
+
519
+	/**
520
+	 * espresso admin page select_input
521
+	 * Turns an array into a select fields
522
+	 *
523
+	 * @static
524
+	 * @access public
525
+	 * @param string  $name       field name
526
+	 * @param array   $values     option values, numbered array starting at 0, where each value is an array with a key
527
+	 *                            'text' (meaning text to display' and 'id' (meaning the internal value) eg:
528
+	 *                            array(1=>array('text'=>'Monday','id'=>1),2=>array('text'=>'Tuesday','id'=>2)...). or
529
+	 *                            as an array of key-value pairs, where the key is to be used for the select input's
530
+	 *                            name, and the value will be the text shown to the user.  Optionally you can also
531
+	 *                            include an additional key of "class" which will add a specific class to the option
532
+	 *                            for that value.
533
+	 * @param string  $default    default value
534
+	 * @param string  $parameters extra parameters
535
+	 * @param string  $class      css class
536
+	 * @param boolean $autosize   whether to autosize the select or not
537
+	 * @return string              html string for the select input
538
+	 */
539
+	public static function select_input(
540
+		$name,
541
+		$values,
542
+		$default = '',
543
+		$parameters = '',
544
+		$class = '',
545
+		$autosize = true
546
+	) {
547
+		// if $values was submitted in the wrong format, convert it over
548
+		if (! empty($values) && (! array_key_exists(0, $values) || ! is_array($values[0]))) {
549
+			$converted_values = [];
550
+			foreach ($values as $id => $text) {
551
+				$converted_values[] = ['id' => $id, 'text' => $text];
552
+			}
553
+			$values = $converted_values;
554
+		}
555
+
556
+		$field =
557
+			'<select id="' . EEH_Formatter::ee_tep_output_string($name)
558
+			. '" name="' . EEH_Formatter::ee_tep_output_string($name)
559
+			. '"';
560
+
561
+		if (EEH_Formatter::ee_tep_not_null($parameters)) {
562
+			$field .= ' ' . $parameters;
563
+		}
564
+		$class = $autosize ? self::appendInputSizeClass($class, $values) : '';
565
+
566
+		$field .= ' class="' . $class . '">';
567
+
568
+		if (empty($default) && isset($GLOBALS[ $name ])) {
569
+			$default = stripslashes($GLOBALS[ $name ]);
570
+		}
571
+
572
+		$field .= self::selectInputOption($values, $default);
573
+		$field .= '</select>';
574
+
575
+		return $field;
576
+	}
577
+
578
+
579
+	private static function selectInputOption(array $values, $default): string
580
+	{
581
+		if (isset($values['id'], $values['text'])) {
582
+			$id = is_scalar($values['id']) ? $values['id'] : '';
583
+			$text = is_scalar($values['text']) ? $values['text'] : '';
584
+			$selected = $default == $values['id'] ? ' selected = "selected"' : '';
585
+			$html_class = isset($values['class']) ? ' class="' . $values['class'] . '"' : '';
586
+			return "<option value='{$id}'{$selected}{$html_class}>{$text}</option>";
587
+		}
588
+		$options = '';
589
+		foreach ($values as $value) {
590
+			$options .= self::selectInputOption($value, $default);
591
+		}
592
+		return $options;
593
+	}
594
+
595
+
596
+	/**
597
+	 * @param mixed $value
598
+	 * @return int
599
+	 * @since   5.0.0.p
600
+	 */
601
+	private static function getInputValueLength($value): int
602
+	{
603
+		if ($value instanceof EE_Question_Option) {
604
+			return self::getInputValueLength($value->desc());
605
+		}
606
+		if (is_array($value)) {
607
+			$chars = 0;
608
+			foreach ($value as $val) {
609
+				$length = self::getInputValueLength($val);
610
+				$chars = max($length, $chars);
611
+			}
612
+			return $chars;
613
+		}
614
+		// not a primitive? return something big
615
+		if (! is_scalar($value)) {
616
+			return 500;
617
+		}
618
+		return strlen((string) $value);
619
+	}
620
+
621
+
622
+	/**
623
+	 * @param string $class
624
+	 * @param mixed $value
625
+	 * @return string
626
+	 * @since   5.0.0.p
627
+	 */
628
+	private static function appendInputSizeClass(string $class, $value): string
629
+	{
630
+		if (strpos($class, 'ee-input-width--') !== false) {
631
+			return $class;
632
+		}
633
+		$chars = self::getInputValueLength($value);
634
+		if ($chars && $chars < 5) {
635
+			return "{$class} ee-input-width--tiny";
636
+		}
637
+		if ($chars && $chars < 25) {
638
+			return "{$class} ee-input-width--small";
639
+		}
640
+		if ($chars && $chars > 100) {
641
+			return "{$class} ee-input-width--big";
642
+		}
643
+		return "{$class} ee-input-width--reg";
644
+	}
645
+
646
+
647
+	/**
648
+	 * generate_question_groups_html
649
+	 *
650
+	 * @param array  $question_groups
651
+	 * @param string $group_wrapper
652
+	 * @return string HTML
653
+	 * @throws EE_Error
654
+	 * @throws ReflectionException
655
+	 */
656
+	public static function generate_question_groups_html($question_groups = [], $group_wrapper = 'fieldset')
657
+	{
658
+
659
+		$html                            = '';
660
+		$before_question_group_questions =
661
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
662
+		$after_question_group_questions  =
663
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
664
+
665
+		if (! empty($question_groups)) {
666
+			// loop thru question groups
667
+			foreach ($question_groups as $QSG) {
668
+				// check that questions exist
669
+				if (! empty($QSG['QSG_questions'])) {
670
+					// use fieldsets
671
+					$html .= "\n\t"
672
+							 . '<'
673
+							 . $group_wrapper
674
+							 . ' class="espresso-question-group-wrap" id="'
675
+							 . $QSG['QSG_identifier']
676
+							 . '">';
677
+					// group_name
678
+					$html .= $QSG['QSG_show_group_name']
679
+						? "\n\t\t"
680
+						  . '<h5 class="espresso-question-group-title-h5 section-title">'
681
+						  . self::prep_answer($QSG['QSG_name'])
682
+						  . '</h5>'
683
+						: '';
684
+					// group_desc
685
+					$html .= $QSG['QSG_show_group_desc'] && ! empty($QSG['QSG_desc'])
686
+						? '<div class="espresso-question-group-desc-pg">'
687
+						  . self::prep_answer($QSG['QSG_desc'])
688
+						  . '</div>'
689
+						: '';
690
+
691
+					$html .= $before_question_group_questions;
692
+					// loop thru questions
693
+					foreach ($QSG['QSG_questions'] as $question) {
694
+						$QFI  = new EE_Question_Form_Input(
695
+							$question['qst_obj'],
696
+							$question['ans_obj'],
697
+							$question
698
+						);
699
+						$html .= self::generate_form_input($QFI);
700
+					}
701
+					$html .= $after_question_group_questions;
702
+					$html .= "\n\t" . '</' . $group_wrapper . '>';
703
+				}
704
+			}
705
+		}
706
+
707
+		return $html;
708
+	}
709
+
710
+
711
+	/**
712
+	 * generate_question_groups_html
713
+	 *
714
+	 * @param array  $question_groups
715
+	 * @param array  $q_meta
716
+	 * @param bool   $from_admin
717
+	 * @param string $group_wrapper
718
+	 * @return string HTML
719
+	 * @throws EE_Error
720
+	 * @throws ReflectionException
721
+	 */
722
+	public static function generate_question_groups_html2(
723
+		$question_groups = [],
724
+		$q_meta = [],
725
+		$from_admin = false,
726
+		$group_wrapper = 'fieldset'
727
+	) {
728
+
729
+		$html                            = '';
730
+		$before_question_group_questions =
731
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
732
+		$after_question_group_questions  =
733
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
734
+
735
+		$default_q_meta = [
736
+			'att_nmbr'    => 1,
737
+			'ticket_id'   => '',
738
+			'input_name'  => '',
739
+			'input_id'    => '',
740
+			'input_class' => '',
741
+		];
742
+		$q_meta         = array_merge($default_q_meta, $q_meta);
743
+
744
+		if (! empty($question_groups)) {
745
+			// loop thru question groups
746
+			foreach ($question_groups as $QSG) {
747
+				if ($QSG instanceof EE_Question_Group) {
748
+					// check that questions exist
749
+
750
+					$where = ['QST_deleted' => 0];
751
+					if (! $from_admin) {
752
+						$where['QST_admin_only'] = 0;
753
+					}
754
+					$questions =
755
+						$QSG->questions([$where, 'order_by' => ['Question_Group_Question.QGQ_order' => 'ASC']]);
756
+					if (! empty($questions)) {
757
+						// use fieldsets
758
+						$html .= "\n\t"
759
+								 . '<' . $group_wrapper . ' class="espresso-question-group-wrap" '
760
+								 . 'id="' . $QSG->get('QSG_identifier') . '">';
761
+						// group_name
762
+						if ($QSG->show_group_name()) {
763
+							$html .= "\n\t\t"
764
+									 . '<h5 class="espresso-question-group-title-h5 section-title">'
765
+									 . $QSG->get_pretty('QSG_name')
766
+									 . '</h5>';
767
+						}
768
+						// group_desc
769
+						if ($QSG->show_group_desc()) {
770
+							$html .= '<div class="espresso-question-group-desc-pg">'
771
+									 . $QSG->get_pretty('QSG_desc')
772
+									 . '</div>';
773
+						}
774
+
775
+						$html .= $before_question_group_questions;
776
+						// loop thru questions
777
+						foreach ($questions as $QST) {
778
+							$qstn_id = $QST->is_system_question() ? $QST->system_ID() : $QST->ID();
779
+
780
+							$answer = null;
781
+
782
+							/** @var RequestInterface $request */
783
+							$request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
784
+							$request_qstn = $request->getRequestParam('qstn', [], 'string', true);
785
+							if (! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
786
+								// check for answer in $request_qstn in case we are reprocessing a form after an error
787
+								if (isset($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])) {
788
+									$answer = is_array($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])
789
+										? $request_qstn[ $q_meta['input_id'] ][ $qstn_id ]
790
+										: sanitize_text_field($request_qstn[ $q_meta['input_id'] ][ $qstn_id ]);
791
+								}
792
+							} elseif (isset($q_meta['attendee']) && $q_meta['attendee']) {
793
+								// attendee data from the session
794
+								$answer =
795
+									isset($q_meta['attendee'][ $qstn_id ]) ? $q_meta['attendee'][ $qstn_id ] : null;
796
+							}
797
+
798
+
799
+							$QFI  = new EE_Question_Form_Input(
800
+								$QST,
801
+								EE_Answer::new_instance(
802
+									[
803
+										'ANS_ID'    => 0,
804
+										'QST_ID'    => 0,
805
+										'REG_ID'    => 0,
806
+										'ANS_value' => $answer,
807
+									]
808
+								),
809
+								$q_meta
810
+							);
811
+							$html .= self::generate_form_input($QFI);
812
+						}
813
+						$html .= $after_question_group_questions;
814
+						$html .= "\n\t" . '</' . $group_wrapper . '>';
815
+					}
816
+				}
817
+			}
818
+		}
819
+		return $html;
820
+	}
821
+
822
+
823
+	/**
824
+	 * generate_form_input
825
+	 *
826
+	 * @param EE_Question_Form_Input $QFI
827
+	 * @return string HTML
828
+	 * @throws EE_Error
829
+	 * @throws ReflectionException
830
+	 */
831
+	public static function generate_form_input(EE_Question_Form_Input $QFI)
832
+	{
833
+		if (isset($QFI->QST_admin_only) && $QFI->QST_admin_only && ! is_admin()) {
834
+			return '';
835
+		}
836
+		/** @var RequestInterface $request */
837
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
838
+
839
+		$QFI = self::_load_system_dropdowns($QFI);
840
+		$QFI = self::_load_specialized_dropdowns($QFI);
841
+
842
+		// we also need to verify
843
+
844
+		$display_text = (string) $QFI->get('QST_display_text');
845
+		$input_name   = (string) $QFI->get('QST_input_name');
846
+		$answer       = $request->getRequestParam($input_name, $QFI->get('ANS_value'));
847
+		$input_id     = (string) $QFI->get('QST_input_id');
848
+		$input_class  = (string) $QFI->get('QST_input_class');
849
+		//      $disabled = $QFI->get('QST_disabled') ? ' disabled="disabled"' : '';
850
+		$disabled          = (bool) $QFI->get('QST_disabled');
851
+		$required_label    = apply_filters(' FHEE__EEH_Form_Fields__generate_form_input__required_label', '<em>*</em>');
852
+		$QST_required      = (bool) $QFI->get('QST_required');
853
+		$required          = $QST_required
854
+			? ['label' => $required_label, 'class' => 'required needs-value', 'title' => $QST_required]
855
+			: [];
856
+		$use_html_entities = $QFI->get_meta('htmlentities');
857
+		$required_text     = (string) $QFI->get('QST_required_text') !== ''
858
+			? (string) $QFI->get('QST_required_text')
859
+			: esc_html__('This field is required', 'event_espresso');
860
+		$required_text     = $QST_required
861
+			? "\n\t\t\t"
862
+			  . '<div class="required-text hidden">'
863
+			  . self::prep_answer($required_text, $use_html_entities)
864
+			  . '</div>'
865
+			: '';
866
+		$label_class       = (string) $QFI->get('label_class');
867
+		$label_class       = $label_class ? "{$label_class} espresso-form-input-lbl" : 'espresso-form-input-lbl';
868
+		$QST_options       = $QFI->options(true, $answer);
869
+		$options           = is_array($QST_options) ? self::prep_answer_options($QST_options) : [];
870
+		$system_ID         = (string) $QFI->get('QST_system');
871
+		$label_b4          = (bool) $QFI->get_meta('label_b4');
872
+		$use_desc_4_label  = (bool) $QFI->get_meta('use_desc_4_label');
873
+		$add_mobile_label  = (bool) $QFI->get_meta('add_mobile_label');
874
+
875
+
876
+		switch ($QFI->get('QST_type')) {
877
+			case 'TEXTAREA':
878
+				return EEH_Form_Fields::textarea(
879
+					$display_text,
880
+					$answer,
881
+					$input_name,
882
+					$input_id,
883
+					$input_class,
884
+					[],
885
+					$required,
886
+					$required_text,
887
+					$label_class,
888
+					$disabled,
889
+					$system_ID,
890
+					$use_html_entities,
891
+					$add_mobile_label
892
+				);
893
+
894
+			case 'DROPDOWN':
895
+				return EEH_Form_Fields::select(
896
+					$display_text,
897
+					$answer,
898
+					$options,
899
+					$input_name,
900
+					$input_id,
901
+					$input_class,
902
+					$required,
903
+					$required_text,
904
+					$label_class,
905
+					$disabled,
906
+					$system_ID,
907
+					$use_html_entities,
908
+					true,
909
+					$add_mobile_label
910
+				);
911
+
912
+
913
+			case 'RADIO_BTN':
914
+				return EEH_Form_Fields::radio(
915
+					$display_text,
916
+					$answer,
917
+					$options,
918
+					$input_name,
919
+					$input_id,
920
+					$input_class,
921
+					$required,
922
+					$required_text,
923
+					$label_class,
924
+					$disabled,
925
+					$system_ID,
926
+					$use_html_entities,
927
+					$label_b4,
928
+					$use_desc_4_label,
929
+					$add_mobile_label
930
+				);
931
+
932
+			case 'CHECKBOX':
933
+				return EEH_Form_Fields::checkbox(
934
+					$display_text,
935
+					$answer,
936
+					$options,
937
+					$input_name,
938
+					$input_id,
939
+					$input_class,
940
+					$required,
941
+					$required_text,
942
+					$label_class,
943
+					$disabled,
944
+					$label_b4,
945
+					$system_ID,
946
+					$use_html_entities,
947
+					$add_mobile_label
948
+				);
949
+
950
+			case 'DATE':
951
+				return EEH_Form_Fields::datepicker(
952
+					$display_text,
953
+					$answer,
954
+					$input_name,
955
+					$input_id,
956
+					$input_class,
957
+					$required,
958
+					$required_text,
959
+					$label_class,
960
+					$disabled,
961
+					$system_ID,
962
+					$use_html_entities,
963
+					$add_mobile_label
964
+				);
965
+
966
+			case 'TEXT':
967
+			default:
968
+				return EEH_Form_Fields::text(
969
+					$display_text,
970
+					$answer,
971
+					$input_name,
972
+					$input_id,
973
+					$input_class,
974
+					$required,
975
+					$required_text,
976
+					$label_class,
977
+					$disabled,
978
+					$system_ID,
979
+					$use_html_entities,
980
+					$add_mobile_label
981
+				);
982
+		}
983
+	}
984
+
985
+
986
+	public static function label(
987
+		string $question,
988
+		string $required_text = '',
989
+		string $required_label = '',
990
+		string $name = '',
991
+		string $label_class = '',
992
+		bool $filter = true
993
+	): string {
994
+		$for   = ! empty($name) ? " for='{$name}'" : '';
995
+		$class = ! empty($label_class) ? " class='{$label_class}'" : '';
996
+		$label = self::prep_question($question) . $required_label;
997
+		$label_html = "
998 998
             {$required_text}
999 999
             <label{$for}{$class}>{$label}</label>";
1000
-        // filter label but ensure required text comes before it
1001
-        return $filter
1002
-            ? apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text)
1003
-            : $label_html;
1004
-    }
1005
-
1006
-
1007
-
1008
-    public static function mobileLabel(
1009
-        bool $add_mobile_label,
1010
-        string $question,
1011
-        string $required_text = '',
1012
-        string $required_label = '',
1013
-        string $label_class = '',
1014
-        string $name = ''
1015
-    ): string {
1016
-        return $add_mobile_label
1017
-            ? self::label($question, $required_text, $required_label, $name, $label_class, false)
1018
-            : '';
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * generates HTML for a form text input
1024
-     *
1025
-     * @param string $question    label content
1026
-     * @param string $answer      form input value attribute
1027
-     * @param string $name        form input name attribute
1028
-     * @param string $id          form input css id attribute
1029
-     * @param string $class       form input css class attribute
1030
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1031
-     *                            required 'class', and required 'msg' attribute
1032
-     * @param string $label_class css class attribute for the label
1033
-     * @param string $disabled    disabled="disabled" or null
1034
-     * @return string HTML
1035
-     */
1036
-    public static function text(
1037
-        $question = false,
1038
-        $answer = null,
1039
-        $name = false,
1040
-        $id = '',
1041
-        $class = '',
1042
-        $required = false,
1043
-        $required_text = '',
1044
-        $label_class = '',
1045
-        $disabled = false,
1046
-        $system_ID = false,
1047
-        $use_html_entities = true,
1048
-        $add_mobile_label = false,
1049
-        $extra_attributes = ''
1050
-    ) {
1051
-        // need these
1052
-        if (! $question || ! $name) {
1053
-            return null;
1054
-        }
1055
-        // prep the answer
1056
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1057
-        // prep the required array
1058
-        $required = self::prep_required($required);
1059
-        // set disabled tag
1060
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1061
-        // ya gots ta have style man!!!
1062
-        $txt_class = is_admin() ? 'regular-text' : 'espresso-text-inp';
1063
-        $class     = empty($class) ? $txt_class : $class;
1064
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1065
-        $class = self::appendInputSizeClass($class, $answer);
1066
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1067
-        $extra_attributes = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', $extra_attributes);
1068
-
1069
-        $label_html = self::label($question, $required_text, $required['label'], $name, $label_class);
1070
-        $mobile_label = self::mobileLabel(
1071
-            $add_mobile_label,
1072
-            $question,
1073
-            $required_text,
1074
-            $required['label'],
1075
-            $label_class,
1076
-            $name
1077
-        );
1078
-
1079
-        $input_html = $mobile_label . '
1000
+		// filter label but ensure required text comes before it
1001
+		return $filter
1002
+			? apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text)
1003
+			: $label_html;
1004
+	}
1005
+
1006
+
1007
+
1008
+	public static function mobileLabel(
1009
+		bool $add_mobile_label,
1010
+		string $question,
1011
+		string $required_text = '',
1012
+		string $required_label = '',
1013
+		string $label_class = '',
1014
+		string $name = ''
1015
+	): string {
1016
+		return $add_mobile_label
1017
+			? self::label($question, $required_text, $required_label, $name, $label_class, false)
1018
+			: '';
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * generates HTML for a form text input
1024
+	 *
1025
+	 * @param string $question    label content
1026
+	 * @param string $answer      form input value attribute
1027
+	 * @param string $name        form input name attribute
1028
+	 * @param string $id          form input css id attribute
1029
+	 * @param string $class       form input css class attribute
1030
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1031
+	 *                            required 'class', and required 'msg' attribute
1032
+	 * @param string $label_class css class attribute for the label
1033
+	 * @param string $disabled    disabled="disabled" or null
1034
+	 * @return string HTML
1035
+	 */
1036
+	public static function text(
1037
+		$question = false,
1038
+		$answer = null,
1039
+		$name = false,
1040
+		$id = '',
1041
+		$class = '',
1042
+		$required = false,
1043
+		$required_text = '',
1044
+		$label_class = '',
1045
+		$disabled = false,
1046
+		$system_ID = false,
1047
+		$use_html_entities = true,
1048
+		$add_mobile_label = false,
1049
+		$extra_attributes = ''
1050
+	) {
1051
+		// need these
1052
+		if (! $question || ! $name) {
1053
+			return null;
1054
+		}
1055
+		// prep the answer
1056
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1057
+		// prep the required array
1058
+		$required = self::prep_required($required);
1059
+		// set disabled tag
1060
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1061
+		// ya gots ta have style man!!!
1062
+		$txt_class = is_admin() ? 'regular-text' : 'espresso-text-inp';
1063
+		$class     = empty($class) ? $txt_class : $class;
1064
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1065
+		$class = self::appendInputSizeClass($class, $answer);
1066
+		$class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1067
+		$extra_attributes = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', $extra_attributes);
1068
+
1069
+		$label_html = self::label($question, $required_text, $required['label'], $name, $label_class);
1070
+		$mobile_label = self::mobileLabel(
1071
+			$add_mobile_label,
1072
+			$question,
1073
+			$required_text,
1074
+			$required['label'],
1075
+			$label_class,
1076
+			$name
1077
+		);
1078
+
1079
+		$input_html = $mobile_label . '
1080 1080
             <input  type="text"
1081 1081
                     name="' . $name . '"
1082 1082
                     id="' . $id . '"
@@ -1086,1035 +1086,1035 @@  discard block
 block discarded – undo
1086 1086
                     ' . $disabled . ' ' . $extra_attributes . '
1087 1087
             />';
1088 1088
 
1089
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1090
-        return $label_html . $input_html;
1091
-    }
1092
-
1093
-
1094
-    /**
1095
-     * generates HTML for a form textarea
1096
-     *
1097
-     * @param string $question    label content
1098
-     * @param string $answer      form input value attribute
1099
-     * @param string $name        form input name attribute
1100
-     * @param string $id          form input css id attribute
1101
-     * @param string $class       form input css class attribute
1102
-     * @param array  $dimensions  array of form input rows and cols attributes : array( 'rows' => 3, 'cols' => 40 )
1103
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1104
-     *                            required 'class', and required 'msg' attribute
1105
-     * @param string $label_class css class attribute for the label
1106
-     * @param string $disabled    disabled="disabled" or null
1107
-     * @return string HTML
1108
-     */
1109
-    public static function textarea(
1110
-        $question = false,
1111
-        $answer = null,
1112
-        $name = false,
1113
-        $id = '',
1114
-        $class = '',
1115
-        $dimensions = false,
1116
-        $required = false,
1117
-        $required_text = '',
1118
-        $label_class = '',
1119
-        $disabled = false,
1120
-        $system_ID = false,
1121
-        $use_html_entities = true,
1122
-        $add_mobile_label = false
1123
-    ) {
1124
-        // need these
1125
-        if (! $question || ! $name) {
1126
-            return null;
1127
-        }
1128
-        // prep the answer
1129
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1130
-        // prep the required array
1131
-        $required = self::prep_required($required);
1132
-        // make sure $dimensions is an array
1133
-        $dimensions = is_array($dimensions) ? $dimensions : [];
1134
-        // and set some defaults
1135
-        $dimensions = array_merge(['rows' => 3, 'cols' => 40], $dimensions);
1136
-        // set disabled tag
1137
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1138
-        // ya gots ta have style man!!!
1139
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1140
-        $class     .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1141
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1142
-
1143
-        $label_html   = self::label($question, $required_text, $required['label'], $name, $label_class);
1144
-        $mobile_label = self::mobileLabel(
1145
-            $add_mobile_label,
1146
-            $question,
1147
-            $required_text,
1148
-            $required['label'],
1149
-            $label_class,
1150
-            $name
1151
-        );
1152
-
1153
-        $input_html = $mobile_label
1154
-            . '<textarea name="' . $name . '" id="' . $id . '" class="' . trim($class) . '" '
1155
-            . 'rows="' . $dimensions['rows'] . '" cols="' . $dimensions['cols'] . '"  '
1156
-            . 'aria-label="' . $required['msg'] . '" ' . $disabled . ' ' . $extra . '>'
1157
-             . esc_textarea($answer)
1158
-              . '</textarea>';
1159
-
1160
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1161
-        return $label_html . $input_html;
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * generates HTML for a form select input
1167
-     *
1168
-     * @param string $question    label content
1169
-     * @param string $answer      form input value attribute
1170
-     * @param array  $options     array of answer options where array key = option value and array value = option
1171
-     *                            display text
1172
-     * @param string $name        form input name attribute
1173
-     * @param string $id          form input css id attribute
1174
-     * @param string $class       form input css class attribute
1175
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1176
-     *                            required 'class', and required 'msg' attribute
1177
-     * @param string $label_class css class attribute for the label
1178
-     * @param string $disabled    disabled="disabled" or null
1179
-     * @return string HTML
1180
-     */
1181
-    public static function select(
1182
-        $question = false,
1183
-        $answer = null,
1184
-        $options = false,
1185
-        $name = false,
1186
-        $id = '',
1187
-        $class = '',
1188
-        $required = false,
1189
-        $required_text = '',
1190
-        $label_class = '',
1191
-        $disabled = false,
1192
-        $system_ID = false,
1193
-        $use_html_entities = true,
1194
-        $add_please_select_option = false,
1195
-        $add_mobile_label = false
1196
-    ) {
1197
-
1198
-        // need these
1199
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1200
-            return null;
1201
-        }
1202
-        // prep the answer
1203
-        $answer = is_array($answer)
1204
-            ? self::prep_answer(array_shift($answer), $use_html_entities)
1205
-            : self::prep_answer($answer, $use_html_entities);
1206
-        // prep the required array
1207
-        $required = self::prep_required($required);
1208
-        // set disabled tag
1209
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1210
-        // ya gots ta have style man!!!
1211
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1212
-        $class = self::appendInputSizeClass($class, $options);
1213
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1214
-
1215
-        $label_html   = self::label($question, $required_text, $required['label'], $name, $label_class);
1216
-        $mobile_label = self::mobileLabel(
1217
-            $add_mobile_label,
1218
-            $question,
1219
-            $required_text,
1220
-            $required['label'],
1221
-            $label_class,
1222
-            $name
1223
-        );
1224
-
1225
-        $input_html = $mobile_label
1226
-            . '<select name="' . $name . '" id="' . $id . '" class="' . trim($class) . ' ' . $required['class'] . '" '
1227
-            . 'aria-label="' . esc_attr($required['msg']) . '"' . $disabled . ' ' . $extra . '>';
1228
-        // recursively count array elements, to determine total number of options
1229
-        $only_option = count($options, 1) == 1;
1230
-        if (! $only_option) {
1231
-            // if there is NO answer set and there are multiple options to choose from, then set the "please select" message as selected
1232
-            $selected   = $answer === null ? ' selected' : '';
1233
-            $input_html .= $add_please_select_option
1234
-                ? "\n\t\t\t\t"
1235
-                  . '<option value=""' . $selected . '>'
1236
-                  . esc_html__(' - please select - ', 'event_espresso')
1237
-                  . '</option>'
1238
-                : '';
1239
-        }
1240
-        foreach ($options as $key => $value) {
1241
-            // if value is an array, then create option groups, else create regular ol' options
1242
-            $input_html .= is_array($value)
1243
-                ? self::_generate_select_option_group(
1244
-                    $key,
1245
-                    $value,
1246
-                    $answer,
1247
-                    $use_html_entities
1248
-                )
1249
-                : self::_generate_select_option(
1250
-                    $value->value(),
1251
-                    $value->desc(),
1252
-                    $answer,
1253
-                    $only_option,
1254
-                    $use_html_entities
1255
-                );
1256
-        }
1257
-
1258
-        $input_html .= "\n\t\t\t" . '</select>';
1259
-
1260
-        $input_html =
1261
-            apply_filters(
1262
-                'FHEE__EEH_Form_Fields__select__before_end_wrapper',
1263
-                $input_html,
1264
-                $question,
1265
-                $answer,
1266
-                $name,
1267
-                $id,
1268
-                $class,
1269
-                $system_ID
1270
-            );
1271
-
1272
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1273
-        return $label_html . $input_html;
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     *  _generate_select_option_group
1279
-     *
1280
-     *  if  $value for a select box is an array, then the key will be used as the optgroup label
1281
-     *  and the value array will be looped thru and the elements sent to _generate_select_option
1282
-     *
1283
-     * @param mixed   $opt_group
1284
-     * @param mixed   $QSOs
1285
-     * @param mixed   $answer
1286
-     * @param boolean $use_html_entities
1287
-     * @return string
1288
-     */
1289
-    private static function _generate_select_option_group($opt_group, $QSOs, $answer, $use_html_entities = true)
1290
-    {
1291
-        $html = "\n\t\t\t\t" . '<optgroup label="' . self::prep_option_value($opt_group) . '">';
1292
-        foreach ($QSOs as $QSO) {
1293
-            $html .= self::_generate_select_option($QSO->value(), $QSO->desc(), $answer, false, $use_html_entities);
1294
-        }
1295
-        $html .= "\n\t\t\t\t" . '</optgroup>';
1296
-        return $html;
1297
-    }
1298
-
1299
-
1300
-    /**
1301
-     *  _generate_select_option
1302
-     *
1303
-     * @param mixed   $key
1304
-     * @param mixed   $value
1305
-     * @param mixed   $answer
1306
-     * @param int     $only_option
1307
-     * @param boolean $use_html_entities
1308
-     * @return string
1309
-     */
1310
-    private static function _generate_select_option(
1311
-        $key,
1312
-        $value,
1313
-        $answer,
1314
-        $only_option = false,
1315
-        $use_html_entities = true
1316
-    ) {
1317
-        $key      = self::prep_answer($key, $use_html_entities);
1318
-        $value    = self::prep_answer($value, $use_html_entities);
1319
-        $value    = ! empty($value) ? $value : $key;
1320
-        $selected = ($answer == $key || $only_option) ? 'selected' : '';
1321
-        return "\n\t\t\t\t"
1322
-               . '<option value="' . self::prep_option_value($key) . '" ' . $selected . '> '
1323
-               . $value
1324
-               . '&nbsp;&nbsp;&nbsp;</option>';
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * generates HTML for form radio button inputs
1330
-     *
1331
-     * @param string      $question    label content
1332
-     * @param string|int  $answer      form input value attribute
1333
-     * @param array|bool  $options     array of answer options where array key = option value and array value = option
1334
-     *                                 display text
1335
-     * @param string $name        form input name attribute
1336
-     * @param string      $id          form input css id attribute
1337
-     * @param string      $class       form input css class attribute
1338
-     * @param array|bool  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1339
-     *                                 required 'class', and required 'msg' attribute
1340
-     * @param string      $required_text
1341
-     * @param string      $label_class css class attribute for the label
1342
-     * @param bool|string $disabled    disabled="disabled" or null
1343
-     * @param string      $system_ID
1344
-     * @param bool        $use_html_entities
1345
-     * @param bool        $label_b4
1346
-     * @param bool        $use_desc_4_label
1347
-     * @return string HTML
1348
-     */
1349
-    public static function radio(
1350
-        string $question = '',
1351
-        $answer = null,
1352
-        $options = false,
1353
-        string $name = '',
1354
-        string $id = '',
1355
-        string $class = '',
1356
-        $required = false,
1357
-        string $required_text = '',
1358
-        string $label_class = '',
1359
-        bool $disabled = false,
1360
-        string $system_ID = '',
1361
-        bool $use_html_entities = true,
1362
-        bool $label_b4 = false,
1363
-        bool $use_desc_4_label = false,
1364
-        bool $add_mobile_label = false
1365
-    ) {
1366
-        // need these
1367
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1368
-            return null;
1369
-        }
1370
-        // prep the answer
1371
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1372
-        // prep the required array
1373
-        $required = self::prep_required($required);
1374
-        // set disabled tag
1375
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1376
-        // ya gots ta have style man!!!
1377
-        $radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1378
-        $class       = ! empty($class) ? $class : 'espresso-radio-btn-inp';
1379
-        $extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1380
-
1381
-        $label_html = self::label($question, $required_text, $required['label'], '', $label_class);
1382
-        $mobile_label = self::mobileLabel(
1383
-            $add_mobile_label,
1384
-            $question,
1385
-            $required_text,
1386
-            $required['label'],
1387
-            $label_class
1388
-        );
1389
-
1390
-        $input_html = $mobile_label
1391
-            . '<ul id="' . $id . '-ul" class="espresso-radio-btn-options-ul ' . $class . '-ul">';
1392
-
1393
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1394
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1395
-
1396
-        foreach ($options as $OPT) {
1397
-            if ($OPT instanceof EE_Question_Option) {
1398
-                $value   = self::prep_option_value($OPT->value());
1399
-                $label   = $use_desc_4_label ? $OPT->desc() : $OPT->value();
1400
-                $size    = $use_desc_4_label
1401
-                    ? self::get_label_size_class($OPT->value() . ' ' . $OPT->desc())
1402
-                    : self::get_label_size_class($OPT->value());
1403
-                $desc    = $OPT->desc();// no self::prep_answer
1404
-                $answer  = is_numeric($value) && empty($answer) ? 0 : $answer;
1405
-                $value  = is_numeric($answer) && empty($value) ? 0 : $value;
1406
-                $checked = (string) $value == (string) $answer ? ' checked' : '';
1407
-                $opt     = '-' . sanitize_key($value);
1408
-
1409
-                $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1410
-                $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-radio-btn-lbl">';
1411
-                $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $label . '</span>&nbsp;' : '';
1412
-                $input_html .= "\n\t\t\t\t\t\t"
1413
-                               . '<input type="radio" name="' . $name . '" id="' . $id . $opt . '" '
1414
-                               . 'class="' . $class . '" value="' . $value . '" '
1415
-                               . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled
1416
-                               . $checked . ' ' . $extra . '/>';
1417
-                $input_html .= ! $label_b4
1418
-                    ? "\n\t\t\t\t\t\t"
1419
-                      . '&nbsp;<span class="espresso-radio-btn-desc">'
1420
-                      . $label
1421
-                      . '</span>'
1422
-                    : '';
1423
-                $input_html .= "\n\t\t\t\t\t" . '</label>';
1424
-                $input_html .= $use_desc_4_label
1425
-                    ? ''
1426
-                    : '<span class="espresso-radio-btn-option-desc small-text grey-text">' . $desc . '</span>';
1427
-                $input_html .= "\n\t\t\t\t" . '</li>';
1428
-            }
1429
-        }
1430
-
1431
-        $input_html .= "\n\t\t\t" . '</ul>';
1432
-
1433
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1434
-        return $label_html . $input_html;
1435
-    }
1436
-
1437
-
1438
-    /**
1439
-     * generates HTML for form checkbox inputs
1440
-     *
1441
-     * @param string $question    label content
1442
-     * @param string $answer      form input value attribute
1443
-     * @param array  $options     array of options where array key = option value and array value = option display text
1444
-     * @param string $name        form input name attribute
1445
-     * @param string $id          form input css id attribute
1446
-     * @param string $class       form input css class attribute
1447
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1448
-     *                            required 'class', and required 'msg' attribute
1449
-     * @param string $label_class css class attribute for the label
1450
-     * @param string $disabled    disabled="disabled" or null
1451
-     * @return string HTML
1452
-     */
1453
-    public static function checkbox(
1454
-        $question = false,
1455
-        $answer = null,
1456
-        $options = false,
1457
-        $name = false,
1458
-        $id = '',
1459
-        $class = '',
1460
-        $required = false,
1461
-        $required_text = '',
1462
-        $label_class = '',
1463
-        $disabled = false,
1464
-        $label_b4 = false,
1465
-        $system_ID = false,
1466
-        $use_html_entities = true,
1467
-        $add_mobile_label = false
1468
-    ) {
1469
-        // need these
1470
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1471
-            return null;
1472
-        }
1473
-        $answer = maybe_unserialize($answer);
1474
-
1475
-        // prep the answer(s)
1476
-        $answer = is_array($answer) ? $answer : [sanitize_key($answer) => $answer];
1477
-
1478
-        foreach ($answer as $key => $value) {
1479
-            $key            = self::prep_option_value($key);
1480
-            $answer[ $key ] = self::prep_answer($value, $use_html_entities);
1481
-        }
1482
-
1483
-        // prep the required array
1484
-        $required = self::prep_required($required);
1485
-        // set disabled tag
1486
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1487
-        // ya gots ta have style man!!!
1488
-        $radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1489
-        $class       = empty($class) ? 'espresso-radio-btn-inp' : $class;
1490
-        $extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1491
-
1492
-        $label_html   = self::label($question, $required_text, $required['label'], '', $label_class);
1493
-        $mobile_label = self::mobileLabel(
1494
-            $add_mobile_label,
1495
-            $question,
1496
-            $required_text,
1497
-            $required['label'],
1498
-            $label_class
1499
-        );
1500
-
1501
-        $input_html = $mobile_label
1502
-            . '<ul id="' . $id . '-ul" class="espresso-checkbox-options-ul ' . $class . '-ul">';
1503
-
1504
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1505
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1506
-
1507
-        foreach ($options as $OPT) {
1508
-            $value = $OPT->value();// self::prep_option_value( $OPT->value() );
1509
-            $size  = self::get_label_size_class($OPT->value() . ' ' . $OPT->desc());
1510
-            $text  = self::prep_answer($OPT->value());
1511
-            $desc  = $OPT->desc();
1512
-            $opt   = '-' . sanitize_key($value);
1513
-
1514
-            $checked = is_array($answer) && in_array($text, $answer) ? ' checked' : '';
1515
-
1516
-            $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1517
-            $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-checkbox-lbl">';
1518
-            $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>&nbsp;' : '';
1519
-            $input_html .= "\n\t\t\t\t\t\t"
1520
-                           . '<input type="checkbox" name="' . $name . '[' . $OPT->ID() . ']" '
1521
-                           . 'id="' . $id . $opt . '" class="' . $class . '" value="' . $value . '" '
1522
-                           . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled . $checked . ' ' . $extra . '/>';
1523
-            $input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t" . '&nbsp;<span>' . $text . '</span>' : '';
1524
-            $input_html .= "\n\t\t\t\t\t" . '</label>';
1525
-            if (! empty($desc) && $desc != $text) {
1526
-                $input_html .= "\n\t\t\t\t\t"
1527
-                               . ' &nbsp; <br/><div class="espresso-checkbox-option-desc small-text grey-text">'
1528
-                               . $desc
1529
-                               . '</div>';
1530
-            }
1531
-            $input_html .= "\n\t\t\t\t" . '</li>';
1532
-        }
1533
-
1534
-        $input_html .= "\n\t\t\t" . '</ul>';
1535
-
1536
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1537
-        return $label_html . $input_html;
1538
-    }
1539
-
1540
-
1541
-    /**
1542
-     * generates HTML for a form datepicker input
1543
-     *
1544
-     * @param string $question    label content
1545
-     * @param string $answer      form input value attribute
1546
-     * @param string $name        form input name attribute
1547
-     * @param string $id          form input css id attribute
1548
-     * @param string $class       form input css class attribute
1549
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1550
-     *                            required 'class', and required 'msg' attribute
1551
-     * @param string $label_class css class attribute for the label
1552
-     * @param string $disabled    disabled="disabled" or null
1553
-     * @return string HTML
1554
-     */
1555
-    public static function datepicker(
1556
-        $question = false,
1557
-        $answer = null,
1558
-        $name = false,
1559
-        $id = '',
1560
-        $class = '',
1561
-        $required = false,
1562
-        $required_text = '',
1563
-        $label_class = '',
1564
-        $disabled = false,
1565
-        $system_ID = false,
1566
-        $use_html_entities = true,
1567
-        $add_mobile_label = false
1568
-    ) {
1569
-        // need these
1570
-        if (! $question || ! $name) {
1571
-            return null;
1572
-        }
1573
-        // prep the answer
1574
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1575
-        // prep the required array
1576
-        $required = self::prep_required($required);
1577
-        // set disabled tag
1578
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1579
-        // ya gots ta have style man!!!
1580
-        $txt_class = is_admin() ? 'regular-text' : 'espresso-datepicker-inp';
1581
-        $class     = empty($class) ? $txt_class : $class;
1582
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1583
-        $class = self::appendInputSizeClass($class, $answer);
1584
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1585
-
1586
-        $label_html   = self::label($question, $required_text, $required['label'], '', $label_class);
1587
-        $mobile_label = self::mobileLabel(
1588
-            $add_mobile_label,
1589
-            $question,
1590
-            $required_text,
1591
-            $required['label'],
1592
-            $label_class,
1593
-            $name
1594
-        );
1595
-
1596
-        $input_html = $mobile_label
1597
-            . '<input type="text" name="' . $name . '" id="' . $id . '" '
1598
-            . 'class="' . $class . ' ' . $required['class'] . ' datepicker" value="' . $answer . '"  '
1599
-            . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
1600
-
1601
-        // enqueue scripts
1602
-        wp_register_style(
1603
-            'espresso-ui-theme',
1604
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1605
-            [],
1606
-            EVENT_ESPRESSO_VERSION
1607
-        );
1608
-        wp_enqueue_style('espresso-ui-theme');
1609
-        wp_enqueue_script('jquery-ui-datepicker');
1610
-
1611
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1612
-        return $label_html . $input_html;
1613
-    }
1614
-
1615
-
1616
-    /**
1617
-     *  remove_label_keep_required_msg
1618
-     *  this will strip out a form input's label HTML while keeping the required text HTML that MUST be before the label
1619
-     *
1620
-     * @access public
1621
-     * @return     string
1622
-     */
1623
-    public static function remove_label_keep_required_msg($label_html, $required_text)
1624
-    {
1625
-        return $required_text;
1626
-    }
1627
-
1628
-
1629
-    /**
1630
-     * Simply returns the HTML for a hidden input of the given name and value.
1631
-     *
1632
-     * @param string $name
1633
-     * @param string $value
1634
-     * @return string HTML
1635
-     */
1636
-    public static function hidden_input($name, $value, $id = '')
1637
-    {
1638
-        $id = ! empty($id) ? $id : $name;
1639
-        return '<input id="' . $id . '" type="hidden" name="' . $name . '" value="' . $value . '"/>';
1640
-    }
1641
-
1642
-
1643
-    /**
1644
-     * prep_question
1645
-     *
1646
-     * @param string $question
1647
-     * @return string
1648
-     */
1649
-    public static function prep_question($question)
1650
-    {
1651
-        return $question;
1652
-    }
1653
-
1654
-
1655
-    /**
1656
-     *  prep_answer
1657
-     *
1658
-     * @param mixed $answer
1659
-     * @return string
1660
-     */
1661
-    public static function prep_answer($answer, $use_html_entities = true)
1662
-    {
1663
-        // make sure we convert bools first.  Otherwise (bool) false becomes an empty string which is NOT desired,
1664
-        // we want "0".
1665
-        if (is_bool($answer)) {
1666
-            $answer = $answer ? 1 : 0;
1667
-        }
1668
-        $answer = trim(stripslashes(str_replace('&#039;', "'", $answer)));
1669
-        return $use_html_entities ? htmlentities($answer, ENT_QUOTES, 'UTF-8') : $answer;
1670
-    }
1671
-
1672
-
1673
-    /**
1674
-     *  prep_answer_options
1675
-     *
1676
-     * @param array $QSOs array of EE_Question_Option objects
1677
-     * @return array
1678
-     */
1679
-    public static function prep_answer_options($QSOs = [])
1680
-    {
1681
-        $prepped_answer_options = [];
1682
-        if (is_array($QSOs) && ! empty($QSOs)) {
1683
-            foreach ($QSOs as $key => $QSO) {
1684
-                if (! $QSO instanceof EE_Question_Option) {
1685
-                    $QSO = EE_Question_Option::new_instance(
1686
-                        [
1687
-                            'QSO_value' => is_array($QSO) && isset($QSO['id'])
1688
-                                ? (string) $QSO['id']
1689
-                                : (string) $key,
1690
-                            'QSO_desc'  => is_array($QSO) && isset($QSO['text'])
1691
-                                ? (string) $QSO['text']
1692
-                                : (string) $QSO,
1693
-                        ]
1694
-                    );
1695
-                }
1696
-                if ($QSO->opt_group()) {
1697
-                    $prepped_answer_options[ $QSO->opt_group() ][] = $QSO;
1698
-                } else {
1699
-                    $prepped_answer_options[] = $QSO;
1700
-                }
1701
-            }
1702
-        }
1703
-        //      d( $prepped_answer_options );
1704
-        return $prepped_answer_options;
1705
-    }
1706
-
1707
-
1708
-    /**
1709
-     *  prep_option_value
1710
-     *
1711
-     * @param string|int $option_value
1712
-     * @return string
1713
-     */
1714
-    public static function prep_option_value($option_value)
1715
-    {
1716
-        return esc_attr(trim(stripslashes($option_value)));
1717
-    }
1718
-
1719
-
1720
-    /**
1721
-     *  prep_required
1722
-     *
1723
-     * @param string|array $required
1724
-     * @return array
1725
-     */
1726
-    public static function prep_required($required = [])
1727
-    {
1728
-        // make sure required is an array
1729
-        $required = is_array($required) ? $required : [];
1730
-        // and set some defaults
1731
-        return array_merge(['label' => '', 'class' => '', 'msg' => ''], $required);
1732
-    }
1733
-
1734
-
1735
-    /**
1736
-     *  get_label_size_class
1737
-     *
1738
-     * @param string $value
1739
-     * @return string
1740
-     */
1741
-    public static function get_label_size_class($value = false)
1742
-    {
1743
-        if ($value === false || $value === '') {
1744
-            return ' class="medium-lbl"';
1745
-        }
1746
-        // determine length of option value
1747
-        $val_size = strlen($value);
1748
-        switch ($val_size) {
1749
-            case $val_size < 3:
1750
-                $size = ' class="nano-lbl"';
1751
-                break;
1752
-            case $val_size < 6:
1753
-                $size = ' class="micro-lbl"';
1754
-                break;
1755
-            case $val_size < 12:
1756
-                $size = ' class="tiny-lbl"';
1757
-                break;
1758
-            case $val_size < 25:
1759
-                $size = ' class="small-lbl"';
1760
-                break;
1761
-            case $val_size > 100:
1762
-                $size = ' class="big-lbl"';
1763
-                break;
1764
-            default:
1765
-                $size = ' class="medium-lbl"';
1766
-                break;
1767
-        }
1768
-        return $size;
1769
-    }
1770
-
1771
-
1772
-    /**
1773
-     *  _load_system_dropdowns
1774
-     *
1775
-     * @param EE_Question_Form_Input $QFI
1776
-     * @return array
1777
-     * @throws EE_Error
1778
-     * @throws ReflectionException
1779
-     */
1780
-    private static function _load_system_dropdowns($QFI)
1781
-    {
1782
-        $QST_system = $QFI->get('QST_system');
1783
-        switch ($QST_system) {
1784
-            case 'state':
1785
-                $QFI = self::generate_state_dropdown($QFI);
1786
-                break;
1787
-            case 'country':
1788
-                $QFI = self::generate_country_dropdown($QFI);
1789
-                break;
1790
-            case 'admin-state':
1791
-                $QFI = self::generate_state_dropdown($QFI, true);
1792
-                break;
1793
-            case 'admin-country':
1794
-                $QFI = self::generate_country_dropdown($QFI, true);
1795
-                break;
1796
-        }
1797
-        return $QFI;
1798
-    }
1799
-
1800
-
1801
-    /**
1802
-     * This preps dropdowns that are specialized.
1803
-     *
1804
-     * @param EE_Question_Form_Input $QFI
1805
-     *
1806
-     * @return EE_Question_Form_Input
1807
-     * @throws EE_Error
1808
-     * @throws ReflectionException
1809
-     * @since  4.6.0
1810
-     */
1811
-    protected static function _load_specialized_dropdowns($QFI)
1812
-    {
1813
-        switch ($QFI->get('QST_type')) {
1814
-            case 'STATE':
1815
-                $QFI = self::generate_state_dropdown($QFI);
1816
-                break;
1817
-            case 'COUNTRY':
1818
-                $QFI = self::generate_country_dropdown($QFI);
1819
-                break;
1820
-        }
1821
-        return $QFI;
1822
-    }
1823
-
1824
-
1825
-    /**
1826
-     *    generate_state_dropdown
1827
-     *
1828
-     * @param EE_Question_Form_Input $QST
1829
-     * @param bool                   $get_all
1830
-     * @return EE_Question_Form_Input
1831
-     * @throws EE_Error
1832
-     * @throws ReflectionException
1833
-     */
1834
-    public static function generate_state_dropdown($QST, $get_all = false)
1835
-    {
1836
-        $states = $get_all
1837
-            ? EEM_State::instance()->get_all_states()
1838
-            : EEM_State::instance()->get_all_states_of_active_countries();
1839
-        if ($states && count($states) != count($QST->options())) {
1840
-            $QST->set('QST_type', 'DROPDOWN');
1841
-            // if multiple countries, we'll create option groups within the dropdown
1842
-            foreach ($states as $state) {
1843
-                if ($state instanceof EE_State) {
1844
-                    $QSO = EE_Question_Option::new_instance(
1845
-                        [
1846
-                            'QSO_value'   => $state->ID(),
1847
-                            'QSO_desc'    => $state->name(),
1848
-                            'QST_ID'      => $QST->get('QST_ID'),
1849
-                            'QSO_deleted' => false,
1850
-                        ]
1851
-                    );
1852
-                    // set option group
1853
-                    $QSO->set_opt_group($state->country()->name());
1854
-                    // add option to question
1855
-                    $QST->add_temp_option($QSO);
1856
-                }
1857
-            }
1858
-        }
1859
-        return $QST;
1860
-    }
1861
-
1862
-
1863
-    /**
1864
-     *    generate_country_dropdown
1865
-     *
1866
-     * @param      $QST
1867
-     * @param bool $get_all
1868
-     * @return array
1869
-     * @throws EE_Error
1870
-     * @throws ReflectionException
1871
-     * @internal param array $question
1872
-     */
1873
-    public static function generate_country_dropdown($QST, $get_all = false)
1874
-    {
1875
-        $countries = $get_all
1876
-            ? EEM_Country::instance()->get_all_countries()
1877
-            : EEM_Country::instance()->get_all_active_countries();
1878
-        if ($countries && count($countries) != count($QST->options())) {
1879
-            $QST->set('QST_type', 'DROPDOWN');
1880
-            // now add countries
1881
-            foreach ($countries as $country) {
1882
-                if ($country instanceof EE_Country) {
1883
-                    $QSO = EE_Question_Option::new_instance(
1884
-                        [
1885
-                            'QSO_value'   => $country->ID(),
1886
-                            'QSO_desc'    => $country->name(),
1887
-                            'QST_ID'      => $QST->get('QST_ID'),
1888
-                            'QSO_deleted' => false,
1889
-                        ]
1890
-                    );
1891
-                    $QST->add_temp_option($QSO);
1892
-                }
1893
-            }
1894
-        }
1895
-        return $QST;
1896
-    }
1897
-
1898
-
1899
-    /**
1900
-     *  generates options for a month dropdown selector with numbers from 01 to 12
1901
-     *
1902
-     * @return array()
1903
-     */
1904
-    public static function two_digit_months_dropdown_options()
1905
-    {
1906
-        $options = [];
1907
-        for ($x = 1; $x <= 12; $x++) {
1908
-            $mm             = str_pad($x, 2, '0', STR_PAD_LEFT);
1909
-            $options[ $mm ] = $mm;
1910
-        }
1911
-        return EEH_Form_Fields::prep_answer_options($options);
1912
-    }
1913
-
1914
-
1915
-    /**
1916
-     *  generates a year dropdown selector with numbers for the next ten years
1917
-     *
1918
-     * @return array
1919
-     */
1920
-    public static function next_decade_two_digit_year_dropdown_options()
1921
-    {
1922
-        $options      = [];
1923
-        $current_year = date('y');
1924
-        $next_decade  = $current_year + 10;
1925
-        for ($x = $current_year; $x <= $next_decade; $x++) {
1926
-            $yy             = str_pad($x, 2, '0', STR_PAD_LEFT);
1927
-            $options[ $yy ] = $yy;
1928
-        }
1929
-        return EEH_Form_Fields::prep_answer_options($options);
1930
-    }
1931
-
1932
-
1933
-    /**
1934
-     * generates a month/year dropdown selector for all registrations matching the given criteria.  Typically used for
1935
-     * list table filter.
1936
-     *
1937
-     * @param string  $cur_date     any currently selected date can be entered here.
1938
-     * @param string  $status       Registration status
1939
-     * @param integer $evt_category Event Category ID if the Event Category filter is selected
1940
-     * @return string                html
1941
-     * @throws EE_Error
1942
-     */
1943
-    public static function generate_registration_months_dropdown($cur_date = '', $status = '', $evt_category = 0)
1944
-    {
1945
-        $_where = [];
1946
-        if (! empty($status)) {
1947
-            $_where['STS_ID'] = $status;
1948
-        }
1949
-
1950
-        if ($evt_category > 0) {
1951
-            $_where['Event.Term_Taxonomy.term_id'] = $evt_category;
1952
-        }
1953
-
1954
-        $reg_dates = EEM_Registration::instance()->get_reg_months_and_years($_where);
1955
-
1956
-        // setup vals for select input helper
1957
-        $options = [
1958
-            0 => [
1959
-                'text' => esc_html__('Select a Month/Year', 'event_espresso'),
1960
-                'id'   => '',
1961
-            ],
1962
-        ];
1963
-
1964
-        foreach ($reg_dates as $reg_date) {
1965
-            $date      = $reg_date->reg_month . ' ' . $reg_date->reg_year;
1966
-            $options[] = [
1967
-                'text' => $date,
1968
-                'id'   => $date,
1969
-            ];
1970
-        }
1971
-
1972
-        return self::select_input('month_range', $options, $cur_date, '', 'ee-list-table-filter');
1973
-    }
1974
-
1975
-
1976
-    /**
1977
-     * generates a month/year dropdown selector for all events matching the given criteria
1978
-     * Typically used for list table filter
1979
-     *
1980
-     * @param string $cur_date          any currently selected date can be entered here.
1981
-     * @param string $status            "view" (i.e. all, today, month, draft)
1982
-     * @param int    $evt_category      category event belongs to
1983
-     * @param string $evt_active_status "upcoming", "expired", "active", or "inactive"
1984
-     * @return string
1985
-     * @throws EE_Error
1986
-     * @throws ReflectionException
1987
-     */
1988
-    public static function generate_event_months_dropdown(
1989
-        string $cur_date = '',
1990
-        string $status = 'all',
1991
-        int $evt_category = 0,
1992
-        string $evt_active_status = ''
1993
-    ): string {
1994
-        $status = empty($status) ? 'all' : $status;
1995
-        // determine what post_status our condition will have for the query.
1996
-        switch ($status) {
1997
-            case 'month':
1998
-            case 'today':
1999
-            case 'all':
2000
-                $where['Event.status'] = ['NOT IN', ['trash']];
2001
-                break;
2002
-            case 'draft':
2003
-                $where['Event.status'] = ['IN', ['draft', 'auto-draft']];
2004
-                break;
2005
-            default:
2006
-                $where['Event.status'] = $status;
2007
-        }
2008
-
2009
-        // categories?
2010
-        if (! empty($evt_category) and $evt_category > 0) {
2011
-            $where['Event.Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
2012
-            $where['Event.Term_Taxonomy.term_id']  = $evt_category;
2013
-        }
2014
-
2015
-        //      $where['DTT_is_primary'] = 1;
2016
-
2017
-        $DTTS = EEM_Datetime::instance()->get_dtt_months_and_years($where, $evt_active_status);
2018
-
2019
-        // let's setup vals for select input helper
2020
-        $options = [
2021
-            0 => [
2022
-                'text' => esc_html__('Select a Month/Year', 'event_espresso'),
2023
-                'id'   => "",
2024
-            ],
2025
-        ];
2026
-
2027
-
2028
-        // translate month and date
2029
-        global $wp_locale;
2030
-
2031
-        foreach ($DTTS as $DTT) {
2032
-            $localized_date = $wp_locale->get_month($DTT->dtt_month_num) . ' ' . $DTT->dtt_year;
2033
-            $id             = $DTT->dtt_month . ' ' . $DTT->dtt_year;
2034
-            $options[]      = [
2035
-                'text' => $localized_date,
2036
-                'id'   => $id,
2037
-            ];
2038
-        }
2039
-
2040
-
2041
-        return self::select_input('month_range', $options, $cur_date, '', 'ee-list-table-filter');
2042
-    }
2043
-
2044
-
2045
-    /**
2046
-     * generates the dropdown selector for event categories
2047
-     * typically used as a filter on list tables.
2048
-     *
2049
-     * @param integer $current_cat currently selected category
2050
-     * @return string               html for dropdown
2051
-     * @throws EE_Error
2052
-     * @throws ReflectionException
2053
-     */
2054
-    public static function generate_event_category_dropdown($current_cat = -1)
2055
-    {
2056
-        $categories = EEM_Term::instance()->get_all_ee_categories(true);
2057
-        $options    = [
2058
-            '0' => [
2059
-                'text' => esc_html__('All Categories', 'event_espresso'),
2060
-                'id'   => -1,
2061
-            ],
2062
-        ];
2063
-
2064
-        // setup categories for dropdown
2065
-        foreach ($categories as $category) {
2066
-            $options[] = [
2067
-                'text' => $category->get('name'),
2068
-                'id'   => $category->ID(),
2069
-            ];
2070
-        }
2071
-
2072
-        return self::select_input('EVT_CAT', $options, $current_cat, '', 'ee-list-table-filter');
2073
-    }
2074
-
2075
-
2076
-    /**
2077
-     *    generate a submit button with or without its own microform
2078
-     *    this is the only way to create buttons that are compatible across all themes
2079
-     *
2080
-     * @access    public
2081
-     * @param string      $url              - the form action
2082
-     * @param string      $ID               - some kind of unique ID, appended with "-sbmt" for the input and "-frm"
2083
-     *                                      for the form
2084
-     * @param string      $class            - css classes (separated by spaces if more than one)
2085
-     * @param string      $text             - what appears on the button
2086
-     * @param string      $nonce_action     - if using nonces
2087
-     * @param bool|string $input_only       - whether to print form header and footer. TRUE returns the input without
2088
-     *                                      the form
2089
-     * @param string      $extra_attributes - any extra attributes that need to be attached to the form input
2090
-     * @return    string
2091
-     */
2092
-    public static function submit_button(
2093
-        $url = '',
2094
-        $ID = '',
2095
-        $class = '',
2096
-        $text = '',
2097
-        $nonce_action = '',
2098
-        $input_only = false,
2099
-        $extra_attributes = ''
2100
-    ) {
2101
-        $btn = '';
2102
-        if (empty($url) || empty($ID)) {
2103
-            return $btn;
2104
-        }
2105
-        $text = ! empty($text) ? $text : esc_html__('Submit', 'event_espresso');
2106
-        $btn  .= '<input id="' . $ID . '-btn" class="' . $class . '" '
2107
-                 . 'type="submit" value="' . $text . '" ' . $extra_attributes . '/>';
2108
-        if (! $input_only) {
2109
-            $btn_frm = '<form id="' . $ID . '-frm" method="POST" action="' . $url . '">';
2110
-            $btn_frm .= ! empty($nonce_action)
2111
-                ? wp_nonce_field($nonce_action, $nonce_action . '_nonce', true, false)
2112
-                : '';
2113
-            $btn_frm .= $btn;
2114
-            $btn_frm .= '</form>';
2115
-            $btn     = $btn_frm;
2116
-            unset($btn_frm);
2117
-        }
2118
-        return $btn;
2119
-    }
1089
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1090
+		return $label_html . $input_html;
1091
+	}
1092
+
1093
+
1094
+	/**
1095
+	 * generates HTML for a form textarea
1096
+	 *
1097
+	 * @param string $question    label content
1098
+	 * @param string $answer      form input value attribute
1099
+	 * @param string $name        form input name attribute
1100
+	 * @param string $id          form input css id attribute
1101
+	 * @param string $class       form input css class attribute
1102
+	 * @param array  $dimensions  array of form input rows and cols attributes : array( 'rows' => 3, 'cols' => 40 )
1103
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1104
+	 *                            required 'class', and required 'msg' attribute
1105
+	 * @param string $label_class css class attribute for the label
1106
+	 * @param string $disabled    disabled="disabled" or null
1107
+	 * @return string HTML
1108
+	 */
1109
+	public static function textarea(
1110
+		$question = false,
1111
+		$answer = null,
1112
+		$name = false,
1113
+		$id = '',
1114
+		$class = '',
1115
+		$dimensions = false,
1116
+		$required = false,
1117
+		$required_text = '',
1118
+		$label_class = '',
1119
+		$disabled = false,
1120
+		$system_ID = false,
1121
+		$use_html_entities = true,
1122
+		$add_mobile_label = false
1123
+	) {
1124
+		// need these
1125
+		if (! $question || ! $name) {
1126
+			return null;
1127
+		}
1128
+		// prep the answer
1129
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1130
+		// prep the required array
1131
+		$required = self::prep_required($required);
1132
+		// make sure $dimensions is an array
1133
+		$dimensions = is_array($dimensions) ? $dimensions : [];
1134
+		// and set some defaults
1135
+		$dimensions = array_merge(['rows' => 3, 'cols' => 40], $dimensions);
1136
+		// set disabled tag
1137
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1138
+		// ya gots ta have style man!!!
1139
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1140
+		$class     .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1141
+		$extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1142
+
1143
+		$label_html   = self::label($question, $required_text, $required['label'], $name, $label_class);
1144
+		$mobile_label = self::mobileLabel(
1145
+			$add_mobile_label,
1146
+			$question,
1147
+			$required_text,
1148
+			$required['label'],
1149
+			$label_class,
1150
+			$name
1151
+		);
1152
+
1153
+		$input_html = $mobile_label
1154
+			. '<textarea name="' . $name . '" id="' . $id . '" class="' . trim($class) . '" '
1155
+			. 'rows="' . $dimensions['rows'] . '" cols="' . $dimensions['cols'] . '"  '
1156
+			. 'aria-label="' . $required['msg'] . '" ' . $disabled . ' ' . $extra . '>'
1157
+			 . esc_textarea($answer)
1158
+			  . '</textarea>';
1159
+
1160
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1161
+		return $label_html . $input_html;
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * generates HTML for a form select input
1167
+	 *
1168
+	 * @param string $question    label content
1169
+	 * @param string $answer      form input value attribute
1170
+	 * @param array  $options     array of answer options where array key = option value and array value = option
1171
+	 *                            display text
1172
+	 * @param string $name        form input name attribute
1173
+	 * @param string $id          form input css id attribute
1174
+	 * @param string $class       form input css class attribute
1175
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1176
+	 *                            required 'class', and required 'msg' attribute
1177
+	 * @param string $label_class css class attribute for the label
1178
+	 * @param string $disabled    disabled="disabled" or null
1179
+	 * @return string HTML
1180
+	 */
1181
+	public static function select(
1182
+		$question = false,
1183
+		$answer = null,
1184
+		$options = false,
1185
+		$name = false,
1186
+		$id = '',
1187
+		$class = '',
1188
+		$required = false,
1189
+		$required_text = '',
1190
+		$label_class = '',
1191
+		$disabled = false,
1192
+		$system_ID = false,
1193
+		$use_html_entities = true,
1194
+		$add_please_select_option = false,
1195
+		$add_mobile_label = false
1196
+	) {
1197
+
1198
+		// need these
1199
+		if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1200
+			return null;
1201
+		}
1202
+		// prep the answer
1203
+		$answer = is_array($answer)
1204
+			? self::prep_answer(array_shift($answer), $use_html_entities)
1205
+			: self::prep_answer($answer, $use_html_entities);
1206
+		// prep the required array
1207
+		$required = self::prep_required($required);
1208
+		// set disabled tag
1209
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1210
+		// ya gots ta have style man!!!
1211
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1212
+		$class = self::appendInputSizeClass($class, $options);
1213
+		$extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1214
+
1215
+		$label_html   = self::label($question, $required_text, $required['label'], $name, $label_class);
1216
+		$mobile_label = self::mobileLabel(
1217
+			$add_mobile_label,
1218
+			$question,
1219
+			$required_text,
1220
+			$required['label'],
1221
+			$label_class,
1222
+			$name
1223
+		);
1224
+
1225
+		$input_html = $mobile_label
1226
+			. '<select name="' . $name . '" id="' . $id . '" class="' . trim($class) . ' ' . $required['class'] . '" '
1227
+			. 'aria-label="' . esc_attr($required['msg']) . '"' . $disabled . ' ' . $extra . '>';
1228
+		// recursively count array elements, to determine total number of options
1229
+		$only_option = count($options, 1) == 1;
1230
+		if (! $only_option) {
1231
+			// if there is NO answer set and there are multiple options to choose from, then set the "please select" message as selected
1232
+			$selected   = $answer === null ? ' selected' : '';
1233
+			$input_html .= $add_please_select_option
1234
+				? "\n\t\t\t\t"
1235
+				  . '<option value=""' . $selected . '>'
1236
+				  . esc_html__(' - please select - ', 'event_espresso')
1237
+				  . '</option>'
1238
+				: '';
1239
+		}
1240
+		foreach ($options as $key => $value) {
1241
+			// if value is an array, then create option groups, else create regular ol' options
1242
+			$input_html .= is_array($value)
1243
+				? self::_generate_select_option_group(
1244
+					$key,
1245
+					$value,
1246
+					$answer,
1247
+					$use_html_entities
1248
+				)
1249
+				: self::_generate_select_option(
1250
+					$value->value(),
1251
+					$value->desc(),
1252
+					$answer,
1253
+					$only_option,
1254
+					$use_html_entities
1255
+				);
1256
+		}
1257
+
1258
+		$input_html .= "\n\t\t\t" . '</select>';
1259
+
1260
+		$input_html =
1261
+			apply_filters(
1262
+				'FHEE__EEH_Form_Fields__select__before_end_wrapper',
1263
+				$input_html,
1264
+				$question,
1265
+				$answer,
1266
+				$name,
1267
+				$id,
1268
+				$class,
1269
+				$system_ID
1270
+			);
1271
+
1272
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1273
+		return $label_html . $input_html;
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 *  _generate_select_option_group
1279
+	 *
1280
+	 *  if  $value for a select box is an array, then the key will be used as the optgroup label
1281
+	 *  and the value array will be looped thru and the elements sent to _generate_select_option
1282
+	 *
1283
+	 * @param mixed   $opt_group
1284
+	 * @param mixed   $QSOs
1285
+	 * @param mixed   $answer
1286
+	 * @param boolean $use_html_entities
1287
+	 * @return string
1288
+	 */
1289
+	private static function _generate_select_option_group($opt_group, $QSOs, $answer, $use_html_entities = true)
1290
+	{
1291
+		$html = "\n\t\t\t\t" . '<optgroup label="' . self::prep_option_value($opt_group) . '">';
1292
+		foreach ($QSOs as $QSO) {
1293
+			$html .= self::_generate_select_option($QSO->value(), $QSO->desc(), $answer, false, $use_html_entities);
1294
+		}
1295
+		$html .= "\n\t\t\t\t" . '</optgroup>';
1296
+		return $html;
1297
+	}
1298
+
1299
+
1300
+	/**
1301
+	 *  _generate_select_option
1302
+	 *
1303
+	 * @param mixed   $key
1304
+	 * @param mixed   $value
1305
+	 * @param mixed   $answer
1306
+	 * @param int     $only_option
1307
+	 * @param boolean $use_html_entities
1308
+	 * @return string
1309
+	 */
1310
+	private static function _generate_select_option(
1311
+		$key,
1312
+		$value,
1313
+		$answer,
1314
+		$only_option = false,
1315
+		$use_html_entities = true
1316
+	) {
1317
+		$key      = self::prep_answer($key, $use_html_entities);
1318
+		$value    = self::prep_answer($value, $use_html_entities);
1319
+		$value    = ! empty($value) ? $value : $key;
1320
+		$selected = ($answer == $key || $only_option) ? 'selected' : '';
1321
+		return "\n\t\t\t\t"
1322
+			   . '<option value="' . self::prep_option_value($key) . '" ' . $selected . '> '
1323
+			   . $value
1324
+			   . '&nbsp;&nbsp;&nbsp;</option>';
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * generates HTML for form radio button inputs
1330
+	 *
1331
+	 * @param string      $question    label content
1332
+	 * @param string|int  $answer      form input value attribute
1333
+	 * @param array|bool  $options     array of answer options where array key = option value and array value = option
1334
+	 *                                 display text
1335
+	 * @param string $name        form input name attribute
1336
+	 * @param string      $id          form input css id attribute
1337
+	 * @param string      $class       form input css class attribute
1338
+	 * @param array|bool  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1339
+	 *                                 required 'class', and required 'msg' attribute
1340
+	 * @param string      $required_text
1341
+	 * @param string      $label_class css class attribute for the label
1342
+	 * @param bool|string $disabled    disabled="disabled" or null
1343
+	 * @param string      $system_ID
1344
+	 * @param bool        $use_html_entities
1345
+	 * @param bool        $label_b4
1346
+	 * @param bool        $use_desc_4_label
1347
+	 * @return string HTML
1348
+	 */
1349
+	public static function radio(
1350
+		string $question = '',
1351
+		$answer = null,
1352
+		$options = false,
1353
+		string $name = '',
1354
+		string $id = '',
1355
+		string $class = '',
1356
+		$required = false,
1357
+		string $required_text = '',
1358
+		string $label_class = '',
1359
+		bool $disabled = false,
1360
+		string $system_ID = '',
1361
+		bool $use_html_entities = true,
1362
+		bool $label_b4 = false,
1363
+		bool $use_desc_4_label = false,
1364
+		bool $add_mobile_label = false
1365
+	) {
1366
+		// need these
1367
+		if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1368
+			return null;
1369
+		}
1370
+		// prep the answer
1371
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1372
+		// prep the required array
1373
+		$required = self::prep_required($required);
1374
+		// set disabled tag
1375
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1376
+		// ya gots ta have style man!!!
1377
+		$radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1378
+		$class       = ! empty($class) ? $class : 'espresso-radio-btn-inp';
1379
+		$extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1380
+
1381
+		$label_html = self::label($question, $required_text, $required['label'], '', $label_class);
1382
+		$mobile_label = self::mobileLabel(
1383
+			$add_mobile_label,
1384
+			$question,
1385
+			$required_text,
1386
+			$required['label'],
1387
+			$label_class
1388
+		);
1389
+
1390
+		$input_html = $mobile_label
1391
+			. '<ul id="' . $id . '-ul" class="espresso-radio-btn-options-ul ' . $class . '-ul">';
1392
+
1393
+		$class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1394
+		$class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1395
+
1396
+		foreach ($options as $OPT) {
1397
+			if ($OPT instanceof EE_Question_Option) {
1398
+				$value   = self::prep_option_value($OPT->value());
1399
+				$label   = $use_desc_4_label ? $OPT->desc() : $OPT->value();
1400
+				$size    = $use_desc_4_label
1401
+					? self::get_label_size_class($OPT->value() . ' ' . $OPT->desc())
1402
+					: self::get_label_size_class($OPT->value());
1403
+				$desc    = $OPT->desc();// no self::prep_answer
1404
+				$answer  = is_numeric($value) && empty($answer) ? 0 : $answer;
1405
+				$value  = is_numeric($answer) && empty($value) ? 0 : $value;
1406
+				$checked = (string) $value == (string) $answer ? ' checked' : '';
1407
+				$opt     = '-' . sanitize_key($value);
1408
+
1409
+				$input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1410
+				$input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-radio-btn-lbl">';
1411
+				$input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $label . '</span>&nbsp;' : '';
1412
+				$input_html .= "\n\t\t\t\t\t\t"
1413
+							   . '<input type="radio" name="' . $name . '" id="' . $id . $opt . '" '
1414
+							   . 'class="' . $class . '" value="' . $value . '" '
1415
+							   . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled
1416
+							   . $checked . ' ' . $extra . '/>';
1417
+				$input_html .= ! $label_b4
1418
+					? "\n\t\t\t\t\t\t"
1419
+					  . '&nbsp;<span class="espresso-radio-btn-desc">'
1420
+					  . $label
1421
+					  . '</span>'
1422
+					: '';
1423
+				$input_html .= "\n\t\t\t\t\t" . '</label>';
1424
+				$input_html .= $use_desc_4_label
1425
+					? ''
1426
+					: '<span class="espresso-radio-btn-option-desc small-text grey-text">' . $desc . '</span>';
1427
+				$input_html .= "\n\t\t\t\t" . '</li>';
1428
+			}
1429
+		}
1430
+
1431
+		$input_html .= "\n\t\t\t" . '</ul>';
1432
+
1433
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1434
+		return $label_html . $input_html;
1435
+	}
1436
+
1437
+
1438
+	/**
1439
+	 * generates HTML for form checkbox inputs
1440
+	 *
1441
+	 * @param string $question    label content
1442
+	 * @param string $answer      form input value attribute
1443
+	 * @param array  $options     array of options where array key = option value and array value = option display text
1444
+	 * @param string $name        form input name attribute
1445
+	 * @param string $id          form input css id attribute
1446
+	 * @param string $class       form input css class attribute
1447
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1448
+	 *                            required 'class', and required 'msg' attribute
1449
+	 * @param string $label_class css class attribute for the label
1450
+	 * @param string $disabled    disabled="disabled" or null
1451
+	 * @return string HTML
1452
+	 */
1453
+	public static function checkbox(
1454
+		$question = false,
1455
+		$answer = null,
1456
+		$options = false,
1457
+		$name = false,
1458
+		$id = '',
1459
+		$class = '',
1460
+		$required = false,
1461
+		$required_text = '',
1462
+		$label_class = '',
1463
+		$disabled = false,
1464
+		$label_b4 = false,
1465
+		$system_ID = false,
1466
+		$use_html_entities = true,
1467
+		$add_mobile_label = false
1468
+	) {
1469
+		// need these
1470
+		if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1471
+			return null;
1472
+		}
1473
+		$answer = maybe_unserialize($answer);
1474
+
1475
+		// prep the answer(s)
1476
+		$answer = is_array($answer) ? $answer : [sanitize_key($answer) => $answer];
1477
+
1478
+		foreach ($answer as $key => $value) {
1479
+			$key            = self::prep_option_value($key);
1480
+			$answer[ $key ] = self::prep_answer($value, $use_html_entities);
1481
+		}
1482
+
1483
+		// prep the required array
1484
+		$required = self::prep_required($required);
1485
+		// set disabled tag
1486
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1487
+		// ya gots ta have style man!!!
1488
+		$radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1489
+		$class       = empty($class) ? 'espresso-radio-btn-inp' : $class;
1490
+		$extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1491
+
1492
+		$label_html   = self::label($question, $required_text, $required['label'], '', $label_class);
1493
+		$mobile_label = self::mobileLabel(
1494
+			$add_mobile_label,
1495
+			$question,
1496
+			$required_text,
1497
+			$required['label'],
1498
+			$label_class
1499
+		);
1500
+
1501
+		$input_html = $mobile_label
1502
+			. '<ul id="' . $id . '-ul" class="espresso-checkbox-options-ul ' . $class . '-ul">';
1503
+
1504
+		$class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1505
+		$class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1506
+
1507
+		foreach ($options as $OPT) {
1508
+			$value = $OPT->value();// self::prep_option_value( $OPT->value() );
1509
+			$size  = self::get_label_size_class($OPT->value() . ' ' . $OPT->desc());
1510
+			$text  = self::prep_answer($OPT->value());
1511
+			$desc  = $OPT->desc();
1512
+			$opt   = '-' . sanitize_key($value);
1513
+
1514
+			$checked = is_array($answer) && in_array($text, $answer) ? ' checked' : '';
1515
+
1516
+			$input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1517
+			$input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-checkbox-lbl">';
1518
+			$input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>&nbsp;' : '';
1519
+			$input_html .= "\n\t\t\t\t\t\t"
1520
+						   . '<input type="checkbox" name="' . $name . '[' . $OPT->ID() . ']" '
1521
+						   . 'id="' . $id . $opt . '" class="' . $class . '" value="' . $value . '" '
1522
+						   . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled . $checked . ' ' . $extra . '/>';
1523
+			$input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t" . '&nbsp;<span>' . $text . '</span>' : '';
1524
+			$input_html .= "\n\t\t\t\t\t" . '</label>';
1525
+			if (! empty($desc) && $desc != $text) {
1526
+				$input_html .= "\n\t\t\t\t\t"
1527
+							   . ' &nbsp; <br/><div class="espresso-checkbox-option-desc small-text grey-text">'
1528
+							   . $desc
1529
+							   . '</div>';
1530
+			}
1531
+			$input_html .= "\n\t\t\t\t" . '</li>';
1532
+		}
1533
+
1534
+		$input_html .= "\n\t\t\t" . '</ul>';
1535
+
1536
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1537
+		return $label_html . $input_html;
1538
+	}
1539
+
1540
+
1541
+	/**
1542
+	 * generates HTML for a form datepicker input
1543
+	 *
1544
+	 * @param string $question    label content
1545
+	 * @param string $answer      form input value attribute
1546
+	 * @param string $name        form input name attribute
1547
+	 * @param string $id          form input css id attribute
1548
+	 * @param string $class       form input css class attribute
1549
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1550
+	 *                            required 'class', and required 'msg' attribute
1551
+	 * @param string $label_class css class attribute for the label
1552
+	 * @param string $disabled    disabled="disabled" or null
1553
+	 * @return string HTML
1554
+	 */
1555
+	public static function datepicker(
1556
+		$question = false,
1557
+		$answer = null,
1558
+		$name = false,
1559
+		$id = '',
1560
+		$class = '',
1561
+		$required = false,
1562
+		$required_text = '',
1563
+		$label_class = '',
1564
+		$disabled = false,
1565
+		$system_ID = false,
1566
+		$use_html_entities = true,
1567
+		$add_mobile_label = false
1568
+	) {
1569
+		// need these
1570
+		if (! $question || ! $name) {
1571
+			return null;
1572
+		}
1573
+		// prep the answer
1574
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1575
+		// prep the required array
1576
+		$required = self::prep_required($required);
1577
+		// set disabled tag
1578
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1579
+		// ya gots ta have style man!!!
1580
+		$txt_class = is_admin() ? 'regular-text' : 'espresso-datepicker-inp';
1581
+		$class     = empty($class) ? $txt_class : $class;
1582
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1583
+		$class = self::appendInputSizeClass($class, $answer);
1584
+		$extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1585
+
1586
+		$label_html   = self::label($question, $required_text, $required['label'], '', $label_class);
1587
+		$mobile_label = self::mobileLabel(
1588
+			$add_mobile_label,
1589
+			$question,
1590
+			$required_text,
1591
+			$required['label'],
1592
+			$label_class,
1593
+			$name
1594
+		);
1595
+
1596
+		$input_html = $mobile_label
1597
+			. '<input type="text" name="' . $name . '" id="' . $id . '" '
1598
+			. 'class="' . $class . ' ' . $required['class'] . ' datepicker" value="' . $answer . '"  '
1599
+			. 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
1600
+
1601
+		// enqueue scripts
1602
+		wp_register_style(
1603
+			'espresso-ui-theme',
1604
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1605
+			[],
1606
+			EVENT_ESPRESSO_VERSION
1607
+		);
1608
+		wp_enqueue_style('espresso-ui-theme');
1609
+		wp_enqueue_script('jquery-ui-datepicker');
1610
+
1611
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1612
+		return $label_html . $input_html;
1613
+	}
1614
+
1615
+
1616
+	/**
1617
+	 *  remove_label_keep_required_msg
1618
+	 *  this will strip out a form input's label HTML while keeping the required text HTML that MUST be before the label
1619
+	 *
1620
+	 * @access public
1621
+	 * @return     string
1622
+	 */
1623
+	public static function remove_label_keep_required_msg($label_html, $required_text)
1624
+	{
1625
+		return $required_text;
1626
+	}
1627
+
1628
+
1629
+	/**
1630
+	 * Simply returns the HTML for a hidden input of the given name and value.
1631
+	 *
1632
+	 * @param string $name
1633
+	 * @param string $value
1634
+	 * @return string HTML
1635
+	 */
1636
+	public static function hidden_input($name, $value, $id = '')
1637
+	{
1638
+		$id = ! empty($id) ? $id : $name;
1639
+		return '<input id="' . $id . '" type="hidden" name="' . $name . '" value="' . $value . '"/>';
1640
+	}
1641
+
1642
+
1643
+	/**
1644
+	 * prep_question
1645
+	 *
1646
+	 * @param string $question
1647
+	 * @return string
1648
+	 */
1649
+	public static function prep_question($question)
1650
+	{
1651
+		return $question;
1652
+	}
1653
+
1654
+
1655
+	/**
1656
+	 *  prep_answer
1657
+	 *
1658
+	 * @param mixed $answer
1659
+	 * @return string
1660
+	 */
1661
+	public static function prep_answer($answer, $use_html_entities = true)
1662
+	{
1663
+		// make sure we convert bools first.  Otherwise (bool) false becomes an empty string which is NOT desired,
1664
+		// we want "0".
1665
+		if (is_bool($answer)) {
1666
+			$answer = $answer ? 1 : 0;
1667
+		}
1668
+		$answer = trim(stripslashes(str_replace('&#039;', "'", $answer)));
1669
+		return $use_html_entities ? htmlentities($answer, ENT_QUOTES, 'UTF-8') : $answer;
1670
+	}
1671
+
1672
+
1673
+	/**
1674
+	 *  prep_answer_options
1675
+	 *
1676
+	 * @param array $QSOs array of EE_Question_Option objects
1677
+	 * @return array
1678
+	 */
1679
+	public static function prep_answer_options($QSOs = [])
1680
+	{
1681
+		$prepped_answer_options = [];
1682
+		if (is_array($QSOs) && ! empty($QSOs)) {
1683
+			foreach ($QSOs as $key => $QSO) {
1684
+				if (! $QSO instanceof EE_Question_Option) {
1685
+					$QSO = EE_Question_Option::new_instance(
1686
+						[
1687
+							'QSO_value' => is_array($QSO) && isset($QSO['id'])
1688
+								? (string) $QSO['id']
1689
+								: (string) $key,
1690
+							'QSO_desc'  => is_array($QSO) && isset($QSO['text'])
1691
+								? (string) $QSO['text']
1692
+								: (string) $QSO,
1693
+						]
1694
+					);
1695
+				}
1696
+				if ($QSO->opt_group()) {
1697
+					$prepped_answer_options[ $QSO->opt_group() ][] = $QSO;
1698
+				} else {
1699
+					$prepped_answer_options[] = $QSO;
1700
+				}
1701
+			}
1702
+		}
1703
+		//      d( $prepped_answer_options );
1704
+		return $prepped_answer_options;
1705
+	}
1706
+
1707
+
1708
+	/**
1709
+	 *  prep_option_value
1710
+	 *
1711
+	 * @param string|int $option_value
1712
+	 * @return string
1713
+	 */
1714
+	public static function prep_option_value($option_value)
1715
+	{
1716
+		return esc_attr(trim(stripslashes($option_value)));
1717
+	}
1718
+
1719
+
1720
+	/**
1721
+	 *  prep_required
1722
+	 *
1723
+	 * @param string|array $required
1724
+	 * @return array
1725
+	 */
1726
+	public static function prep_required($required = [])
1727
+	{
1728
+		// make sure required is an array
1729
+		$required = is_array($required) ? $required : [];
1730
+		// and set some defaults
1731
+		return array_merge(['label' => '', 'class' => '', 'msg' => ''], $required);
1732
+	}
1733
+
1734
+
1735
+	/**
1736
+	 *  get_label_size_class
1737
+	 *
1738
+	 * @param string $value
1739
+	 * @return string
1740
+	 */
1741
+	public static function get_label_size_class($value = false)
1742
+	{
1743
+		if ($value === false || $value === '') {
1744
+			return ' class="medium-lbl"';
1745
+		}
1746
+		// determine length of option value
1747
+		$val_size = strlen($value);
1748
+		switch ($val_size) {
1749
+			case $val_size < 3:
1750
+				$size = ' class="nano-lbl"';
1751
+				break;
1752
+			case $val_size < 6:
1753
+				$size = ' class="micro-lbl"';
1754
+				break;
1755
+			case $val_size < 12:
1756
+				$size = ' class="tiny-lbl"';
1757
+				break;
1758
+			case $val_size < 25:
1759
+				$size = ' class="small-lbl"';
1760
+				break;
1761
+			case $val_size > 100:
1762
+				$size = ' class="big-lbl"';
1763
+				break;
1764
+			default:
1765
+				$size = ' class="medium-lbl"';
1766
+				break;
1767
+		}
1768
+		return $size;
1769
+	}
1770
+
1771
+
1772
+	/**
1773
+	 *  _load_system_dropdowns
1774
+	 *
1775
+	 * @param EE_Question_Form_Input $QFI
1776
+	 * @return array
1777
+	 * @throws EE_Error
1778
+	 * @throws ReflectionException
1779
+	 */
1780
+	private static function _load_system_dropdowns($QFI)
1781
+	{
1782
+		$QST_system = $QFI->get('QST_system');
1783
+		switch ($QST_system) {
1784
+			case 'state':
1785
+				$QFI = self::generate_state_dropdown($QFI);
1786
+				break;
1787
+			case 'country':
1788
+				$QFI = self::generate_country_dropdown($QFI);
1789
+				break;
1790
+			case 'admin-state':
1791
+				$QFI = self::generate_state_dropdown($QFI, true);
1792
+				break;
1793
+			case 'admin-country':
1794
+				$QFI = self::generate_country_dropdown($QFI, true);
1795
+				break;
1796
+		}
1797
+		return $QFI;
1798
+	}
1799
+
1800
+
1801
+	/**
1802
+	 * This preps dropdowns that are specialized.
1803
+	 *
1804
+	 * @param EE_Question_Form_Input $QFI
1805
+	 *
1806
+	 * @return EE_Question_Form_Input
1807
+	 * @throws EE_Error
1808
+	 * @throws ReflectionException
1809
+	 * @since  4.6.0
1810
+	 */
1811
+	protected static function _load_specialized_dropdowns($QFI)
1812
+	{
1813
+		switch ($QFI->get('QST_type')) {
1814
+			case 'STATE':
1815
+				$QFI = self::generate_state_dropdown($QFI);
1816
+				break;
1817
+			case 'COUNTRY':
1818
+				$QFI = self::generate_country_dropdown($QFI);
1819
+				break;
1820
+		}
1821
+		return $QFI;
1822
+	}
1823
+
1824
+
1825
+	/**
1826
+	 *    generate_state_dropdown
1827
+	 *
1828
+	 * @param EE_Question_Form_Input $QST
1829
+	 * @param bool                   $get_all
1830
+	 * @return EE_Question_Form_Input
1831
+	 * @throws EE_Error
1832
+	 * @throws ReflectionException
1833
+	 */
1834
+	public static function generate_state_dropdown($QST, $get_all = false)
1835
+	{
1836
+		$states = $get_all
1837
+			? EEM_State::instance()->get_all_states()
1838
+			: EEM_State::instance()->get_all_states_of_active_countries();
1839
+		if ($states && count($states) != count($QST->options())) {
1840
+			$QST->set('QST_type', 'DROPDOWN');
1841
+			// if multiple countries, we'll create option groups within the dropdown
1842
+			foreach ($states as $state) {
1843
+				if ($state instanceof EE_State) {
1844
+					$QSO = EE_Question_Option::new_instance(
1845
+						[
1846
+							'QSO_value'   => $state->ID(),
1847
+							'QSO_desc'    => $state->name(),
1848
+							'QST_ID'      => $QST->get('QST_ID'),
1849
+							'QSO_deleted' => false,
1850
+						]
1851
+					);
1852
+					// set option group
1853
+					$QSO->set_opt_group($state->country()->name());
1854
+					// add option to question
1855
+					$QST->add_temp_option($QSO);
1856
+				}
1857
+			}
1858
+		}
1859
+		return $QST;
1860
+	}
1861
+
1862
+
1863
+	/**
1864
+	 *    generate_country_dropdown
1865
+	 *
1866
+	 * @param      $QST
1867
+	 * @param bool $get_all
1868
+	 * @return array
1869
+	 * @throws EE_Error
1870
+	 * @throws ReflectionException
1871
+	 * @internal param array $question
1872
+	 */
1873
+	public static function generate_country_dropdown($QST, $get_all = false)
1874
+	{
1875
+		$countries = $get_all
1876
+			? EEM_Country::instance()->get_all_countries()
1877
+			: EEM_Country::instance()->get_all_active_countries();
1878
+		if ($countries && count($countries) != count($QST->options())) {
1879
+			$QST->set('QST_type', 'DROPDOWN');
1880
+			// now add countries
1881
+			foreach ($countries as $country) {
1882
+				if ($country instanceof EE_Country) {
1883
+					$QSO = EE_Question_Option::new_instance(
1884
+						[
1885
+							'QSO_value'   => $country->ID(),
1886
+							'QSO_desc'    => $country->name(),
1887
+							'QST_ID'      => $QST->get('QST_ID'),
1888
+							'QSO_deleted' => false,
1889
+						]
1890
+					);
1891
+					$QST->add_temp_option($QSO);
1892
+				}
1893
+			}
1894
+		}
1895
+		return $QST;
1896
+	}
1897
+
1898
+
1899
+	/**
1900
+	 *  generates options for a month dropdown selector with numbers from 01 to 12
1901
+	 *
1902
+	 * @return array()
1903
+	 */
1904
+	public static function two_digit_months_dropdown_options()
1905
+	{
1906
+		$options = [];
1907
+		for ($x = 1; $x <= 12; $x++) {
1908
+			$mm             = str_pad($x, 2, '0', STR_PAD_LEFT);
1909
+			$options[ $mm ] = $mm;
1910
+		}
1911
+		return EEH_Form_Fields::prep_answer_options($options);
1912
+	}
1913
+
1914
+
1915
+	/**
1916
+	 *  generates a year dropdown selector with numbers for the next ten years
1917
+	 *
1918
+	 * @return array
1919
+	 */
1920
+	public static function next_decade_two_digit_year_dropdown_options()
1921
+	{
1922
+		$options      = [];
1923
+		$current_year = date('y');
1924
+		$next_decade  = $current_year + 10;
1925
+		for ($x = $current_year; $x <= $next_decade; $x++) {
1926
+			$yy             = str_pad($x, 2, '0', STR_PAD_LEFT);
1927
+			$options[ $yy ] = $yy;
1928
+		}
1929
+		return EEH_Form_Fields::prep_answer_options($options);
1930
+	}
1931
+
1932
+
1933
+	/**
1934
+	 * generates a month/year dropdown selector for all registrations matching the given criteria.  Typically used for
1935
+	 * list table filter.
1936
+	 *
1937
+	 * @param string  $cur_date     any currently selected date can be entered here.
1938
+	 * @param string  $status       Registration status
1939
+	 * @param integer $evt_category Event Category ID if the Event Category filter is selected
1940
+	 * @return string                html
1941
+	 * @throws EE_Error
1942
+	 */
1943
+	public static function generate_registration_months_dropdown($cur_date = '', $status = '', $evt_category = 0)
1944
+	{
1945
+		$_where = [];
1946
+		if (! empty($status)) {
1947
+			$_where['STS_ID'] = $status;
1948
+		}
1949
+
1950
+		if ($evt_category > 0) {
1951
+			$_where['Event.Term_Taxonomy.term_id'] = $evt_category;
1952
+		}
1953
+
1954
+		$reg_dates = EEM_Registration::instance()->get_reg_months_and_years($_where);
1955
+
1956
+		// setup vals for select input helper
1957
+		$options = [
1958
+			0 => [
1959
+				'text' => esc_html__('Select a Month/Year', 'event_espresso'),
1960
+				'id'   => '',
1961
+			],
1962
+		];
1963
+
1964
+		foreach ($reg_dates as $reg_date) {
1965
+			$date      = $reg_date->reg_month . ' ' . $reg_date->reg_year;
1966
+			$options[] = [
1967
+				'text' => $date,
1968
+				'id'   => $date,
1969
+			];
1970
+		}
1971
+
1972
+		return self::select_input('month_range', $options, $cur_date, '', 'ee-list-table-filter');
1973
+	}
1974
+
1975
+
1976
+	/**
1977
+	 * generates a month/year dropdown selector for all events matching the given criteria
1978
+	 * Typically used for list table filter
1979
+	 *
1980
+	 * @param string $cur_date          any currently selected date can be entered here.
1981
+	 * @param string $status            "view" (i.e. all, today, month, draft)
1982
+	 * @param int    $evt_category      category event belongs to
1983
+	 * @param string $evt_active_status "upcoming", "expired", "active", or "inactive"
1984
+	 * @return string
1985
+	 * @throws EE_Error
1986
+	 * @throws ReflectionException
1987
+	 */
1988
+	public static function generate_event_months_dropdown(
1989
+		string $cur_date = '',
1990
+		string $status = 'all',
1991
+		int $evt_category = 0,
1992
+		string $evt_active_status = ''
1993
+	): string {
1994
+		$status = empty($status) ? 'all' : $status;
1995
+		// determine what post_status our condition will have for the query.
1996
+		switch ($status) {
1997
+			case 'month':
1998
+			case 'today':
1999
+			case 'all':
2000
+				$where['Event.status'] = ['NOT IN', ['trash']];
2001
+				break;
2002
+			case 'draft':
2003
+				$where['Event.status'] = ['IN', ['draft', 'auto-draft']];
2004
+				break;
2005
+			default:
2006
+				$where['Event.status'] = $status;
2007
+		}
2008
+
2009
+		// categories?
2010
+		if (! empty($evt_category) and $evt_category > 0) {
2011
+			$where['Event.Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
2012
+			$where['Event.Term_Taxonomy.term_id']  = $evt_category;
2013
+		}
2014
+
2015
+		//      $where['DTT_is_primary'] = 1;
2016
+
2017
+		$DTTS = EEM_Datetime::instance()->get_dtt_months_and_years($where, $evt_active_status);
2018
+
2019
+		// let's setup vals for select input helper
2020
+		$options = [
2021
+			0 => [
2022
+				'text' => esc_html__('Select a Month/Year', 'event_espresso'),
2023
+				'id'   => "",
2024
+			],
2025
+		];
2026
+
2027
+
2028
+		// translate month and date
2029
+		global $wp_locale;
2030
+
2031
+		foreach ($DTTS as $DTT) {
2032
+			$localized_date = $wp_locale->get_month($DTT->dtt_month_num) . ' ' . $DTT->dtt_year;
2033
+			$id             = $DTT->dtt_month . ' ' . $DTT->dtt_year;
2034
+			$options[]      = [
2035
+				'text' => $localized_date,
2036
+				'id'   => $id,
2037
+			];
2038
+		}
2039
+
2040
+
2041
+		return self::select_input('month_range', $options, $cur_date, '', 'ee-list-table-filter');
2042
+	}
2043
+
2044
+
2045
+	/**
2046
+	 * generates the dropdown selector for event categories
2047
+	 * typically used as a filter on list tables.
2048
+	 *
2049
+	 * @param integer $current_cat currently selected category
2050
+	 * @return string               html for dropdown
2051
+	 * @throws EE_Error
2052
+	 * @throws ReflectionException
2053
+	 */
2054
+	public static function generate_event_category_dropdown($current_cat = -1)
2055
+	{
2056
+		$categories = EEM_Term::instance()->get_all_ee_categories(true);
2057
+		$options    = [
2058
+			'0' => [
2059
+				'text' => esc_html__('All Categories', 'event_espresso'),
2060
+				'id'   => -1,
2061
+			],
2062
+		];
2063
+
2064
+		// setup categories for dropdown
2065
+		foreach ($categories as $category) {
2066
+			$options[] = [
2067
+				'text' => $category->get('name'),
2068
+				'id'   => $category->ID(),
2069
+			];
2070
+		}
2071
+
2072
+		return self::select_input('EVT_CAT', $options, $current_cat, '', 'ee-list-table-filter');
2073
+	}
2074
+
2075
+
2076
+	/**
2077
+	 *    generate a submit button with or without its own microform
2078
+	 *    this is the only way to create buttons that are compatible across all themes
2079
+	 *
2080
+	 * @access    public
2081
+	 * @param string      $url              - the form action
2082
+	 * @param string      $ID               - some kind of unique ID, appended with "-sbmt" for the input and "-frm"
2083
+	 *                                      for the form
2084
+	 * @param string      $class            - css classes (separated by spaces if more than one)
2085
+	 * @param string      $text             - what appears on the button
2086
+	 * @param string      $nonce_action     - if using nonces
2087
+	 * @param bool|string $input_only       - whether to print form header and footer. TRUE returns the input without
2088
+	 *                                      the form
2089
+	 * @param string      $extra_attributes - any extra attributes that need to be attached to the form input
2090
+	 * @return    string
2091
+	 */
2092
+	public static function submit_button(
2093
+		$url = '',
2094
+		$ID = '',
2095
+		$class = '',
2096
+		$text = '',
2097
+		$nonce_action = '',
2098
+		$input_only = false,
2099
+		$extra_attributes = ''
2100
+	) {
2101
+		$btn = '';
2102
+		if (empty($url) || empty($ID)) {
2103
+			return $btn;
2104
+		}
2105
+		$text = ! empty($text) ? $text : esc_html__('Submit', 'event_espresso');
2106
+		$btn  .= '<input id="' . $ID . '-btn" class="' . $class . '" '
2107
+				 . 'type="submit" value="' . $text . '" ' . $extra_attributes . '/>';
2108
+		if (! $input_only) {
2109
+			$btn_frm = '<form id="' . $ID . '-frm" method="POST" action="' . $url . '">';
2110
+			$btn_frm .= ! empty($nonce_action)
2111
+				? wp_nonce_field($nonce_action, $nonce_action . '_nonce', true, false)
2112
+				: '';
2113
+			$btn_frm .= $btn;
2114
+			$btn_frm .= '</form>';
2115
+			$btn     = $btn_frm;
2116
+			unset($btn_frm);
2117
+		}
2118
+		return $btn;
2119
+	}
2120 2120
 }
Please login to merge, or discard this patch.
Spacing   +135 added lines, -135 removed lines patch added patch discarded remove patch
@@ -108,8 +108,8 @@  discard block
 block discarded – undo
108 108
             $type           = $input_value['input'];
109 109
             $value          = $input_value['value'];
110 110
 
111
-            $id    = $form_id ? $form_id . '-' . $input_key : $input_key;
112
-            $class = $required ? 'required ' . $css_class : $css_class;
111
+            $id    = $form_id ? $form_id.'-'.$input_key : $input_key;
112
+            $class = $required ? 'required '.$css_class : $css_class;
113 113
 
114 114
             // what type of input are we dealing with ?
115 115
             switch ($type) {
@@ -161,8 +161,8 @@  discard block
 block discarded – undo
161 161
             }
162 162
         } // end foreach( $input_vars as $input_key => $input_value )
163 163
 
164
-        if (! empty($inputs)) {
165
-            $glue   = "
164
+        if ( ! empty($inputs)) {
165
+            $glue = "
166 166
                 </li>
167 167
                 <li>
168 168
                     ";
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
             </ul>
176 176
             ";
177 177
         }
178
-        return $output . implode("\n", $hidden_inputs);
178
+        return $output.implode("\n", $hidden_inputs);
179 179
     }
180 180
 
181 181
 
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
             // generate label
257 257
             $label = ! empty($label) ? self::adminLabel($id, $label, $required) : '';
258 258
             // generate field name
259
-            $name = ! empty($unique_id) ? $field_name . '[' . $unique_id . ']' : $field_name;
259
+            $name = ! empty($unique_id) ? $field_name.'['.$unique_id.']' : $field_name;
260 260
 
261 261
             // we determine what we're building based on the type
262 262
             switch ($type) {
@@ -267,14 +267,14 @@  discard block
 block discarded – undo
267 267
                         foreach ($value as $key => $val) {
268 268
                             $c_input .= self::adminMulti(
269 269
                                 $default,
270
-                                isset($classes[ $key ]) ? $classes[ $key ] : '',
271
-                                $field_name . '_' . $value,
270
+                                isset($classes[$key]) ? $classes[$key] : '',
271
+                                $field_name.'_'.$value,
272 272
                                 $name,
273 273
                                 $required,
274 274
                                 $tab_index,
275 275
                                 $type,
276 276
                                 $val,
277
-                                isset($labels[ $key ]) ? $labels[ $key ] : ''
277
+                                isset($labels[$key]) ? $labels[$key] : ''
278 278
                             );
279 279
                         }
280 280
                         $field = $c_input;
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
                 case 'select':
301 301
                     $options = [];
302 302
                     foreach ($value as $key => $val) {
303
-                        $options[ $val ] = isset($labels[ $key ]) ? $labels[ $key ] : '';
303
+                        $options[$val] = isset($labels[$key]) ? $labels[$key] : '';
304 304
                     }
305 305
                     $field = self::adminSelect($default, $class, $id, $name, $required, $tab_index, $options);
306 306
                     break;
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
                     $field = self::adminText($class, $id, $name, $required, $tab_index, $value);
327 327
             }
328 328
 
329
-            $form_fields[ $field_name ] = ['label' => $label, 'field' => $field . $extra_desc];
329
+            $form_fields[$field_name] = ['label' => $label, 'field' => $field.$extra_desc];
330 330
         }
331 331
 
332 332
         return $form_fields;
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
         }
396 396
         $label = esc_html($label);
397 397
         $label_class = self::appendInputSizeClass('', $label);
398
-        $label_class = $label_class ? ' class="' . $label_class . '"' : '';
398
+        $label_class = $label_class ? ' class="'.$label_class.'"' : '';
399 399
         return "
400 400
         <label for='$id'{$label_class}>
401 401
             {$input}
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
         $autosize = true
546 546
     ) {
547 547
         // if $values was submitted in the wrong format, convert it over
548
-        if (! empty($values) && (! array_key_exists(0, $values) || ! is_array($values[0]))) {
548
+        if ( ! empty($values) && ( ! array_key_exists(0, $values) || ! is_array($values[0]))) {
549 549
             $converted_values = [];
550 550
             foreach ($values as $id => $text) {
551 551
                 $converted_values[] = ['id' => $id, 'text' => $text];
@@ -554,19 +554,19 @@  discard block
 block discarded – undo
554 554
         }
555 555
 
556 556
         $field =
557
-            '<select id="' . EEH_Formatter::ee_tep_output_string($name)
558
-            . '" name="' . EEH_Formatter::ee_tep_output_string($name)
557
+            '<select id="'.EEH_Formatter::ee_tep_output_string($name)
558
+            . '" name="'.EEH_Formatter::ee_tep_output_string($name)
559 559
             . '"';
560 560
 
561 561
         if (EEH_Formatter::ee_tep_not_null($parameters)) {
562
-            $field .= ' ' . $parameters;
562
+            $field .= ' '.$parameters;
563 563
         }
564 564
         $class = $autosize ? self::appendInputSizeClass($class, $values) : '';
565 565
 
566
-        $field .= ' class="' . $class . '">';
566
+        $field .= ' class="'.$class.'">';
567 567
 
568
-        if (empty($default) && isset($GLOBALS[ $name ])) {
569
-            $default = stripslashes($GLOBALS[ $name ]);
568
+        if (empty($default) && isset($GLOBALS[$name])) {
569
+            $default = stripslashes($GLOBALS[$name]);
570 570
         }
571 571
 
572 572
         $field .= self::selectInputOption($values, $default);
@@ -582,7 +582,7 @@  discard block
 block discarded – undo
582 582
             $id = is_scalar($values['id']) ? $values['id'] : '';
583 583
             $text = is_scalar($values['text']) ? $values['text'] : '';
584 584
             $selected = $default == $values['id'] ? ' selected = "selected"' : '';
585
-            $html_class = isset($values['class']) ? ' class="' . $values['class'] . '"' : '';
585
+            $html_class = isset($values['class']) ? ' class="'.$values['class'].'"' : '';
586 586
             return "<option value='{$id}'{$selected}{$html_class}>{$text}</option>";
587 587
         }
588 588
         $options = '';
@@ -612,7 +612,7 @@  discard block
 block discarded – undo
612 612
             return $chars;
613 613
         }
614 614
         // not a primitive? return something big
615
-        if (! is_scalar($value)) {
615
+        if ( ! is_scalar($value)) {
616 616
             return 500;
617 617
         }
618 618
         return strlen((string) $value);
@@ -662,11 +662,11 @@  discard block
 block discarded – undo
662 662
         $after_question_group_questions  =
663 663
             apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
664 664
 
665
-        if (! empty($question_groups)) {
665
+        if ( ! empty($question_groups)) {
666 666
             // loop thru question groups
667 667
             foreach ($question_groups as $QSG) {
668 668
                 // check that questions exist
669
-                if (! empty($QSG['QSG_questions'])) {
669
+                if ( ! empty($QSG['QSG_questions'])) {
670 670
                     // use fieldsets
671 671
                     $html .= "\n\t"
672 672
                              . '<'
@@ -691,7 +691,7 @@  discard block
 block discarded – undo
691 691
                     $html .= $before_question_group_questions;
692 692
                     // loop thru questions
693 693
                     foreach ($QSG['QSG_questions'] as $question) {
694
-                        $QFI  = new EE_Question_Form_Input(
694
+                        $QFI = new EE_Question_Form_Input(
695 695
                             $question['qst_obj'],
696 696
                             $question['ans_obj'],
697 697
                             $question
@@ -699,7 +699,7 @@  discard block
 block discarded – undo
699 699
                         $html .= self::generate_form_input($QFI);
700 700
                     }
701 701
                     $html .= $after_question_group_questions;
702
-                    $html .= "\n\t" . '</' . $group_wrapper . '>';
702
+                    $html .= "\n\t".'</'.$group_wrapper.'>';
703 703
                 }
704 704
             }
705 705
         }
@@ -739,25 +739,25 @@  discard block
 block discarded – undo
739 739
             'input_id'    => '',
740 740
             'input_class' => '',
741 741
         ];
742
-        $q_meta         = array_merge($default_q_meta, $q_meta);
742
+        $q_meta = array_merge($default_q_meta, $q_meta);
743 743
 
744
-        if (! empty($question_groups)) {
744
+        if ( ! empty($question_groups)) {
745 745
             // loop thru question groups
746 746
             foreach ($question_groups as $QSG) {
747 747
                 if ($QSG instanceof EE_Question_Group) {
748 748
                     // check that questions exist
749 749
 
750 750
                     $where = ['QST_deleted' => 0];
751
-                    if (! $from_admin) {
751
+                    if ( ! $from_admin) {
752 752
                         $where['QST_admin_only'] = 0;
753 753
                     }
754 754
                     $questions =
755 755
                         $QSG->questions([$where, 'order_by' => ['Question_Group_Question.QGQ_order' => 'ASC']]);
756
-                    if (! empty($questions)) {
756
+                    if ( ! empty($questions)) {
757 757
                         // use fieldsets
758 758
                         $html .= "\n\t"
759
-                                 . '<' . $group_wrapper . ' class="espresso-question-group-wrap" '
760
-                                 . 'id="' . $QSG->get('QSG_identifier') . '">';
759
+                                 . '<'.$group_wrapper.' class="espresso-question-group-wrap" '
760
+                                 . 'id="'.$QSG->get('QSG_identifier').'">';
761 761
                         // group_name
762 762
                         if ($QSG->show_group_name()) {
763 763
                             $html .= "\n\t\t"
@@ -782,21 +782,21 @@  discard block
 block discarded – undo
782 782
                             /** @var RequestInterface $request */
783 783
                             $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
784 784
                             $request_qstn = $request->getRequestParam('qstn', [], 'string', true);
785
-                            if (! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
785
+                            if ( ! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
786 786
                                 // check for answer in $request_qstn in case we are reprocessing a form after an error
787
-                                if (isset($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])) {
788
-                                    $answer = is_array($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])
789
-                                        ? $request_qstn[ $q_meta['input_id'] ][ $qstn_id ]
790
-                                        : sanitize_text_field($request_qstn[ $q_meta['input_id'] ][ $qstn_id ]);
787
+                                if (isset($request_qstn[$q_meta['input_id']][$qstn_id])) {
788
+                                    $answer = is_array($request_qstn[$q_meta['input_id']][$qstn_id])
789
+                                        ? $request_qstn[$q_meta['input_id']][$qstn_id]
790
+                                        : sanitize_text_field($request_qstn[$q_meta['input_id']][$qstn_id]);
791 791
                                 }
792 792
                             } elseif (isset($q_meta['attendee']) && $q_meta['attendee']) {
793 793
                                 // attendee data from the session
794 794
                                 $answer =
795
-                                    isset($q_meta['attendee'][ $qstn_id ]) ? $q_meta['attendee'][ $qstn_id ] : null;
795
+                                    isset($q_meta['attendee'][$qstn_id]) ? $q_meta['attendee'][$qstn_id] : null;
796 796
                             }
797 797
 
798 798
 
799
-                            $QFI  = new EE_Question_Form_Input(
799
+                            $QFI = new EE_Question_Form_Input(
800 800
                                 $QST,
801 801
                                 EE_Answer::new_instance(
802 802
                                     [
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
                             $html .= self::generate_form_input($QFI);
812 812
                         }
813 813
                         $html .= $after_question_group_questions;
814
-                        $html .= "\n\t" . '</' . $group_wrapper . '>';
814
+                        $html .= "\n\t".'</'.$group_wrapper.'>';
815 815
                     }
816 816
                 }
817 817
             }
@@ -993,7 +993,7 @@  discard block
 block discarded – undo
993 993
     ): string {
994 994
         $for   = ! empty($name) ? " for='{$name}'" : '';
995 995
         $class = ! empty($label_class) ? " class='{$label_class}'" : '';
996
-        $label = self::prep_question($question) . $required_label;
996
+        $label = self::prep_question($question).$required_label;
997 997
         $label_html = "
998 998
             {$required_text}
999 999
             <label{$for}{$class}>{$label}</label>";
@@ -1049,7 +1049,7 @@  discard block
 block discarded – undo
1049 1049
         $extra_attributes = ''
1050 1050
     ) {
1051 1051
         // need these
1052
-        if (! $question || ! $name) {
1052
+        if ( ! $question || ! $name) {
1053 1053
             return null;
1054 1054
         }
1055 1055
         // prep the answer
@@ -1061,9 +1061,9 @@  discard block
 block discarded – undo
1061 1061
         // ya gots ta have style man!!!
1062 1062
         $txt_class = is_admin() ? 'regular-text' : 'espresso-text-inp';
1063 1063
         $class     = empty($class) ? $txt_class : $class;
1064
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1064
+        $class .= ! empty($system_ID) ? ' '.$system_ID : '';
1065 1065
         $class = self::appendInputSizeClass($class, $answer);
1066
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1066
+        $class .= ! empty($required['class']) ? ' '.$required['class'] : '';
1067 1067
         $extra_attributes = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', $extra_attributes);
1068 1068
 
1069 1069
         $label_html = self::label($question, $required_text, $required['label'], $name, $label_class);
@@ -1076,18 +1076,18 @@  discard block
 block discarded – undo
1076 1076
             $name
1077 1077
         );
1078 1078
 
1079
-        $input_html = $mobile_label . '
1079
+        $input_html = $mobile_label.'
1080 1080
             <input  type="text"
1081
-                    name="' . $name . '"
1082
-                    id="' . $id . '"
1083
-                    class="' . trim($class) . '"
1084
-                    value="' . esc_attr($answer) . '"
1085
-                    aria-label="' . esc_attr($required['msg']) . '"
1086
-                    ' . $disabled . ' ' . $extra_attributes . '
1081
+                    name="' . $name.'"
1082
+                    id="' . $id.'"
1083
+                    class="' . trim($class).'"
1084
+                    value="' . esc_attr($answer).'"
1085
+                    aria-label="' . esc_attr($required['msg']).'"
1086
+                    ' . $disabled.' '.$extra_attributes.'
1087 1087
             />';
1088 1088
 
1089 1089
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1090
-        return $label_html . $input_html;
1090
+        return $label_html.$input_html;
1091 1091
     }
1092 1092
 
1093 1093
 
@@ -1122,7 +1122,7 @@  discard block
 block discarded – undo
1122 1122
         $add_mobile_label = false
1123 1123
     ) {
1124 1124
         // need these
1125
-        if (! $question || ! $name) {
1125
+        if ( ! $question || ! $name) {
1126 1126
             return null;
1127 1127
         }
1128 1128
         // prep the answer
@@ -1136,9 +1136,9 @@  discard block
 block discarded – undo
1136 1136
         // set disabled tag
1137 1137
         $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1138 1138
         // ya gots ta have style man!!!
1139
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1140
-        $class     .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1141
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1139
+        $class     .= ! empty($system_ID) ? ' '.$system_ID : '';
1140
+        $class     .= ! empty($required['class']) ? ' '.$required['class'] : '';
1141
+        $extra = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1142 1142
 
1143 1143
         $label_html   = self::label($question, $required_text, $required['label'], $name, $label_class);
1144 1144
         $mobile_label = self::mobileLabel(
@@ -1151,14 +1151,14 @@  discard block
 block discarded – undo
1151 1151
         );
1152 1152
 
1153 1153
         $input_html = $mobile_label
1154
-            . '<textarea name="' . $name . '" id="' . $id . '" class="' . trim($class) . '" '
1155
-            . 'rows="' . $dimensions['rows'] . '" cols="' . $dimensions['cols'] . '"  '
1156
-            . 'aria-label="' . $required['msg'] . '" ' . $disabled . ' ' . $extra . '>'
1154
+            . '<textarea name="'.$name.'" id="'.$id.'" class="'.trim($class).'" '
1155
+            . 'rows="'.$dimensions['rows'].'" cols="'.$dimensions['cols'].'"  '
1156
+            . 'aria-label="'.$required['msg'].'" '.$disabled.' '.$extra.'>'
1157 1157
              . esc_textarea($answer)
1158 1158
               . '</textarea>';
1159 1159
 
1160 1160
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1161
-        return $label_html . $input_html;
1161
+        return $label_html.$input_html;
1162 1162
     }
1163 1163
 
1164 1164
 
@@ -1196,7 +1196,7 @@  discard block
 block discarded – undo
1196 1196
     ) {
1197 1197
 
1198 1198
         // need these
1199
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1199
+        if ( ! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1200 1200
             return null;
1201 1201
         }
1202 1202
         // prep the answer
@@ -1208,9 +1208,9 @@  discard block
 block discarded – undo
1208 1208
         // set disabled tag
1209 1209
         $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1210 1210
         // ya gots ta have style man!!!
1211
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1211
+        $class .= ! empty($system_ID) ? ' '.$system_ID : '';
1212 1212
         $class = self::appendInputSizeClass($class, $options);
1213
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1213
+        $extra = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1214 1214
 
1215 1215
         $label_html   = self::label($question, $required_text, $required['label'], $name, $label_class);
1216 1216
         $mobile_label = self::mobileLabel(
@@ -1223,16 +1223,16 @@  discard block
 block discarded – undo
1223 1223
         );
1224 1224
 
1225 1225
         $input_html = $mobile_label
1226
-            . '<select name="' . $name . '" id="' . $id . '" class="' . trim($class) . ' ' . $required['class'] . '" '
1227
-            . 'aria-label="' . esc_attr($required['msg']) . '"' . $disabled . ' ' . $extra . '>';
1226
+            . '<select name="'.$name.'" id="'.$id.'" class="'.trim($class).' '.$required['class'].'" '
1227
+            . 'aria-label="'.esc_attr($required['msg']).'"'.$disabled.' '.$extra.'>';
1228 1228
         // recursively count array elements, to determine total number of options
1229 1229
         $only_option = count($options, 1) == 1;
1230
-        if (! $only_option) {
1230
+        if ( ! $only_option) {
1231 1231
             // if there is NO answer set and there are multiple options to choose from, then set the "please select" message as selected
1232
-            $selected   = $answer === null ? ' selected' : '';
1232
+            $selected = $answer === null ? ' selected' : '';
1233 1233
             $input_html .= $add_please_select_option
1234 1234
                 ? "\n\t\t\t\t"
1235
-                  . '<option value=""' . $selected . '>'
1235
+                  . '<option value=""'.$selected.'>'
1236 1236
                   . esc_html__(' - please select - ', 'event_espresso')
1237 1237
                   . '</option>'
1238 1238
                 : '';
@@ -1255,7 +1255,7 @@  discard block
 block discarded – undo
1255 1255
                 );
1256 1256
         }
1257 1257
 
1258
-        $input_html .= "\n\t\t\t" . '</select>';
1258
+        $input_html .= "\n\t\t\t".'</select>';
1259 1259
 
1260 1260
         $input_html =
1261 1261
             apply_filters(
@@ -1270,7 +1270,7 @@  discard block
 block discarded – undo
1270 1270
             );
1271 1271
 
1272 1272
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1273
-        return $label_html . $input_html;
1273
+        return $label_html.$input_html;
1274 1274
     }
1275 1275
 
1276 1276
 
@@ -1288,11 +1288,11 @@  discard block
 block discarded – undo
1288 1288
      */
1289 1289
     private static function _generate_select_option_group($opt_group, $QSOs, $answer, $use_html_entities = true)
1290 1290
     {
1291
-        $html = "\n\t\t\t\t" . '<optgroup label="' . self::prep_option_value($opt_group) . '">';
1291
+        $html = "\n\t\t\t\t".'<optgroup label="'.self::prep_option_value($opt_group).'">';
1292 1292
         foreach ($QSOs as $QSO) {
1293 1293
             $html .= self::_generate_select_option($QSO->value(), $QSO->desc(), $answer, false, $use_html_entities);
1294 1294
         }
1295
-        $html .= "\n\t\t\t\t" . '</optgroup>';
1295
+        $html .= "\n\t\t\t\t".'</optgroup>';
1296 1296
         return $html;
1297 1297
     }
1298 1298
 
@@ -1319,7 +1319,7 @@  discard block
 block discarded – undo
1319 1319
         $value    = ! empty($value) ? $value : $key;
1320 1320
         $selected = ($answer == $key || $only_option) ? 'selected' : '';
1321 1321
         return "\n\t\t\t\t"
1322
-               . '<option value="' . self::prep_option_value($key) . '" ' . $selected . '> '
1322
+               . '<option value="'.self::prep_option_value($key).'" '.$selected.'> '
1323 1323
                . $value
1324 1324
                . '&nbsp;&nbsp;&nbsp;</option>';
1325 1325
     }
@@ -1364,7 +1364,7 @@  discard block
 block discarded – undo
1364 1364
         bool $add_mobile_label = false
1365 1365
     ) {
1366 1366
         // need these
1367
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1367
+        if ( ! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1368 1368
             return null;
1369 1369
         }
1370 1370
         // prep the answer
@@ -1388,50 +1388,50 @@  discard block
 block discarded – undo
1388 1388
         );
1389 1389
 
1390 1390
         $input_html = $mobile_label
1391
-            . '<ul id="' . $id . '-ul" class="espresso-radio-btn-options-ul ' . $class . '-ul">';
1391
+            . '<ul id="'.$id.'-ul" class="espresso-radio-btn-options-ul '.$class.'-ul">';
1392 1392
 
1393
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1394
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1393
+        $class .= ! empty($system_ID) ? ' '.$system_ID : '';
1394
+        $class .= ! empty($required['class']) ? ' '.$required['class'] : '';
1395 1395
 
1396 1396
         foreach ($options as $OPT) {
1397 1397
             if ($OPT instanceof EE_Question_Option) {
1398 1398
                 $value   = self::prep_option_value($OPT->value());
1399 1399
                 $label   = $use_desc_4_label ? $OPT->desc() : $OPT->value();
1400 1400
                 $size    = $use_desc_4_label
1401
-                    ? self::get_label_size_class($OPT->value() . ' ' . $OPT->desc())
1401
+                    ? self::get_label_size_class($OPT->value().' '.$OPT->desc())
1402 1402
                     : self::get_label_size_class($OPT->value());
1403
-                $desc    = $OPT->desc();// no self::prep_answer
1403
+                $desc    = $OPT->desc(); // no self::prep_answer
1404 1404
                 $answer  = is_numeric($value) && empty($answer) ? 0 : $answer;
1405
-                $value  = is_numeric($answer) && empty($value) ? 0 : $value;
1405
+                $value = is_numeric($answer) && empty($value) ? 0 : $value;
1406 1406
                 $checked = (string) $value == (string) $answer ? ' checked' : '';
1407
-                $opt     = '-' . sanitize_key($value);
1407
+                $opt     = '-'.sanitize_key($value);
1408 1408
 
1409
-                $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1410
-                $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-radio-btn-lbl">';
1411
-                $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $label . '</span>&nbsp;' : '';
1409
+                $input_html .= "\n\t\t\t\t".'<li'.$size.'>';
1410
+                $input_html .= "\n\t\t\t\t\t".'<label class="'.$radio_class.' espresso-radio-btn-lbl">';
1411
+                $input_html .= $label_b4 ? "\n\t\t\t\t\t\t".'<span>'.$label.'</span>&nbsp;' : '';
1412 1412
                 $input_html .= "\n\t\t\t\t\t\t"
1413
-                               . '<input type="radio" name="' . $name . '" id="' . $id . $opt . '" '
1414
-                               . 'class="' . $class . '" value="' . $value . '" '
1415
-                               . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled
1416
-                               . $checked . ' ' . $extra . '/>';
1413
+                               . '<input type="radio" name="'.$name.'" id="'.$id.$opt.'" '
1414
+                               . 'class="'.$class.'" value="'.$value.'" '
1415
+                               . 'aria-label="'.esc_attr($required['msg']).'" '.$disabled
1416
+                               . $checked.' '.$extra.'/>';
1417 1417
                 $input_html .= ! $label_b4
1418 1418
                     ? "\n\t\t\t\t\t\t"
1419 1419
                       . '&nbsp;<span class="espresso-radio-btn-desc">'
1420 1420
                       . $label
1421 1421
                       . '</span>'
1422 1422
                     : '';
1423
-                $input_html .= "\n\t\t\t\t\t" . '</label>';
1423
+                $input_html .= "\n\t\t\t\t\t".'</label>';
1424 1424
                 $input_html .= $use_desc_4_label
1425 1425
                     ? ''
1426
-                    : '<span class="espresso-radio-btn-option-desc small-text grey-text">' . $desc . '</span>';
1427
-                $input_html .= "\n\t\t\t\t" . '</li>';
1426
+                    : '<span class="espresso-radio-btn-option-desc small-text grey-text">'.$desc.'</span>';
1427
+                $input_html .= "\n\t\t\t\t".'</li>';
1428 1428
             }
1429 1429
         }
1430 1430
 
1431
-        $input_html .= "\n\t\t\t" . '</ul>';
1431
+        $input_html .= "\n\t\t\t".'</ul>';
1432 1432
 
1433 1433
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1434
-        return $label_html . $input_html;
1434
+        return $label_html.$input_html;
1435 1435
     }
1436 1436
 
1437 1437
 
@@ -1467,7 +1467,7 @@  discard block
 block discarded – undo
1467 1467
         $add_mobile_label = false
1468 1468
     ) {
1469 1469
         // need these
1470
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1470
+        if ( ! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1471 1471
             return null;
1472 1472
         }
1473 1473
         $answer = maybe_unserialize($answer);
@@ -1477,7 +1477,7 @@  discard block
 block discarded – undo
1477 1477
 
1478 1478
         foreach ($answer as $key => $value) {
1479 1479
             $key            = self::prep_option_value($key);
1480
-            $answer[ $key ] = self::prep_answer($value, $use_html_entities);
1480
+            $answer[$key] = self::prep_answer($value, $use_html_entities);
1481 1481
         }
1482 1482
 
1483 1483
         // prep the required array
@@ -1499,42 +1499,42 @@  discard block
 block discarded – undo
1499 1499
         );
1500 1500
 
1501 1501
         $input_html = $mobile_label
1502
-            . '<ul id="' . $id . '-ul" class="espresso-checkbox-options-ul ' . $class . '-ul">';
1502
+            . '<ul id="'.$id.'-ul" class="espresso-checkbox-options-ul '.$class.'-ul">';
1503 1503
 
1504
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1505
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1504
+        $class .= ! empty($system_ID) ? ' '.$system_ID : '';
1505
+        $class .= ! empty($required['class']) ? ' '.$required['class'] : '';
1506 1506
 
1507 1507
         foreach ($options as $OPT) {
1508
-            $value = $OPT->value();// self::prep_option_value( $OPT->value() );
1509
-            $size  = self::get_label_size_class($OPT->value() . ' ' . $OPT->desc());
1508
+            $value = $OPT->value(); // self::prep_option_value( $OPT->value() );
1509
+            $size  = self::get_label_size_class($OPT->value().' '.$OPT->desc());
1510 1510
             $text  = self::prep_answer($OPT->value());
1511 1511
             $desc  = $OPT->desc();
1512
-            $opt   = '-' . sanitize_key($value);
1512
+            $opt   = '-'.sanitize_key($value);
1513 1513
 
1514 1514
             $checked = is_array($answer) && in_array($text, $answer) ? ' checked' : '';
1515 1515
 
1516
-            $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1517
-            $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-checkbox-lbl">';
1518
-            $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>&nbsp;' : '';
1516
+            $input_html .= "\n\t\t\t\t".'<li'.$size.'>';
1517
+            $input_html .= "\n\t\t\t\t\t".'<label class="'.$radio_class.' espresso-checkbox-lbl">';
1518
+            $input_html .= $label_b4 ? "\n\t\t\t\t\t\t".'<span>'.$text.'</span>&nbsp;' : '';
1519 1519
             $input_html .= "\n\t\t\t\t\t\t"
1520
-                           . '<input type="checkbox" name="' . $name . '[' . $OPT->ID() . ']" '
1521
-                           . 'id="' . $id . $opt . '" class="' . $class . '" value="' . $value . '" '
1522
-                           . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled . $checked . ' ' . $extra . '/>';
1523
-            $input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t" . '&nbsp;<span>' . $text . '</span>' : '';
1524
-            $input_html .= "\n\t\t\t\t\t" . '</label>';
1525
-            if (! empty($desc) && $desc != $text) {
1520
+                           . '<input type="checkbox" name="'.$name.'['.$OPT->ID().']" '
1521
+                           . 'id="'.$id.$opt.'" class="'.$class.'" value="'.$value.'" '
1522
+                           . 'aria-label="'.esc_attr($required['msg']).'" '.$disabled.$checked.' '.$extra.'/>';
1523
+            $input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t".'&nbsp;<span>'.$text.'</span>' : '';
1524
+            $input_html .= "\n\t\t\t\t\t".'</label>';
1525
+            if ( ! empty($desc) && $desc != $text) {
1526 1526
                 $input_html .= "\n\t\t\t\t\t"
1527 1527
                                . ' &nbsp; <br/><div class="espresso-checkbox-option-desc small-text grey-text">'
1528 1528
                                . $desc
1529 1529
                                . '</div>';
1530 1530
             }
1531
-            $input_html .= "\n\t\t\t\t" . '</li>';
1531
+            $input_html .= "\n\t\t\t\t".'</li>';
1532 1532
         }
1533 1533
 
1534
-        $input_html .= "\n\t\t\t" . '</ul>';
1534
+        $input_html .= "\n\t\t\t".'</ul>';
1535 1535
 
1536 1536
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1537
-        return $label_html . $input_html;
1537
+        return $label_html.$input_html;
1538 1538
     }
1539 1539
 
1540 1540
 
@@ -1567,7 +1567,7 @@  discard block
 block discarded – undo
1567 1567
         $add_mobile_label = false
1568 1568
     ) {
1569 1569
         // need these
1570
-        if (! $question || ! $name) {
1570
+        if ( ! $question || ! $name) {
1571 1571
             return null;
1572 1572
         }
1573 1573
         // prep the answer
@@ -1579,7 +1579,7 @@  discard block
 block discarded – undo
1579 1579
         // ya gots ta have style man!!!
1580 1580
         $txt_class = is_admin() ? 'regular-text' : 'espresso-datepicker-inp';
1581 1581
         $class     = empty($class) ? $txt_class : $class;
1582
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1582
+        $class .= ! empty($system_ID) ? ' '.$system_ID : '';
1583 1583
         $class = self::appendInputSizeClass($class, $answer);
1584 1584
         $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1585 1585
 
@@ -1594,14 +1594,14 @@  discard block
 block discarded – undo
1594 1594
         );
1595 1595
 
1596 1596
         $input_html = $mobile_label
1597
-            . '<input type="text" name="' . $name . '" id="' . $id . '" '
1598
-            . 'class="' . $class . ' ' . $required['class'] . ' datepicker" value="' . $answer . '"  '
1599
-            . 'aria-label="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
1597
+            . '<input type="text" name="'.$name.'" id="'.$id.'" '
1598
+            . 'class="'.$class.' '.$required['class'].' datepicker" value="'.$answer.'"  '
1599
+            . 'aria-label="'.esc_attr($required['msg']).'" '.$disabled.' '.$extra.'/>';
1600 1600
 
1601 1601
         // enqueue scripts
1602 1602
         wp_register_style(
1603 1603
             'espresso-ui-theme',
1604
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1604
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1605 1605
             [],
1606 1606
             EVENT_ESPRESSO_VERSION
1607 1607
         );
@@ -1609,7 +1609,7 @@  discard block
 block discarded – undo
1609 1609
         wp_enqueue_script('jquery-ui-datepicker');
1610 1610
 
1611 1611
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1612
-        return $label_html . $input_html;
1612
+        return $label_html.$input_html;
1613 1613
     }
1614 1614
 
1615 1615
 
@@ -1636,7 +1636,7 @@  discard block
 block discarded – undo
1636 1636
     public static function hidden_input($name, $value, $id = '')
1637 1637
     {
1638 1638
         $id = ! empty($id) ? $id : $name;
1639
-        return '<input id="' . $id . '" type="hidden" name="' . $name . '" value="' . $value . '"/>';
1639
+        return '<input id="'.$id.'" type="hidden" name="'.$name.'" value="'.$value.'"/>';
1640 1640
     }
1641 1641
 
1642 1642
 
@@ -1681,7 +1681,7 @@  discard block
 block discarded – undo
1681 1681
         $prepped_answer_options = [];
1682 1682
         if (is_array($QSOs) && ! empty($QSOs)) {
1683 1683
             foreach ($QSOs as $key => $QSO) {
1684
-                if (! $QSO instanceof EE_Question_Option) {
1684
+                if ( ! $QSO instanceof EE_Question_Option) {
1685 1685
                     $QSO = EE_Question_Option::new_instance(
1686 1686
                         [
1687 1687
                             'QSO_value' => is_array($QSO) && isset($QSO['id'])
@@ -1694,7 +1694,7 @@  discard block
 block discarded – undo
1694 1694
                     );
1695 1695
                 }
1696 1696
                 if ($QSO->opt_group()) {
1697
-                    $prepped_answer_options[ $QSO->opt_group() ][] = $QSO;
1697
+                    $prepped_answer_options[$QSO->opt_group()][] = $QSO;
1698 1698
                 } else {
1699 1699
                     $prepped_answer_options[] = $QSO;
1700 1700
                 }
@@ -1906,7 +1906,7 @@  discard block
 block discarded – undo
1906 1906
         $options = [];
1907 1907
         for ($x = 1; $x <= 12; $x++) {
1908 1908
             $mm             = str_pad($x, 2, '0', STR_PAD_LEFT);
1909
-            $options[ $mm ] = $mm;
1909
+            $options[$mm] = $mm;
1910 1910
         }
1911 1911
         return EEH_Form_Fields::prep_answer_options($options);
1912 1912
     }
@@ -1924,7 +1924,7 @@  discard block
 block discarded – undo
1924 1924
         $next_decade  = $current_year + 10;
1925 1925
         for ($x = $current_year; $x <= $next_decade; $x++) {
1926 1926
             $yy             = str_pad($x, 2, '0', STR_PAD_LEFT);
1927
-            $options[ $yy ] = $yy;
1927
+            $options[$yy] = $yy;
1928 1928
         }
1929 1929
         return EEH_Form_Fields::prep_answer_options($options);
1930 1930
     }
@@ -1943,7 +1943,7 @@  discard block
 block discarded – undo
1943 1943
     public static function generate_registration_months_dropdown($cur_date = '', $status = '', $evt_category = 0)
1944 1944
     {
1945 1945
         $_where = [];
1946
-        if (! empty($status)) {
1946
+        if ( ! empty($status)) {
1947 1947
             $_where['STS_ID'] = $status;
1948 1948
         }
1949 1949
 
@@ -1962,7 +1962,7 @@  discard block
 block discarded – undo
1962 1962
         ];
1963 1963
 
1964 1964
         foreach ($reg_dates as $reg_date) {
1965
-            $date      = $reg_date->reg_month . ' ' . $reg_date->reg_year;
1965
+            $date      = $reg_date->reg_month.' '.$reg_date->reg_year;
1966 1966
             $options[] = [
1967 1967
                 'text' => $date,
1968 1968
                 'id'   => $date,
@@ -2007,7 +2007,7 @@  discard block
 block discarded – undo
2007 2007
         }
2008 2008
 
2009 2009
         // categories?
2010
-        if (! empty($evt_category) and $evt_category > 0) {
2010
+        if ( ! empty($evt_category) and $evt_category > 0) {
2011 2011
             $where['Event.Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
2012 2012
             $where['Event.Term_Taxonomy.term_id']  = $evt_category;
2013 2013
         }
@@ -2029,8 +2029,8 @@  discard block
 block discarded – undo
2029 2029
         global $wp_locale;
2030 2030
 
2031 2031
         foreach ($DTTS as $DTT) {
2032
-            $localized_date = $wp_locale->get_month($DTT->dtt_month_num) . ' ' . $DTT->dtt_year;
2033
-            $id             = $DTT->dtt_month . ' ' . $DTT->dtt_year;
2032
+            $localized_date = $wp_locale->get_month($DTT->dtt_month_num).' '.$DTT->dtt_year;
2033
+            $id             = $DTT->dtt_month.' '.$DTT->dtt_year;
2034 2034
             $options[]      = [
2035 2035
                 'text' => $localized_date,
2036 2036
                 'id'   => $id,
@@ -2103,16 +2103,16 @@  discard block
 block discarded – undo
2103 2103
             return $btn;
2104 2104
         }
2105 2105
         $text = ! empty($text) ? $text : esc_html__('Submit', 'event_espresso');
2106
-        $btn  .= '<input id="' . $ID . '-btn" class="' . $class . '" '
2107
-                 . 'type="submit" value="' . $text . '" ' . $extra_attributes . '/>';
2108
-        if (! $input_only) {
2109
-            $btn_frm = '<form id="' . $ID . '-frm" method="POST" action="' . $url . '">';
2106
+        $btn .= '<input id="'.$ID.'-btn" class="'.$class.'" '
2107
+                 . 'type="submit" value="'.$text.'" '.$extra_attributes.'/>';
2108
+        if ( ! $input_only) {
2109
+            $btn_frm = '<form id="'.$ID.'-frm" method="POST" action="'.$url.'">';
2110 2110
             $btn_frm .= ! empty($nonce_action)
2111
-                ? wp_nonce_field($nonce_action, $nonce_action . '_nonce', true, false)
2111
+                ? wp_nonce_field($nonce_action, $nonce_action.'_nonce', true, false)
2112 2112
                 : '';
2113 2113
             $btn_frm .= $btn;
2114 2114
             $btn_frm .= '</form>';
2115
-            $btn     = $btn_frm;
2115
+            $btn = $btn_frm;
2116 2116
             unset($btn_frm);
2117 2117
         }
2118 2118
         return $btn;
Please login to merge, or discard this patch.
core/db_models/EEM_Payment_Method.model.php 2 patches
Indentation   +453 added lines, -453 removed lines patch added patch discarded remove patch
@@ -16,457 +16,457 @@
 block discarded – undo
16 16
  */
17 17
 class EEM_Payment_Method extends EEM_Base
18 18
 {
19
-    const scope_cart  = 'CART';
20
-
21
-    const scope_admin = 'ADMIN';
22
-
23
-    const scope_api   = 'API';
24
-
25
-
26
-    protected static ?EEM_Payment_Method $_instance = null;
27
-
28
-
29
-    /**
30
-     * private constructor to prevent direct creation
31
-     *
32
-     * @param string|null $timezone
33
-     * @throws EE_Error
34
-     */
35
-    protected function __construct(?string $timezone = '')
36
-    {
37
-        $this->singular_item    = esc_html__('Payment Method', 'event_espresso');
38
-        $this->plural_item      = esc_html__('Payment Methods', 'event_espresso');
39
-        $this->_tables          = [
40
-            'Payment_Method' => new EE_Primary_Table('esp_payment_method', 'PMD_ID'),
41
-        ];
42
-        $this->_fields          = [
43
-            'Payment_Method' => [
44
-                'PMD_ID'              => new EE_Primary_Key_Int_Field(
45
-                    'PMD_ID',
46
-                    esc_html__('ID', 'event_espresso')
47
-                ),
48
-                'PMD_type'            => new EE_Plain_Text_Field(
49
-                    'PMD_type',
50
-                    esc_html__('Payment Method Type', 'event_espresso'),
51
-                    false,
52
-                    'Admin_Only'
53
-                ),
54
-                'PMD_name'            => new EE_Plain_Text_Field(
55
-                    'PMD_name',
56
-                    esc_html__('Name', 'event_espresso'),
57
-                    false
58
-                ),
59
-                'PMD_desc'            => new EE_Post_Content_Field(
60
-                    'PMD_desc',
61
-                    esc_html__('Description', 'event_espresso'),
62
-                    false,
63
-                    ''
64
-                ),
65
-                'PMD_admin_name'      => new EE_Plain_Text_Field(
66
-                    'PMD_admin_name',
67
-                    esc_html__('Admin-Only Name', 'event_espresso'),
68
-                    true
69
-                ),
70
-                'PMD_admin_desc'      => new EE_Post_Content_Field(
71
-                    'PMD_admin_desc',
72
-                    esc_html__('Admin-Only Description', 'event_espresso'),
73
-                    true
74
-                ),
75
-                'PMD_slug'            => new EE_Slug_Field(
76
-                    'PMD_slug',
77
-                    esc_html__('Slug', 'event_espresso'),
78
-                    false
79
-                ),
80
-                'PMD_order'           => new EE_Integer_Field(
81
-                    'PMD_order',
82
-                    esc_html__('Order', 'event_espresso'),
83
-                    false,
84
-                    0
85
-                ),
86
-                'PMD_debug_mode'      => new EE_Boolean_Field(
87
-                    'PMD_debug_mode',
88
-                    esc_html__('Sandbox Mode On? (AKA: debug mode)', 'event_espresso'),
89
-                    false,
90
-                    false
91
-                ),
92
-                'PMD_wp_user'         => new EE_WP_User_Field(
93
-                    'PMD_wp_user',
94
-                    esc_html__('Payment Method Creator ID', 'event_espresso'),
95
-                    false
96
-                ),
97
-                'PMD_open_by_default' => new EE_Boolean_Field(
98
-                    'PMD_open_by_default',
99
-                    esc_html__('Open by Default?', 'event_espresso'),
100
-                    false,
101
-                    false
102
-                ),
103
-                'PMD_button_url'      => new EE_Plain_Text_Field(
104
-                    'PMD_button_url',
105
-                    esc_html__('Button URL', 'event_espresso'),
106
-                    true,
107
-                    ''
108
-                ),
109
-                'PMD_scope'           => new EE_Serialized_Text_Field(
110
-                    'PMD_scope',
111
-                    esc_html__('Usable From?', 'event_espresso'),
112
-                    false,
113
-                    []// possible values currently are 'CART','ADMIN','API'
114
-                ),
115
-            ],
116
-        ];
117
-        $this->_model_relations = [
118
-            'Currency'    => new EE_HABTM_Relation('Currency_Payment_Method'),
119
-            'Payment'     => new EE_Has_Many_Relation(),
120
-            'Transaction' => new EE_Has_Many_Relation(),
121
-            'WP_User'     => new EE_Belongs_To_Relation(),
122
-        ];
123
-        parent::__construct($timezone);
124
-    }
125
-
126
-
127
-    /**
128
-     * Gets one by the slug provided
129
-     *
130
-     * @param string $slug
131
-     * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|NULL
132
-     * @throws EE_Error
133
-     */
134
-    public function get_one_by_slug($slug)
135
-    {
136
-        return $this->get_one([['PMD_slug' => $slug]]);
137
-    }
138
-
139
-
140
-    /**
141
-     * Gets all the acceptable scopes for payment methods.
142
-     * Keys are their names as store din the DB, and values are nice names for displaying them
143
-     *
144
-     * @return array
145
-     */
146
-    public function scopes()
147
-    {
148
-        return apply_filters(
149
-            'FHEE__EEM_Payment_Method__scopes',
150
-            [
151
-                EEM_Payment_Method::scope_cart  => esc_html__('Front-end Registration Page', 'event_espresso'),
152
-                EEM_Payment_Method::scope_admin => esc_html__(
153
-                    'Admin Registration Page (no online processing)',
154
-                    'event_espresso'
155
-                ),
156
-            ]
157
-        );
158
-    }
159
-
160
-
161
-    /**
162
-     * Determines if this is an valid scope
163
-     *
164
-     * @param string $scope like one of EEM_Payment_Method::instance()->scopes()
165
-     * @return boolean
166
-     */
167
-    public function is_valid_scope($scope)
168
-    {
169
-        $scopes = $this->scopes();
170
-        if (isset($scopes[ $scope ])) {
171
-            return true;
172
-        }
173
-        return false;
174
-    }
175
-
176
-
177
-    /**
178
-     * Gets all active payment methods
179
-     *
180
-     * @param string $scope one of
181
-     * @param array  $query_params
182
-     * @return EE_Base_Class[]|EE_Payment_Method[]
183
-     * @throws EE_Error
184
-     */
185
-    public function get_all_active($scope = null, $query_params = [])
186
-    {
187
-        if (! isset($query_params['order_by']) && ! isset($query_params['order'])) {
188
-            $query_params['order_by'] = ['PMD_order' => 'ASC', 'PMD_ID' => 'ASC'];
189
-        }
190
-        return $this->get_all($this->_get_query_params_for_all_active($scope, $query_params));
191
-    }
192
-
193
-
194
-    /**
195
-     * Counts all active gateways in the specified scope
196
-     *
197
-     * @param string $scope one of EEM_Payment_Method::scope_*
198
-     * @param array  $query_params
199
-     * @return int
200
-     * @throws EE_Error
201
-     */
202
-    public function count_active($scope = null, $query_params = [])
203
-    {
204
-        return $this->count($this->_get_query_params_for_all_active($scope, $query_params));
205
-    }
206
-
207
-
208
-    /**
209
-     * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
210
-     * argument to get all active for a given scope
211
-     *
212
-     * @param string $scope one of the constants EEM_Payment_Method::scope_*
213
-     * @param array  $query_params
214
-     * @return array
215
-     * @throws EE_Error
216
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
217
-     */
218
-    protected function _get_query_params_for_all_active($scope = null, $query_params = [])
219
-    {
220
-        if ($scope) {
221
-            if ($this->is_valid_scope($scope)) {
222
-                return array_replace_recursive([['PMD_scope' => ['LIKE', "%$scope%"]]], $query_params);
223
-            }
224
-            throw new EE_Error(
225
-                sprintf(
226
-                    esc_html__("'%s' is not a valid scope for a payment method", 'event_espresso'),
227
-                    $scope
228
-                )
229
-            );
230
-        }
231
-        $acceptable_scopes = [];
232
-        $count             = 0;
233
-        foreach ($this->scopes() as $scope_name => $desc) {
234
-            $count++;
235
-            $acceptable_scopes[ 'PMD_scope*' . $count ] = ['LIKE', '%' . $scope_name . '%'];
236
-        }
237
-        return array_replace_recursive([['OR*active_scope' => $acceptable_scopes]], $query_params);
238
-    }
239
-
240
-
241
-    /**
242
-     * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
243
-     * argument to get all active for a given scope
244
-     *
245
-     * @param string $scope one of the constants EEM_Payment_Method::scope_*
246
-     * @param array  $query_params
247
-     * @return array
248
-     * @throws EE_Error
249
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
250
-     */
251
-    public function get_query_params_for_all_active($scope = null, $query_params = [])
252
-    {
253
-        return $this->_get_query_params_for_all_active($scope, $query_params);
254
-    }
255
-
256
-
257
-    /**
258
-     * Gets one active payment method. see @get_all_active for documentation
259
-     *
260
-     * @param string $scope
261
-     * @param array  $query_params
262
-     * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|NULL
263
-     * @throws EE_Error
264
-     */
265
-    public function get_one_active($scope = null, $query_params = [])
266
-    {
267
-        return $this->get_one($this->_get_query_params_for_all_active($scope, $query_params));
268
-    }
269
-
270
-
271
-    /**
272
-     * Gets one payment method of that type, regardless of whether its active or not
273
-     *
274
-     * @param string $type
275
-     * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|NULL
276
-     * @throws EE_Error
277
-     */
278
-    public function get_one_of_type($type)
279
-    {
280
-        return $this->get_one([['PMD_type' => $type]]);
281
-    }
282
-
283
-
284
-    /**
285
-     * Overrides parent ot also check by the slug
286
-     *
287
-     * @param string|int|EE_Payment_Method $base_class_obj_or_id
288
-     * @param boolean                      $ensure_is_in_db
289
-     * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|int|string
290
-     * @throws EE_Error
291
-     * @see EEM_Base::ensure_is_obj()
292
-     */
293
-    public function ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db = false)
294
-    {
295
-        // first: check if it's a slug
296
-        if (is_string($base_class_obj_or_id)) {
297
-            $obj = $this->get_one_by_slug($base_class_obj_or_id);
298
-            if ($obj) {
299
-                return $obj;
300
-            }
301
-        }
302
-        // ok so it wasn't a slug we were passed. try the usual then (ie, it's an object or an ID)
303
-        try {
304
-            return parent::ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db);
305
-        } catch (EE_Error $e) {
306
-            // handle it outside the catch
307
-        }
308
-        throw new EE_Error(
309
-            sprintf(
310
-                esc_html__("'%s' is neither a Payment Method ID, slug, nor object.", 'event_espresso'),
311
-                $base_class_obj_or_id
312
-            )
313
-        );
314
-    }
315
-
316
-
317
-    /**
318
-     * Gets the ID of this object, or if its a string finds the object's id
319
-     * associated with that slug
320
-     *
321
-     * @param mixed $base_obj_or_id_or_slug
322
-     * @return int
323
-     * @throws EE_Error
324
-     */
325
-    public function ensure_is_ID($base_obj_or_id_or_slug)
326
-    {
327
-        if (is_string($base_obj_or_id_or_slug)) {
328
-            // assume it's a slug
329
-            $base_obj_or_id_or_slug = $this->get_one_by_slug($base_obj_or_id_or_slug);
330
-        }
331
-        return parent::ensure_is_ID($base_obj_or_id_or_slug);
332
-    }
333
-
334
-
335
-    /**
336
-     * Verifies the button urls on all the passed payment methods have a valid button url.
337
-     * If not, resets them to their default.
338
-     *
339
-     * @param EE_Payment_Method[] $payment_methods if NULL, defaults to all payment methods active in the cart
340
-     * @throws EE_Error
341
-     * @throws ReflectionException
342
-     */
343
-    public function verify_button_urls($payment_methods = null)
344
-    {
345
-        $payment_methods = is_array($payment_methods)
346
-            ? $payment_methods
347
-            : $this->get_all_active(EEM_Payment_Method::scope_cart);
348
-        foreach ($payment_methods as $payment_method) {
349
-            try {
350
-                // If there is really no button URL at all, or if the button URLs still point to decaf folder even
351
-                // though this is a caffeinated install, reset it to the default.
352
-                $current_button_url = $payment_method->button_url();
353
-                if (
354
-                    empty($current_button_url)
355
-                    || (
356
-                        strpos($current_button_url, 'decaf') !== false
357
-                        && strpos($payment_method->type_obj()->default_button_url(), 'decaf') === false
358
-                    )
359
-                ) {
360
-                    $payment_method->save(
361
-                        [
362
-                            'PMD_button_url' => $payment_method->type_obj()->default_button_url(),
363
-                        ]
364
-                    );
365
-                }
366
-            } catch (EE_Error $e) {
367
-                $payment_method->deactivate();
368
-            }
369
-        }
370
-    }
371
-
372
-
373
-    /**
374
-     * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
375
-     * but also verifies the payment method type of each is a usable object. If not,
376
-     * deactivate it, sets a notification, and deactivates it
377
-     *
378
-     * @param array $rows
379
-     * @return EE_Payment_Method[]
380
-     * @throws EE_Error
381
-     * @throws InvalidDataTypeException
382
-     * @throws ReflectionException
383
-     */
384
-    protected function _create_objects($rows = [])
385
-    {
386
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
387
-        $PMM = EE_Payment_Method_Manager::instance();
388
-        $payment_methods = parent::_create_objects($rows);
389
-        /* @var $payment_methods EE_Payment_Method[] */
390
-        $usable_payment_methods = [];
391
-        foreach ($payment_methods as $key => $payment_method) {
392
-            // check if the payment method type exists and force recheck
393
-            $pm_type_exists = $PMM->payment_method_type_exists($payment_method->type(), true);
394
-            if ($pm_type_exists) {
395
-                $usable_payment_methods[ $key ] = $payment_method;
396
-                // some payment methods enqueue their scripts in EE_PMT_*::__construct
397
-                // which is kinda a no-no (just because it's being constructed doesn't mean we need to enqueue
398
-                // its scripts). but for backwards-compat we should continue to do that
399
-                $payment_method->type_obj();
400
-            } elseif ($payment_method->active()) {
401
-                // only deactivate and notify the admin if the payment is active somewhere
402
-                $payment_method->deactivate();
403
-                $payment_method->save();
404
-                do_action(
405
-                    'AHEE__EEM_Payment_Method___create_objects_auto_deactivated_payment_method',
406
-                    $payment_method
407
-                );
408
-                new PersistentAdminNotice(
409
-                    'auto-deactivated-' . $payment_method->type(),
410
-                    sprintf(
411
-                        esc_html__(
412
-                            'The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
413
-                            'event_espresso'
414
-                        ),
415
-                        $payment_method->admin_name(),
416
-                        '<br />',
417
-                        '<a href="' . admin_url('plugins.php') . '">',
418
-                        '</a>'
419
-                    ),
420
-                    true
421
-                );
422
-            }
423
-        }
424
-        return $usable_payment_methods;
425
-    }
426
-
427
-
428
-    /**
429
-     * Gets all the payment methods which can be used for transaction
430
-     * (according to the relations between payment methods and events, and
431
-     * the currencies used for the transaction and their relation to payment methods)
432
-     *
433
-     * @param EE_Transaction $transaction
434
-     * @param string         $scope @see EEM_Payment_Method::get_all_for_events
435
-     * @return EE_Payment_Method[]
436
-     * @throws EE_Error
437
-     */
438
-    public function get_all_for_transaction($transaction, $scope)
439
-    {
440
-        // give addons a chance to override what payment methods are chosen based on the transaction
441
-        return apply_filters(
442
-            'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
443
-            $this->get_all_active($scope, ['group_by' => 'PMD_type']),
444
-            $transaction,
445
-            $scope
446
-        );
447
-    }
448
-
449
-
450
-    /**
451
-     * Returns the payment method used for the last payment made for a registration.
452
-     * Note: if an offline payment method was selected on the related transaction then this will have no payment
453
-     * methods returned. It will ONLY return a payment method for a PAYMENT recorded against the registration.
454
-     *
455
-     * @param EE_Registration|int $registration_or_reg_id Either the EE_Registration object or the id for the
456
-     *                                                    registration.
457
-     * @return EE_Payment|null
458
-     * @throws EE_Error
459
-     */
460
-    public function get_last_used_for_registration($registration_or_reg_id)
461
-    {
462
-        $registration_id = EEM_Registration::instance()->ensure_is_ID($registration_or_reg_id);
463
-
464
-        $query_params = [
465
-            0          => [
466
-                'Payment.Registration.REG_ID' => $registration_id,
467
-            ],
468
-            'order_by' => ['Payment.PAY_ID' => 'DESC'],
469
-        ];
470
-        return $this->get_one($query_params);
471
-    }
19
+	const scope_cart  = 'CART';
20
+
21
+	const scope_admin = 'ADMIN';
22
+
23
+	const scope_api   = 'API';
24
+
25
+
26
+	protected static ?EEM_Payment_Method $_instance = null;
27
+
28
+
29
+	/**
30
+	 * private constructor to prevent direct creation
31
+	 *
32
+	 * @param string|null $timezone
33
+	 * @throws EE_Error
34
+	 */
35
+	protected function __construct(?string $timezone = '')
36
+	{
37
+		$this->singular_item    = esc_html__('Payment Method', 'event_espresso');
38
+		$this->plural_item      = esc_html__('Payment Methods', 'event_espresso');
39
+		$this->_tables          = [
40
+			'Payment_Method' => new EE_Primary_Table('esp_payment_method', 'PMD_ID'),
41
+		];
42
+		$this->_fields          = [
43
+			'Payment_Method' => [
44
+				'PMD_ID'              => new EE_Primary_Key_Int_Field(
45
+					'PMD_ID',
46
+					esc_html__('ID', 'event_espresso')
47
+				),
48
+				'PMD_type'            => new EE_Plain_Text_Field(
49
+					'PMD_type',
50
+					esc_html__('Payment Method Type', 'event_espresso'),
51
+					false,
52
+					'Admin_Only'
53
+				),
54
+				'PMD_name'            => new EE_Plain_Text_Field(
55
+					'PMD_name',
56
+					esc_html__('Name', 'event_espresso'),
57
+					false
58
+				),
59
+				'PMD_desc'            => new EE_Post_Content_Field(
60
+					'PMD_desc',
61
+					esc_html__('Description', 'event_espresso'),
62
+					false,
63
+					''
64
+				),
65
+				'PMD_admin_name'      => new EE_Plain_Text_Field(
66
+					'PMD_admin_name',
67
+					esc_html__('Admin-Only Name', 'event_espresso'),
68
+					true
69
+				),
70
+				'PMD_admin_desc'      => new EE_Post_Content_Field(
71
+					'PMD_admin_desc',
72
+					esc_html__('Admin-Only Description', 'event_espresso'),
73
+					true
74
+				),
75
+				'PMD_slug'            => new EE_Slug_Field(
76
+					'PMD_slug',
77
+					esc_html__('Slug', 'event_espresso'),
78
+					false
79
+				),
80
+				'PMD_order'           => new EE_Integer_Field(
81
+					'PMD_order',
82
+					esc_html__('Order', 'event_espresso'),
83
+					false,
84
+					0
85
+				),
86
+				'PMD_debug_mode'      => new EE_Boolean_Field(
87
+					'PMD_debug_mode',
88
+					esc_html__('Sandbox Mode On? (AKA: debug mode)', 'event_espresso'),
89
+					false,
90
+					false
91
+				),
92
+				'PMD_wp_user'         => new EE_WP_User_Field(
93
+					'PMD_wp_user',
94
+					esc_html__('Payment Method Creator ID', 'event_espresso'),
95
+					false
96
+				),
97
+				'PMD_open_by_default' => new EE_Boolean_Field(
98
+					'PMD_open_by_default',
99
+					esc_html__('Open by Default?', 'event_espresso'),
100
+					false,
101
+					false
102
+				),
103
+				'PMD_button_url'      => new EE_Plain_Text_Field(
104
+					'PMD_button_url',
105
+					esc_html__('Button URL', 'event_espresso'),
106
+					true,
107
+					''
108
+				),
109
+				'PMD_scope'           => new EE_Serialized_Text_Field(
110
+					'PMD_scope',
111
+					esc_html__('Usable From?', 'event_espresso'),
112
+					false,
113
+					[]// possible values currently are 'CART','ADMIN','API'
114
+				),
115
+			],
116
+		];
117
+		$this->_model_relations = [
118
+			'Currency'    => new EE_HABTM_Relation('Currency_Payment_Method'),
119
+			'Payment'     => new EE_Has_Many_Relation(),
120
+			'Transaction' => new EE_Has_Many_Relation(),
121
+			'WP_User'     => new EE_Belongs_To_Relation(),
122
+		];
123
+		parent::__construct($timezone);
124
+	}
125
+
126
+
127
+	/**
128
+	 * Gets one by the slug provided
129
+	 *
130
+	 * @param string $slug
131
+	 * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|NULL
132
+	 * @throws EE_Error
133
+	 */
134
+	public function get_one_by_slug($slug)
135
+	{
136
+		return $this->get_one([['PMD_slug' => $slug]]);
137
+	}
138
+
139
+
140
+	/**
141
+	 * Gets all the acceptable scopes for payment methods.
142
+	 * Keys are their names as store din the DB, and values are nice names for displaying them
143
+	 *
144
+	 * @return array
145
+	 */
146
+	public function scopes()
147
+	{
148
+		return apply_filters(
149
+			'FHEE__EEM_Payment_Method__scopes',
150
+			[
151
+				EEM_Payment_Method::scope_cart  => esc_html__('Front-end Registration Page', 'event_espresso'),
152
+				EEM_Payment_Method::scope_admin => esc_html__(
153
+					'Admin Registration Page (no online processing)',
154
+					'event_espresso'
155
+				),
156
+			]
157
+		);
158
+	}
159
+
160
+
161
+	/**
162
+	 * Determines if this is an valid scope
163
+	 *
164
+	 * @param string $scope like one of EEM_Payment_Method::instance()->scopes()
165
+	 * @return boolean
166
+	 */
167
+	public function is_valid_scope($scope)
168
+	{
169
+		$scopes = $this->scopes();
170
+		if (isset($scopes[ $scope ])) {
171
+			return true;
172
+		}
173
+		return false;
174
+	}
175
+
176
+
177
+	/**
178
+	 * Gets all active payment methods
179
+	 *
180
+	 * @param string $scope one of
181
+	 * @param array  $query_params
182
+	 * @return EE_Base_Class[]|EE_Payment_Method[]
183
+	 * @throws EE_Error
184
+	 */
185
+	public function get_all_active($scope = null, $query_params = [])
186
+	{
187
+		if (! isset($query_params['order_by']) && ! isset($query_params['order'])) {
188
+			$query_params['order_by'] = ['PMD_order' => 'ASC', 'PMD_ID' => 'ASC'];
189
+		}
190
+		return $this->get_all($this->_get_query_params_for_all_active($scope, $query_params));
191
+	}
192
+
193
+
194
+	/**
195
+	 * Counts all active gateways in the specified scope
196
+	 *
197
+	 * @param string $scope one of EEM_Payment_Method::scope_*
198
+	 * @param array  $query_params
199
+	 * @return int
200
+	 * @throws EE_Error
201
+	 */
202
+	public function count_active($scope = null, $query_params = [])
203
+	{
204
+		return $this->count($this->_get_query_params_for_all_active($scope, $query_params));
205
+	}
206
+
207
+
208
+	/**
209
+	 * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
210
+	 * argument to get all active for a given scope
211
+	 *
212
+	 * @param string $scope one of the constants EEM_Payment_Method::scope_*
213
+	 * @param array  $query_params
214
+	 * @return array
215
+	 * @throws EE_Error
216
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
217
+	 */
218
+	protected function _get_query_params_for_all_active($scope = null, $query_params = [])
219
+	{
220
+		if ($scope) {
221
+			if ($this->is_valid_scope($scope)) {
222
+				return array_replace_recursive([['PMD_scope' => ['LIKE', "%$scope%"]]], $query_params);
223
+			}
224
+			throw new EE_Error(
225
+				sprintf(
226
+					esc_html__("'%s' is not a valid scope for a payment method", 'event_espresso'),
227
+					$scope
228
+				)
229
+			);
230
+		}
231
+		$acceptable_scopes = [];
232
+		$count             = 0;
233
+		foreach ($this->scopes() as $scope_name => $desc) {
234
+			$count++;
235
+			$acceptable_scopes[ 'PMD_scope*' . $count ] = ['LIKE', '%' . $scope_name . '%'];
236
+		}
237
+		return array_replace_recursive([['OR*active_scope' => $acceptable_scopes]], $query_params);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
243
+	 * argument to get all active for a given scope
244
+	 *
245
+	 * @param string $scope one of the constants EEM_Payment_Method::scope_*
246
+	 * @param array  $query_params
247
+	 * @return array
248
+	 * @throws EE_Error
249
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
250
+	 */
251
+	public function get_query_params_for_all_active($scope = null, $query_params = [])
252
+	{
253
+		return $this->_get_query_params_for_all_active($scope, $query_params);
254
+	}
255
+
256
+
257
+	/**
258
+	 * Gets one active payment method. see @get_all_active for documentation
259
+	 *
260
+	 * @param string $scope
261
+	 * @param array  $query_params
262
+	 * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|NULL
263
+	 * @throws EE_Error
264
+	 */
265
+	public function get_one_active($scope = null, $query_params = [])
266
+	{
267
+		return $this->get_one($this->_get_query_params_for_all_active($scope, $query_params));
268
+	}
269
+
270
+
271
+	/**
272
+	 * Gets one payment method of that type, regardless of whether its active or not
273
+	 *
274
+	 * @param string $type
275
+	 * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|NULL
276
+	 * @throws EE_Error
277
+	 */
278
+	public function get_one_of_type($type)
279
+	{
280
+		return $this->get_one([['PMD_type' => $type]]);
281
+	}
282
+
283
+
284
+	/**
285
+	 * Overrides parent ot also check by the slug
286
+	 *
287
+	 * @param string|int|EE_Payment_Method $base_class_obj_or_id
288
+	 * @param boolean                      $ensure_is_in_db
289
+	 * @return EE_Base_Class|EE_Payment_Method|EE_Soft_Delete_Base_Class|int|string
290
+	 * @throws EE_Error
291
+	 * @see EEM_Base::ensure_is_obj()
292
+	 */
293
+	public function ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db = false)
294
+	{
295
+		// first: check if it's a slug
296
+		if (is_string($base_class_obj_or_id)) {
297
+			$obj = $this->get_one_by_slug($base_class_obj_or_id);
298
+			if ($obj) {
299
+				return $obj;
300
+			}
301
+		}
302
+		// ok so it wasn't a slug we were passed. try the usual then (ie, it's an object or an ID)
303
+		try {
304
+			return parent::ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db);
305
+		} catch (EE_Error $e) {
306
+			// handle it outside the catch
307
+		}
308
+		throw new EE_Error(
309
+			sprintf(
310
+				esc_html__("'%s' is neither a Payment Method ID, slug, nor object.", 'event_espresso'),
311
+				$base_class_obj_or_id
312
+			)
313
+		);
314
+	}
315
+
316
+
317
+	/**
318
+	 * Gets the ID of this object, or if its a string finds the object's id
319
+	 * associated with that slug
320
+	 *
321
+	 * @param mixed $base_obj_or_id_or_slug
322
+	 * @return int
323
+	 * @throws EE_Error
324
+	 */
325
+	public function ensure_is_ID($base_obj_or_id_or_slug)
326
+	{
327
+		if (is_string($base_obj_or_id_or_slug)) {
328
+			// assume it's a slug
329
+			$base_obj_or_id_or_slug = $this->get_one_by_slug($base_obj_or_id_or_slug);
330
+		}
331
+		return parent::ensure_is_ID($base_obj_or_id_or_slug);
332
+	}
333
+
334
+
335
+	/**
336
+	 * Verifies the button urls on all the passed payment methods have a valid button url.
337
+	 * If not, resets them to their default.
338
+	 *
339
+	 * @param EE_Payment_Method[] $payment_methods if NULL, defaults to all payment methods active in the cart
340
+	 * @throws EE_Error
341
+	 * @throws ReflectionException
342
+	 */
343
+	public function verify_button_urls($payment_methods = null)
344
+	{
345
+		$payment_methods = is_array($payment_methods)
346
+			? $payment_methods
347
+			: $this->get_all_active(EEM_Payment_Method::scope_cart);
348
+		foreach ($payment_methods as $payment_method) {
349
+			try {
350
+				// If there is really no button URL at all, or if the button URLs still point to decaf folder even
351
+				// though this is a caffeinated install, reset it to the default.
352
+				$current_button_url = $payment_method->button_url();
353
+				if (
354
+					empty($current_button_url)
355
+					|| (
356
+						strpos($current_button_url, 'decaf') !== false
357
+						&& strpos($payment_method->type_obj()->default_button_url(), 'decaf') === false
358
+					)
359
+				) {
360
+					$payment_method->save(
361
+						[
362
+							'PMD_button_url' => $payment_method->type_obj()->default_button_url(),
363
+						]
364
+					);
365
+				}
366
+			} catch (EE_Error $e) {
367
+				$payment_method->deactivate();
368
+			}
369
+		}
370
+	}
371
+
372
+
373
+	/**
374
+	 * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
375
+	 * but also verifies the payment method type of each is a usable object. If not,
376
+	 * deactivate it, sets a notification, and deactivates it
377
+	 *
378
+	 * @param array $rows
379
+	 * @return EE_Payment_Method[]
380
+	 * @throws EE_Error
381
+	 * @throws InvalidDataTypeException
382
+	 * @throws ReflectionException
383
+	 */
384
+	protected function _create_objects($rows = [])
385
+	{
386
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
387
+		$PMM = EE_Payment_Method_Manager::instance();
388
+		$payment_methods = parent::_create_objects($rows);
389
+		/* @var $payment_methods EE_Payment_Method[] */
390
+		$usable_payment_methods = [];
391
+		foreach ($payment_methods as $key => $payment_method) {
392
+			// check if the payment method type exists and force recheck
393
+			$pm_type_exists = $PMM->payment_method_type_exists($payment_method->type(), true);
394
+			if ($pm_type_exists) {
395
+				$usable_payment_methods[ $key ] = $payment_method;
396
+				// some payment methods enqueue their scripts in EE_PMT_*::__construct
397
+				// which is kinda a no-no (just because it's being constructed doesn't mean we need to enqueue
398
+				// its scripts). but for backwards-compat we should continue to do that
399
+				$payment_method->type_obj();
400
+			} elseif ($payment_method->active()) {
401
+				// only deactivate and notify the admin if the payment is active somewhere
402
+				$payment_method->deactivate();
403
+				$payment_method->save();
404
+				do_action(
405
+					'AHEE__EEM_Payment_Method___create_objects_auto_deactivated_payment_method',
406
+					$payment_method
407
+				);
408
+				new PersistentAdminNotice(
409
+					'auto-deactivated-' . $payment_method->type(),
410
+					sprintf(
411
+						esc_html__(
412
+							'The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
413
+							'event_espresso'
414
+						),
415
+						$payment_method->admin_name(),
416
+						'<br />',
417
+						'<a href="' . admin_url('plugins.php') . '">',
418
+						'</a>'
419
+					),
420
+					true
421
+				);
422
+			}
423
+		}
424
+		return $usable_payment_methods;
425
+	}
426
+
427
+
428
+	/**
429
+	 * Gets all the payment methods which can be used for transaction
430
+	 * (according to the relations between payment methods and events, and
431
+	 * the currencies used for the transaction and their relation to payment methods)
432
+	 *
433
+	 * @param EE_Transaction $transaction
434
+	 * @param string         $scope @see EEM_Payment_Method::get_all_for_events
435
+	 * @return EE_Payment_Method[]
436
+	 * @throws EE_Error
437
+	 */
438
+	public function get_all_for_transaction($transaction, $scope)
439
+	{
440
+		// give addons a chance to override what payment methods are chosen based on the transaction
441
+		return apply_filters(
442
+			'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
443
+			$this->get_all_active($scope, ['group_by' => 'PMD_type']),
444
+			$transaction,
445
+			$scope
446
+		);
447
+	}
448
+
449
+
450
+	/**
451
+	 * Returns the payment method used for the last payment made for a registration.
452
+	 * Note: if an offline payment method was selected on the related transaction then this will have no payment
453
+	 * methods returned. It will ONLY return a payment method for a PAYMENT recorded against the registration.
454
+	 *
455
+	 * @param EE_Registration|int $registration_or_reg_id Either the EE_Registration object or the id for the
456
+	 *                                                    registration.
457
+	 * @return EE_Payment|null
458
+	 * @throws EE_Error
459
+	 */
460
+	public function get_last_used_for_registration($registration_or_reg_id)
461
+	{
462
+		$registration_id = EEM_Registration::instance()->ensure_is_ID($registration_or_reg_id);
463
+
464
+		$query_params = [
465
+			0          => [
466
+				'Payment.Registration.REG_ID' => $registration_id,
467
+			],
468
+			'order_by' => ['Payment.PAY_ID' => 'DESC'],
469
+		];
470
+		return $this->get_one($query_params);
471
+	}
472 472
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -167,7 +167,7 @@  discard block
 block discarded – undo
167 167
     public function is_valid_scope($scope)
168 168
     {
169 169
         $scopes = $this->scopes();
170
-        if (isset($scopes[ $scope ])) {
170
+        if (isset($scopes[$scope])) {
171 171
             return true;
172 172
         }
173 173
         return false;
@@ -184,7 +184,7 @@  discard block
 block discarded – undo
184 184
      */
185 185
     public function get_all_active($scope = null, $query_params = [])
186 186
     {
187
-        if (! isset($query_params['order_by']) && ! isset($query_params['order'])) {
187
+        if ( ! isset($query_params['order_by']) && ! isset($query_params['order'])) {
188 188
             $query_params['order_by'] = ['PMD_order' => 'ASC', 'PMD_ID' => 'ASC'];
189 189
         }
190 190
         return $this->get_all($this->_get_query_params_for_all_active($scope, $query_params));
@@ -232,7 +232,7 @@  discard block
 block discarded – undo
232 232
         $count             = 0;
233 233
         foreach ($this->scopes() as $scope_name => $desc) {
234 234
             $count++;
235
-            $acceptable_scopes[ 'PMD_scope*' . $count ] = ['LIKE', '%' . $scope_name . '%'];
235
+            $acceptable_scopes['PMD_scope*'.$count] = ['LIKE', '%'.$scope_name.'%'];
236 236
         }
237 237
         return array_replace_recursive([['OR*active_scope' => $acceptable_scopes]], $query_params);
238 238
     }
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
             // check if the payment method type exists and force recheck
393 393
             $pm_type_exists = $PMM->payment_method_type_exists($payment_method->type(), true);
394 394
             if ($pm_type_exists) {
395
-                $usable_payment_methods[ $key ] = $payment_method;
395
+                $usable_payment_methods[$key] = $payment_method;
396 396
                 // some payment methods enqueue their scripts in EE_PMT_*::__construct
397 397
                 // which is kinda a no-no (just because it's being constructed doesn't mean we need to enqueue
398 398
                 // its scripts). but for backwards-compat we should continue to do that
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
                     $payment_method
407 407
                 );
408 408
                 new PersistentAdminNotice(
409
-                    'auto-deactivated-' . $payment_method->type(),
409
+                    'auto-deactivated-'.$payment_method->type(),
410 410
                     sprintf(
411 411
                         esc_html__(
412 412
                             'The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
                         ),
415 415
                         $payment_method->admin_name(),
416 416
                         '<br />',
417
-                        '<a href="' . admin_url('plugins.php') . '">',
417
+                        '<a href="'.admin_url('plugins.php').'">',
418 418
                         '</a>'
419 419
                     ),
420 420
                     true
Please login to merge, or discard this patch.
core/admin/EE_Admin_List_Table.core.php 2 patches
Indentation   +972 added lines, -972 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
7 7
 
8 8
 if (! class_exists('WP_List_Table')) {
9
-    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
9
+	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
10 10
 }
11 11
 
12 12
 
@@ -24,465 +24,465 @@  discard block
 block discarded – undo
24 24
  */
25 25
 abstract class EE_Admin_List_Table extends WP_List_Table
26 26
 {
27
-    const ACTION_COPY    = 'duplicate';
28
-
29
-    const ACTION_DELETE  = 'delete';
30
-
31
-    const ACTION_EDIT    = 'edit';
32
-
33
-    const ACTION_RESTORE = 'restore';
34
-
35
-    const ACTION_TRASH   = 'trash';
36
-
37
-    protected static array $actions = [
38
-        self::ACTION_COPY,
39
-        self::ACTION_DELETE,
40
-        self::ACTION_EDIT,
41
-        self::ACTION_RESTORE,
42
-        self::ACTION_TRASH,
43
-    ];
44
-
45
-    /**
46
-     * holds the data that will be processed for the table
47
-     *
48
-     * @var array $_data
49
-     */
50
-    protected array $_data;
51
-
52
-
53
-    /**
54
-     * This holds the value of all the data available for the given view (for all pages).
55
-     *
56
-     * @var int $_all_data_count
57
-     */
58
-    protected int $_all_data_count;
59
-
60
-
61
-    /**
62
-     * Will contain the count of trashed items for the view label.
63
-     *
64
-     * @var int $_trashed_count
65
-     */
66
-    protected int $_trashed_count;
67
-
68
-
69
-    /**
70
-     * This is what will be referenced as the slug for the current screen
71
-     *
72
-     * @var string $_screen
73
-     */
74
-    protected string $_screen;
75
-
76
-
77
-    /**
78
-     * this is the EE_Admin_Page object
79
-     *
80
-     * @var EE_Admin_Page $_admin_page
81
-     */
82
-    protected EE_Admin_Page $_admin_page;
83
-
84
-
85
-    /**
86
-     * The current view
87
-     *
88
-     * @var string $_view
89
-     */
90
-    protected string $_view;
91
-
92
-
93
-    /**
94
-     * array of possible views for this table
95
-     *
96
-     * @var array $_views
97
-     */
98
-    protected array $_views;
99
-
100
-
101
-    /**
102
-     * An array of key => value pairs containing information about the current table
103
-     * array(
104
-     *        'plural' => 'plural label',
105
-     *        'singular' => 'singular label',
106
-     *        'ajax' => false, //whether to use ajax or not
107
-     *        'screen' => null, //string used to reference what screen this is
108
-     *        (WP_List_table converts to screen object)
109
-     * )
110
-     *
111
-     * @var array $_wp_list_args
112
-     */
113
-    protected array $_wp_list_args;
114
-
115
-    /**
116
-     * an array of column names
117
-     * array(
118
-     *    'internal-name' => 'Title'
119
-     * )
120
-     *
121
-     * @var array $_columns
122
-     */
123
-    protected array $_columns;
124
-
125
-    /**
126
-     * An array of sortable columns
127
-     * array(
128
-     *    'internal-name' => 'orderby' //or
129
-     *    'internal-name' => array( 'orderby', true )
130
-     * )
131
-     *
132
-     * @var array $_sortable_columns
133
-     */
134
-    protected array $_sortable_columns;
135
-
136
-    /**
137
-     * callback method used to perform AJAX row reordering
138
-     *
139
-     * @var string|null $_ajax_sorting_callback
140
-     */
141
-    protected ?string $_ajax_sorting_callback = null;
142
-
143
-    /**
144
-     * An array of hidden columns (if needed)
145
-     * array('internal-name', 'internal-name')
146
-     *
147
-     * @var array $_hidden_columns
148
-     */
149
-    protected array $_hidden_columns;
150
-
151
-    /**
152
-     * holds the per_page value
153
-     *
154
-     * @var int $_per_page
155
-     */
156
-    protected int $_per_page;
157
-
158
-    /**
159
-     * holds what page number is currently being viewed
160
-     *
161
-     * @var int $_current_page
162
-     */
163
-    protected int $_current_page;
164
-
165
-    /**
166
-     * the reference string for the nonce_action
167
-     *
168
-     * @var string $_nonce_action_ref
169
-     */
170
-    protected string $_nonce_action_ref;
171
-
172
-    /**
173
-     * property to hold incoming request data (as set by the admin_page_core)
174
-     *
175
-     * @var array $_req_data
176
-     */
177
-    protected array $_req_data;
178
-
179
-
180
-    /**
181
-     * yes / no array for admin form fields
182
-     *
183
-     * @var array $_yes_no
184
-     */
185
-    protected array $_yes_no = [];
186
-
187
-    /**
188
-     * Array describing buttons that should appear at the bottom of the page
189
-     * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
190
-     * and the values are another array with the following keys
191
-     * array(
192
-     *    'route' => 'page_route',
193
-     *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
194
-     * )
195
-     *
196
-     * @var array $_bottom_buttons
197
-     */
198
-    protected array $_bottom_buttons = [];
199
-
200
-
201
-    /**
202
-     * Used to indicate what should be the primary column for the list table.
203
-     * If not present then falls back to what WP calculates
204
-     * as the primary column.
205
-     *
206
-     * @type string $_primary_column
207
-     */
208
-    protected string $_primary_column = '';
209
-
210
-
211
-    /**
212
-     * Used to indicate whether the table has a checkbox column or not.
213
-     *
214
-     * @type bool $_has_checkbox_column
215
-     */
216
-    protected bool $_has_checkbox_column = false;
217
-
218
-    /**
219
-     * @var AdminListTableFilters|null
220
-     */
221
-    protected ?AdminListTableFilters $admin_list_table_filters = null;
222
-
223
-    protected ?RequestInterface $request = null;
224
-
225
-
226
-    /**
227
-     * @param EE_Admin_Page              $admin_page we use this for obtaining everything we need in the list table
228
-     * @param AdminListTableFilters|null $filters    to display list table filters
229
-     */
230
-    public function __construct(EE_Admin_Page $admin_page, ?AdminListTableFilters $filters = null)
231
-    {
232
-        $this->request     = $this->request ?? LoaderFactory::getShared(RequestInterface::class);
233
-        $this->_admin_page = $admin_page;
234
-        // kept for back compat
235
-        $this->_req_data     = $this->_admin_page->get_request_data();
236
-        $this->_view         = $this->_admin_page->get_view();
237
-        $this->_views        = $this->_admin_page->get_list_table_view_RLs();
238
-        $this->_current_page = $this->get_pagenum();
239
-        $this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
240
-        $this->_yes_no       = [
241
-            esc_html__('No', 'event_espresso'),
242
-            esc_html__('Yes', 'event_espresso'),
243
-        ];
244
-
245
-        $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
246
-
247
-        $this->admin_list_table_filters = $filters instanceof AdminListTableFilters
248
-            ? $filters
249
-            : LoaderFactory::getShared(AdminListTableFilters::class);
250
-
251
-        $this->_setup_data();
252
-        $this->_add_view_counts();
253
-        // ensure changes made to views in child classes get ported back to the admin page
254
-        $this->_admin_page->updateViews($this->_views);
255
-
256
-        $this->_nonce_action_ref = $this->_view;
257
-
258
-        $this->_set_properties();
259
-
260
-        // set primary column
261
-        add_filter('list_table_primary_column', [$this, 'set_primary_column']);
262
-
263
-        // set parent defaults
264
-        parent::__construct($this->_wp_list_args);
265
-
266
-        $this->prepare_items();
267
-    }
268
-
269
-
270
-    /**
271
-     * _setup_data
272
-     * this method is used to setup the $_data, $_all_data_count, and _per_page properties
273
-     *
274
-     * @return void
275
-     * @uses $this->_admin_page
276
-     */
277
-    abstract protected function _setup_data();
278
-
279
-
280
-    /**
281
-     * set the properties that this class needs to be able to execute wp_list_table properly
282
-     * properties set:
283
-     * _wp_list_args = what the arguments required for the parent _wp_list_table.
284
-     * _columns = set the columns in an array.
285
-     * _sortable_columns = columns that are sortable (array).
286
-     * _hidden_columns = columns that are hidden (array)
287
-     * _default_orderby = the default orderby for sorting.
288
-     *
289
-     * @abstract
290
-     * @access protected
291
-     * @return void
292
-     */
293
-    abstract protected function _set_properties();
294
-
295
-
296
-    /**
297
-     * _get_table_filters
298
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
299
-     * gets shown in the table.
300
-     *
301
-     * @abstract
302
-     * @access protected
303
-     * @return string[]
304
-     */
305
-    abstract protected function _get_table_filters();
306
-
307
-
308
-    /**
309
-     * this is a method that child class will do to add counts to the views array so when views are displayed the
310
-     * counts of the views is accurate.
311
-     *
312
-     * @abstract
313
-     * @access protected
314
-     * @return void
315
-     */
316
-    abstract protected function _add_view_counts();
317
-
318
-
319
-    /**
320
-     * _get_hidden_fields
321
-     * returns a html string of hidden fields so if any table filters are used the current view will be respected.
322
-     *
323
-     * @return string
324
-     */
325
-    protected function _get_hidden_fields()
326
-    {
327
-        $page   = $this->request->getRequestParam('page', '');
328
-        $action = $this->request->getRequestParam('route', '');
329
-        $action = $this->request->getRequestParam('action', $action);
330
-        // if action is STILL empty, then we set it to default
331
-        $action = empty($action) || $action === '-1' ? 'default' : $action;
332
-        $field  = '<input type="hidden" name="page" value="' . esc_attr($page) . '" />' . "\n";
333
-        $field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
334
-        $field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
335
-
336
-        $bulk_actions = $this->_get_bulk_actions();
337
-        foreach ($bulk_actions as $bulk_action => $label) {
338
-            $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
339
-                . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
340
-        }
341
-
342
-        return $field;
343
-    }
344
-
345
-
346
-    /**
347
-     * _set_column_info
348
-     * we're using this to set the column headers property.
349
-     *
350
-     * @access protected
351
-     * @return void
352
-     */
353
-    protected function _set_column_info()
354
-    {
355
-        $columns   = $this->get_columns();
356
-        $hidden    = $this->get_hidden_columns();
357
-        $_sortable = $this->get_sortable_columns();
358
-
359
-        /**
360
-         * Dynamic hook allowing for adding sortable columns in this list table.
361
-         * Note that $this->screen->id is in the format
362
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
363
-         * table it is: event-espresso_page_espresso_messages.
364
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
365
-         * hook prefix ("event-espresso") will be different.
366
-         *
367
-         * @var array $_sortable
368
-         */
369
-        $_sortable = apply_filters(
370
-            "FHEE_manage_{$this->screen->id}_sortable_columns",
371
-            $_sortable,
372
-            $this->_screen,
373
-            $this
374
-        );
375
-
376
-        $sortable = [];
377
-        foreach ($_sortable as $id => $data) {
378
-            if (empty($data)) {
379
-                continue;
380
-            }
381
-            // fix for offset errors with WP_List_Table default get_columninfo()
382
-            if (is_array($data)) {
383
-                $_data[0] = key($data);
384
-                $_data[1] = $data[1] ?? false;
385
-            } else {
386
-                $_data[0] = $data;
387
-            }
388
-
389
-            $data = (array) $data;
390
-
391
-            if (! isset($data[1])) {
392
-                $_data[1] = false;
393
-            }
394
-
395
-            $sortable[ $id ] = $_data;
396
-        }
397
-        $primary               = $this->get_primary_column_name();
398
-        $this->_column_headers = [$columns, $hidden, $sortable, $primary];
399
-    }
400
-
401
-
402
-    /**
403
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
404
-     *
405
-     * @return string
406
-     */
407
-    protected function get_primary_column_name()
408
-    {
409
-        foreach (class_parents($this) as $parent) {
410
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
411
-                return parent::get_primary_column_name();
412
-            }
413
-        }
414
-        return $this->_primary_column;
415
-    }
416
-
417
-
418
-    /**
419
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
420
-     *
421
-     * @param EE_Base_Class $item
422
-     * @param string        $column_name
423
-     * @param string        $primary
424
-     * @return string
425
-     */
426
-    protected function handle_row_actions($item, $column_name, $primary)
427
-    {
428
-        foreach (class_parents($this) as $parent) {
429
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
430
-                return parent::handle_row_actions($item, $column_name, $primary);
431
-            }
432
-        }
433
-        return '';
434
-    }
435
-
436
-
437
-    /**
438
-     * _get_bulk_actions
439
-     * This is a wrapper called by WP_List_Table::get_bulk_actions()
440
-     *
441
-     * @access protected
442
-     * @return array bulk_actions
443
-     */
444
-    protected function _get_bulk_actions(): array
445
-    {
446
-        $actions = [];
447
-        // the _views property should have the bulk_actions, so let's go through and extract them into a properly
448
-        // formatted array for the wp_list_table();
449
-        foreach ($this->_views as $view => $args) {
450
-            if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
451
-                // each bulk action will correspond with a admin page route, so we can check whatever the capability is
452
-                // for that page route and skip adding the bulk action if no access for the current logged in user.
453
-                foreach ($args['bulk_action'] as $route => $label) {
454
-                    if ($this->_admin_page->check_user_access($route, true)) {
455
-                        $actions[ $route ] = $label;
456
-                    }
457
-                }
458
-            }
459
-        }
460
-        return $actions;
461
-    }
462
-
463
-
464
-    /**
465
-     * Generate the table navigation above or below the table.
466
-     * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
467
-     *
468
-     * @throws EE_Error
469
-     * @since 4.9.44.rc.001
470
-     */
471
-    public function display_tablenav($which)
472
-    {
473
-        if ('top' === $which) {
474
-            wp_nonce_field('bulk-' . $this->_args['plural']);
475
-        }
476
-
477
-        ob_start();
478
-        $this->extra_tablenav($which);
479
-        $ee_tablenav = ob_get_clean();
480
-
481
-        ob_start();
482
-        $this->bulk_actions();
483
-        $bulkactions = ob_get_clean();
484
-
485
-        ?>
27
+	const ACTION_COPY    = 'duplicate';
28
+
29
+	const ACTION_DELETE  = 'delete';
30
+
31
+	const ACTION_EDIT    = 'edit';
32
+
33
+	const ACTION_RESTORE = 'restore';
34
+
35
+	const ACTION_TRASH   = 'trash';
36
+
37
+	protected static array $actions = [
38
+		self::ACTION_COPY,
39
+		self::ACTION_DELETE,
40
+		self::ACTION_EDIT,
41
+		self::ACTION_RESTORE,
42
+		self::ACTION_TRASH,
43
+	];
44
+
45
+	/**
46
+	 * holds the data that will be processed for the table
47
+	 *
48
+	 * @var array $_data
49
+	 */
50
+	protected array $_data;
51
+
52
+
53
+	/**
54
+	 * This holds the value of all the data available for the given view (for all pages).
55
+	 *
56
+	 * @var int $_all_data_count
57
+	 */
58
+	protected int $_all_data_count;
59
+
60
+
61
+	/**
62
+	 * Will contain the count of trashed items for the view label.
63
+	 *
64
+	 * @var int $_trashed_count
65
+	 */
66
+	protected int $_trashed_count;
67
+
68
+
69
+	/**
70
+	 * This is what will be referenced as the slug for the current screen
71
+	 *
72
+	 * @var string $_screen
73
+	 */
74
+	protected string $_screen;
75
+
76
+
77
+	/**
78
+	 * this is the EE_Admin_Page object
79
+	 *
80
+	 * @var EE_Admin_Page $_admin_page
81
+	 */
82
+	protected EE_Admin_Page $_admin_page;
83
+
84
+
85
+	/**
86
+	 * The current view
87
+	 *
88
+	 * @var string $_view
89
+	 */
90
+	protected string $_view;
91
+
92
+
93
+	/**
94
+	 * array of possible views for this table
95
+	 *
96
+	 * @var array $_views
97
+	 */
98
+	protected array $_views;
99
+
100
+
101
+	/**
102
+	 * An array of key => value pairs containing information about the current table
103
+	 * array(
104
+	 *        'plural' => 'plural label',
105
+	 *        'singular' => 'singular label',
106
+	 *        'ajax' => false, //whether to use ajax or not
107
+	 *        'screen' => null, //string used to reference what screen this is
108
+	 *        (WP_List_table converts to screen object)
109
+	 * )
110
+	 *
111
+	 * @var array $_wp_list_args
112
+	 */
113
+	protected array $_wp_list_args;
114
+
115
+	/**
116
+	 * an array of column names
117
+	 * array(
118
+	 *    'internal-name' => 'Title'
119
+	 * )
120
+	 *
121
+	 * @var array $_columns
122
+	 */
123
+	protected array $_columns;
124
+
125
+	/**
126
+	 * An array of sortable columns
127
+	 * array(
128
+	 *    'internal-name' => 'orderby' //or
129
+	 *    'internal-name' => array( 'orderby', true )
130
+	 * )
131
+	 *
132
+	 * @var array $_sortable_columns
133
+	 */
134
+	protected array $_sortable_columns;
135
+
136
+	/**
137
+	 * callback method used to perform AJAX row reordering
138
+	 *
139
+	 * @var string|null $_ajax_sorting_callback
140
+	 */
141
+	protected ?string $_ajax_sorting_callback = null;
142
+
143
+	/**
144
+	 * An array of hidden columns (if needed)
145
+	 * array('internal-name', 'internal-name')
146
+	 *
147
+	 * @var array $_hidden_columns
148
+	 */
149
+	protected array $_hidden_columns;
150
+
151
+	/**
152
+	 * holds the per_page value
153
+	 *
154
+	 * @var int $_per_page
155
+	 */
156
+	protected int $_per_page;
157
+
158
+	/**
159
+	 * holds what page number is currently being viewed
160
+	 *
161
+	 * @var int $_current_page
162
+	 */
163
+	protected int $_current_page;
164
+
165
+	/**
166
+	 * the reference string for the nonce_action
167
+	 *
168
+	 * @var string $_nonce_action_ref
169
+	 */
170
+	protected string $_nonce_action_ref;
171
+
172
+	/**
173
+	 * property to hold incoming request data (as set by the admin_page_core)
174
+	 *
175
+	 * @var array $_req_data
176
+	 */
177
+	protected array $_req_data;
178
+
179
+
180
+	/**
181
+	 * yes / no array for admin form fields
182
+	 *
183
+	 * @var array $_yes_no
184
+	 */
185
+	protected array $_yes_no = [];
186
+
187
+	/**
188
+	 * Array describing buttons that should appear at the bottom of the page
189
+	 * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
190
+	 * and the values are another array with the following keys
191
+	 * array(
192
+	 *    'route' => 'page_route',
193
+	 *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
194
+	 * )
195
+	 *
196
+	 * @var array $_bottom_buttons
197
+	 */
198
+	protected array $_bottom_buttons = [];
199
+
200
+
201
+	/**
202
+	 * Used to indicate what should be the primary column for the list table.
203
+	 * If not present then falls back to what WP calculates
204
+	 * as the primary column.
205
+	 *
206
+	 * @type string $_primary_column
207
+	 */
208
+	protected string $_primary_column = '';
209
+
210
+
211
+	/**
212
+	 * Used to indicate whether the table has a checkbox column or not.
213
+	 *
214
+	 * @type bool $_has_checkbox_column
215
+	 */
216
+	protected bool $_has_checkbox_column = false;
217
+
218
+	/**
219
+	 * @var AdminListTableFilters|null
220
+	 */
221
+	protected ?AdminListTableFilters $admin_list_table_filters = null;
222
+
223
+	protected ?RequestInterface $request = null;
224
+
225
+
226
+	/**
227
+	 * @param EE_Admin_Page              $admin_page we use this for obtaining everything we need in the list table
228
+	 * @param AdminListTableFilters|null $filters    to display list table filters
229
+	 */
230
+	public function __construct(EE_Admin_Page $admin_page, ?AdminListTableFilters $filters = null)
231
+	{
232
+		$this->request     = $this->request ?? LoaderFactory::getShared(RequestInterface::class);
233
+		$this->_admin_page = $admin_page;
234
+		// kept for back compat
235
+		$this->_req_data     = $this->_admin_page->get_request_data();
236
+		$this->_view         = $this->_admin_page->get_view();
237
+		$this->_views        = $this->_admin_page->get_list_table_view_RLs();
238
+		$this->_current_page = $this->get_pagenum();
239
+		$this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
240
+		$this->_yes_no       = [
241
+			esc_html__('No', 'event_espresso'),
242
+			esc_html__('Yes', 'event_espresso'),
243
+		];
244
+
245
+		$this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
246
+
247
+		$this->admin_list_table_filters = $filters instanceof AdminListTableFilters
248
+			? $filters
249
+			: LoaderFactory::getShared(AdminListTableFilters::class);
250
+
251
+		$this->_setup_data();
252
+		$this->_add_view_counts();
253
+		// ensure changes made to views in child classes get ported back to the admin page
254
+		$this->_admin_page->updateViews($this->_views);
255
+
256
+		$this->_nonce_action_ref = $this->_view;
257
+
258
+		$this->_set_properties();
259
+
260
+		// set primary column
261
+		add_filter('list_table_primary_column', [$this, 'set_primary_column']);
262
+
263
+		// set parent defaults
264
+		parent::__construct($this->_wp_list_args);
265
+
266
+		$this->prepare_items();
267
+	}
268
+
269
+
270
+	/**
271
+	 * _setup_data
272
+	 * this method is used to setup the $_data, $_all_data_count, and _per_page properties
273
+	 *
274
+	 * @return void
275
+	 * @uses $this->_admin_page
276
+	 */
277
+	abstract protected function _setup_data();
278
+
279
+
280
+	/**
281
+	 * set the properties that this class needs to be able to execute wp_list_table properly
282
+	 * properties set:
283
+	 * _wp_list_args = what the arguments required for the parent _wp_list_table.
284
+	 * _columns = set the columns in an array.
285
+	 * _sortable_columns = columns that are sortable (array).
286
+	 * _hidden_columns = columns that are hidden (array)
287
+	 * _default_orderby = the default orderby for sorting.
288
+	 *
289
+	 * @abstract
290
+	 * @access protected
291
+	 * @return void
292
+	 */
293
+	abstract protected function _set_properties();
294
+
295
+
296
+	/**
297
+	 * _get_table_filters
298
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
299
+	 * gets shown in the table.
300
+	 *
301
+	 * @abstract
302
+	 * @access protected
303
+	 * @return string[]
304
+	 */
305
+	abstract protected function _get_table_filters();
306
+
307
+
308
+	/**
309
+	 * this is a method that child class will do to add counts to the views array so when views are displayed the
310
+	 * counts of the views is accurate.
311
+	 *
312
+	 * @abstract
313
+	 * @access protected
314
+	 * @return void
315
+	 */
316
+	abstract protected function _add_view_counts();
317
+
318
+
319
+	/**
320
+	 * _get_hidden_fields
321
+	 * returns a html string of hidden fields so if any table filters are used the current view will be respected.
322
+	 *
323
+	 * @return string
324
+	 */
325
+	protected function _get_hidden_fields()
326
+	{
327
+		$page   = $this->request->getRequestParam('page', '');
328
+		$action = $this->request->getRequestParam('route', '');
329
+		$action = $this->request->getRequestParam('action', $action);
330
+		// if action is STILL empty, then we set it to default
331
+		$action = empty($action) || $action === '-1' ? 'default' : $action;
332
+		$field  = '<input type="hidden" name="page" value="' . esc_attr($page) . '" />' . "\n";
333
+		$field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
334
+		$field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
335
+
336
+		$bulk_actions = $this->_get_bulk_actions();
337
+		foreach ($bulk_actions as $bulk_action => $label) {
338
+			$field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
339
+				. ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
340
+		}
341
+
342
+		return $field;
343
+	}
344
+
345
+
346
+	/**
347
+	 * _set_column_info
348
+	 * we're using this to set the column headers property.
349
+	 *
350
+	 * @access protected
351
+	 * @return void
352
+	 */
353
+	protected function _set_column_info()
354
+	{
355
+		$columns   = $this->get_columns();
356
+		$hidden    = $this->get_hidden_columns();
357
+		$_sortable = $this->get_sortable_columns();
358
+
359
+		/**
360
+		 * Dynamic hook allowing for adding sortable columns in this list table.
361
+		 * Note that $this->screen->id is in the format
362
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
363
+		 * table it is: event-espresso_page_espresso_messages.
364
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
365
+		 * hook prefix ("event-espresso") will be different.
366
+		 *
367
+		 * @var array $_sortable
368
+		 */
369
+		$_sortable = apply_filters(
370
+			"FHEE_manage_{$this->screen->id}_sortable_columns",
371
+			$_sortable,
372
+			$this->_screen,
373
+			$this
374
+		);
375
+
376
+		$sortable = [];
377
+		foreach ($_sortable as $id => $data) {
378
+			if (empty($data)) {
379
+				continue;
380
+			}
381
+			// fix for offset errors with WP_List_Table default get_columninfo()
382
+			if (is_array($data)) {
383
+				$_data[0] = key($data);
384
+				$_data[1] = $data[1] ?? false;
385
+			} else {
386
+				$_data[0] = $data;
387
+			}
388
+
389
+			$data = (array) $data;
390
+
391
+			if (! isset($data[1])) {
392
+				$_data[1] = false;
393
+			}
394
+
395
+			$sortable[ $id ] = $_data;
396
+		}
397
+		$primary               = $this->get_primary_column_name();
398
+		$this->_column_headers = [$columns, $hidden, $sortable, $primary];
399
+	}
400
+
401
+
402
+	/**
403
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
404
+	 *
405
+	 * @return string
406
+	 */
407
+	protected function get_primary_column_name()
408
+	{
409
+		foreach (class_parents($this) as $parent) {
410
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
411
+				return parent::get_primary_column_name();
412
+			}
413
+		}
414
+		return $this->_primary_column;
415
+	}
416
+
417
+
418
+	/**
419
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
420
+	 *
421
+	 * @param EE_Base_Class $item
422
+	 * @param string        $column_name
423
+	 * @param string        $primary
424
+	 * @return string
425
+	 */
426
+	protected function handle_row_actions($item, $column_name, $primary)
427
+	{
428
+		foreach (class_parents($this) as $parent) {
429
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
430
+				return parent::handle_row_actions($item, $column_name, $primary);
431
+			}
432
+		}
433
+		return '';
434
+	}
435
+
436
+
437
+	/**
438
+	 * _get_bulk_actions
439
+	 * This is a wrapper called by WP_List_Table::get_bulk_actions()
440
+	 *
441
+	 * @access protected
442
+	 * @return array bulk_actions
443
+	 */
444
+	protected function _get_bulk_actions(): array
445
+	{
446
+		$actions = [];
447
+		// the _views property should have the bulk_actions, so let's go through and extract them into a properly
448
+		// formatted array for the wp_list_table();
449
+		foreach ($this->_views as $view => $args) {
450
+			if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
451
+				// each bulk action will correspond with a admin page route, so we can check whatever the capability is
452
+				// for that page route and skip adding the bulk action if no access for the current logged in user.
453
+				foreach ($args['bulk_action'] as $route => $label) {
454
+					if ($this->_admin_page->check_user_access($route, true)) {
455
+						$actions[ $route ] = $label;
456
+					}
457
+				}
458
+			}
459
+		}
460
+		return $actions;
461
+	}
462
+
463
+
464
+	/**
465
+	 * Generate the table navigation above or below the table.
466
+	 * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
467
+	 *
468
+	 * @throws EE_Error
469
+	 * @since 4.9.44.rc.001
470
+	 */
471
+	public function display_tablenav($which)
472
+	{
473
+		if ('top' === $which) {
474
+			wp_nonce_field('bulk-' . $this->_args['plural']);
475
+		}
476
+
477
+		ob_start();
478
+		$this->extra_tablenav($which);
479
+		$ee_tablenav = ob_get_clean();
480
+
481
+		ob_start();
482
+		$this->bulk_actions();
483
+		$bulkactions = ob_get_clean();
484
+
485
+		?>
486 486
     <?php if ($ee_tablenav && $which === 'top') : ?>
487 487
     <div class="tablenav <?php echo esc_attr($which); ?> ee-tablenav">
488 488
         <?php echo wp_kses($ee_tablenav, AllowedTags::getWithFormTags()); ?>
@@ -502,484 +502,484 @@  discard block
 block discarded – undo
502 502
     </div>
503 503
     <?php endif; ?>
504 504
         <?php
505
-        if ($which === 'top') {
506
-            echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
507
-        }
508
-    }
509
-
510
-
511
-    /**
512
-     * _filters
513
-     * This receives the filters array from children _get_table_filters() and assembles the string including the filter
514
-     * button.
515
-     *
516
-     * @access private
517
-     * @return void  echos html showing filters
518
-     */
519
-    private function _filters(): void
520
-    {
521
-        $classname = get_class($this);
522
-        $filters   = apply_filters(
523
-            "FHEE__{$classname}__filters",
524
-            $this->_get_table_filters(),
525
-            $this,
526
-            $this->_screen
527
-        );
528
-
529
-        if (empty($filters)) {
530
-            return;
531
-        }
532
-
533
-        $this->admin_list_table_filters->filters(
534
-            $filters,
535
-            $this->get_admin_page()->get_current_page_view_url()
536
-        );
537
-    }
538
-
539
-
540
-    /**
541
-     * Callback for 'list_table_primary_column' WordPress filter
542
-     * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
543
-     * column when class is instantiated.
544
-     *
545
-     * @param string $column_name
546
-     * @return string
547
-     * @see WP_List_Table::get_primary_column_name
548
-     */
549
-    public function set_primary_column($column_name)
550
-    {
551
-        return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
552
-    }
553
-
554
-
555
-    /**
556
-     *
557
-     */
558
-    public function prepare_items()
559
-    {
560
-        $this->_set_column_info();
561
-        $this->process_bulk_action();
562
-
563
-        $this->items = $this->_data;
564
-        $this->set_pagination_args(
565
-            [
566
-                'total_items' => $this->_all_data_count,
567
-                'per_page'    => $this->_per_page,
568
-                'total_pages' => (int) ceil($this->_all_data_count / $this->_per_page),
569
-            ]
570
-        );
571
-    }
572
-
573
-
574
-    /**
575
-     * @param object|array $item
576
-     * @return string html content for the column
577
-     */
578
-    protected function column_cb($item)
579
-    {
580
-        return '';
581
-    }
582
-
583
-
584
-    /**
585
-     * This column is the default for when there is no defined column method for a registered column.
586
-     * This can be overridden by child classes, but allows for hooking in for custom columns.
587
-     *
588
-     * @param EE_Base_Class $item
589
-     * @param string        $column_name The column being called.
590
-     * @return string html content for the column
591
-     */
592
-    public function column_default($item, $column_name)
593
-    {
594
-        /**
595
-         * Dynamic hook allowing for adding additional column content in this list table.
596
-         * Note that $this->screen->id is in the format
597
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
598
-         * table it is: event-espresso_page_espresso_messages.
599
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
600
-         * hook prefix ("event-espresso") will be different.
601
-         */
602
-        ob_start();
603
-        do_action(
604
-            'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
605
-            $item,
606
-            $this->_screen
607
-        );
608
-        $content = ob_get_clean();
609
-        return $column_name === 'actions' ? $this->actionsModalMenu($content) : $content;
610
-    }
611
-
612
-
613
-    /**
614
-     * Get a list of columns. The format is:
615
-     * 'internal-name' => 'Title'
616
-     *
617
-     * @return array
618
-     * @since  3.1.0
619
-     * @access public
620
-     * @abstract
621
-     */
622
-    public function get_columns()
623
-    {
624
-        /**
625
-         * Dynamic hook allowing for adding additional columns in this list table.
626
-         * Note that $this->screen->id is in the format
627
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
628
-         * table it is: event-espresso_page_espresso_messages.
629
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
630
-         * hook prefix ("event-espresso") will be different.
631
-         *
632
-         * @var array
633
-         */
634
-        return apply_filters("FHEE_manage_{$this->screen->id}_columns", $this->_columns, $this->_screen, $this);
635
-    }
636
-
637
-
638
-    /**
639
-     * Get an associative array ( id => link ) with the list
640
-     * of views available on this table.
641
-     *
642
-     * @return array
643
-     * @since  3.1.0
644
-     * @access protected
645
-     */
646
-    public function get_views()
647
-    {
648
-        return $this->_views;
649
-    }
650
-
651
-
652
-    /**
653
-     * Generate the views html.
654
-     */
655
-    public function display_views()
656
-    {
657
-        $views           = $this->get_views();
658
-        $assembled_views = [];
659
-
660
-        if (empty($views)) {
661
-            return;
662
-        }
663
-        echo "<ul class='subsubsub'>\n";
664
-        foreach ($views as $view) {
665
-            $count = ! empty($view['count']) ? absint($view['count']) : 0;
666
-            if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
667
-                $filter                           = "<li";
668
-                $filter                           .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
669
-                $filter                           .= ">";
670
-                $filter                           .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html(
671
-                        $view['label']
672
-                    ) . '</a>';
673
-                $filter                           .= '<span class="count">(' . $count . ')</span>';
674
-                $filter                           .= '</li>';
675
-                $assembled_views[ $view['slug'] ] = $filter;
676
-            }
677
-        }
678
-
679
-        echo ! empty($assembled_views)
680
-            ? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
681
-            : '';
682
-        echo "</ul>";
683
-    }
684
-
685
-
686
-    /**
687
-     * Generates content for a single row of the table
688
-     *
689
-     * @param EE_Base_Class $item The current item
690
-     * @since  4.1
691
-     * @access public
692
-     */
693
-    public function single_row($item)
694
-    {
695
-        $row_class = $this->_get_row_class($item);
696
-        echo '<tr class="' . esc_attr($row_class) . '">';
697
-        $this->single_row_columns($item); // already escaped
698
-        echo '</tr>';
699
-    }
700
-
701
-
702
-    /**
703
-     * This simply sets up the row class for the table rows.
704
-     * Allows for easier overriding of child methods for setting up sorting.
705
-     *
706
-     * @param EE_Base_Class $item the current item
707
-     * @return string
708
-     */
709
-    protected function _get_row_class($item)
710
-    {
711
-        static $row_class = '';
712
-        $row_class = ($row_class === '' ? 'alternate' : '');
713
-
714
-        $new_row_class = $row_class;
715
-
716
-        if (! empty($this->_ajax_sorting_callback)) {
717
-            $new_row_class .= ' rowsortable';
718
-        }
719
-
720
-        return $new_row_class;
721
-    }
722
-
723
-
724
-    /**
725
-     * @return array
726
-     */
727
-    public function get_sortable_columns()
728
-    {
729
-        return (array) $this->_sortable_columns;
730
-    }
731
-
732
-
733
-    /**
734
-     * @return string
735
-     */
736
-    public function get_ajax_sorting_callback()
737
-    {
738
-        return $this->_ajax_sorting_callback;
739
-    }
740
-
741
-
742
-    /**
743
-     * @return array
744
-     */
745
-    public function get_hidden_columns(): array
746
-    {
747
-        $user_id     = get_current_user_id();
748
-        $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
749
-        if (empty($has_default) && ! empty($this->_hidden_columns)) {
750
-            update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
751
-            update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
752
-        }
753
-        $ref = 'manage' . $this->screen->id . 'columnshidden';
754
-        return (array) get_user_option($ref, $user_id);
755
-    }
756
-
757
-
758
-    /**
759
-     * Generates the columns for a single row of the table.
760
-     * Overridden from wp_list_table so as to allow us to filter the column content for a given
761
-     * column.
762
-     *
763
-     * @param EE_Base_Class $item The current item
764
-     * @since 3.1.0
765
-     */
766
-    public function single_row_columns($item)
767
-    {
768
-        [$columns, $hidden, $sortable, $primary] = $this->get_column_info();
769
-
770
-        foreach ($columns as $column_name => $column_display_name) {
771
-            /**
772
-             * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
773
-             * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
774
-             */
775
-            $hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
776
-
777
-            $classes = $column_name . ' column-' . $column_name . $hidden_class;
778
-            if ($primary === $column_name) {
779
-                $classes .= ' has-row-actions column-primary';
780
-            }
781
-
782
-            $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
783
-
784
-            $class = 'class="' . esc_attr($classes) . '"';
785
-
786
-            $attributes = "$class$data";
787
-
788
-            if ($column_name === 'cb') {
789
-                echo '<th scope="row" class="check-column">';
790
-                echo apply_filters(
791
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
792
-                    $this->column_cb($item), // already escaped
793
-                    $item,
794
-                    $this
795
-                );
796
-                echo '</th>';
797
-            } elseif (method_exists($this, "column_$column_name")) {
798
-                echo "<td $attributes>"; // already escaped
799
-                echo apply_filters(
800
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
801
-                    call_user_func([$this, "column_$column_name"], $item),
802
-                    $item,
803
-                    $this
804
-                );
805
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
806
-                echo "</td>";
807
-            } else {
808
-                echo "<td $attributes>"; // already escaped
809
-                echo apply_filters(
810
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
811
-                    $this->column_default($item, $column_name),
812
-                    $item,
813
-                    $column_name,
814
-                    $this
815
-                );
816
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
817
-                echo "</td>";
818
-            }
819
-        }
820
-    }
821
-
822
-
823
-    /**
824
-     * Extra controls to be displayed between bulk actions and pagination
825
-     *
826
-     * @access public
827
-     * @param string $which
828
-     * @throws EE_Error
829
-     */
830
-    public function extra_tablenav($which)
831
-    {
832
-        if ($which === 'top') {
833
-            $this->_filters();
834
-        } elseif($this->_bottom_buttons) {
835
-            echo '<div class="list-table-bottom-buttons alignleft actions">';
836
-            foreach ($this->_bottom_buttons as $type => $action) {
837
-                $route         = $action['route'] ?? '';
838
-                $extra_request = $action['extra_request'] ?? [];
839
-                $btn_class     = $action['btn_class'] ?? 'button button--secondary';
840
-                // already escaped
841
-                echo wp_kses(
842
-                    $this->_admin_page->get_action_link_or_button(
843
-                        $route,
844
-                        $type,
845
-                        $extra_request,
846
-                        $btn_class
847
-                    ),
848
-                    AllowedTags::getWithFormTags()
849
-                );
850
-            }
851
-            do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
852
-            echo '</div>';
853
-        }
854
-    }
855
-
856
-
857
-    /**
858
-     * Get an associative array ( option_name => option_title ) with the list
859
-     * of bulk actions available on this table.
860
-     *
861
-     * @return array
862
-     * @since  3.1.0
863
-     * @access protected
864
-     */
865
-    public function get_bulk_actions()
866
-    {
867
-        return (array) $this->_get_bulk_actions();
868
-    }
869
-
870
-
871
-    /**
872
-     * Processing bulk actions.
873
-     */
874
-    public function process_bulk_action()
875
-    {
876
-        // this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
877
-        // reference in case there is a case where it gets used.
878
-    }
879
-
880
-
881
-    /**
882
-     * returns the EE admin page this list table is associated with
883
-     *
884
-     * @return EE_Admin_Page
885
-     */
886
-    public function get_admin_page()
887
-    {
888
-        return $this->_admin_page;
889
-    }
890
-
891
-
892
-    /**
893
-     * A "helper" function for all children to provide an html string of
894
-     * actions to output in their content.  It is preferable for child classes
895
-     * to use this method for generating their actions content so that it's
896
-     * filterable by plugins
897
-     *
898
-     * @param string        $action_container           what are the html container
899
-     *                                                  elements for this actions string?
900
-     * @param string        $action_class               What class is for the container
901
-     *                                                  element.
902
-     * @param string        $action_items               The contents for the action items
903
-     *                                                  container.  This is filtered before
904
-     *                                                  returned.
905
-     * @param string        $action_id                  What id (optional) is used for the
906
-     *                                                  container element.
907
-     * @param EE_Base_Class $item                       The object for the column displaying
908
-     *                                                  the actions.
909
-     * @return string The assembled action elements container.
910
-     */
911
-    protected function _action_string(
912
-        $action_items,
913
-        $item,
914
-        $action_container = 'ul',
915
-        $action_class = '',
916
-        $action_id = ''
917
-    ) {
918
-        $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
919
-        $action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
920
-        $open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
921
-        $close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
922
-        try {
923
-            $content = apply_filters(
924
-                'FHEE__EE_Admin_List_Table___action_string__action_items',
925
-                $action_items,
926
-                $item,
927
-                $this
928
-            );
929
-        } catch (Exception $e) {
930
-            if (WP_DEBUG) {
931
-                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
932
-            }
933
-            $content = $action_items;
934
-        }
935
-        return "$open_tag$content$close_tag";
936
-    }
937
-
938
-
939
-    /**
940
-     * @return string
941
-     */
942
-    protected function getReturnUrl()
943
-    {
944
-        $host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
945
-        $uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
946
-        return urlencode(esc_url_raw("//$host$uri"));
947
-    }
948
-
949
-
950
-    /**
951
-     * @param string $id
952
-     * @param string $content
953
-     * @param string $align  start (default), center, end
954
-     * @param string $layout row (default) or stack
955
-     * @return string
956
-     * @since   5.0.0.p
957
-     */
958
-    protected function columnContent(
959
-        string $id,
960
-        string $content,
961
-        string $align = 'start',
962
-        string $layout = 'row'
963
-    ): string {
964
-        if (! isset($this->_columns[ $id ])) {
965
-            throw new DomainException('missing column id');
966
-        }
967
-        $heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
968
-        $align   = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
969
-        $align   = "ee-responsive-table-cell--$align";
970
-        $layout  = $layout === 'row' ? 'ee-layout-row' : 'ee-layout-stack';
971
-
972
-        $html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-$id $align $layout'>";
973
-        $html .= "<div class='ee-responsive-table-cell__heading'>$heading</div>";
974
-        $html .= "<div class='ee-responsive-table-cell__content $layout'>$content</div>";
975
-        $html .= "</div>";
976
-        return $html;
977
-    }
978
-
979
-
980
-    protected function actionsModalMenu($actions): string
981
-    {
982
-        return '
505
+		if ($which === 'top') {
506
+			echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
507
+		}
508
+	}
509
+
510
+
511
+	/**
512
+	 * _filters
513
+	 * This receives the filters array from children _get_table_filters() and assembles the string including the filter
514
+	 * button.
515
+	 *
516
+	 * @access private
517
+	 * @return void  echos html showing filters
518
+	 */
519
+	private function _filters(): void
520
+	{
521
+		$classname = get_class($this);
522
+		$filters   = apply_filters(
523
+			"FHEE__{$classname}__filters",
524
+			$this->_get_table_filters(),
525
+			$this,
526
+			$this->_screen
527
+		);
528
+
529
+		if (empty($filters)) {
530
+			return;
531
+		}
532
+
533
+		$this->admin_list_table_filters->filters(
534
+			$filters,
535
+			$this->get_admin_page()->get_current_page_view_url()
536
+		);
537
+	}
538
+
539
+
540
+	/**
541
+	 * Callback for 'list_table_primary_column' WordPress filter
542
+	 * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
543
+	 * column when class is instantiated.
544
+	 *
545
+	 * @param string $column_name
546
+	 * @return string
547
+	 * @see WP_List_Table::get_primary_column_name
548
+	 */
549
+	public function set_primary_column($column_name)
550
+	{
551
+		return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
552
+	}
553
+
554
+
555
+	/**
556
+	 *
557
+	 */
558
+	public function prepare_items()
559
+	{
560
+		$this->_set_column_info();
561
+		$this->process_bulk_action();
562
+
563
+		$this->items = $this->_data;
564
+		$this->set_pagination_args(
565
+			[
566
+				'total_items' => $this->_all_data_count,
567
+				'per_page'    => $this->_per_page,
568
+				'total_pages' => (int) ceil($this->_all_data_count / $this->_per_page),
569
+			]
570
+		);
571
+	}
572
+
573
+
574
+	/**
575
+	 * @param object|array $item
576
+	 * @return string html content for the column
577
+	 */
578
+	protected function column_cb($item)
579
+	{
580
+		return '';
581
+	}
582
+
583
+
584
+	/**
585
+	 * This column is the default for when there is no defined column method for a registered column.
586
+	 * This can be overridden by child classes, but allows for hooking in for custom columns.
587
+	 *
588
+	 * @param EE_Base_Class $item
589
+	 * @param string        $column_name The column being called.
590
+	 * @return string html content for the column
591
+	 */
592
+	public function column_default($item, $column_name)
593
+	{
594
+		/**
595
+		 * Dynamic hook allowing for adding additional column content in this list table.
596
+		 * Note that $this->screen->id is in the format
597
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
598
+		 * table it is: event-espresso_page_espresso_messages.
599
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
600
+		 * hook prefix ("event-espresso") will be different.
601
+		 */
602
+		ob_start();
603
+		do_action(
604
+			'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
605
+			$item,
606
+			$this->_screen
607
+		);
608
+		$content = ob_get_clean();
609
+		return $column_name === 'actions' ? $this->actionsModalMenu($content) : $content;
610
+	}
611
+
612
+
613
+	/**
614
+	 * Get a list of columns. The format is:
615
+	 * 'internal-name' => 'Title'
616
+	 *
617
+	 * @return array
618
+	 * @since  3.1.0
619
+	 * @access public
620
+	 * @abstract
621
+	 */
622
+	public function get_columns()
623
+	{
624
+		/**
625
+		 * Dynamic hook allowing for adding additional columns in this list table.
626
+		 * Note that $this->screen->id is in the format
627
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
628
+		 * table it is: event-espresso_page_espresso_messages.
629
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
630
+		 * hook prefix ("event-espresso") will be different.
631
+		 *
632
+		 * @var array
633
+		 */
634
+		return apply_filters("FHEE_manage_{$this->screen->id}_columns", $this->_columns, $this->_screen, $this);
635
+	}
636
+
637
+
638
+	/**
639
+	 * Get an associative array ( id => link ) with the list
640
+	 * of views available on this table.
641
+	 *
642
+	 * @return array
643
+	 * @since  3.1.0
644
+	 * @access protected
645
+	 */
646
+	public function get_views()
647
+	{
648
+		return $this->_views;
649
+	}
650
+
651
+
652
+	/**
653
+	 * Generate the views html.
654
+	 */
655
+	public function display_views()
656
+	{
657
+		$views           = $this->get_views();
658
+		$assembled_views = [];
659
+
660
+		if (empty($views)) {
661
+			return;
662
+		}
663
+		echo "<ul class='subsubsub'>\n";
664
+		foreach ($views as $view) {
665
+			$count = ! empty($view['count']) ? absint($view['count']) : 0;
666
+			if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
667
+				$filter                           = "<li";
668
+				$filter                           .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
669
+				$filter                           .= ">";
670
+				$filter                           .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html(
671
+						$view['label']
672
+					) . '</a>';
673
+				$filter                           .= '<span class="count">(' . $count . ')</span>';
674
+				$filter                           .= '</li>';
675
+				$assembled_views[ $view['slug'] ] = $filter;
676
+			}
677
+		}
678
+
679
+		echo ! empty($assembled_views)
680
+			? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
681
+			: '';
682
+		echo "</ul>";
683
+	}
684
+
685
+
686
+	/**
687
+	 * Generates content for a single row of the table
688
+	 *
689
+	 * @param EE_Base_Class $item The current item
690
+	 * @since  4.1
691
+	 * @access public
692
+	 */
693
+	public function single_row($item)
694
+	{
695
+		$row_class = $this->_get_row_class($item);
696
+		echo '<tr class="' . esc_attr($row_class) . '">';
697
+		$this->single_row_columns($item); // already escaped
698
+		echo '</tr>';
699
+	}
700
+
701
+
702
+	/**
703
+	 * This simply sets up the row class for the table rows.
704
+	 * Allows for easier overriding of child methods for setting up sorting.
705
+	 *
706
+	 * @param EE_Base_Class $item the current item
707
+	 * @return string
708
+	 */
709
+	protected function _get_row_class($item)
710
+	{
711
+		static $row_class = '';
712
+		$row_class = ($row_class === '' ? 'alternate' : '');
713
+
714
+		$new_row_class = $row_class;
715
+
716
+		if (! empty($this->_ajax_sorting_callback)) {
717
+			$new_row_class .= ' rowsortable';
718
+		}
719
+
720
+		return $new_row_class;
721
+	}
722
+
723
+
724
+	/**
725
+	 * @return array
726
+	 */
727
+	public function get_sortable_columns()
728
+	{
729
+		return (array) $this->_sortable_columns;
730
+	}
731
+
732
+
733
+	/**
734
+	 * @return string
735
+	 */
736
+	public function get_ajax_sorting_callback()
737
+	{
738
+		return $this->_ajax_sorting_callback;
739
+	}
740
+
741
+
742
+	/**
743
+	 * @return array
744
+	 */
745
+	public function get_hidden_columns(): array
746
+	{
747
+		$user_id     = get_current_user_id();
748
+		$has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
749
+		if (empty($has_default) && ! empty($this->_hidden_columns)) {
750
+			update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
751
+			update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
752
+		}
753
+		$ref = 'manage' . $this->screen->id . 'columnshidden';
754
+		return (array) get_user_option($ref, $user_id);
755
+	}
756
+
757
+
758
+	/**
759
+	 * Generates the columns for a single row of the table.
760
+	 * Overridden from wp_list_table so as to allow us to filter the column content for a given
761
+	 * column.
762
+	 *
763
+	 * @param EE_Base_Class $item The current item
764
+	 * @since 3.1.0
765
+	 */
766
+	public function single_row_columns($item)
767
+	{
768
+		[$columns, $hidden, $sortable, $primary] = $this->get_column_info();
769
+
770
+		foreach ($columns as $column_name => $column_display_name) {
771
+			/**
772
+			 * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
773
+			 * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
774
+			 */
775
+			$hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
776
+
777
+			$classes = $column_name . ' column-' . $column_name . $hidden_class;
778
+			if ($primary === $column_name) {
779
+				$classes .= ' has-row-actions column-primary';
780
+			}
781
+
782
+			$data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
783
+
784
+			$class = 'class="' . esc_attr($classes) . '"';
785
+
786
+			$attributes = "$class$data";
787
+
788
+			if ($column_name === 'cb') {
789
+				echo '<th scope="row" class="check-column">';
790
+				echo apply_filters(
791
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
792
+					$this->column_cb($item), // already escaped
793
+					$item,
794
+					$this
795
+				);
796
+				echo '</th>';
797
+			} elseif (method_exists($this, "column_$column_name")) {
798
+				echo "<td $attributes>"; // already escaped
799
+				echo apply_filters(
800
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
801
+					call_user_func([$this, "column_$column_name"], $item),
802
+					$item,
803
+					$this
804
+				);
805
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
806
+				echo "</td>";
807
+			} else {
808
+				echo "<td $attributes>"; // already escaped
809
+				echo apply_filters(
810
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
811
+					$this->column_default($item, $column_name),
812
+					$item,
813
+					$column_name,
814
+					$this
815
+				);
816
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
817
+				echo "</td>";
818
+			}
819
+		}
820
+	}
821
+
822
+
823
+	/**
824
+	 * Extra controls to be displayed between bulk actions and pagination
825
+	 *
826
+	 * @access public
827
+	 * @param string $which
828
+	 * @throws EE_Error
829
+	 */
830
+	public function extra_tablenav($which)
831
+	{
832
+		if ($which === 'top') {
833
+			$this->_filters();
834
+		} elseif($this->_bottom_buttons) {
835
+			echo '<div class="list-table-bottom-buttons alignleft actions">';
836
+			foreach ($this->_bottom_buttons as $type => $action) {
837
+				$route         = $action['route'] ?? '';
838
+				$extra_request = $action['extra_request'] ?? [];
839
+				$btn_class     = $action['btn_class'] ?? 'button button--secondary';
840
+				// already escaped
841
+				echo wp_kses(
842
+					$this->_admin_page->get_action_link_or_button(
843
+						$route,
844
+						$type,
845
+						$extra_request,
846
+						$btn_class
847
+					),
848
+					AllowedTags::getWithFormTags()
849
+				);
850
+			}
851
+			do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
852
+			echo '</div>';
853
+		}
854
+	}
855
+
856
+
857
+	/**
858
+	 * Get an associative array ( option_name => option_title ) with the list
859
+	 * of bulk actions available on this table.
860
+	 *
861
+	 * @return array
862
+	 * @since  3.1.0
863
+	 * @access protected
864
+	 */
865
+	public function get_bulk_actions()
866
+	{
867
+		return (array) $this->_get_bulk_actions();
868
+	}
869
+
870
+
871
+	/**
872
+	 * Processing bulk actions.
873
+	 */
874
+	public function process_bulk_action()
875
+	{
876
+		// this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
877
+		// reference in case there is a case where it gets used.
878
+	}
879
+
880
+
881
+	/**
882
+	 * returns the EE admin page this list table is associated with
883
+	 *
884
+	 * @return EE_Admin_Page
885
+	 */
886
+	public function get_admin_page()
887
+	{
888
+		return $this->_admin_page;
889
+	}
890
+
891
+
892
+	/**
893
+	 * A "helper" function for all children to provide an html string of
894
+	 * actions to output in their content.  It is preferable for child classes
895
+	 * to use this method for generating their actions content so that it's
896
+	 * filterable by plugins
897
+	 *
898
+	 * @param string        $action_container           what are the html container
899
+	 *                                                  elements for this actions string?
900
+	 * @param string        $action_class               What class is for the container
901
+	 *                                                  element.
902
+	 * @param string        $action_items               The contents for the action items
903
+	 *                                                  container.  This is filtered before
904
+	 *                                                  returned.
905
+	 * @param string        $action_id                  What id (optional) is used for the
906
+	 *                                                  container element.
907
+	 * @param EE_Base_Class $item                       The object for the column displaying
908
+	 *                                                  the actions.
909
+	 * @return string The assembled action elements container.
910
+	 */
911
+	protected function _action_string(
912
+		$action_items,
913
+		$item,
914
+		$action_container = 'ul',
915
+		$action_class = '',
916
+		$action_id = ''
917
+	) {
918
+		$action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
919
+		$action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
920
+		$open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
921
+		$close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
922
+		try {
923
+			$content = apply_filters(
924
+				'FHEE__EE_Admin_List_Table___action_string__action_items',
925
+				$action_items,
926
+				$item,
927
+				$this
928
+			);
929
+		} catch (Exception $e) {
930
+			if (WP_DEBUG) {
931
+				EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
932
+			}
933
+			$content = $action_items;
934
+		}
935
+		return "$open_tag$content$close_tag";
936
+	}
937
+
938
+
939
+	/**
940
+	 * @return string
941
+	 */
942
+	protected function getReturnUrl()
943
+	{
944
+		$host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
945
+		$uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
946
+		return urlencode(esc_url_raw("//$host$uri"));
947
+	}
948
+
949
+
950
+	/**
951
+	 * @param string $id
952
+	 * @param string $content
953
+	 * @param string $align  start (default), center, end
954
+	 * @param string $layout row (default) or stack
955
+	 * @return string
956
+	 * @since   5.0.0.p
957
+	 */
958
+	protected function columnContent(
959
+		string $id,
960
+		string $content,
961
+		string $align = 'start',
962
+		string $layout = 'row'
963
+	): string {
964
+		if (! isset($this->_columns[ $id ])) {
965
+			throw new DomainException('missing column id');
966
+		}
967
+		$heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
968
+		$align   = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
969
+		$align   = "ee-responsive-table-cell--$align";
970
+		$layout  = $layout === 'row' ? 'ee-layout-row' : 'ee-layout-stack';
971
+
972
+		$html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-$id $align $layout'>";
973
+		$html .= "<div class='ee-responsive-table-cell__heading'>$heading</div>";
974
+		$html .= "<div class='ee-responsive-table-cell__content $layout'>$content</div>";
975
+		$html .= "</div>";
976
+		return $html;
977
+	}
978
+
979
+
980
+	protected function actionsModalMenu($actions): string
981
+	{
982
+		return '
983 983
         <div class="ee-modal-menu">
984 984
             <button class="ee-modal-menu__button button button--secondary button--icon-only ee-aria-tooltip"
985 985
                     aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '"
@@ -991,44 +991,44 @@  discard block
 block discarded – undo
991 991
                 ' . $actions . '
992 992
             </div>
993 993
         </div>';
994
-    }
994
+	}
995 995
 
996 996
 
997
-    public function actionsColumnHeader(): string
998
-    {
999
-        return '
997
+	public function actionsColumnHeader(): string
998
+	{
999
+		return '
1000 1000
             <span class="ee-actions-column-header-wrap">
1001 1001
                 <span class="dashicons dashicons-screenoptions"></span>
1002 1002
                 <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span>
1003 1003
             </span>';
1004
-    }
1005
-
1006
-
1007
-    protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
1008
-    {
1009
-        $class = ! empty($class) ? "$class ee-list-table-action" : 'ee-list-table-action';
1010
-        $class = ! empty($label) ? "$class ee-aria-tooltip" : $class;
1011
-        $label = ! empty($label) ? " aria-label='$label'" : '';
1012
-        return "<a href='$url' class='$class'$label>$display_text</a>";
1013
-    }
1014
-
1015
-
1016
-    /**
1017
-     * Override the search box method of WP List Table to include a reset button
1018
-     *
1019
-     * @param string $text     The 'submit' button label.
1020
-     * @param string $input_id ID attribute value for the search input field.
1021
-     */
1022
-    public function search_box($text, $input_id)
1023
-    {
1024
-        if (empty($_REQUEST['s']) && ! $this->has_items()) {
1025
-            return;
1026
-        }
1027
-
1028
-        $this->admin_list_table_filters->searchBox(
1029
-            $text,
1030
-            $input_id,
1031
-            $this->get_admin_page()->get_current_page_view_url()
1032
-        );
1033
-    }
1004
+	}
1005
+
1006
+
1007
+	protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
1008
+	{
1009
+		$class = ! empty($class) ? "$class ee-list-table-action" : 'ee-list-table-action';
1010
+		$class = ! empty($label) ? "$class ee-aria-tooltip" : $class;
1011
+		$label = ! empty($label) ? " aria-label='$label'" : '';
1012
+		return "<a href='$url' class='$class'$label>$display_text</a>";
1013
+	}
1014
+
1015
+
1016
+	/**
1017
+	 * Override the search box method of WP List Table to include a reset button
1018
+	 *
1019
+	 * @param string $text     The 'submit' button label.
1020
+	 * @param string $input_id ID attribute value for the search input field.
1021
+	 */
1022
+	public function search_box($text, $input_id)
1023
+	{
1024
+		if (empty($_REQUEST['s']) && ! $this->has_items()) {
1025
+			return;
1026
+		}
1027
+
1028
+		$this->admin_list_table_filters->searchBox(
1029
+			$text,
1030
+			$input_id,
1031
+			$this->get_admin_page()->get_current_page_view_url()
1032
+		);
1033
+	}
1034 1034
 }
Please login to merge, or discard this patch.
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -5,8 +5,8 @@  discard block
 block discarded – undo
5 5
 use EventEspresso\core\services\request\RequestInterface;
6 6
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
7 7
 
8
-if (! class_exists('WP_List_Table')) {
9
-    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
8
+if ( ! class_exists('WP_List_Table')) {
9
+    require_once ABSPATH.'wp-admin/includes/class-wp-list-table.php';
10 10
 }
11 11
 
12 12
 
@@ -236,13 +236,13 @@  discard block
 block discarded – undo
236 236
         $this->_view         = $this->_admin_page->get_view();
237 237
         $this->_views        = $this->_admin_page->get_list_table_view_RLs();
238 238
         $this->_current_page = $this->get_pagenum();
239
-        $this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
239
+        $this->_screen       = $this->_admin_page->get_current_page().'_'.$this->_admin_page->get_current_view();
240 240
         $this->_yes_no       = [
241 241
             esc_html__('No', 'event_espresso'),
242 242
             esc_html__('Yes', 'event_espresso'),
243 243
         ];
244 244
 
245
-        $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
245
+        $this->_per_page = $this->get_items_per_page($this->_screen.'_per_page');
246 246
 
247 247
         $this->admin_list_table_filters = $filters instanceof AdminListTableFilters
248 248
             ? $filters
@@ -329,14 +329,14 @@  discard block
 block discarded – undo
329 329
         $action = $this->request->getRequestParam('action', $action);
330 330
         // if action is STILL empty, then we set it to default
331 331
         $action = empty($action) || $action === '-1' ? 'default' : $action;
332
-        $field  = '<input type="hidden" name="page" value="' . esc_attr($page) . '" />' . "\n";
333
-        $field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
334
-        $field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
332
+        $field  = '<input type="hidden" name="page" value="'.esc_attr($page).'" />'."\n";
333
+        $field  .= '<input type="hidden" name="route" value="'.esc_attr($action).'" />'."\n";
334
+        $field  .= '<input type="hidden" name="perpage" value="'.esc_attr($this->_per_page).'" />'."\n";
335 335
 
336 336
         $bulk_actions = $this->_get_bulk_actions();
337 337
         foreach ($bulk_actions as $bulk_action => $label) {
338
-            $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
339
-                . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
338
+            $field .= '<input type="hidden" name="'.$bulk_action.'_nonce"'
339
+                . ' value="'.wp_create_nonce($bulk_action.'_nonce').'" />'."\n";
340 340
         }
341 341
 
342 342
         return $field;
@@ -388,11 +388,11 @@  discard block
 block discarded – undo
388 388
 
389 389
             $data = (array) $data;
390 390
 
391
-            if (! isset($data[1])) {
391
+            if ( ! isset($data[1])) {
392 392
                 $_data[1] = false;
393 393
             }
394 394
 
395
-            $sortable[ $id ] = $_data;
395
+            $sortable[$id] = $_data;
396 396
         }
397 397
         $primary               = $this->get_primary_column_name();
398 398
         $this->_column_headers = [$columns, $hidden, $sortable, $primary];
@@ -452,7 +452,7 @@  discard block
 block discarded – undo
452 452
                 // for that page route and skip adding the bulk action if no access for the current logged in user.
453 453
                 foreach ($args['bulk_action'] as $route => $label) {
454 454
                     if ($this->_admin_page->check_user_access($route, true)) {
455
-                        $actions[ $route ] = $label;
455
+                        $actions[$route] = $label;
456 456
                     }
457 457
                 }
458 458
             }
@@ -471,7 +471,7 @@  discard block
 block discarded – undo
471 471
     public function display_tablenav($which)
472 472
     {
473 473
         if ('top' === $which) {
474
-            wp_nonce_field('bulk-' . $this->_args['plural']);
474
+            wp_nonce_field('bulk-'.$this->_args['plural']);
475 475
         }
476 476
 
477 477
         ob_start();
@@ -601,7 +601,7 @@  discard block
 block discarded – undo
601 601
          */
602 602
         ob_start();
603 603
         do_action(
604
-            'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
604
+            'AHEE__EE_Admin_List_Table__column_'.$column_name.'__'.$this->screen->id,
605 605
             $item,
606 606
             $this->_screen
607 607
         );
@@ -664,15 +664,15 @@  discard block
 block discarded – undo
664 664
         foreach ($views as $view) {
665 665
             $count = ! empty($view['count']) ? absint($view['count']) : 0;
666 666
             if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
667
-                $filter                           = "<li";
668
-                $filter                           .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
667
+                $filter = "<li";
668
+                $filter                           .= $view['class'] ? " class='".esc_attr($view['class'])."'" : '';
669 669
                 $filter                           .= ">";
670
-                $filter                           .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html(
670
+                $filter                           .= '<a href="'.esc_url_raw($view['url']).'">'.esc_html(
671 671
                         $view['label']
672
-                    ) . '</a>';
673
-                $filter                           .= '<span class="count">(' . $count . ')</span>';
672
+                    ).'</a>';
673
+                $filter                           .= '<span class="count">('.$count.')</span>';
674 674
                 $filter                           .= '</li>';
675
-                $assembled_views[ $view['slug'] ] = $filter;
675
+                $assembled_views[$view['slug']] = $filter;
676 676
             }
677 677
         }
678 678
 
@@ -693,7 +693,7 @@  discard block
 block discarded – undo
693 693
     public function single_row($item)
694 694
     {
695 695
         $row_class = $this->_get_row_class($item);
696
-        echo '<tr class="' . esc_attr($row_class) . '">';
696
+        echo '<tr class="'.esc_attr($row_class).'">';
697 697
         $this->single_row_columns($item); // already escaped
698 698
         echo '</tr>';
699 699
     }
@@ -713,7 +713,7 @@  discard block
 block discarded – undo
713 713
 
714 714
         $new_row_class = $row_class;
715 715
 
716
-        if (! empty($this->_ajax_sorting_callback)) {
716
+        if ( ! empty($this->_ajax_sorting_callback)) {
717 717
             $new_row_class .= ' rowsortable';
718 718
         }
719 719
 
@@ -745,12 +745,12 @@  discard block
 block discarded – undo
745 745
     public function get_hidden_columns(): array
746 746
     {
747 747
         $user_id     = get_current_user_id();
748
-        $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
748
+        $has_default = get_user_option('default'.$this->screen->id.'columnshidden', $user_id);
749 749
         if (empty($has_default) && ! empty($this->_hidden_columns)) {
750
-            update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
751
-            update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
750
+            update_user_option($user_id, 'default'.$this->screen->id.'columnshidden', true);
751
+            update_user_option($user_id, 'manage'.$this->screen->id.'columnshidden', $this->_hidden_columns, true);
752 752
         }
753
-        $ref = 'manage' . $this->screen->id . 'columnshidden';
753
+        $ref = 'manage'.$this->screen->id.'columnshidden';
754 754
         return (array) get_user_option($ref, $user_id);
755 755
     }
756 756
 
@@ -774,14 +774,14 @@  discard block
 block discarded – undo
774 774
              */
775 775
             $hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
776 776
 
777
-            $classes = $column_name . ' column-' . $column_name . $hidden_class;
777
+            $classes = $column_name.' column-'.$column_name.$hidden_class;
778 778
             if ($primary === $column_name) {
779 779
                 $classes .= ' has-row-actions column-primary';
780 780
             }
781 781
 
782
-            $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
782
+            $data = ' data-colname="'.wp_strip_all_tags($column_display_name).'"';
783 783
 
784
-            $class = 'class="' . esc_attr($classes) . '"';
784
+            $class = 'class="'.esc_attr($classes).'"';
785 785
 
786 786
             $attributes = "$class$data";
787 787
 
@@ -797,7 +797,7 @@  discard block
 block discarded – undo
797 797
             } elseif (method_exists($this, "column_$column_name")) {
798 798
                 echo "<td $attributes>"; // already escaped
799 799
                 echo apply_filters(
800
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
800
+                    'FHEE__EE_Admin_List_Table__single_row_columns__column_'.$column_name.'__column_content',
801 801
                     call_user_func([$this, "column_$column_name"], $item),
802 802
                     $item,
803 803
                     $this
@@ -831,7 +831,7 @@  discard block
 block discarded – undo
831 831
     {
832 832
         if ($which === 'top') {
833 833
             $this->_filters();
834
-        } elseif($this->_bottom_buttons) {
834
+        } elseif ($this->_bottom_buttons) {
835 835
             echo '<div class="list-table-bottom-buttons alignleft actions">';
836 836
             foreach ($this->_bottom_buttons as $type => $action) {
837 837
                 $route         = $action['route'] ?? '';
@@ -915,10 +915,10 @@  discard block
 block discarded – undo
915 915
         $action_class = '',
916 916
         $action_id = ''
917 917
     ) {
918
-        $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
919
-        $action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
920
-        $open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
921
-        $close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
918
+        $action_class = ! empty($action_class) ? ' class="'.esc_attr($action_class).'"' : '';
919
+        $action_id    = ! empty($action_id) ? ' id="'.esc_attr($action_id).'"' : '';
920
+        $open_tag     = ! empty($action_container) ? '<'.$action_container.$action_class.$action_id.'>' : '';
921
+        $close_tag    = ! empty($action_container) ? '</'.$action_container.'>' : '';
922 922
         try {
923 923
             $content = apply_filters(
924 924
                 'FHEE__EE_Admin_List_Table___action_string__action_items',
@@ -961,10 +961,10 @@  discard block
 block discarded – undo
961 961
         string $align = 'start',
962 962
         string $layout = 'row'
963 963
     ): string {
964
-        if (! isset($this->_columns[ $id ])) {
964
+        if ( ! isset($this->_columns[$id])) {
965 965
             throw new DomainException('missing column id');
966 966
         }
967
-        $heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
967
+        $heading = $id !== 'cb' ? $this->_columns[$id] : '';
968 968
         $align   = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
969 969
         $align   = "ee-responsive-table-cell--$align";
970 970
         $layout  = $layout === 'row' ? 'ee-layout-row' : 'ee-layout-stack';
@@ -982,13 +982,13 @@  discard block
 block discarded – undo
982 982
         return '
983 983
         <div class="ee-modal-menu">
984 984
             <button class="ee-modal-menu__button button button--secondary button--icon-only ee-aria-tooltip"
985
-                    aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '"
985
+                    aria-label="' . esc_attr__('list table actions menu', 'event_espresso').'"
986 986
             >
987 987
                 <span class="dashicons dashicons-menu"></span>
988 988
             </button>
989 989
             <div class="ee-modal-menu__content ee-admin-container">
990 990
                 <span class="ee-modal-menu__close dashicons dashicons-no"></span>
991
-                ' . $actions . '
991
+                ' . $actions.'
992 992
             </div>
993 993
         </div>';
994 994
     }
@@ -999,7 +999,7 @@  discard block
 block discarded – undo
999 999
         return '
1000 1000
             <span class="ee-actions-column-header-wrap">
1001 1001
                 <span class="dashicons dashicons-screenoptions"></span>
1002
-                <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span>
1002
+                <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso').'</span>
1003 1003
             </span>';
1004 1004
     }
1005 1005
 
Please login to merge, or discard this patch.
core/admin/EE_Admin_Hooks.core.php 2 patches
Indentation   +756 added lines, -756 removed lines patch added patch discarded remove patch
@@ -15,760 +15,760 @@
 block discarded – undo
15 15
 abstract class EE_Admin_Hooks extends EE_Base
16 16
 {
17 17
 
18
-    /**
19
-     * This just holds an instance of the page object for this hook
20
-     *
21
-     * @var EE_Admin_Page|EE_Admin_Page_CPT|null
22
-     * @deprecated  5.0.8.p
23
-     */
24
-    protected $_page_object = null;
25
-
26
-    /**
27
-     * This holds the EE_Admin_Page object from the calling admin page that this object hooks into.
28
-     *
29
-     * @var EE_Admin_Page|EE_Admin_Page_CPT|null
30
-     */
31
-    protected                   $_adminpage_obj = null;
32
-
33
-    protected ?EE_Registry      $EE             = null;
34
-
35
-    protected ?RequestInterface $request        = null;
36
-
37
-    /**
38
-     * This is set by child classes and is an associative array of ajax hooks in the format:
39
-     * array(
40
-     *    'ajax_action_ref' => 'executing_method'; //must be public
41
-     * )
42
-     */
43
-    protected array $_ajax_func = [];
44
-
45
-    /**
46
-     * This is an array of methods that get executed on a page routes admin_init hook. Use the following format:
47
-     * array(
48
-     *    'page_route' => 'executing_method' //must be public
49
-     * )
50
-     */
51
-    protected array $_init_func = [];
52
-
53
-    /**
54
-     * This is an array of methods that output metabox content for the given page route.  Use the following format:
55
-     * [
56
-     *      0 => [
57
-     *          'page_route' => 'string_for_page_route',    must correspond to a page route in the class being connected
58
-     *                                                      with (i.e. "edit_event") If this is in an array then the
59
-     *                                                      same params below will be used but the metabox will be
60
-     *                                                      added to each route.
61
-     *          'func' =>  'executing_method',              must be public (i.e. public function executing_method
62
-     *                                                      ($post, $callback_args){} ).
63
-     *                                                      Note if you include callback args in the array then you
64
-     *                                                      need to declare them in the method arguments.
65
-     *          'id' => 'identifier_for_metabox',           so it can be removed by addons
66
-     *                                                      (optional, class will set it automatically)
67
-     *          'priority' => 'default',                    default 'default' (optional)
68
-     *          'label' => esc_html__('Localized Title', 'event_espresso'),
69
-     *          'context' => 'advanced'                     advanced is default (optional),
70
-     *      ]
71
-     *      'callback_args' => array() //any callback args to include (optional)
72
-     * ]
73
-     * Why are we indexing numerically?  Because it's possible there may be more than one metabox per page_route.
74
-     */
75
-    protected array $_metaboxes = [];
76
-
77
-    /**
78
-     * This is an array of values that indicate any metaboxes we want removed from a given page route.  Usually this is
79
-     * used when caffeinated functionality is replacing decaffeinated functionality.  Use the following format for the
80
-     * array: array(
81
-     *    0 => array(
82
-     *        'page_route' => 'string_for_page_route' //can be string or array of strings that match a page_route(s)
83
-     *        that are in the class being connected with (i.e. 'edit', or 'create_new').
84
-     *        'id' => 'identifier_for_metabox', //what the id is of the metabox being removed
85
-     *        'context' => 'normal', //the context for the metabox being removed (has to match)
86
-     *        'screen' => 'screen_id', //(optional), if not included then this class will attempt to remove the metabox
87
-     *        using the currently loaded screen object->id  however, there may be cases where you have to specify the
88
-     *        id for the screen the metabox is on.
89
-     *    )
90
-     * )
91
-     */
92
-    protected array $_remove_metaboxes = [];
93
-
94
-    protected array $_req_data         = [];
95
-
96
-    /**
97
-     * This parent class takes care of loading the scripts and styles if the child class has set the properties for
98
-     * them in the following format.  Note, the first array index ('register') is for defining all the registers.  The
99
-     * second array index is for indicating what routes each script/style loads on. array(
100
-     * 'registers' => array(
101
-     *        'script_ref' => array( // if more than one script is to be loaded its best to use the 'dependency'
102
-     *        argument to link scripts together.
103
-     *            'type' => 'js' // 'js' or 'css' (defaults to js).  This tells us what type of wp_function to use
104
-     *            'url' => 'http://urltoscript.css.js',
105
-     *            'depends' => array('jquery'), //an array of dependencies for the scripts. REMEMBER, if a script has
106
-     *            already been registered elsewhere in the system.  You can just use the depends array to make sure it
107
-     *            gets loaded before the one you are setting here.
108
-     *            'footer' => TRUE //defaults to true (styles don't use this parameter)
109
-     *        ),
110
-     *    'enqueues' => array( //this time each key corresponds to the script ref followed by an array of page routes
111
-     *    the script gets enqueued on.
112
-     *        'script_ref' => array('route_one', 'route_two')
113
-     *    ),
114
-     *    'localize' => array( //this allows you to set a localized object.  Indicate which script the object is being
115
-     *    attached to and then include an array indexed by the name of the object and the array of key/value pairs for
116
-     *    the object.
117
-     *        'scrip_ref' => array(
118
-     *            'NAME_OF_JS_OBJECT' => array(
119
-     *                'translate_ref' => esc_html__('localized_string', 'event_espresso'),
120
-     *                'some_data' => 5
121
-     *            )
122
-     *        )
123
-     *    )
124
-     * )
125
-     */
126
-    protected array $_scripts_styles = [];
127
-
128
-    protected array $_scripts        = [];
129
-
130
-    protected array $_styles         = [];
131
-
132
-    /**
133
-     * this optional property can be set by child classes to override the priority for the automatic action/filter hook
134
-     * loading in the `_load_routed_hooks()` method.  Please follow this format: array(
135
-     *    'wp_hook_reference' => 1
136
-     *    )
137
-     * )
138
-     */
139
-    protected array $_wp_action_filters_priority = [];
140
-
141
-    /**
142
-     * this is just a flag set automatically to indicate whether we've got an extended hook class running (i.e.
143
-     * espresso_events_Registration_Form_Hooks_Extend extends espresso_events_Registration_Form_Hooks).  This flag is
144
-     * used later to make sure we require the needed files.
145
-     */
146
-    protected bool $_extend = false;
147
-
148
-    /**
149
-     * we're just going to use this to hold the name of the caller class (child class name)
150
-     */
151
-    public string    $caller         = '';
152
-
153
-    protected string $_current_route = '';
154
-
155
-
156
-    /**
157
-     * child classes MUST set this property so that the page object can be loaded correctly
158
-     */
159
-    protected string $_name = '';
160
-
161
-
162
-    /**
163
-     * constructor
164
-     *
165
-     * @param EE_Admin_Page $admin_page
166
-     * @throws EE_Error
167
-     * @throws ReflectionException
168
-     */
169
-    public function __construct(EE_Admin_Page $admin_page)
170
-    {
171
-        $this->_adminpage_obj = $admin_page;
172
-        $this->request        = LoaderFactory::getLoader()->getShared(RequestInterface::class);
173
-        $this->_req_data      = $this->request->requestParams();
174
-        $current_page         = $this->request->getRequestParam('page');
175
-        $current_page         = $this->request->getRequestParam('current_page', $current_page);
176
-        // first let's verify we're on the right page
177
-        if ($current_page !== $this->_adminpage_obj->page_slug) {
178
-            return;
179
-        }
180
-        $this->_set_defaults();
181
-        $this->_set_hooks_properties();
182
-        // get out nothing more to be done here.
183
-        // allow for extends to modify properties
184
-        if (method_exists($this, '_extend_properties')) {
185
-            $this->_extend_properties();
186
-        }
187
-        // $this->_set_page_object();
188
-        $this->_init_hooks();
189
-        $this->_load_custom_methods();
190
-        $this->_load_routed_hooks();
191
-        add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts_styles']);
192
-        add_action('admin_enqueue_scripts', [$this, 'add_metaboxes'], 20);
193
-        add_action('admin_enqueue_scripts', [$this, 'remove_metaboxes'], 15);
194
-        $this->_ajax_hooks();
195
-    }
196
-
197
-
198
-    /**
199
-     * used by child classes to set the following properties:
200
-     * $_ajax_func (optional)
201
-     * $_init_func (optional)
202
-     * $_metaboxes (optional)
203
-     * $_scripts (optional)
204
-     * $_styles (optional)
205
-     * $_name (required)
206
-     * Also in this method will be registered any scripts or styles loaded on the targeted page (as indicated in the
207
-     * _scripts/_styles properties) Also children should place in this method any filters/actions that have to happen
208
-     * really early on page load (just after admin_init) if they want to have them registered for handling early.
209
-     *
210
-     * @abstract
211
-     * @return void
212
-     */
213
-    abstract protected function _set_hooks_properties();
214
-
215
-
216
-    /**
217
-     * The hooks for enqueue_scripts and enqueue_styles will be run in here.  Child classes need to define their
218
-     * scripts and styles in the relevant $_scripts and $_styles properties.  Child classes must have also already
219
-     * registered the scripts and styles using wp_register_script and wp_register_style functions.
220
-     *
221
-     * @return void
222
-     * @throws EE_Error
223
-     */
224
-    public function enqueue_scripts_styles()
225
-    {
226
-        if (! empty($this->_scripts_styles)) {
227
-            // first let's do all the registrations
228
-            if (! isset($this->_scripts_styles['registers'])) {
229
-                $msg[] = esc_html__(
230
-                    'There is no "registers" index in the <code>$this->_scripts_styles</code> property.',
231
-                    'event_espresso'
232
-                );
233
-                $msg[] = sprintf(
234
-                    esc_html__(
235
-                        'Make sure you read the phpdoc comments above the definition of the $_scripts_styles property in the <code>EE_Admin_Hooks</code> class and modify according in the %s child',
236
-                        'event_espresso'
237
-                    ),
238
-                    '<strong>' . $this->caller . '</strong>'
239
-                );
240
-                throw new EE_Error(implode('||', $msg));
241
-            }
242
-            $defaults = [
243
-                'type'    => 'js',
244
-                'url'     => '',
245
-                'depends' => [],
246
-                'version' => EVENT_ESPRESSO_VERSION,
247
-                'footer'  => true,
248
-            ];
249
-            foreach ($this->_scripts_styles['registers'] as $ref => $details) {
250
-                $details = wp_parse_args($details, $defaults);
251
-                $type    = $details['type'];
252
-                $url     = $details['url'];
253
-                $depends = $details['depends'];
254
-                $version = $details['version'];
255
-                $footer  = $details['footer'];
256
-                // let's make sure that we set the 'registers' type if it's not set!
257
-                // We need it later to determine which enqueue we do
258
-                $this->_scripts_styles['registers'][ $ref ]['type'] = $type;
259
-                // let's make sure we're not missing any REQUIRED parameters
260
-                if (empty($url)) {
261
-                    $msg[] = sprintf(
262
-                        esc_html__('Missing the url for the requested %s', 'event_espresso'),
263
-                        $type == 'js' ? 'script' : 'stylesheet'
264
-                    );
265
-                    $msg[] = sprintf(
266
-                        esc_html__(
267
-                            'Double-check your <code>$this->_scripts_styles</code> array in %s and make sure that there is a "url" set for the %s ref',
268
-                            'event_espresso'
269
-                        ),
270
-                        '<strong>' . $this->caller . '</strong>',
271
-                        $ref
272
-                    );
273
-                    throw new EE_Error(implode('||', $msg));
274
-                }
275
-                // made it here so let's do the appropriate registration
276
-                $type == 'js'
277
-                    ? wp_register_script($ref, $url, $depends, $version, $footer)
278
-                    : wp_register_style(
279
-                    $ref,
280
-                    $url,
281
-                    $depends,
282
-                    $version
283
-                );
284
-            }
285
-            // k now let's do the enqueues
286
-            if (! isset($this->_scripts_styles['enqueues'])) {
287
-                return;
288
-            }  //not sure if we should throw an error here or not.
289
-
290
-            foreach ($this->_scripts_styles['enqueues'] as $ref => $routes) {
291
-                // make sure $routes is an array
292
-                $routes = (array) $routes;
293
-                if (in_array($this->_current_route, $routes)) {
294
-                    $this->_scripts_styles['registers'][ $ref ]['type'] == 'js' ? wp_enqueue_script($ref)
295
-                        : wp_enqueue_style($ref);
296
-                    // if we have a localization for the script let's do that too.
297
-                    if (isset($this->_scripts_styles['localize'][ $ref ])) {
298
-                        foreach ($this->_scripts_styles['localize'][ $ref ] as $object_name => $indexes) {
299
-                            wp_localize_script(
300
-                                $ref,
301
-                                $object_name,
302
-                                $this->_scripts_styles['localize'][ $ref ][ $object_name ]
303
-                            );
304
-                        }
305
-                    }
306
-                }
307
-            }
308
-            // let's do the deregisters
309
-            if (! isset($this->_scripts_styles['deregisters'])) {
310
-                return;
311
-            }
312
-            foreach ($this->_scripts_styles['deregisters'] as $ref => $details) {
313
-                $defaults = ['type' => 'js'];
314
-                $details  = wp_parse_args($details, $defaults);
315
-                $details['type'] === 'js' ? wp_deregister_script($ref) : wp_deregister_style($ref);
316
-            }
317
-        }
318
-    }
319
-
320
-
321
-    /**
322
-     * just set the defaults for the hooks properties.
323
-     *
324
-     * @return void
325
-     */
326
-    private function _set_defaults()
327
-    {
328
-        $this->_ajax_func                  = [];
329
-        $this->_init_func                  = [];
330
-        $this->_metaboxes                  = [];
331
-        $this->_scripts                    = [];
332
-        $this->_styles                     = [];
333
-        $this->_wp_action_filters_priority = [];
334
-        $this->_current_route              = $this->getCurrentRoute();
335
-        $this->caller                      = get_class($this);
336
-        $this->_extend                     = (bool) stripos($this->caller, 'Extend');
337
-    }
338
-
339
-
340
-    /**
341
-     * A helper for determining the current route.
342
-     *
343
-     * @return string
344
-     */
345
-    private function getCurrentRoute(): string
346
-    {
347
-        $action = $this->request->getRequestParam('action');
348
-        // list tables do something else with 'action' for bulk actions.
349
-        $action = $action !== '-1' && $action !== '' ? $action : 'default';
350
-        $route  = $this->request->getRequestParam('route');
351
-        // we set a 'route' variable in some cases where action is being used by something else.
352
-        return $action === 'default' && $route !== '' ? $route : $action;
353
-    }
354
-
355
-
356
-    /**
357
-     * this sets the _page_object property
358
-     *
359
-     * @return void
360
-     * @throws EE_Error
361
-     * @throws ReflectionException
362
-     * @throws Throwable
363
-     * @deprecated  5.0.8.p
364
-     */
365
-    protected function _set_page_object()
366
-    {
367
-        if ($this->_page_object instanceof EE_Admin_Page) {
368
-            return;
369
-        }
370
-        // first make sure $this->_name is set
371
-        if (empty($this->_name)) {
372
-            $msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
373
-            $msg[] = sprintf(
374
-                esc_html__("This is because the %s child class has not set the '_name' property", 'event_espresso'),
375
-                $this->caller
376
-            );
377
-            throw new EE_Error(implode('||', $msg));
378
-        }
379
-        // change "the_message" to "the message"
380
-        $class_name = str_replace('_', ' ', $this->_name);
381
-        // change "the message" to "The_Message_Admin_Page"
382
-        $class_name = str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
383
-        // first default file (if exists)
384
-        $decaf_file = EE_ADMIN_PAGES . "$this->_name/$class_name.core.php";
385
-        if (is_readable($decaf_file)) {
386
-            require_once($decaf_file);
387
-        }
388
-        // now we have to do require for extended file (if needed)
389
-        if ($this->_extend) {
390
-            require_once EE_CORE_CAF_ADMIN_EXTEND . "$this->_name/Extend_$class_name.core.php";
391
-            // and extend the class name as well
392
-            $class_name = 'Extend_' . $class_name;
393
-        }
394
-        // let's make sure the class exists
395
-        if (! class_exists($class_name)) {
396
-            $msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
397
-            $msg[] = sprintf(
398
-                esc_html__(
399
-                    'The class name that was given is %s. Check the spelling and make sure its correct, also there needs to be an autoloader setup for the class',
400
-                    'event_espresso'
401
-                ),
402
-                $class_name
403
-            );
404
-            throw new EE_Error(implode('||', $msg));
405
-        }
406
-        // do NOT load admin pages that are ALREADY LOADED!!!
407
-        if ($class_name !== $this->_adminpage_obj->class_name) {
408
-            return;
409
-        }
410
-        $this->_page_object = LoaderFactory::getLoader()->getShared($class_name, [false]);
411
-        $this->_page_object->initializePage();
412
-    }
413
-
414
-
415
-    /**
416
-     * Child "hook" classes can declare any methods that they want executed when a specific page route is loaded.  The
417
-     * advantage of this is when doing things like running our own db interactions on saves etc.  Remember that
418
-     * $this->_req_data (all the _POST and _GET data) is available to your methods.
419
-     *
420
-     * @return void
421
-     */
422
-    private function _load_custom_methods()
423
-    {
424
-        /**
425
-         * method cannot be named 'default' (@see http://us3.php
426
-         * .net/manual/en/reserved.keywords.php) so need to
427
-         * handle routes that are "default"
428
-         *
429
-         * @since 4.3.0
430
-         */
431
-        $method_callback = $this->_current_route == 'default' ? 'default_callback' : $this->_current_route;
432
-        // these run before the Admin_Page route executes.
433
-        if (is_callable($this, $method_callback)) {
434
-            call_user_func([$this, $method_callback]);
435
-        }
436
-        // these run via the _redirect_after_action method in EE_Admin_Page which usually happens after non_UI methods in EE_Admin_Page classes.  There are two redirect actions, the first fires before $query_args might be manipulated by "save and close" actions and the second fires right before the actual redirect happens.
437
-        // first the actions
438
-        // note that these action hooks will have the $query_args value available.
439
-        $admin_class_name = get_class($this->_adminpage_obj);
440
-        if (method_exists($this, '_redirect_action_early_' . $this->_current_route)) {
441
-            add_action(
442
-                'AHEE__'
443
-                . $admin_class_name
444
-                . '___redirect_after_action__before_redirect_modification_'
445
-                . $this->_current_route,
446
-                [$this, '_redirect_action_early_' . $this->_current_route]
447
-            );
448
-        }
449
-        if (method_exists($this, '_redirect_action_' . $this->_current_route)) {
450
-            add_action(
451
-                'AHEE_redirect_' . $admin_class_name . $this->_current_route,
452
-                [$this, '_redirect_action_' . $this->_current_route]
453
-            );
454
-        }
455
-        // let's hook into the _redirect itself and allow for changing where the user goes after redirect.  This will have $query_args and $redirect_url available.
456
-        if (method_exists($this, '_redirect_filter_' . $this->_current_route)) {
457
-            add_filter(
458
-                'FHEE_redirect_' . $admin_class_name . $this->_current_route,
459
-                [$this, '_redirect_filter_' . $this->_current_route],
460
-                10,
461
-                2
462
-            );
463
-        }
464
-    }
465
-
466
-
467
-    /**
468
-     * This method will search for a corresponding method with a name matching the route and the wp_hook to run.  This
469
-     * allows child hook classes to target hooking into a specific wp action or filter hook ONLY on a certain route.
470
-     * just remember, methods MUST be public Future hooks should be added in here to be access by child classes.
471
-     *
472
-     * @return void
473
-     */
474
-    private function _load_routed_hooks()
475
-    {
476
-        // this array provides the hook action names that will be referenced.  Key is the action. Value is an array with the type (action or filter) and the number of parameters for the hook.  We'll default all priorities for automatic hooks to 10.
477
-        $hook_filter_array = [
478
-            'admin_footer'                                                                            => [
479
-                'type'     => 'action',
480
-                'argnum'   => 1,
481
-                'priority' => 10,
482
-            ],
483
-            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug . '_' . $this->_current_route => [
484
-                'type'     => 'filter',
485
-                'argnum'   => 1,
486
-                'priority' => 10,
487
-            ],
488
-            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug                               => [
489
-                'type'     => 'filter',
490
-                'argnum'   => 1,
491
-                'priority' => 10,
492
-            ],
493
-            'FHEE_list_table_views'                                                                   => [
494
-                'type'     => 'filter',
495
-                'argnum'   => 1,
496
-                'priority' => 10,
497
-            ],
498
-            'AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes'                              => [
499
-                'type'     => 'action',
500
-                'argnum'   => 1,
501
-                'priority' => 10,
502
-            ],
503
-        ];
504
-        foreach ($hook_filter_array as $hook => $args) {
505
-            if (method_exists($this, $this->_current_route . '_' . $hook)) {
506
-                if (isset($this->_wp_action_filters_priority[ $hook ])) {
507
-                    $args['priority'] = $this->_wp_action_filters_priority[ $hook ];
508
-                }
509
-                if ($args['type'] == 'action') {
510
-                    add_action(
511
-                        $hook,
512
-                        [$this, $this->_current_route . '_' . $hook],
513
-                        $args['priority'],
514
-                        $args['argnum']
515
-                    );
516
-                } else {
517
-                    add_filter(
518
-                        $hook,
519
-                        [$this, $this->_current_route . '_' . $hook],
520
-                        $args['priority'],
521
-                        $args['argnum']
522
-                    );
523
-                }
524
-            }
525
-        }
526
-    }
527
-
528
-
529
-    /**
530
-     * Loop through the $_ajax_func array and add_actions for the array.
531
-     *
532
-     * @return void
533
-     * @throws EE_Error
534
-     */
535
-    private function _ajax_hooks()
536
-    {
537
-        if (empty($this->_ajax_func)) {
538
-            // get out there's nothing to take care of.
539
-            return;
540
-        }
541
-
542
-        // check for the most basic EE capability
543
-        if (! $this->_adminpage_obj->capabilities()->current_user_can('ee_read_ee', 'access-ajax-actions')) {
544
-            return;
545
-        }
546
-
547
-        foreach ($this->_ajax_func as $action => $method) {
548
-            // make sure method exists
549
-            if (! method_exists($this, $method)) {
550
-                $msg[] = esc_html__(
551
-                             'There is no corresponding method for the hook labeled in the _ajax_func array',
552
-                             'event_espresso'
553
-                         ) . '<br />';
554
-                $msg[] = sprintf(
555
-                    esc_html__(
556
-                        'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
557
-                        'event_espresso'
558
-                    ),
559
-                    $method,
560
-                    $this->caller
561
-                );
562
-                throw new EE_Error(implode('||', $msg));
563
-            }
564
-            add_action('wp_ajax_' . $action, [$this, $method]);
565
-        }
566
-    }
567
-
568
-
569
-    /**
570
-     * Loop through the $_init_func array and add_actions for the array.
571
-     *
572
-     * @return void
573
-     * @throws EE_Error
574
-     */
575
-    protected function _init_hooks()
576
-    {
577
-        if (empty($this->_init_func)) {
578
-            return;
579
-        }
580
-        // get out there's nothing to take care of.
581
-        // We need to determine what page_route we are on!
582
-        foreach ($this->_init_func as $route => $method) {
583
-            // make sure method exists
584
-            if (! method_exists($this, $method)) {
585
-                $msg[] = esc_html__(
586
-                             'There is no corresponding method for the hook labeled in the _init_func array',
587
-                             'event_espresso'
588
-                         ) . '<br />';
589
-                $msg[] = sprintf(
590
-                    esc_html__(
591
-                        'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
592
-                        'event_espresso'
593
-                    ),
594
-                    $method,
595
-                    $this->caller
596
-                );
597
-                throw new EE_Error(implode('||', $msg));
598
-            }
599
-            if ($route == $this->_current_route) {
600
-                add_action('admin_init', [$this, $method]);
601
-            }
602
-        }
603
-    }
604
-
605
-
606
-    /**
607
-     * Loop through the _metaboxes property and add_metaboxes accordingly
608
-     * //todo we could eventually make this a config component class (i.e. new EE_Metabox);
609
-     *
610
-     * @return void
611
-     * @throws EE_Error
612
-     */
613
-    public function add_metaboxes()
614
-    {
615
-        if (empty($this->_metaboxes)) {
616
-            return;
617
-        } //get out we don't have any metaboxes to set for this connection
618
-        $this->_handle_metabox_array($this->_metaboxes);
619
-    }
620
-
621
-
622
-    /**
623
-     * @param array     $boxes
624
-     * @param bool|null $add
625
-     * @throws EE_Error
626
-     */
627
-    private function _handle_metabox_array(array $boxes, ?bool $add = true)
628
-    {
629
-        foreach ($boxes as $box) {
630
-            if (! isset($box['page_route'])) {
631
-                continue;
632
-            }
633
-            // we don't have a valid array
634
-            // let's make sure $box['page_route'] is an array so the "foreach" will work.
635
-            $box['page_route'] = (array) $box['page_route'];
636
-            foreach ($box['page_route'] as $route) {
637
-                if ($route != $this->_current_route) {
638
-                    continue;
639
-                } //get out we only add metaboxes for set route.
640
-                if ($add) {
641
-                    $this->_add_metabox($box);
642
-                } else {
643
-                    $this->_remove_metabox($box);
644
-                }
645
-            }
646
-        }
647
-    }
648
-
649
-
650
-    /**
651
-     * Loop through the _remove_metaboxes property and remove metaboxes accordingly.
652
-     *
653
-     * @return void
654
-     * @throws EE_Error
655
-     */
656
-    public function remove_metaboxes()
657
-    {
658
-        if (empty($this->_remove_metaboxes)) {
659
-            return;
660
-        } //get out there are no metaboxes to remove
661
-        $this->_handle_metabox_array($this->_remove_metaboxes, false);
662
-    }
663
-
664
-
665
-    /**
666
-     * This just handles adding a metabox
667
-     *
668
-     * @param array $args an array of args that have been set for this metabox by the child class
669
-     * @throws EE_Error
670
-     */
671
-    private function _add_metabox(array $args)
672
-    {
673
-        $current_screen    = get_current_screen();
674
-        $screen_id         = is_object($current_screen) ? $current_screen->id : null;
675
-        $callback          = $args['func'] ?? 'some_invalid_callback';
676
-        $callback_function = is_array($callback) ? end($callback) : $callback;
677
-        // set defaults
678
-        $defaults      = [
679
-            'callback_args' => [],
680
-            'context'       => 'advanced',
681
-            'func'          => $callback,
682
-            'id'            => $this->caller . '_' . $callback_function . '_metabox',
683
-            'label'         => $this->caller,
684
-            'page'          => $args['page'] ?? $screen_id,
685
-            'priority'      => 'default',
686
-        ];
687
-        $args          = wp_parse_args($args, $defaults);
688
-        $callback_args = $args['callback_args'];
689
-        $context       = $args['context'];
690
-        $id            = $args['id'];
691
-        $label         = $args['label'];
692
-        $page          = $args['page'];
693
-        $priority      = $args['priority'];
694
-        // make sure method exists
695
-        if (! method_exists($this, $callback_function)) {
696
-            $msg[] =
697
-                esc_html__('There is no corresponding method to display the metabox content', 'event_espresso')
698
-                . '<br />';
699
-            $msg[] = sprintf(
700
-                esc_html__(
701
-                    'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
702
-                    'event_espresso'
703
-                ),
704
-                $callback_function,
705
-                $this->caller
706
-            );
707
-            throw new EE_Error(implode('||', $msg));
708
-        }
709
-        // everything checks out so let's add the metabox
710
-        add_meta_box($id, $label, [$this, $callback_function], $page, $context, $priority, $callback_args);
711
-        add_filter(
712
-            "postbox_classes_{$page}_$id",
713
-            function ($classes) {
714
-                $classes[] = 'ee-admin-container';
715
-                return $classes;
716
-            }
717
-        );
718
-    }
719
-
720
-
721
-    private function _remove_metabox($args)
722
-    {
723
-        $current_screen = get_current_screen();
724
-        $screen_id      = is_object($current_screen) ? $current_screen->id : null;
725
-        $func           = $args['func'] ?? 'some_invalid_callback';
726
-        // set defaults
727
-        $defaults = [
728
-            'context' => 'default',
729
-            'id'      => $args['id'] ?? "{$this->_current_route}_{$this->caller}_{$func}_metabox",
730
-            'screen'  => $args['screen'] ?? $screen_id,
731
-        ];
732
-        $args     = wp_parse_args($args, $defaults);
733
-        $context  = $args['context'];
734
-        $id       = $args['id'];
735
-        $screen   = $args['screen'];
736
-        // everything checks out so lets remove the box!
737
-        remove_meta_box($id, $screen, $context);
738
-    }
739
-
740
-    /**
741
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
742
-     * The returned json object is created from an array in the following format:
743
-     * array(
744
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
745
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
746
-     *  'notices' => '', // - contains any EE_Error formatted notices
747
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
748
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
749
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
750
-     *  that might be included in here)
751
-     * )
752
-     * The json object is populated by whatever is set in the $_template_args property.
753
-     *
754
-     * @param string $content
755
-     * @param array $data
756
-     */
757
-    public function returnJson(string $content = '', array $data = []): void
758
-    {
759
-        // make sure any EE_Error notices have been handled.
760
-        $notices = EE_Error::get_notices(false);
761
-        wp_send_json(
762
-            [
763
-                'success'   => $notices['success'] ?? false,
764
-                'errors'    => $notices['errors'] ?? false,
765
-                'attention' => $notices['attention'] ?? false,
766
-                'notices'   => $notices,
767
-                'content'   => $content,
768
-                'data'      => $data,
769
-                // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
770
-                'isEEajax'  => true,
771
-            ]
772
-        );
773
-    }
18
+	/**
19
+	 * This just holds an instance of the page object for this hook
20
+	 *
21
+	 * @var EE_Admin_Page|EE_Admin_Page_CPT|null
22
+	 * @deprecated  5.0.8.p
23
+	 */
24
+	protected $_page_object = null;
25
+
26
+	/**
27
+	 * This holds the EE_Admin_Page object from the calling admin page that this object hooks into.
28
+	 *
29
+	 * @var EE_Admin_Page|EE_Admin_Page_CPT|null
30
+	 */
31
+	protected                   $_adminpage_obj = null;
32
+
33
+	protected ?EE_Registry      $EE             = null;
34
+
35
+	protected ?RequestInterface $request        = null;
36
+
37
+	/**
38
+	 * This is set by child classes and is an associative array of ajax hooks in the format:
39
+	 * array(
40
+	 *    'ajax_action_ref' => 'executing_method'; //must be public
41
+	 * )
42
+	 */
43
+	protected array $_ajax_func = [];
44
+
45
+	/**
46
+	 * This is an array of methods that get executed on a page routes admin_init hook. Use the following format:
47
+	 * array(
48
+	 *    'page_route' => 'executing_method' //must be public
49
+	 * )
50
+	 */
51
+	protected array $_init_func = [];
52
+
53
+	/**
54
+	 * This is an array of methods that output metabox content for the given page route.  Use the following format:
55
+	 * [
56
+	 *      0 => [
57
+	 *          'page_route' => 'string_for_page_route',    must correspond to a page route in the class being connected
58
+	 *                                                      with (i.e. "edit_event") If this is in an array then the
59
+	 *                                                      same params below will be used but the metabox will be
60
+	 *                                                      added to each route.
61
+	 *          'func' =>  'executing_method',              must be public (i.e. public function executing_method
62
+	 *                                                      ($post, $callback_args){} ).
63
+	 *                                                      Note if you include callback args in the array then you
64
+	 *                                                      need to declare them in the method arguments.
65
+	 *          'id' => 'identifier_for_metabox',           so it can be removed by addons
66
+	 *                                                      (optional, class will set it automatically)
67
+	 *          'priority' => 'default',                    default 'default' (optional)
68
+	 *          'label' => esc_html__('Localized Title', 'event_espresso'),
69
+	 *          'context' => 'advanced'                     advanced is default (optional),
70
+	 *      ]
71
+	 *      'callback_args' => array() //any callback args to include (optional)
72
+	 * ]
73
+	 * Why are we indexing numerically?  Because it's possible there may be more than one metabox per page_route.
74
+	 */
75
+	protected array $_metaboxes = [];
76
+
77
+	/**
78
+	 * This is an array of values that indicate any metaboxes we want removed from a given page route.  Usually this is
79
+	 * used when caffeinated functionality is replacing decaffeinated functionality.  Use the following format for the
80
+	 * array: array(
81
+	 *    0 => array(
82
+	 *        'page_route' => 'string_for_page_route' //can be string or array of strings that match a page_route(s)
83
+	 *        that are in the class being connected with (i.e. 'edit', or 'create_new').
84
+	 *        'id' => 'identifier_for_metabox', //what the id is of the metabox being removed
85
+	 *        'context' => 'normal', //the context for the metabox being removed (has to match)
86
+	 *        'screen' => 'screen_id', //(optional), if not included then this class will attempt to remove the metabox
87
+	 *        using the currently loaded screen object->id  however, there may be cases where you have to specify the
88
+	 *        id for the screen the metabox is on.
89
+	 *    )
90
+	 * )
91
+	 */
92
+	protected array $_remove_metaboxes = [];
93
+
94
+	protected array $_req_data         = [];
95
+
96
+	/**
97
+	 * This parent class takes care of loading the scripts and styles if the child class has set the properties for
98
+	 * them in the following format.  Note, the first array index ('register') is for defining all the registers.  The
99
+	 * second array index is for indicating what routes each script/style loads on. array(
100
+	 * 'registers' => array(
101
+	 *        'script_ref' => array( // if more than one script is to be loaded its best to use the 'dependency'
102
+	 *        argument to link scripts together.
103
+	 *            'type' => 'js' // 'js' or 'css' (defaults to js).  This tells us what type of wp_function to use
104
+	 *            'url' => 'http://urltoscript.css.js',
105
+	 *            'depends' => array('jquery'), //an array of dependencies for the scripts. REMEMBER, if a script has
106
+	 *            already been registered elsewhere in the system.  You can just use the depends array to make sure it
107
+	 *            gets loaded before the one you are setting here.
108
+	 *            'footer' => TRUE //defaults to true (styles don't use this parameter)
109
+	 *        ),
110
+	 *    'enqueues' => array( //this time each key corresponds to the script ref followed by an array of page routes
111
+	 *    the script gets enqueued on.
112
+	 *        'script_ref' => array('route_one', 'route_two')
113
+	 *    ),
114
+	 *    'localize' => array( //this allows you to set a localized object.  Indicate which script the object is being
115
+	 *    attached to and then include an array indexed by the name of the object and the array of key/value pairs for
116
+	 *    the object.
117
+	 *        'scrip_ref' => array(
118
+	 *            'NAME_OF_JS_OBJECT' => array(
119
+	 *                'translate_ref' => esc_html__('localized_string', 'event_espresso'),
120
+	 *                'some_data' => 5
121
+	 *            )
122
+	 *        )
123
+	 *    )
124
+	 * )
125
+	 */
126
+	protected array $_scripts_styles = [];
127
+
128
+	protected array $_scripts        = [];
129
+
130
+	protected array $_styles         = [];
131
+
132
+	/**
133
+	 * this optional property can be set by child classes to override the priority for the automatic action/filter hook
134
+	 * loading in the `_load_routed_hooks()` method.  Please follow this format: array(
135
+	 *    'wp_hook_reference' => 1
136
+	 *    )
137
+	 * )
138
+	 */
139
+	protected array $_wp_action_filters_priority = [];
140
+
141
+	/**
142
+	 * this is just a flag set automatically to indicate whether we've got an extended hook class running (i.e.
143
+	 * espresso_events_Registration_Form_Hooks_Extend extends espresso_events_Registration_Form_Hooks).  This flag is
144
+	 * used later to make sure we require the needed files.
145
+	 */
146
+	protected bool $_extend = false;
147
+
148
+	/**
149
+	 * we're just going to use this to hold the name of the caller class (child class name)
150
+	 */
151
+	public string    $caller         = '';
152
+
153
+	protected string $_current_route = '';
154
+
155
+
156
+	/**
157
+	 * child classes MUST set this property so that the page object can be loaded correctly
158
+	 */
159
+	protected string $_name = '';
160
+
161
+
162
+	/**
163
+	 * constructor
164
+	 *
165
+	 * @param EE_Admin_Page $admin_page
166
+	 * @throws EE_Error
167
+	 * @throws ReflectionException
168
+	 */
169
+	public function __construct(EE_Admin_Page $admin_page)
170
+	{
171
+		$this->_adminpage_obj = $admin_page;
172
+		$this->request        = LoaderFactory::getLoader()->getShared(RequestInterface::class);
173
+		$this->_req_data      = $this->request->requestParams();
174
+		$current_page         = $this->request->getRequestParam('page');
175
+		$current_page         = $this->request->getRequestParam('current_page', $current_page);
176
+		// first let's verify we're on the right page
177
+		if ($current_page !== $this->_adminpage_obj->page_slug) {
178
+			return;
179
+		}
180
+		$this->_set_defaults();
181
+		$this->_set_hooks_properties();
182
+		// get out nothing more to be done here.
183
+		// allow for extends to modify properties
184
+		if (method_exists($this, '_extend_properties')) {
185
+			$this->_extend_properties();
186
+		}
187
+		// $this->_set_page_object();
188
+		$this->_init_hooks();
189
+		$this->_load_custom_methods();
190
+		$this->_load_routed_hooks();
191
+		add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts_styles']);
192
+		add_action('admin_enqueue_scripts', [$this, 'add_metaboxes'], 20);
193
+		add_action('admin_enqueue_scripts', [$this, 'remove_metaboxes'], 15);
194
+		$this->_ajax_hooks();
195
+	}
196
+
197
+
198
+	/**
199
+	 * used by child classes to set the following properties:
200
+	 * $_ajax_func (optional)
201
+	 * $_init_func (optional)
202
+	 * $_metaboxes (optional)
203
+	 * $_scripts (optional)
204
+	 * $_styles (optional)
205
+	 * $_name (required)
206
+	 * Also in this method will be registered any scripts or styles loaded on the targeted page (as indicated in the
207
+	 * _scripts/_styles properties) Also children should place in this method any filters/actions that have to happen
208
+	 * really early on page load (just after admin_init) if they want to have them registered for handling early.
209
+	 *
210
+	 * @abstract
211
+	 * @return void
212
+	 */
213
+	abstract protected function _set_hooks_properties();
214
+
215
+
216
+	/**
217
+	 * The hooks for enqueue_scripts and enqueue_styles will be run in here.  Child classes need to define their
218
+	 * scripts and styles in the relevant $_scripts and $_styles properties.  Child classes must have also already
219
+	 * registered the scripts and styles using wp_register_script and wp_register_style functions.
220
+	 *
221
+	 * @return void
222
+	 * @throws EE_Error
223
+	 */
224
+	public function enqueue_scripts_styles()
225
+	{
226
+		if (! empty($this->_scripts_styles)) {
227
+			// first let's do all the registrations
228
+			if (! isset($this->_scripts_styles['registers'])) {
229
+				$msg[] = esc_html__(
230
+					'There is no "registers" index in the <code>$this->_scripts_styles</code> property.',
231
+					'event_espresso'
232
+				);
233
+				$msg[] = sprintf(
234
+					esc_html__(
235
+						'Make sure you read the phpdoc comments above the definition of the $_scripts_styles property in the <code>EE_Admin_Hooks</code> class and modify according in the %s child',
236
+						'event_espresso'
237
+					),
238
+					'<strong>' . $this->caller . '</strong>'
239
+				);
240
+				throw new EE_Error(implode('||', $msg));
241
+			}
242
+			$defaults = [
243
+				'type'    => 'js',
244
+				'url'     => '',
245
+				'depends' => [],
246
+				'version' => EVENT_ESPRESSO_VERSION,
247
+				'footer'  => true,
248
+			];
249
+			foreach ($this->_scripts_styles['registers'] as $ref => $details) {
250
+				$details = wp_parse_args($details, $defaults);
251
+				$type    = $details['type'];
252
+				$url     = $details['url'];
253
+				$depends = $details['depends'];
254
+				$version = $details['version'];
255
+				$footer  = $details['footer'];
256
+				// let's make sure that we set the 'registers' type if it's not set!
257
+				// We need it later to determine which enqueue we do
258
+				$this->_scripts_styles['registers'][ $ref ]['type'] = $type;
259
+				// let's make sure we're not missing any REQUIRED parameters
260
+				if (empty($url)) {
261
+					$msg[] = sprintf(
262
+						esc_html__('Missing the url for the requested %s', 'event_espresso'),
263
+						$type == 'js' ? 'script' : 'stylesheet'
264
+					);
265
+					$msg[] = sprintf(
266
+						esc_html__(
267
+							'Double-check your <code>$this->_scripts_styles</code> array in %s and make sure that there is a "url" set for the %s ref',
268
+							'event_espresso'
269
+						),
270
+						'<strong>' . $this->caller . '</strong>',
271
+						$ref
272
+					);
273
+					throw new EE_Error(implode('||', $msg));
274
+				}
275
+				// made it here so let's do the appropriate registration
276
+				$type == 'js'
277
+					? wp_register_script($ref, $url, $depends, $version, $footer)
278
+					: wp_register_style(
279
+					$ref,
280
+					$url,
281
+					$depends,
282
+					$version
283
+				);
284
+			}
285
+			// k now let's do the enqueues
286
+			if (! isset($this->_scripts_styles['enqueues'])) {
287
+				return;
288
+			}  //not sure if we should throw an error here or not.
289
+
290
+			foreach ($this->_scripts_styles['enqueues'] as $ref => $routes) {
291
+				// make sure $routes is an array
292
+				$routes = (array) $routes;
293
+				if (in_array($this->_current_route, $routes)) {
294
+					$this->_scripts_styles['registers'][ $ref ]['type'] == 'js' ? wp_enqueue_script($ref)
295
+						: wp_enqueue_style($ref);
296
+					// if we have a localization for the script let's do that too.
297
+					if (isset($this->_scripts_styles['localize'][ $ref ])) {
298
+						foreach ($this->_scripts_styles['localize'][ $ref ] as $object_name => $indexes) {
299
+							wp_localize_script(
300
+								$ref,
301
+								$object_name,
302
+								$this->_scripts_styles['localize'][ $ref ][ $object_name ]
303
+							);
304
+						}
305
+					}
306
+				}
307
+			}
308
+			// let's do the deregisters
309
+			if (! isset($this->_scripts_styles['deregisters'])) {
310
+				return;
311
+			}
312
+			foreach ($this->_scripts_styles['deregisters'] as $ref => $details) {
313
+				$defaults = ['type' => 'js'];
314
+				$details  = wp_parse_args($details, $defaults);
315
+				$details['type'] === 'js' ? wp_deregister_script($ref) : wp_deregister_style($ref);
316
+			}
317
+		}
318
+	}
319
+
320
+
321
+	/**
322
+	 * just set the defaults for the hooks properties.
323
+	 *
324
+	 * @return void
325
+	 */
326
+	private function _set_defaults()
327
+	{
328
+		$this->_ajax_func                  = [];
329
+		$this->_init_func                  = [];
330
+		$this->_metaboxes                  = [];
331
+		$this->_scripts                    = [];
332
+		$this->_styles                     = [];
333
+		$this->_wp_action_filters_priority = [];
334
+		$this->_current_route              = $this->getCurrentRoute();
335
+		$this->caller                      = get_class($this);
336
+		$this->_extend                     = (bool) stripos($this->caller, 'Extend');
337
+	}
338
+
339
+
340
+	/**
341
+	 * A helper for determining the current route.
342
+	 *
343
+	 * @return string
344
+	 */
345
+	private function getCurrentRoute(): string
346
+	{
347
+		$action = $this->request->getRequestParam('action');
348
+		// list tables do something else with 'action' for bulk actions.
349
+		$action = $action !== '-1' && $action !== '' ? $action : 'default';
350
+		$route  = $this->request->getRequestParam('route');
351
+		// we set a 'route' variable in some cases where action is being used by something else.
352
+		return $action === 'default' && $route !== '' ? $route : $action;
353
+	}
354
+
355
+
356
+	/**
357
+	 * this sets the _page_object property
358
+	 *
359
+	 * @return void
360
+	 * @throws EE_Error
361
+	 * @throws ReflectionException
362
+	 * @throws Throwable
363
+	 * @deprecated  5.0.8.p
364
+	 */
365
+	protected function _set_page_object()
366
+	{
367
+		if ($this->_page_object instanceof EE_Admin_Page) {
368
+			return;
369
+		}
370
+		// first make sure $this->_name is set
371
+		if (empty($this->_name)) {
372
+			$msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
373
+			$msg[] = sprintf(
374
+				esc_html__("This is because the %s child class has not set the '_name' property", 'event_espresso'),
375
+				$this->caller
376
+			);
377
+			throw new EE_Error(implode('||', $msg));
378
+		}
379
+		// change "the_message" to "the message"
380
+		$class_name = str_replace('_', ' ', $this->_name);
381
+		// change "the message" to "The_Message_Admin_Page"
382
+		$class_name = str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
383
+		// first default file (if exists)
384
+		$decaf_file = EE_ADMIN_PAGES . "$this->_name/$class_name.core.php";
385
+		if (is_readable($decaf_file)) {
386
+			require_once($decaf_file);
387
+		}
388
+		// now we have to do require for extended file (if needed)
389
+		if ($this->_extend) {
390
+			require_once EE_CORE_CAF_ADMIN_EXTEND . "$this->_name/Extend_$class_name.core.php";
391
+			// and extend the class name as well
392
+			$class_name = 'Extend_' . $class_name;
393
+		}
394
+		// let's make sure the class exists
395
+		if (! class_exists($class_name)) {
396
+			$msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
397
+			$msg[] = sprintf(
398
+				esc_html__(
399
+					'The class name that was given is %s. Check the spelling and make sure its correct, also there needs to be an autoloader setup for the class',
400
+					'event_espresso'
401
+				),
402
+				$class_name
403
+			);
404
+			throw new EE_Error(implode('||', $msg));
405
+		}
406
+		// do NOT load admin pages that are ALREADY LOADED!!!
407
+		if ($class_name !== $this->_adminpage_obj->class_name) {
408
+			return;
409
+		}
410
+		$this->_page_object = LoaderFactory::getLoader()->getShared($class_name, [false]);
411
+		$this->_page_object->initializePage();
412
+	}
413
+
414
+
415
+	/**
416
+	 * Child "hook" classes can declare any methods that they want executed when a specific page route is loaded.  The
417
+	 * advantage of this is when doing things like running our own db interactions on saves etc.  Remember that
418
+	 * $this->_req_data (all the _POST and _GET data) is available to your methods.
419
+	 *
420
+	 * @return void
421
+	 */
422
+	private function _load_custom_methods()
423
+	{
424
+		/**
425
+		 * method cannot be named 'default' (@see http://us3.php
426
+		 * .net/manual/en/reserved.keywords.php) so need to
427
+		 * handle routes that are "default"
428
+		 *
429
+		 * @since 4.3.0
430
+		 */
431
+		$method_callback = $this->_current_route == 'default' ? 'default_callback' : $this->_current_route;
432
+		// these run before the Admin_Page route executes.
433
+		if (is_callable($this, $method_callback)) {
434
+			call_user_func([$this, $method_callback]);
435
+		}
436
+		// these run via the _redirect_after_action method in EE_Admin_Page which usually happens after non_UI methods in EE_Admin_Page classes.  There are two redirect actions, the first fires before $query_args might be manipulated by "save and close" actions and the second fires right before the actual redirect happens.
437
+		// first the actions
438
+		// note that these action hooks will have the $query_args value available.
439
+		$admin_class_name = get_class($this->_adminpage_obj);
440
+		if (method_exists($this, '_redirect_action_early_' . $this->_current_route)) {
441
+			add_action(
442
+				'AHEE__'
443
+				. $admin_class_name
444
+				. '___redirect_after_action__before_redirect_modification_'
445
+				. $this->_current_route,
446
+				[$this, '_redirect_action_early_' . $this->_current_route]
447
+			);
448
+		}
449
+		if (method_exists($this, '_redirect_action_' . $this->_current_route)) {
450
+			add_action(
451
+				'AHEE_redirect_' . $admin_class_name . $this->_current_route,
452
+				[$this, '_redirect_action_' . $this->_current_route]
453
+			);
454
+		}
455
+		// let's hook into the _redirect itself and allow for changing where the user goes after redirect.  This will have $query_args and $redirect_url available.
456
+		if (method_exists($this, '_redirect_filter_' . $this->_current_route)) {
457
+			add_filter(
458
+				'FHEE_redirect_' . $admin_class_name . $this->_current_route,
459
+				[$this, '_redirect_filter_' . $this->_current_route],
460
+				10,
461
+				2
462
+			);
463
+		}
464
+	}
465
+
466
+
467
+	/**
468
+	 * This method will search for a corresponding method with a name matching the route and the wp_hook to run.  This
469
+	 * allows child hook classes to target hooking into a specific wp action or filter hook ONLY on a certain route.
470
+	 * just remember, methods MUST be public Future hooks should be added in here to be access by child classes.
471
+	 *
472
+	 * @return void
473
+	 */
474
+	private function _load_routed_hooks()
475
+	{
476
+		// this array provides the hook action names that will be referenced.  Key is the action. Value is an array with the type (action or filter) and the number of parameters for the hook.  We'll default all priorities for automatic hooks to 10.
477
+		$hook_filter_array = [
478
+			'admin_footer'                                                                            => [
479
+				'type'     => 'action',
480
+				'argnum'   => 1,
481
+				'priority' => 10,
482
+			],
483
+			'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug . '_' . $this->_current_route => [
484
+				'type'     => 'filter',
485
+				'argnum'   => 1,
486
+				'priority' => 10,
487
+			],
488
+			'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug                               => [
489
+				'type'     => 'filter',
490
+				'argnum'   => 1,
491
+				'priority' => 10,
492
+			],
493
+			'FHEE_list_table_views'                                                                   => [
494
+				'type'     => 'filter',
495
+				'argnum'   => 1,
496
+				'priority' => 10,
497
+			],
498
+			'AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes'                              => [
499
+				'type'     => 'action',
500
+				'argnum'   => 1,
501
+				'priority' => 10,
502
+			],
503
+		];
504
+		foreach ($hook_filter_array as $hook => $args) {
505
+			if (method_exists($this, $this->_current_route . '_' . $hook)) {
506
+				if (isset($this->_wp_action_filters_priority[ $hook ])) {
507
+					$args['priority'] = $this->_wp_action_filters_priority[ $hook ];
508
+				}
509
+				if ($args['type'] == 'action') {
510
+					add_action(
511
+						$hook,
512
+						[$this, $this->_current_route . '_' . $hook],
513
+						$args['priority'],
514
+						$args['argnum']
515
+					);
516
+				} else {
517
+					add_filter(
518
+						$hook,
519
+						[$this, $this->_current_route . '_' . $hook],
520
+						$args['priority'],
521
+						$args['argnum']
522
+					);
523
+				}
524
+			}
525
+		}
526
+	}
527
+
528
+
529
+	/**
530
+	 * Loop through the $_ajax_func array and add_actions for the array.
531
+	 *
532
+	 * @return void
533
+	 * @throws EE_Error
534
+	 */
535
+	private function _ajax_hooks()
536
+	{
537
+		if (empty($this->_ajax_func)) {
538
+			// get out there's nothing to take care of.
539
+			return;
540
+		}
541
+
542
+		// check for the most basic EE capability
543
+		if (! $this->_adminpage_obj->capabilities()->current_user_can('ee_read_ee', 'access-ajax-actions')) {
544
+			return;
545
+		}
546
+
547
+		foreach ($this->_ajax_func as $action => $method) {
548
+			// make sure method exists
549
+			if (! method_exists($this, $method)) {
550
+				$msg[] = esc_html__(
551
+							 'There is no corresponding method for the hook labeled in the _ajax_func array',
552
+							 'event_espresso'
553
+						 ) . '<br />';
554
+				$msg[] = sprintf(
555
+					esc_html__(
556
+						'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
557
+						'event_espresso'
558
+					),
559
+					$method,
560
+					$this->caller
561
+				);
562
+				throw new EE_Error(implode('||', $msg));
563
+			}
564
+			add_action('wp_ajax_' . $action, [$this, $method]);
565
+		}
566
+	}
567
+
568
+
569
+	/**
570
+	 * Loop through the $_init_func array and add_actions for the array.
571
+	 *
572
+	 * @return void
573
+	 * @throws EE_Error
574
+	 */
575
+	protected function _init_hooks()
576
+	{
577
+		if (empty($this->_init_func)) {
578
+			return;
579
+		}
580
+		// get out there's nothing to take care of.
581
+		// We need to determine what page_route we are on!
582
+		foreach ($this->_init_func as $route => $method) {
583
+			// make sure method exists
584
+			if (! method_exists($this, $method)) {
585
+				$msg[] = esc_html__(
586
+							 'There is no corresponding method for the hook labeled in the _init_func array',
587
+							 'event_espresso'
588
+						 ) . '<br />';
589
+				$msg[] = sprintf(
590
+					esc_html__(
591
+						'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
592
+						'event_espresso'
593
+					),
594
+					$method,
595
+					$this->caller
596
+				);
597
+				throw new EE_Error(implode('||', $msg));
598
+			}
599
+			if ($route == $this->_current_route) {
600
+				add_action('admin_init', [$this, $method]);
601
+			}
602
+		}
603
+	}
604
+
605
+
606
+	/**
607
+	 * Loop through the _metaboxes property and add_metaboxes accordingly
608
+	 * //todo we could eventually make this a config component class (i.e. new EE_Metabox);
609
+	 *
610
+	 * @return void
611
+	 * @throws EE_Error
612
+	 */
613
+	public function add_metaboxes()
614
+	{
615
+		if (empty($this->_metaboxes)) {
616
+			return;
617
+		} //get out we don't have any metaboxes to set for this connection
618
+		$this->_handle_metabox_array($this->_metaboxes);
619
+	}
620
+
621
+
622
+	/**
623
+	 * @param array     $boxes
624
+	 * @param bool|null $add
625
+	 * @throws EE_Error
626
+	 */
627
+	private function _handle_metabox_array(array $boxes, ?bool $add = true)
628
+	{
629
+		foreach ($boxes as $box) {
630
+			if (! isset($box['page_route'])) {
631
+				continue;
632
+			}
633
+			// we don't have a valid array
634
+			// let's make sure $box['page_route'] is an array so the "foreach" will work.
635
+			$box['page_route'] = (array) $box['page_route'];
636
+			foreach ($box['page_route'] as $route) {
637
+				if ($route != $this->_current_route) {
638
+					continue;
639
+				} //get out we only add metaboxes for set route.
640
+				if ($add) {
641
+					$this->_add_metabox($box);
642
+				} else {
643
+					$this->_remove_metabox($box);
644
+				}
645
+			}
646
+		}
647
+	}
648
+
649
+
650
+	/**
651
+	 * Loop through the _remove_metaboxes property and remove metaboxes accordingly.
652
+	 *
653
+	 * @return void
654
+	 * @throws EE_Error
655
+	 */
656
+	public function remove_metaboxes()
657
+	{
658
+		if (empty($this->_remove_metaboxes)) {
659
+			return;
660
+		} //get out there are no metaboxes to remove
661
+		$this->_handle_metabox_array($this->_remove_metaboxes, false);
662
+	}
663
+
664
+
665
+	/**
666
+	 * This just handles adding a metabox
667
+	 *
668
+	 * @param array $args an array of args that have been set for this metabox by the child class
669
+	 * @throws EE_Error
670
+	 */
671
+	private function _add_metabox(array $args)
672
+	{
673
+		$current_screen    = get_current_screen();
674
+		$screen_id         = is_object($current_screen) ? $current_screen->id : null;
675
+		$callback          = $args['func'] ?? 'some_invalid_callback';
676
+		$callback_function = is_array($callback) ? end($callback) : $callback;
677
+		// set defaults
678
+		$defaults      = [
679
+			'callback_args' => [],
680
+			'context'       => 'advanced',
681
+			'func'          => $callback,
682
+			'id'            => $this->caller . '_' . $callback_function . '_metabox',
683
+			'label'         => $this->caller,
684
+			'page'          => $args['page'] ?? $screen_id,
685
+			'priority'      => 'default',
686
+		];
687
+		$args          = wp_parse_args($args, $defaults);
688
+		$callback_args = $args['callback_args'];
689
+		$context       = $args['context'];
690
+		$id            = $args['id'];
691
+		$label         = $args['label'];
692
+		$page          = $args['page'];
693
+		$priority      = $args['priority'];
694
+		// make sure method exists
695
+		if (! method_exists($this, $callback_function)) {
696
+			$msg[] =
697
+				esc_html__('There is no corresponding method to display the metabox content', 'event_espresso')
698
+				. '<br />';
699
+			$msg[] = sprintf(
700
+				esc_html__(
701
+					'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
702
+					'event_espresso'
703
+				),
704
+				$callback_function,
705
+				$this->caller
706
+			);
707
+			throw new EE_Error(implode('||', $msg));
708
+		}
709
+		// everything checks out so let's add the metabox
710
+		add_meta_box($id, $label, [$this, $callback_function], $page, $context, $priority, $callback_args);
711
+		add_filter(
712
+			"postbox_classes_{$page}_$id",
713
+			function ($classes) {
714
+				$classes[] = 'ee-admin-container';
715
+				return $classes;
716
+			}
717
+		);
718
+	}
719
+
720
+
721
+	private function _remove_metabox($args)
722
+	{
723
+		$current_screen = get_current_screen();
724
+		$screen_id      = is_object($current_screen) ? $current_screen->id : null;
725
+		$func           = $args['func'] ?? 'some_invalid_callback';
726
+		// set defaults
727
+		$defaults = [
728
+			'context' => 'default',
729
+			'id'      => $args['id'] ?? "{$this->_current_route}_{$this->caller}_{$func}_metabox",
730
+			'screen'  => $args['screen'] ?? $screen_id,
731
+		];
732
+		$args     = wp_parse_args($args, $defaults);
733
+		$context  = $args['context'];
734
+		$id       = $args['id'];
735
+		$screen   = $args['screen'];
736
+		// everything checks out so lets remove the box!
737
+		remove_meta_box($id, $screen, $context);
738
+	}
739
+
740
+	/**
741
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
742
+	 * The returned json object is created from an array in the following format:
743
+	 * array(
744
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
745
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
746
+	 *  'notices' => '', // - contains any EE_Error formatted notices
747
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
748
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
749
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
750
+	 *  that might be included in here)
751
+	 * )
752
+	 * The json object is populated by whatever is set in the $_template_args property.
753
+	 *
754
+	 * @param string $content
755
+	 * @param array $data
756
+	 */
757
+	public function returnJson(string $content = '', array $data = []): void
758
+	{
759
+		// make sure any EE_Error notices have been handled.
760
+		$notices = EE_Error::get_notices(false);
761
+		wp_send_json(
762
+			[
763
+				'success'   => $notices['success'] ?? false,
764
+				'errors'    => $notices['errors'] ?? false,
765
+				'attention' => $notices['attention'] ?? false,
766
+				'notices'   => $notices,
767
+				'content'   => $content,
768
+				'data'      => $data,
769
+				// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
770
+				'isEEajax'  => true,
771
+			]
772
+		);
773
+	}
774 774
 }
Please login to merge, or discard this patch.
Spacing   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -223,9 +223,9 @@  discard block
 block discarded – undo
223 223
      */
224 224
     public function enqueue_scripts_styles()
225 225
     {
226
-        if (! empty($this->_scripts_styles)) {
226
+        if ( ! empty($this->_scripts_styles)) {
227 227
             // first let's do all the registrations
228
-            if (! isset($this->_scripts_styles['registers'])) {
228
+            if ( ! isset($this->_scripts_styles['registers'])) {
229 229
                 $msg[] = esc_html__(
230 230
                     'There is no "registers" index in the <code>$this->_scripts_styles</code> property.',
231 231
                     'event_espresso'
@@ -235,7 +235,7 @@  discard block
 block discarded – undo
235 235
                         'Make sure you read the phpdoc comments above the definition of the $_scripts_styles property in the <code>EE_Admin_Hooks</code> class and modify according in the %s child',
236 236
                         'event_espresso'
237 237
                     ),
238
-                    '<strong>' . $this->caller . '</strong>'
238
+                    '<strong>'.$this->caller.'</strong>'
239 239
                 );
240 240
                 throw new EE_Error(implode('||', $msg));
241 241
             }
@@ -255,7 +255,7 @@  discard block
 block discarded – undo
255 255
                 $footer  = $details['footer'];
256 256
                 // let's make sure that we set the 'registers' type if it's not set!
257 257
                 // We need it later to determine which enqueue we do
258
-                $this->_scripts_styles['registers'][ $ref ]['type'] = $type;
258
+                $this->_scripts_styles['registers'][$ref]['type'] = $type;
259 259
                 // let's make sure we're not missing any REQUIRED parameters
260 260
                 if (empty($url)) {
261 261
                     $msg[] = sprintf(
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
                             'Double-check your <code>$this->_scripts_styles</code> array in %s and make sure that there is a "url" set for the %s ref',
268 268
                             'event_espresso'
269 269
                         ),
270
-                        '<strong>' . $this->caller . '</strong>',
270
+                        '<strong>'.$this->caller.'</strong>',
271 271
                         $ref
272 272
                     );
273 273
                     throw new EE_Error(implode('||', $msg));
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
                 );
284 284
             }
285 285
             // k now let's do the enqueues
286
-            if (! isset($this->_scripts_styles['enqueues'])) {
286
+            if ( ! isset($this->_scripts_styles['enqueues'])) {
287 287
                 return;
288 288
             }  //not sure if we should throw an error here or not.
289 289
 
@@ -291,22 +291,22 @@  discard block
 block discarded – undo
291 291
                 // make sure $routes is an array
292 292
                 $routes = (array) $routes;
293 293
                 if (in_array($this->_current_route, $routes)) {
294
-                    $this->_scripts_styles['registers'][ $ref ]['type'] == 'js' ? wp_enqueue_script($ref)
294
+                    $this->_scripts_styles['registers'][$ref]['type'] == 'js' ? wp_enqueue_script($ref)
295 295
                         : wp_enqueue_style($ref);
296 296
                     // if we have a localization for the script let's do that too.
297
-                    if (isset($this->_scripts_styles['localize'][ $ref ])) {
298
-                        foreach ($this->_scripts_styles['localize'][ $ref ] as $object_name => $indexes) {
297
+                    if (isset($this->_scripts_styles['localize'][$ref])) {
298
+                        foreach ($this->_scripts_styles['localize'][$ref] as $object_name => $indexes) {
299 299
                             wp_localize_script(
300 300
                                 $ref,
301 301
                                 $object_name,
302
-                                $this->_scripts_styles['localize'][ $ref ][ $object_name ]
302
+                                $this->_scripts_styles['localize'][$ref][$object_name]
303 303
                             );
304 304
                         }
305 305
                     }
306 306
                 }
307 307
             }
308 308
             // let's do the deregisters
309
-            if (! isset($this->_scripts_styles['deregisters'])) {
309
+            if ( ! isset($this->_scripts_styles['deregisters'])) {
310 310
                 return;
311 311
             }
312 312
             foreach ($this->_scripts_styles['deregisters'] as $ref => $details) {
@@ -379,20 +379,20 @@  discard block
 block discarded – undo
379 379
         // change "the_message" to "the message"
380 380
         $class_name = str_replace('_', ' ', $this->_name);
381 381
         // change "the message" to "The_Message_Admin_Page"
382
-        $class_name = str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
382
+        $class_name = str_replace(' ', '_', ucwords($class_name)).'_Admin_Page';
383 383
         // first default file (if exists)
384
-        $decaf_file = EE_ADMIN_PAGES . "$this->_name/$class_name.core.php";
384
+        $decaf_file = EE_ADMIN_PAGES."$this->_name/$class_name.core.php";
385 385
         if (is_readable($decaf_file)) {
386 386
             require_once($decaf_file);
387 387
         }
388 388
         // now we have to do require for extended file (if needed)
389 389
         if ($this->_extend) {
390
-            require_once EE_CORE_CAF_ADMIN_EXTEND . "$this->_name/Extend_$class_name.core.php";
390
+            require_once EE_CORE_CAF_ADMIN_EXTEND."$this->_name/Extend_$class_name.core.php";
391 391
             // and extend the class name as well
392
-            $class_name = 'Extend_' . $class_name;
392
+            $class_name = 'Extend_'.$class_name;
393 393
         }
394 394
         // let's make sure the class exists
395
-        if (! class_exists($class_name)) {
395
+        if ( ! class_exists($class_name)) {
396 396
             $msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
397 397
             $msg[] = sprintf(
398 398
                 esc_html__(
@@ -437,26 +437,26 @@  discard block
 block discarded – undo
437 437
         // first the actions
438 438
         // note that these action hooks will have the $query_args value available.
439 439
         $admin_class_name = get_class($this->_adminpage_obj);
440
-        if (method_exists($this, '_redirect_action_early_' . $this->_current_route)) {
440
+        if (method_exists($this, '_redirect_action_early_'.$this->_current_route)) {
441 441
             add_action(
442 442
                 'AHEE__'
443 443
                 . $admin_class_name
444 444
                 . '___redirect_after_action__before_redirect_modification_'
445 445
                 . $this->_current_route,
446
-                [$this, '_redirect_action_early_' . $this->_current_route]
446
+                [$this, '_redirect_action_early_'.$this->_current_route]
447 447
             );
448 448
         }
449
-        if (method_exists($this, '_redirect_action_' . $this->_current_route)) {
449
+        if (method_exists($this, '_redirect_action_'.$this->_current_route)) {
450 450
             add_action(
451
-                'AHEE_redirect_' . $admin_class_name . $this->_current_route,
452
-                [$this, '_redirect_action_' . $this->_current_route]
451
+                'AHEE_redirect_'.$admin_class_name.$this->_current_route,
452
+                [$this, '_redirect_action_'.$this->_current_route]
453 453
             );
454 454
         }
455 455
         // let's hook into the _redirect itself and allow for changing where the user goes after redirect.  This will have $query_args and $redirect_url available.
456
-        if (method_exists($this, '_redirect_filter_' . $this->_current_route)) {
456
+        if (method_exists($this, '_redirect_filter_'.$this->_current_route)) {
457 457
             add_filter(
458
-                'FHEE_redirect_' . $admin_class_name . $this->_current_route,
459
-                [$this, '_redirect_filter_' . $this->_current_route],
458
+                'FHEE_redirect_'.$admin_class_name.$this->_current_route,
459
+                [$this, '_redirect_filter_'.$this->_current_route],
460 460
                 10,
461 461
                 2
462 462
             );
@@ -480,12 +480,12 @@  discard block
 block discarded – undo
480 480
                 'argnum'   => 1,
481 481
                 'priority' => 10,
482 482
             ],
483
-            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug . '_' . $this->_current_route => [
483
+            'FHEE_list_table_views_'.$this->_adminpage_obj->page_slug.'_'.$this->_current_route => [
484 484
                 'type'     => 'filter',
485 485
                 'argnum'   => 1,
486 486
                 'priority' => 10,
487 487
             ],
488
-            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug                               => [
488
+            'FHEE_list_table_views_'.$this->_adminpage_obj->page_slug                               => [
489 489
                 'type'     => 'filter',
490 490
                 'argnum'   => 1,
491 491
                 'priority' => 10,
@@ -502,21 +502,21 @@  discard block
 block discarded – undo
502 502
             ],
503 503
         ];
504 504
         foreach ($hook_filter_array as $hook => $args) {
505
-            if (method_exists($this, $this->_current_route . '_' . $hook)) {
506
-                if (isset($this->_wp_action_filters_priority[ $hook ])) {
507
-                    $args['priority'] = $this->_wp_action_filters_priority[ $hook ];
505
+            if (method_exists($this, $this->_current_route.'_'.$hook)) {
506
+                if (isset($this->_wp_action_filters_priority[$hook])) {
507
+                    $args['priority'] = $this->_wp_action_filters_priority[$hook];
508 508
                 }
509 509
                 if ($args['type'] == 'action') {
510 510
                     add_action(
511 511
                         $hook,
512
-                        [$this, $this->_current_route . '_' . $hook],
512
+                        [$this, $this->_current_route.'_'.$hook],
513 513
                         $args['priority'],
514 514
                         $args['argnum']
515 515
                     );
516 516
                 } else {
517 517
                     add_filter(
518 518
                         $hook,
519
-                        [$this, $this->_current_route . '_' . $hook],
519
+                        [$this, $this->_current_route.'_'.$hook],
520 520
                         $args['priority'],
521 521
                         $args['argnum']
522 522
                     );
@@ -540,17 +540,17 @@  discard block
 block discarded – undo
540 540
         }
541 541
 
542 542
         // check for the most basic EE capability
543
-        if (! $this->_adminpage_obj->capabilities()->current_user_can('ee_read_ee', 'access-ajax-actions')) {
543
+        if ( ! $this->_adminpage_obj->capabilities()->current_user_can('ee_read_ee', 'access-ajax-actions')) {
544 544
             return;
545 545
         }
546 546
 
547 547
         foreach ($this->_ajax_func as $action => $method) {
548 548
             // make sure method exists
549
-            if (! method_exists($this, $method)) {
549
+            if ( ! method_exists($this, $method)) {
550 550
                 $msg[] = esc_html__(
551 551
                              'There is no corresponding method for the hook labeled in the _ajax_func array',
552 552
                              'event_espresso'
553
-                         ) . '<br />';
553
+                         ).'<br />';
554 554
                 $msg[] = sprintf(
555 555
                     esc_html__(
556 556
                         'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
@@ -561,7 +561,7 @@  discard block
 block discarded – undo
561 561
                 );
562 562
                 throw new EE_Error(implode('||', $msg));
563 563
             }
564
-            add_action('wp_ajax_' . $action, [$this, $method]);
564
+            add_action('wp_ajax_'.$action, [$this, $method]);
565 565
         }
566 566
     }
567 567
 
@@ -581,11 +581,11 @@  discard block
 block discarded – undo
581 581
         // We need to determine what page_route we are on!
582 582
         foreach ($this->_init_func as $route => $method) {
583 583
             // make sure method exists
584
-            if (! method_exists($this, $method)) {
584
+            if ( ! method_exists($this, $method)) {
585 585
                 $msg[] = esc_html__(
586 586
                              'There is no corresponding method for the hook labeled in the _init_func array',
587 587
                              'event_espresso'
588
-                         ) . '<br />';
588
+                         ).'<br />';
589 589
                 $msg[] = sprintf(
590 590
                     esc_html__(
591 591
                         'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
@@ -627,7 +627,7 @@  discard block
 block discarded – undo
627 627
     private function _handle_metabox_array(array $boxes, ?bool $add = true)
628 628
     {
629 629
         foreach ($boxes as $box) {
630
-            if (! isset($box['page_route'])) {
630
+            if ( ! isset($box['page_route'])) {
631 631
                 continue;
632 632
             }
633 633
             // we don't have a valid array
@@ -675,11 +675,11 @@  discard block
 block discarded – undo
675 675
         $callback          = $args['func'] ?? 'some_invalid_callback';
676 676
         $callback_function = is_array($callback) ? end($callback) : $callback;
677 677
         // set defaults
678
-        $defaults      = [
678
+        $defaults = [
679 679
             'callback_args' => [],
680 680
             'context'       => 'advanced',
681 681
             'func'          => $callback,
682
-            'id'            => $this->caller . '_' . $callback_function . '_metabox',
682
+            'id'            => $this->caller.'_'.$callback_function.'_metabox',
683 683
             'label'         => $this->caller,
684 684
             'page'          => $args['page'] ?? $screen_id,
685 685
             'priority'      => 'default',
@@ -692,7 +692,7 @@  discard block
 block discarded – undo
692 692
         $page          = $args['page'];
693 693
         $priority      = $args['priority'];
694 694
         // make sure method exists
695
-        if (! method_exists($this, $callback_function)) {
695
+        if ( ! method_exists($this, $callback_function)) {
696 696
             $msg[] =
697 697
                 esc_html__('There is no corresponding method to display the metabox content', 'event_espresso')
698 698
                 . '<br />';
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
         add_meta_box($id, $label, [$this, $callback_function], $page, $context, $priority, $callback_args);
711 711
         add_filter(
712 712
             "postbox_classes_{$page}_$id",
713
-            function ($classes) {
713
+            function($classes) {
714 714
                 $classes[] = 'ee-admin-container';
715 715
                 return $classes;
716 716
             }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4231 added lines, -4231 removed lines patch added patch discarded remove patch
@@ -24,4324 +24,4324 @@
 block discarded – undo
24 24
  */
25 25
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
26 26
 {
27
-    protected ?EE_Admin_Config     $admin_config       = null;
27
+	protected ?EE_Admin_Config     $admin_config       = null;
28 28
 
29
-    protected ?EE_Admin_Hooks      $_hook_obj          = null;
29
+	protected ?EE_Admin_Hooks      $_hook_obj          = null;
30 30
 
31
-    protected ?EE_Admin_List_Table $_list_table_object = null;
31
+	protected ?EE_Admin_List_Table $_list_table_object = null;
32 32
 
33
-    protected ?EE_Capabilities     $capabilities       = null;
33
+	protected ?EE_Capabilities     $capabilities       = null;
34 34
 
35
-    protected ?EE_Registry         $EE                 = null;
35
+	protected ?EE_Registry         $EE                 = null;
36 36
 
37
-    protected ?FeatureFlags        $feature            = null;
37
+	protected ?FeatureFlags        $feature            = null;
38 38
 
39
-    protected ?LoaderInterface     $loader             = null;
39
+	protected ?LoaderInterface     $loader             = null;
40 40
 
41
-    protected ?RequestInterface    $request            = null;
41
+	protected ?RequestInterface    $request            = null;
42 42
 
43
-    protected ?WP_Screen           $_current_screen    = null;
43
+	protected ?WP_Screen           $_current_screen    = null;
44 44
 
45
-    /**
46
-     * @var array
47
-     * @since 5.0.0.p
48
-     */
49
-    private array $publish_post_meta_box_hidden_fields = [];
50
-
51
-    /**
52
-     * some default things shared by all child classes
53
-     *
54
-     * @var string[]
55
-     */
56
-    protected array $_default_espresso_metaboxes = [
57
-        '_espresso_news_post_box',
58
-        '_espresso_links_post_box',
59
-        '_espresso_ratings_request',
60
-        '_espresso_sponsors_post_box',
61
-    ];
62
-
63
-    /**
64
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
65
-     * actions.
66
-     *
67
-     * @since 4.6.x
68
-     */
69
-    protected array $_default_route_query_args = [];
70
-
71
-    protected array $_labels                   = [];
72
-
73
-    protected array $_nav_tabs                 = [];
74
-
75
-    protected array $_page_config              = [];
76
-
77
-    /**
78
-     * action => method pairs used for routing incoming requests
79
-     *
80
-     * @var array
81
-     */
82
-    protected array $_page_routes   = [];
83
-
84
-    protected array $_req_data      = [];
85
-
86
-    protected array $_route_config  = [];
87
-
88
-    protected array $_template_args = [];
89
-
90
-    protected array $_views         = [];
91
-
92
-    /**
93
-     * yes / no array for admin form fields
94
-     *
95
-     * @var array|array[]
96
-     */
97
-    protected array $_yes_no_values = [];
98
-
99
-    /**
100
-     * this starts at null so we can have no header routes progress through two states.
101
-     */
102
-    protected ?bool $_is_UI_request = null;
103
-
104
-    /**
105
-     * flags whether the given route is a caffeinated route or not.
106
-     */
107
-    protected bool  $_is_caf        = false;
108
-
109
-    protected bool  $_routing       = false;
110
-
111
-    /**
112
-     * whether initializePage() has run
113
-     *
114
-     * @var bool
115
-     */
116
-    protected bool $initialized = false;
117
-
118
-
119
-    protected string $_admin_base_path      = '';
120
-
121
-    protected string $_admin_base_url       = '';
122
-
123
-    protected string $_admin_page_title     = '';
124
-
125
-    protected string $_column_template_path = '';
126
-
127
-    protected bool   $_cpt_route            = false;
128
-
129
-    /**
130
-     * set via request page and action args.
131
-     */
132
-    protected string $_current_page          = '';
133
-
134
-    protected string $_current_page_view_url = '';
135
-
136
-    protected string $_current_view          = '';
137
-
138
-    protected string $_default_nav_tab_name  = 'overview';
139
-
140
-    /**
141
-     * sanitized request action
142
-     */
143
-    protected string $_req_action = '';
144
-
145
-    /**
146
-     * sanitized request action nonce
147
-     */
148
-    protected string $_req_nonce        = '';
149
-
150
-    protected string $_search_btn_label = '';
151
-
152
-    protected string $_template_path    = '';
153
-
154
-    protected string $_view             = '';
155
-
156
-    /**
157
-     * set early within EE_Admin_Init
158
-     *
159
-     * @var string
160
-     */
161
-    protected string $_wp_page_slug = '';
162
-
163
-    /**
164
-     * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
165
-     * then this would be the parent classname: Events_Admin_Page
166
-     *
167
-     * @var string
168
-     */
169
-    public string $base_class_name = '';
170
-
171
-    public string $class_name      = '';
172
-
173
-    /**
174
-     * unprocessed value for the 'action' request param (default '')
175
-     *
176
-     * @var string
177
-     */
178
-    protected string $raw_req_action = '';
179
-
180
-    /**
181
-     * unprocessed value for the 'page' request param (default '')
182
-     *
183
-     * @var string
184
-     */
185
-    protected string $raw_req_page = '';
186
-
187
-    public string    $page_folder  = '';
188
-
189
-    public string    $page_label   = '';
190
-
191
-    public string    $page_slug    = '';
192
-
193
-
194
-    /**
195
-     * the current page route and route config
196
-     *
197
-     * @var array|callable|string|null
198
-     */
199
-    protected $_route = null;
200
-
201
-
202
-    /**
203
-     * @Constructor
204
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
205
-     * @throws InvalidArgumentException
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     * @throws ReflectionException
209
-     */
210
-    public function __construct($routing = true)
211
-    {
212
-        $this->loader       = LoaderFactory::getLoader();
213
-        $this->admin_config = $this->loader->getShared(EE_Admin_Config::class);
214
-        $this->feature      = $this->loader->getShared(FeatureFlags::class);
215
-        $this->request      = $this->loader->getShared(RequestInterface::class);
216
-        $this->capabilities = $this->loader->getShared(EE_Capabilities::class);
217
-        // routing enabled?
218
-        $this->_routing = $routing;
219
-
220
-        $this->class_name      = get_class($this);
221
-        $this->base_class_name = strpos($this->class_name, 'Extend_') === 0
222
-            ? str_replace('Extend_', '', $this->class_name)
223
-            : '';
224
-
225
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
226
-            $this->_is_caf = true;
227
-        }
228
-        $this->_yes_no_values = [
229
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
230
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
231
-        ];
232
-        // set the _req_data property.
233
-        $this->_req_data = $this->request->requestParams();
234
-    }
235
-
236
-
237
-    /**
238
-     * @return EE_Admin_Config
239
-     */
240
-    public function adminConfig(): EE_Admin_Config
241
-    {
242
-        return $this->admin_config;
243
-    }
244
-
245
-
246
-    public function capabilities(): EE_Capabilities
247
-    {
248
-        if (! $this->capabilities instanceof EE_Capabilities) {
249
-            $this->capabilities = $this->loader->getShared(EE_Capabilities::class);
250
-        }
251
-        return $this->capabilities;
252
-    }
253
-
254
-
255
-    /**
256
-     * @return FeatureFlags
257
-     */
258
-    public function feature(): FeatureFlags
259
-    {
260
-        return $this->feature;
261
-    }
262
-
263
-
264
-    /**
265
-     * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
266
-     * for child classes that needed to set properties prior to these methods getting called,
267
-     * but also needed the parent class to have its construction completed as well.
268
-     * Bottom line is that constructors should ONLY be used for setting initial properties
269
-     * and any complex initialization logic should only run after instantiation is complete.
270
-     * This method gets called immediately after construction from within
271
-     *      EE_Admin_Page_Init::_initialize_admin_page()
272
-     *
273
-     * @throws EE_Error
274
-     * @throws InvalidArgumentException
275
-     * @throws InvalidDataTypeException
276
-     * @throws InvalidInterfaceException
277
-     * @throws ReflectionException
278
-     * @throws Throwable
279
-     * @since 5.0.0.p
280
-     */
281
-    public function initializePage()
282
-    {
283
-        if ($this->initialized) {
284
-            return;
285
-        }
286
-        // set initial page props (child method)
287
-        $this->_init_page_props();
288
-        // set global defaults
289
-        $this->_set_defaults();
290
-        // set early because incoming requests could be ajax related and we need to register those hooks.
291
-        if ($this->request->isAjax()) {
292
-            $this->_global_ajax_hooks();
293
-            $this->_ajax_hooks();
294
-        }
295
-        // other_page_hooks have to be early too.
296
-        $this->_do_other_page_hooks();
297
-        // set up page dependencies
298
-        $this->_before_page_setup();
299
-        $this->_page_setup();
300
-        $this->initialized = true;
301
-    }
302
-
303
-
304
-    /**
305
-     * _init_page_props
306
-     * Child classes use to set at least the following properties:
307
-     * $page_slug.
308
-     * $page_label.
309
-     *
310
-     * @abstract
311
-     * @return void
312
-     */
313
-    abstract protected function _init_page_props();
314
-
315
-
316
-    /**
317
-     * _ajax_hooks
318
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
319
-     * Note: within the ajax callback methods.
320
-     *
321
-     * @abstract
322
-     * @return void
323
-     */
324
-    abstract protected function _ajax_hooks();
325
-
326
-
327
-    /**
328
-     * _define_page_props
329
-     * child classes define page properties in here.  Must include at least:
330
-     * $_admin_base_url = base_url for all admin pages
331
-     * $_admin_page_title = default admin_page_title for admin pages
332
-     * $_labels = array of default labels for various automatically generated elements:
333
-     *    array(
334
-     *        'buttons' => array(
335
-     *            'add' => esc_html__('label for add new button'),
336
-     *            'edit' => esc_html__('label for edit button'),
337
-     *            'delete' => esc_html__('label for delete button')
338
-     *            )
339
-     *        )
340
-     *
341
-     * @abstract
342
-     * @return void
343
-     */
344
-    abstract protected function _define_page_props();
345
-
346
-
347
-    /**
348
-     * _set_page_routes
349
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
350
-     * assigned to an action => method pairs in an array and to the $_page_routes property.  Each page route must also
351
-     * have a 'default' route. Here's the format
352
-     * $this->_page_routes = array(
353
-     *        'default' => array(
354
-     *            'func' => '_default_method_handling_route',
355
-     *            'args' => array('array','of','args'),
356
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
357
-     *            ajax request, backend processing)
358
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
359
-     *            headers route after.  The string you enter here should match the defined route reference for a
360
-     *            headers sent route.
361
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
362
-     *            this route.
363
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
364
-     *            checks).
365
-     *        ),
366
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
367
-     *        handling method.
368
-     *        )
369
-     * )
370
-     *
371
-     * @abstract
372
-     * @return void
373
-     */
374
-    abstract protected function _set_page_routes();
375
-
376
-
377
-    /**
378
-     * _set_page_config
379
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
380
-     * array corresponds to the page_route for the loaded page. Format:
381
-     * $this->_page_config = array(
382
-     *        'default' => array(
383
-     *            'labels' => array(
384
-     *                'buttons' => array(
385
-     *                    'add' => esc_html__('label for adding item'),
386
-     *                    'edit' => esc_html__('label for editing item'),
387
-     *                    'delete' => esc_html__('label for deleting item')
388
-     *                ),
389
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
390
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
391
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
392
-     *            _define_page_props() method
393
-     *            'nav' => array(
394
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
395
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
396
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
397
-     *                'order' => 10, //required to indicate tab position.
398
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
399
-     *                displayed then add this parameter.
400
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
401
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
402
-     *            metaboxes set for eventespresso admin pages.
403
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
404
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
405
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
406
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
407
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
408
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
409
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
410
-     *            There is an option in the "screen_options" dropdown that is set up so users can pick what columns they
411
-     *            want to display.
412
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
413
-     *                'tab_id' => array(
414
-     *                    'title' => 'tab_title',
415
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
416
-     *                    help tab content.  The fallback if it isn't present is to try the callback.  Filename
417
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
418
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
419
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
420
-     *                    attempt to use the callback which should match the name of a method in the class
421
-     *                    ),
422
-     *                'tab2_id' => array(
423
-     *                    'title' => 'tab2 title',
424
-     *                    'filename' => 'file_name_2'
425
-     *                    'callback' => 'callback_method_for_content',
426
-     *                 ),
427
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
428
-     *            help tab area on an admin page. @return void
429
-     *
430
-     * @abstract
431
-     */
432
-    abstract protected function _set_page_config();
433
-
434
-
435
-    /**
436
-     * _add_screen_options
437
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
438
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
439
-     * to a particular view.
440
-     *
441
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
442
-     *         see also WP_Screen object documents...
443
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
444
-     * @abstract
445
-     * @return void
446
-     */
447
-    abstract protected function _add_screen_options();
448
-
449
-
450
-    /**
451
-     * _add_feature_pointers
452
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
453
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
454
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
455
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
456
-     * extended) also see:
457
-     *
458
-     * @link   http://eamann.com/tech/wordpress-portland/
459
-     * @abstract
460
-     * @return void
461
-     */
462
-    abstract protected function _add_feature_pointers();
463
-
464
-
465
-    /**
466
-     * load_scripts_styles
467
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
468
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
469
-     * scripts/styles per view by putting them in a dynamic function in this format
470
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
471
-     *
472
-     * @abstract
473
-     * @return void
474
-     */
475
-    abstract public function load_scripts_styles();
476
-
477
-
478
-    /**
479
-     * admin_init
480
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
481
-     * all pages/views loaded by child class.
482
-     *
483
-     * @abstract
484
-     * @return void
485
-     */
486
-    abstract public function admin_init();
487
-
488
-
489
-    /**
490
-     * admin_notices
491
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
492
-     * all pages/views loaded by child class.
493
-     *
494
-     * @abstract
495
-     * @return void
496
-     */
497
-    abstract public function admin_notices();
498
-
499
-
500
-    /**
501
-     * admin_footer_scripts
502
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
503
-     * will apply to all pages/views loaded by child class.
504
-     *
505
-     * @return void
506
-     */
507
-    abstract public function admin_footer_scripts();
508
-
509
-
510
-    /**
511
-     * admin_footer
512
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
513
-     * apply to all pages/views loaded by child class.
514
-     *
515
-     * @return void
516
-     */
517
-    public function admin_footer()
518
-    {
519
-    }
520
-
521
-
522
-    /**
523
-     * _global_ajax_hooks
524
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
525
-     * Note: within the ajax callback methods.
526
-     *
527
-     * @abstract
528
-     * @return void
529
-     */
530
-    protected function _global_ajax_hooks()
531
-    {
532
-        // for lazy loading of metabox content
533
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content']);
534
-
535
-        add_action(
536
-            'wp_ajax_espresso_hide_status_change_notice',
537
-            [$this, 'hideStatusChangeNotice']
538
-        );
539
-        add_action(
540
-            'wp_ajax_nopriv_espresso_hide_status_change_notice',
541
-            [$this, 'hideStatusChangeNotice']
542
-        );
543
-    }
544
-
545
-
546
-    public function ajax_metabox_content()
547
-    {
548
-        $content_id  = $this->request->getRequestParam('contentid', '');
549
-        $content_url = $this->request->getRequestParam('contenturl', '', DataType::URL);
550
-        EE_Admin_Page::cached_rss_display($content_id, $content_url);
551
-        wp_die();
552
-    }
553
-
554
-
555
-    public function hideStatusChangeNotice()
556
-    {
557
-        $response = [];
558
-        try {
559
-            /** @var StatusChangeNotice $status_change_notice */
560
-            $status_change_notice = $this->loader->getShared(
561
-                'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
562
-            );
563
-            $response['success']  = $status_change_notice->dismiss() > -1;
564
-        } catch (Exception $exception) {
565
-            $response['errors'] = $exception->getMessage();
566
-        }
567
-        wp_send_json($response);
568
-    }
45
+	/**
46
+	 * @var array
47
+	 * @since 5.0.0.p
48
+	 */
49
+	private array $publish_post_meta_box_hidden_fields = [];
569 50
 
51
+	/**
52
+	 * some default things shared by all child classes
53
+	 *
54
+	 * @var string[]
55
+	 */
56
+	protected array $_default_espresso_metaboxes = [
57
+		'_espresso_news_post_box',
58
+		'_espresso_links_post_box',
59
+		'_espresso_ratings_request',
60
+		'_espresso_sponsors_post_box',
61
+	];
570 62
 
571
-    /**
572
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
573
-     *
574
-     * @return void
575
-     */
576
-    protected function _before_page_setup()
577
-    {
578
-        // default is to do nothing
579
-    }
63
+	/**
64
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
65
+	 * actions.
66
+	 *
67
+	 * @since 4.6.x
68
+	 */
69
+	protected array $_default_route_query_args = [];
580 70
 
71
+	protected array $_labels                   = [];
581 72
 
582
-    /**
583
-     * Makes sure any things that need to be loaded early get handled.
584
-     * We also escape early here if the page requested doesn't match the object.
585
-     *
586
-     * @final
587
-     * @return void
588
-     * @throws EE_Error
589
-     * @throws InvalidArgumentException
590
-     * @throws ReflectionException
591
-     * @throws InvalidDataTypeException
592
-     * @throws InvalidInterfaceException
593
-     * @throws Throwable
594
-     */
595
-    final protected function _page_setup()
596
-    {
597
-        // requires?
598
-        // admin_init stuff - global - we're setting this REALLY early
599
-        // so if EE_Admin pages have to hook into other WP pages they can.
600
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
601
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
602
-        // next verify if we need to load anything...
603
-        $this->_current_page = $this->request->getRequestParam('page', '', DataType::KEY);
604
-        $this->_current_page = $this->request->getRequestParam('current_page', $this->_current_page, DataType::KEY);
605
-        $this->page_folder   = strtolower(
606
-            str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
607
-        );
608
-        global $ee_menu_slugs;
609
-        $ee_menu_slugs = (array) $ee_menu_slugs;
610
-        if (
611
-            ! $this->request->isAjax()
612
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
613
-        ) {
614
-            return;
615
-        }
616
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
617
-        // we need to copy the action from the second to the first
618
-        $action     = $this->request->getRequestParam('action', '-1', DataType::KEY);
619
-        $action2    = $this->request->getRequestParam('action2', '-1', DataType::KEY);
620
-        $action     = $action !== '-1' ? $action : $action2;
621
-        $req_action = $action !== '-1' ? $action : 'default';
622
-
623
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
624
-        // then let's use the route as the action.
625
-        // This covers cases where we're coming in from a list table that isn't on the default route.
626
-        $route = $this->request->getRequestParam('route');
627
-        $route = $route !== '-1' ? $route : 'default';
628
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
629
-            ? $route
630
-            : $req_action;
631
-        $this->_current_view = $this->_req_action;
632
-        $this->_req_nonce    = $this->_req_action . '_nonce';
633
-        $this->_define_page_props();
634
-        $this->_current_page_view_url = add_query_arg(
635
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
636
-            $this->_admin_base_url
637
-        );
638
-        // set page configs
639
-        $this->_set_page_routes();
640
-        $this->_set_page_config();
641
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
642
-        if ($this->request->requestParamIsSet('wp_referer')) {
643
-            $wp_referer = $this->request->getRequestParam('wp_referer');
644
-            if ($wp_referer) {
645
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
646
-            }
647
-        }
648
-        // for CPT and other extended functionality.
649
-        // If there is an _extend_page_config_for_cpt
650
-        // then let's run that to modify all the various page configuration arrays.
651
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
652
-            $this->_extend_page_config_for_cpt();
653
-        }
654
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
655
-        $this->_page_routes = apply_filters(
656
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
657
-            $this->_page_routes,
658
-            $this
659
-        );
660
-        $this->_page_config = apply_filters(
661
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
662
-            $this->_page_config,
663
-            $this
664
-        );
665
-        if ($this->base_class_name !== '') {
666
-            $this->_page_routes = apply_filters(
667
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
668
-                $this->_page_routes,
669
-                $this
670
-            );
671
-            $this->_page_config = apply_filters(
672
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
673
-                $this->_page_config,
674
-                $this
675
-            );
676
-        }
677
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
678
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
679
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
680
-            add_action(
681
-                'AHEE__EE_Admin_Page__route_admin_request',
682
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
683
-                10,
684
-                2
685
-            );
686
-        }
687
-        // next route only if routing enabled
688
-        if ($this->_routing && ! $this->request->isAjax()) {
689
-            $this->_verify_routes();
690
-            // next let's just check user_access and kill if no access
691
-            $this->check_user_access();
692
-            if ($this->_is_UI_request) {
693
-                // admin_init stuff - global, all views for this page class, specific view
694
-                add_action('admin_init', [$this, 'admin_init']);
695
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
696
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
697
-                }
698
-            } else {
699
-                // hijack regular WP loading and route admin request immediately
700
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
701
-                $this->route_admin_request();
702
-            }
703
-        }
704
-    }
73
+	protected array $_nav_tabs                 = [];
705 74
 
75
+	protected array $_page_config              = [];
706 76
 
707
-    /**
708
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
709
-     *
710
-     * @return void
711
-     * @throws EE_Error
712
-     */
713
-    private function _do_other_page_hooks()
714
-    {
715
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
716
-        foreach ($registered_pages as $page) {
717
-            // now let's set up the file name and class that should be present
718
-            $classname = str_replace('.class.php', '', $page);
719
-            // autoloaders should take care of loading file
720
-            if (! class_exists($classname)) {
721
-                $error_msg[] = sprintf(
722
-                    esc_html__(
723
-                        'Something went wrong with loading the %s admin hooks page.',
724
-                        'event_espresso'
725
-                    ),
726
-                    $page
727
-                );
728
-                $error_msg[] = $error_msg[0]
729
-                               . "\r\n"
730
-                               . sprintf(
731
-                                   esc_html__(
732
-                                       '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',
733
-                                       'event_espresso'
734
-                                   ),
735
-                                   $page,
736
-                                   '<br />',
737
-                                   '<strong>' . $classname . '</strong>'
738
-                               );
739
-                throw new EE_Error(implode('||', $error_msg));
740
-            }
741
-            // don't load the same class twice
742
-            static $loaded = [];
743
-            if (in_array($classname, $loaded, true)) {
744
-                continue;
745
-            }
746
-            $loaded[] = $classname;
747
-            // notice we are passing the instance of this class to the hook object.
748
-            $this->loader->getShared($classname, [$this]);
749
-        }
750
-    }
77
+	/**
78
+	 * action => method pairs used for routing incoming requests
79
+	 *
80
+	 * @var array
81
+	 */
82
+	protected array $_page_routes   = [];
751 83
 
84
+	protected array $_req_data      = [];
752 85
 
753
-    /**
754
-     * @throws ReflectionException
755
-     * @throws EE_Error
756
-     */
757
-    public function load_page_dependencies()
758
-    {
759
-        try {
760
-            $this->_load_page_dependencies();
761
-        } catch (EE_Error $e) {
762
-            $e->get_error();
763
-        }
764
-    }
86
+	protected array $_route_config  = [];
765 87
 
88
+	protected array $_template_args = [];
766 89
 
767
-    /**
768
-     * load_page_dependencies
769
-     * loads things specific to this page class when it's loaded.  Really helps with efficiency.
770
-     *
771
-     * @return void
772
-     * @throws DomainException
773
-     * @throws EE_Error
774
-     * @throws InvalidArgumentException
775
-     * @throws InvalidDataTypeException
776
-     * @throws InvalidInterfaceException
777
-     * @throws ReflectionException
778
-     */
779
-    protected function _load_page_dependencies()
780
-    {
781
-        // let's set the current_screen and screen options to override what WP set
782
-        $this->_current_screen = get_current_screen();
783
-        // load admin_notices - global, page class, and view specific
784
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
785
-        add_action('admin_notices', [$this, 'admin_notices']);
786
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
787
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
788
-        }
789
-        // load network admin_notices - global, page class, and view specific
790
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
791
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
792
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
793
-        }
794
-        // this will save any per_page screen options if they are present
795
-        $this->_set_per_page_screen_options();
796
-        // setup list table properties
797
-        $this->_set_list_table();
798
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
799
-        // However in some cases the metaboxes will need to be added within a route handling callback.
800
-        add_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
801
-        // hack because promos admin was loading the edited promotion object in the metaboxes callback
802
-        // which should NOT be generated on non-UI requests like POST updates/inserts
803
-        if (
804
-            $this->class_name === 'Promotions_Admin_Page'
805
-            && ($this->_req_action === 'edit' || $this->_req_action === 'create_new')
806
-        ) {
807
-            $this->addRegisteredMetaBoxes();
808
-        }
809
-        $this->_add_screen_columns();
810
-        // add screen options - global, page child class, and view specific
811
-        $this->_add_global_screen_options();
812
-        $this->_add_screen_options();
813
-        $add_screen_options = "_add_screen_options_$this->_current_view";
814
-        if (method_exists($this, $add_screen_options)) {
815
-            $this->{$add_screen_options}();
816
-        }
817
-        // add help tab(s) - set via page_config and qtips.
818
-        $this->_add_help_tabs();
819
-        $this->_add_qtips();
820
-        // add feature_pointers - global, page child class, and view specific
821
-        $this->_add_feature_pointers();
822
-        $this->_add_global_feature_pointers();
823
-        $add_feature_pointer = "_add_feature_pointer_$this->_current_view";
824
-        if (method_exists($this, $add_feature_pointer)) {
825
-            $this->{$add_feature_pointer}();
826
-        }
827
-        // enqueue scripts/styles - global, page class, and view specific
828
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 1);
829
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
830
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles']);
831
-        if (method_exists($this, "load_scripts_styles_$this->_current_view")) {
832
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_$this->_current_view"], 15);
833
-        }
834
-        // admin_print_footer_scripts - global, page child class, and view specific.
835
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
836
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
837
-        // is a good use case. Notice the late priority we're giving these
838
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
839
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
840
-        if (method_exists($this, "admin_footer_scripts_$this->_current_view")) {
841
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_$this->_current_view"], 101);
842
-        }
843
-        // admin footer scripts
844
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
845
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
846
-        if (method_exists($this, "admin_footer_$this->_current_view")) {
847
-            add_action('admin_footer', [$this, "admin_footer_$this->_current_view"], 101);
848
-        }
849
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
850
-        // targeted hook
851
-        do_action(
852
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__$this->_req_action"
853
-        );
854
-    }
90
+	protected array $_views         = [];
855 91
 
92
+	/**
93
+	 * yes / no array for admin form fields
94
+	 *
95
+	 * @var array|array[]
96
+	 */
97
+	protected array $_yes_no_values = [];
856 98
 
857
-    /**
858
-     * _set_defaults
859
-     * This sets some global defaults for class properties.
860
-     */
861
-    private function _set_defaults()
862
-    {
863
-        // init template args
864
-        $this->set_template_args(
865
-            [
866
-                'admin_page_header'  => '',
867
-                'admin_page_content' => '',
868
-                'post_body_content'  => '',
869
-                'before_list_table'  => '',
870
-                'after_list_table'   => '',
871
-            ]
872
-        );
873
-    }
99
+	/**
100
+	 * this starts at null so we can have no header routes progress through two states.
101
+	 */
102
+	protected ?bool $_is_UI_request = null;
874 103
 
104
+	/**
105
+	 * flags whether the given route is a caffeinated route or not.
106
+	 */
107
+	protected bool  $_is_caf        = false;
875 108
 
876
-    /**
877
-     * route_admin_request
878
-     *
879
-     * @return void
880
-     * @throws InvalidArgumentException
881
-     * @throws InvalidInterfaceException
882
-     * @throws InvalidDataTypeException
883
-     * @throws EE_Error
884
-     * @throws ReflectionException
885
-     * @throws Throwable
886
-     * @see    _route_admin_request()
887
-     */
888
-    public function route_admin_request()
889
-    {
890
-        try {
891
-            $this->_route_admin_request();
892
-        } catch (EE_Error $e) {
893
-            $e->get_error();
894
-        }
895
-    }
896
-
897
-
898
-    public function set_wp_page_slug($wp_page_slug)
899
-    {
900
-        $this->_wp_page_slug = $wp_page_slug;
901
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
902
-        if (is_network_admin()) {
903
-            $this->_wp_page_slug .= '-network';
904
-        }
905
-    }
109
+	protected bool  $_routing       = false;
906 110
 
111
+	/**
112
+	 * whether initializePage() has run
113
+	 *
114
+	 * @var bool
115
+	 */
116
+	protected bool $initialized = false;
907 117
 
908
-    /**
909
-     * _verify_routes
910
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
911
-     * we know if we need to drop out.
912
-     *
913
-     * @return bool
914
-     * @throws EE_Error
915
-     */
916
-    protected function _verify_routes(): bool
917
-    {
918
-        if (! $this->_current_page && ! $this->request->isAjax()) {
919
-            return false;
920
-        }
921
-        // check that the page_routes array is not empty
922
-        if (empty($this->_page_routes)) {
923
-            // user error msg
924
-            $error_msg = sprintf(
925
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
926
-                $this->_admin_page_title
927
-            );
928
-            // developer error msg
929
-            $error_msg .= '||' . $error_msg
930
-                          . esc_html__(
931
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
932
-                              'event_espresso'
933
-                          );
934
-            throw new EE_Error($error_msg);
935
-        }
936
-        // route 'editpost' routes to CPT 'edit' routes
937
-        $alt_edit_route = $this instanceof EE_Admin_Page_CPT ? $this->cpt_editpost_route : 'edit';
938
-        if (
939
-            $this->_req_action === 'editpost'
940
-            && ! isset($this->_page_routes['editpost'])
941
-            && isset($this->_page_routes[$alt_edit_route])
942
-        ) {
943
-            $this->_req_action = $alt_edit_route;
944
-        }
945
-        // and that the requested page route exists
946
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
947
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
948
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
949
-        } else {
950
-            // user error msg
951
-            $error_msg = sprintf(
952
-                esc_html__(
953
-                    'The requested page route does not exist for the %s admin page.',
954
-                    'event_espresso'
955
-                ),
956
-                $this->_admin_page_title
957
-            );
958
-            // developer error msg
959
-            $error_msg .= '||' . $error_msg
960
-                          . sprintf(
961
-                              esc_html__(
962
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
963
-                                  'event_espresso'
964
-                              ),
965
-                              $this->_req_action
966
-                          );
967
-            throw new EE_Error($error_msg);
968
-        }
969
-        // and that a default route exists
970
-        if (! array_key_exists('default', $this->_page_routes)) {
971
-            // user error msg
972
-            $error_msg = sprintf(
973
-                esc_html__(
974
-                    'A default page route has not been set for the % admin page.',
975
-                    'event_espresso'
976
-                ),
977
-                $this->_admin_page_title
978
-            );
979
-            // developer error msg
980
-            $error_msg .= '||' . $error_msg
981
-                          . esc_html__(
982
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
983
-                              'event_espresso'
984
-                          );
985
-            throw new EE_Error($error_msg);
986
-        }
987
-
988
-        // first lets' catch if the UI request has EVER been set.
989
-        if ($this->_is_UI_request === null) {
990
-            // let's set if this is a UI request or not.
991
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, DataType::BOOL);
992
-            // wait a minute... we might have a noheader in the route array
993
-            $this->_is_UI_request = ! (isset($this->_route['noheader']) && $this->_route['noheader'])
994
-                ? $this->_is_UI_request
995
-                : false;
996
-        }
997
-        $this->_set_current_labels();
998
-        return true;
999
-    }
1000 118
 
119
+	protected string $_admin_base_path      = '';
1001 120
 
1002
-    /**
1003
-     * this method simply verifies a given route and makes sure it's an actual route available for the loaded page
1004
-     *
1005
-     * @param string $route the route name we're verifying
1006
-     * @return bool we'll throw an exception if this isn't a valid route.
1007
-     * @throws EE_Error
1008
-     */
1009
-    protected function _verify_route(string $route): bool
1010
-    {
1011
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
1012
-            return true;
1013
-        }
1014
-        // user error msg
1015
-        $error_msg = sprintf(
1016
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1017
-            $this->_admin_page_title
1018
-        );
1019
-        // developer error msg
1020
-        $error_msg .= '||' . $error_msg
1021
-                      . sprintf(
1022
-                          esc_html__(
1023
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1024
-                              'event_espresso'
1025
-                          ),
1026
-                          $route
1027
-                      );
1028
-        throw new EE_Error($error_msg);
1029
-    }
121
+	protected string $_admin_base_url       = '';
1030 122
 
123
+	protected string $_admin_page_title     = '';
1031 124
 
1032
-    /**
1033
-     * perform nonce verification
1034
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1035
-     * using this method (and save retyping!)
1036
-     *
1037
-     * @param string $nonce     The nonce sent
1038
-     * @param string $nonce_ref The nonce reference string (name0)
1039
-     * @return void
1040
-     * @throws EE_Error
1041
-     * @throws InvalidArgumentException
1042
-     * @throws InvalidDataTypeException
1043
-     * @throws InvalidInterfaceException
1044
-     */
1045
-    protected function _verify_nonce(string $nonce, string $nonce_ref)
1046
-    {
1047
-        // verify nonce against expected value
1048
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1049
-            // these are not the droids you are looking for !!!
1050
-            $msg = sprintf(
1051
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
1052
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1053
-                '</a>'
1054
-            );
1055
-            if (WP_DEBUG) {
1056
-                $msg .= "\n  ";
1057
-                $msg .= sprintf(
1058
-                    esc_html__(
1059
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1060
-                        'event_espresso'
1061
-                    ),
1062
-                    __CLASS__
1063
-                );
1064
-            }
1065
-            if (! $this->request->isAjax()) {
1066
-                wp_die($msg);
1067
-            }
1068
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1069
-            $this->_return_json();
1070
-        }
1071
-    }
125
+	protected string $_column_template_path = '';
1072 126
 
127
+	protected bool   $_cpt_route            = false;
1073 128
 
1074
-    /**
1075
-     * _route_admin_request()
1076
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1077
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1078
-     * in the page routes and then will try to load the corresponding method.
1079
-     *
1080
-     * @return void
1081
-     * @throws EE_Error
1082
-     * @throws InvalidArgumentException
1083
-     * @throws InvalidDataTypeException
1084
-     * @throws InvalidInterfaceException
1085
-     * @throws ReflectionException
1086
-     * @throws Throwable
1087
-     */
1088
-    protected function _route_admin_request()
1089
-    {
1090
-        if (! $this->_is_UI_request) {
1091
-            $this->_verify_routes();
1092
-        }
1093
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1094
-        if ($this->_req_action !== 'default' && $nonce_check) {
1095
-            // set nonce from post data
1096
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
1097
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1098
-        }
1099
-        // set the nav_tabs array but ONLY if this is  UI_request
1100
-        if ($this->_is_UI_request) {
1101
-            $this->_set_nav_tabs();
1102
-        }
1103
-        // grab callback function
1104
-        $func = $this->_route['func'] ?? $this->_route;
1105
-        // check if callback has args
1106
-        $args = $this->_route['args'] ?? [];
1107
-
1108
-        // action right before calling route
1109
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1110
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1111
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1112
-        }
1113
-        // strip _wp_http_referer from the server REQUEST_URI
1114
-        // else it grows in length on every submission due to recursion,
1115
-        // ultimately causing a "Request-URI Too Large" error
1116
-        $this->request->unSetRequestParam('_wp_http_referer');
1117
-        $this->request->unSetServerParam('_wp_http_referer');
1118
-        $cleaner_request_uri = remove_query_arg(
1119
-            '_wp_http_referer',
1120
-            wp_unslash($this->request->getServerParam('REQUEST_URI'))
1121
-        );
1122
-        $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1123
-        $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1124
-        $route_callback = [];
1125
-        if (! empty($func)) {
1126
-            if (is_array($func) && is_callable($func)) {
1127
-                $route_callback = $func;
1128
-            } elseif (is_string($func)) {
1129
-                if (strpos($func, '::') !== false) {
1130
-                    $route_callback = explode('::', $func);
1131
-                } elseif (method_exists($this, $func)) {
1132
-                    $route_callback = [$this, $func];
1133
-                } else {
1134
-                    $route_callback = $func;
1135
-                }
1136
-            }
1137
-            [$class, $method] = $route_callback;
1138
-            // is it neither a class method NOR a standalone function?
1139
-            if (! is_callable($route_callback)) {
1140
-                // user error msg
1141
-                $error_msg = esc_html__(
1142
-                    'An error occurred. The  requested page route could not be found.',
1143
-                    'event_espresso'
1144
-                );
1145
-                // developer error msg
1146
-                $error_msg .= '||';
1147
-                $error_msg .= sprintf(
1148
-                    esc_html__(
1149
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1150
-                        'event_espresso'
1151
-                    ),
1152
-                    $method
1153
-                );
1154
-                throw new DomainException($error_msg);
1155
-            }
1156
-            if ($class !== $this && ! in_array($this, $args)) {
1157
-                // send along this admin page object for access by addons.
1158
-                $args['admin_page'] = $this;
1159
-            }
1160
-
1161
-            call_user_func_array($route_callback, $args);
1162
-        }
1163
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1164
-        // then we need to reset the routing properties to the new route.
1165
-        // 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.
1166
-        if (
1167
-            $this->_is_UI_request === false
1168
-            && is_array($this->_route)
1169
-            && ! empty($this->_route['headers_sent_route'])
1170
-        ) {
1171
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1172
-        }
1173
-    }
129
+	/**
130
+	 * set via request page and action args.
131
+	 */
132
+	protected string $_current_page          = '';
1174 133
 
134
+	protected string $_current_page_view_url = '';
1175 135
 
1176
-    /**
1177
-     * This method just allows the resetting of page properties in the case where a no headers
1178
-     * route redirects to a headers route in its route config.
1179
-     *
1180
-     * @param string $new_route New (non header) route to redirect to.
1181
-     * @return void
1182
-     * @throws ReflectionException
1183
-     * @throws InvalidArgumentException
1184
-     * @throws InvalidInterfaceException
1185
-     * @throws InvalidDataTypeException
1186
-     * @throws EE_Error
1187
-     * @throws Throwable
1188
-     * @since   4.3.0
1189
-     */
1190
-    protected function _reset_routing_properties(string $new_route)
1191
-    {
1192
-        $this->_is_UI_request = true;
1193
-        // now we set the current route to whatever the headers_sent_route is set at
1194
-        $this->request->setRequestParam('action', $new_route);
1195
-        // rerun page setup
1196
-        $this->_page_setup();
1197
-    }
136
+	protected string $_current_view          = '';
1198 137
 
138
+	protected string $_default_nav_tab_name  = 'overview';
139
+
140
+	/**
141
+	 * sanitized request action
142
+	 */
143
+	protected string $_req_action = '';
144
+
145
+	/**
146
+	 * sanitized request action nonce
147
+	 */
148
+	protected string $_req_nonce        = '';
149
+
150
+	protected string $_search_btn_label = '';
151
+
152
+	protected string $_template_path    = '';
153
+
154
+	protected string $_view             = '';
155
+
156
+	/**
157
+	 * set early within EE_Admin_Init
158
+	 *
159
+	 * @var string
160
+	 */
161
+	protected string $_wp_page_slug = '';
1199 162
 
1200
-    /**
1201
-     * _add_query_arg
1202
-     * adds nonce to array of arguments then calls WP add_query_arg function
1203
-     *(internally just uses EEH_URL's function with the same name)
1204
-     *
1205
-     * @param array  $args
1206
-     * @param string $url
1207
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1208
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1209
-     *                                        Example usage: If the current page is:
1210
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1211
-     *                                        &action=default&event_id=20&month_range=March%202015
1212
-     *                                        &_wpnonce=5467821
1213
-     *                                        and you call:
1214
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1215
-     *                                        array(
1216
-     *                                        'action' => 'resend_something',
1217
-     *                                        'page=>espresso_registrations'
1218
-     *                                        ),
1219
-     *                                        $some_url,
1220
-     *                                        true
1221
-     *                                        );
1222
-     *                                        It will produce a URL in this structure:
1223
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1224
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1225
-     *                                        month_range]=March%202015
1226
-     * @param bool   $exclude_nonce           If true, the nonce will be excluded from the generated nonce.
1227
-     * @param int    $context
1228
-     * @return string
1229
-     */
1230
-    public static function add_query_args_and_nonce(
1231
-        array $args = [],
1232
-        string $url = '',
1233
-        bool $sticky = false,
1234
-        bool $exclude_nonce = false,
1235
-        int $context = EEH_URL::CONTEXT_NONE
1236
-    ): string {
1237
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1238
-        if ($sticky) {
1239
-            /** @var RequestInterface $request */
1240
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1241
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1242
-            $request->unSetServerParam('_wp_http_referer', true);
1243
-            foreach ($request->requestParams() as $key => $value) {
1244
-                // do not add nonces
1245
-                if (strpos($key, 'nonce') !== false) {
1246
-                    continue;
1247
-                }
1248
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1249
-            }
1250
-        }
1251
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce, $context);
1252
-    }
163
+	/**
164
+	 * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
165
+	 * then this would be the parent classname: Events_Admin_Page
166
+	 *
167
+	 * @var string
168
+	 */
169
+	public string $base_class_name = '';
1253 170
 
1254
-
1255
-    /**
1256
-     * This returns a generated link that will load the related help tab.
1257
-     *
1258
-     * @param string $help_tab_id the id for the connected help tab
1259
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1260
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1261
-     * @return string              generated link
1262
-     * @uses EEH_Template::get_help_tab_link()
1263
-     */
1264
-    protected function _get_help_tab_link(string $help_tab_id, string $icon_style = '', string $help_text = ''): string
1265
-    {
1266
-        return EEH_Template::get_help_tab_link(
1267
-            $help_tab_id,
1268
-            $this->page_slug,
1269
-            $this->_req_action,
1270
-            $icon_style,
1271
-            $help_text
1272
-        );
1273
-    }
1274
-
1275
-
1276
-    /**
1277
-     * _add_help_tabs
1278
-     * Note child classes define their help tabs within the page_config array.
1279
-     *
1280
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1281
-     * @return void
1282
-     * @throws DomainException
1283
-     * @throws EE_Error
1284
-     * @throws ReflectionException
1285
-     */
1286
-    protected function _add_help_tabs()
1287
-    {
1288
-        if (isset($this->_page_config[ $this->_req_action ])) {
1289
-            $config = $this->_page_config[ $this->_req_action ];
1290
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1291
-            if (is_array($config) && isset($config['help_sidebar'])) {
1292
-                // check that the callback given is valid
1293
-                if (! method_exists($this, $config['help_sidebar'])) {
1294
-                    throw new EE_Error(
1295
-                        sprintf(
1296
-                            esc_html__(
1297
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Double check the spelling and make sure this method exists for the class %s',
1298
-                                'event_espresso'
1299
-                            ),
1300
-                            $config['help_sidebar'],
1301
-                            $this->class_name
1302
-                        )
1303
-                    );
1304
-                }
1305
-                $content = apply_filters(
1306
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1307
-                    $this->{$config['help_sidebar']}()
1308
-                );
1309
-                $this->_current_screen->set_help_sidebar($content);
1310
-            }
1311
-            if (! isset($config['help_tabs'])) {
1312
-                return;
1313
-            } //no help tabs for this route
1314
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1315
-                // we're here so there ARE help tabs!
1316
-                // make sure we've got what we need
1317
-                if (! isset($cfg['title'])) {
1318
-                    throw new EE_Error(
1319
-                        esc_html__(
1320
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1321
-                            'event_espresso'
1322
-                        )
1323
-                    );
1324
-                }
1325
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1326
-                    throw new EE_Error(
1327
-                        esc_html__(
1328
-                            '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',
1329
-                            'event_espresso'
1330
-                        )
1331
-                    );
1332
-                }
1333
-                // first priority goes to content.
1334
-                if (! empty($cfg['content'])) {
1335
-                    $content = $cfg['content'];
1336
-                    // second priority goes to filename
1337
-                } elseif (! empty($cfg['filename'])) {
1338
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1339
-                    // 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)
1340
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1341
-                                                             . basename($this->_get_dir())
1342
-                                                             . '/help_tabs/'
1343
-                                                             . $cfg['filename']
1344
-                                                             . '.help_tab.php' : $file_path;
1345
-                    // if file is STILL not readable then let's do an EE_Error so its more graceful than a fatal error.
1346
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1347
-                        EE_Error::add_error(
1348
-                            sprintf(
1349
-                                esc_html__(
1350
-                                    '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',
1351
-                                    'event_espresso'
1352
-                                ),
1353
-                                $tab_id,
1354
-                                key($config),
1355
-                                $file_path
1356
-                            ),
1357
-                            __FILE__,
1358
-                            __FUNCTION__,
1359
-                            __LINE__
1360
-                        );
1361
-                        return;
1362
-                    }
1363
-                    $template_args['admin_page_obj'] = $this;
1364
-                    $content                         = EEH_Template::display_template(
1365
-                        $file_path,
1366
-                        $template_args,
1367
-                        true
1368
-                    );
1369
-                } else {
1370
-                    $content = '';
1371
-                }
1372
-                // check if callback is valid
1373
-                if (
1374
-                    empty($content)
1375
-                    && (
1376
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1377
-                    )
1378
-                ) {
1379
-                    EE_Error::add_error(
1380
-                        sprintf(
1381
-                            esc_html__(
1382
-                                '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.',
1383
-                                'event_espresso'
1384
-                            ),
1385
-                            $cfg['title']
1386
-                        ),
1387
-                        __FILE__,
1388
-                        __FUNCTION__,
1389
-                        __LINE__
1390
-                    );
1391
-                    return;
1392
-                }
1393
-                // setup config array for help tab method
1394
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1395
-                $_ht = [
1396
-                    'id'       => $id,
1397
-                    'title'    => $cfg['title'],
1398
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1399
-                    'content'  => $content,
1400
-                ];
1401
-                $this->_current_screen->add_help_tab($_ht);
1402
-            }
1403
-        }
1404
-    }
1405
-
1406
-
1407
-    /**
1408
-     * This simply sets up any qtips that have been defined in the page config
1409
-     *
1410
-     * @return void
1411
-     * @throws ReflectionException
1412
-     * @throws EE_Error
1413
-     */
1414
-    protected function _add_qtips()
1415
-    {
1416
-        if (isset($this->_route_config['qtips'])) {
1417
-            $qtips = (array) $this->_route_config['qtips'];
1418
-            // load qtip loader
1419
-            $path = [
1420
-                $this->_get_dir() . '/qtips/',
1421
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1422
-            ];
1423
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1424
-        }
1425
-    }
1426
-
1427
-
1428
-    /**
1429
-     * _set_nav_tabs
1430
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1431
-     * wish to add additional tabs or modify accordingly.
1432
-     *
1433
-     * @return void
1434
-     * @throws InvalidArgumentException
1435
-     * @throws InvalidInterfaceException
1436
-     * @throws InvalidDataTypeException
1437
-     */
1438
-    protected function _set_nav_tabs()
1439
-    {
1440
-        $i        = 0;
1441
-        $only_tab = count($this->_page_config) < 2;
1442
-        foreach ($this->_page_config as $slug => $config) {
1443
-            if (! is_array($config) || empty($config['nav'])) {
1444
-                continue;
1445
-            }
1446
-            // no nav tab for this config
1447
-            // check for persistent flag
1448
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1449
-                // nav tab is only to appear when route requested.
1450
-                continue;
1451
-            }
1452
-            if (! $this->check_user_access($slug, true)) {
1453
-                // no nav tab because current user does not have access.
1454
-                continue;
1455
-            }
1456
-            $css_class = $config['css_class'] ?? '';
1457
-            $css_class .= $only_tab ? ' ee-only-tab' : '';
1458
-            $css_class .= " ee-nav-tab__$slug";
1459
-
1460
-            $this->_nav_tabs[ $slug ] = [
1461
-                'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1462
-                        ['action' => $slug],
1463
-                        $this->_admin_base_url
1464
-                    ),
1465
-                'link_text' => $this->navTabLabel($config['nav'], $slug),
1466
-                'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1467
-                'order'     => $config['nav']['order'] ?? $i,
1468
-            ];
1469
-            $i++;
1470
-        }
1471
-        // if $this->_nav_tabs is empty then lets set the default
1472
-        if (empty($this->_nav_tabs)) {
1473
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1474
-                'url'       => $this->_admin_base_url,
1475
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1476
-                'css_class' => 'nav-tab-active',
1477
-                'order'     => 10,
1478
-            ];
1479
-        }
1480
-        // now let's sort the tabs according to order
1481
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1482
-    }
1483
-
1484
-
1485
-    private function navTabLabel(array $nav_tab, string $slug): string
1486
-    {
1487
-        $label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1488
-        $icon  = $nav_tab['icon'] ?? null;
1489
-        $icon  = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1490
-        return '
171
+	public string $class_name      = '';
172
+
173
+	/**
174
+	 * unprocessed value for the 'action' request param (default '')
175
+	 *
176
+	 * @var string
177
+	 */
178
+	protected string $raw_req_action = '';
179
+
180
+	/**
181
+	 * unprocessed value for the 'page' request param (default '')
182
+	 *
183
+	 * @var string
184
+	 */
185
+	protected string $raw_req_page = '';
186
+
187
+	public string    $page_folder  = '';
188
+
189
+	public string    $page_label   = '';
190
+
191
+	public string    $page_slug    = '';
192
+
193
+
194
+	/**
195
+	 * the current page route and route config
196
+	 *
197
+	 * @var array|callable|string|null
198
+	 */
199
+	protected $_route = null;
200
+
201
+
202
+	/**
203
+	 * @Constructor
204
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
205
+	 * @throws InvalidArgumentException
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 * @throws ReflectionException
209
+	 */
210
+	public function __construct($routing = true)
211
+	{
212
+		$this->loader       = LoaderFactory::getLoader();
213
+		$this->admin_config = $this->loader->getShared(EE_Admin_Config::class);
214
+		$this->feature      = $this->loader->getShared(FeatureFlags::class);
215
+		$this->request      = $this->loader->getShared(RequestInterface::class);
216
+		$this->capabilities = $this->loader->getShared(EE_Capabilities::class);
217
+		// routing enabled?
218
+		$this->_routing = $routing;
219
+
220
+		$this->class_name      = get_class($this);
221
+		$this->base_class_name = strpos($this->class_name, 'Extend_') === 0
222
+			? str_replace('Extend_', '', $this->class_name)
223
+			: '';
224
+
225
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
226
+			$this->_is_caf = true;
227
+		}
228
+		$this->_yes_no_values = [
229
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
230
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
231
+		];
232
+		// set the _req_data property.
233
+		$this->_req_data = $this->request->requestParams();
234
+	}
235
+
236
+
237
+	/**
238
+	 * @return EE_Admin_Config
239
+	 */
240
+	public function adminConfig(): EE_Admin_Config
241
+	{
242
+		return $this->admin_config;
243
+	}
244
+
245
+
246
+	public function capabilities(): EE_Capabilities
247
+	{
248
+		if (! $this->capabilities instanceof EE_Capabilities) {
249
+			$this->capabilities = $this->loader->getShared(EE_Capabilities::class);
250
+		}
251
+		return $this->capabilities;
252
+	}
253
+
254
+
255
+	/**
256
+	 * @return FeatureFlags
257
+	 */
258
+	public function feature(): FeatureFlags
259
+	{
260
+		return $this->feature;
261
+	}
262
+
263
+
264
+	/**
265
+	 * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
266
+	 * for child classes that needed to set properties prior to these methods getting called,
267
+	 * but also needed the parent class to have its construction completed as well.
268
+	 * Bottom line is that constructors should ONLY be used for setting initial properties
269
+	 * and any complex initialization logic should only run after instantiation is complete.
270
+	 * This method gets called immediately after construction from within
271
+	 *      EE_Admin_Page_Init::_initialize_admin_page()
272
+	 *
273
+	 * @throws EE_Error
274
+	 * @throws InvalidArgumentException
275
+	 * @throws InvalidDataTypeException
276
+	 * @throws InvalidInterfaceException
277
+	 * @throws ReflectionException
278
+	 * @throws Throwable
279
+	 * @since 5.0.0.p
280
+	 */
281
+	public function initializePage()
282
+	{
283
+		if ($this->initialized) {
284
+			return;
285
+		}
286
+		// set initial page props (child method)
287
+		$this->_init_page_props();
288
+		// set global defaults
289
+		$this->_set_defaults();
290
+		// set early because incoming requests could be ajax related and we need to register those hooks.
291
+		if ($this->request->isAjax()) {
292
+			$this->_global_ajax_hooks();
293
+			$this->_ajax_hooks();
294
+		}
295
+		// other_page_hooks have to be early too.
296
+		$this->_do_other_page_hooks();
297
+		// set up page dependencies
298
+		$this->_before_page_setup();
299
+		$this->_page_setup();
300
+		$this->initialized = true;
301
+	}
302
+
303
+
304
+	/**
305
+	 * _init_page_props
306
+	 * Child classes use to set at least the following properties:
307
+	 * $page_slug.
308
+	 * $page_label.
309
+	 *
310
+	 * @abstract
311
+	 * @return void
312
+	 */
313
+	abstract protected function _init_page_props();
314
+
315
+
316
+	/**
317
+	 * _ajax_hooks
318
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
319
+	 * Note: within the ajax callback methods.
320
+	 *
321
+	 * @abstract
322
+	 * @return void
323
+	 */
324
+	abstract protected function _ajax_hooks();
325
+
326
+
327
+	/**
328
+	 * _define_page_props
329
+	 * child classes define page properties in here.  Must include at least:
330
+	 * $_admin_base_url = base_url for all admin pages
331
+	 * $_admin_page_title = default admin_page_title for admin pages
332
+	 * $_labels = array of default labels for various automatically generated elements:
333
+	 *    array(
334
+	 *        'buttons' => array(
335
+	 *            'add' => esc_html__('label for add new button'),
336
+	 *            'edit' => esc_html__('label for edit button'),
337
+	 *            'delete' => esc_html__('label for delete button')
338
+	 *            )
339
+	 *        )
340
+	 *
341
+	 * @abstract
342
+	 * @return void
343
+	 */
344
+	abstract protected function _define_page_props();
345
+
346
+
347
+	/**
348
+	 * _set_page_routes
349
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
350
+	 * assigned to an action => method pairs in an array and to the $_page_routes property.  Each page route must also
351
+	 * have a 'default' route. Here's the format
352
+	 * $this->_page_routes = array(
353
+	 *        'default' => array(
354
+	 *            'func' => '_default_method_handling_route',
355
+	 *            'args' => array('array','of','args'),
356
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
357
+	 *            ajax request, backend processing)
358
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
359
+	 *            headers route after.  The string you enter here should match the defined route reference for a
360
+	 *            headers sent route.
361
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
362
+	 *            this route.
363
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
364
+	 *            checks).
365
+	 *        ),
366
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
367
+	 *        handling method.
368
+	 *        )
369
+	 * )
370
+	 *
371
+	 * @abstract
372
+	 * @return void
373
+	 */
374
+	abstract protected function _set_page_routes();
375
+
376
+
377
+	/**
378
+	 * _set_page_config
379
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
380
+	 * array corresponds to the page_route for the loaded page. Format:
381
+	 * $this->_page_config = array(
382
+	 *        'default' => array(
383
+	 *            'labels' => array(
384
+	 *                'buttons' => array(
385
+	 *                    'add' => esc_html__('label for adding item'),
386
+	 *                    'edit' => esc_html__('label for editing item'),
387
+	 *                    'delete' => esc_html__('label for deleting item')
388
+	 *                ),
389
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
390
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
391
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
392
+	 *            _define_page_props() method
393
+	 *            'nav' => array(
394
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
395
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
396
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
397
+	 *                'order' => 10, //required to indicate tab position.
398
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
399
+	 *                displayed then add this parameter.
400
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
401
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
402
+	 *            metaboxes set for eventespresso admin pages.
403
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
404
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
405
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
406
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
407
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
408
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
409
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
410
+	 *            There is an option in the "screen_options" dropdown that is set up so users can pick what columns they
411
+	 *            want to display.
412
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
413
+	 *                'tab_id' => array(
414
+	 *                    'title' => 'tab_title',
415
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
416
+	 *                    help tab content.  The fallback if it isn't present is to try the callback.  Filename
417
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
418
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
419
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
420
+	 *                    attempt to use the callback which should match the name of a method in the class
421
+	 *                    ),
422
+	 *                'tab2_id' => array(
423
+	 *                    'title' => 'tab2 title',
424
+	 *                    'filename' => 'file_name_2'
425
+	 *                    'callback' => 'callback_method_for_content',
426
+	 *                 ),
427
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
428
+	 *            help tab area on an admin page. @return void
429
+	 *
430
+	 * @abstract
431
+	 */
432
+	abstract protected function _set_page_config();
433
+
434
+
435
+	/**
436
+	 * _add_screen_options
437
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
438
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
439
+	 * to a particular view.
440
+	 *
441
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
442
+	 *         see also WP_Screen object documents...
443
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
444
+	 * @abstract
445
+	 * @return void
446
+	 */
447
+	abstract protected function _add_screen_options();
448
+
449
+
450
+	/**
451
+	 * _add_feature_pointers
452
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
453
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
454
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
455
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
456
+	 * extended) also see:
457
+	 *
458
+	 * @link   http://eamann.com/tech/wordpress-portland/
459
+	 * @abstract
460
+	 * @return void
461
+	 */
462
+	abstract protected function _add_feature_pointers();
463
+
464
+
465
+	/**
466
+	 * load_scripts_styles
467
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
468
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
469
+	 * scripts/styles per view by putting them in a dynamic function in this format
470
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
471
+	 *
472
+	 * @abstract
473
+	 * @return void
474
+	 */
475
+	abstract public function load_scripts_styles();
476
+
477
+
478
+	/**
479
+	 * admin_init
480
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
481
+	 * all pages/views loaded by child class.
482
+	 *
483
+	 * @abstract
484
+	 * @return void
485
+	 */
486
+	abstract public function admin_init();
487
+
488
+
489
+	/**
490
+	 * admin_notices
491
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
492
+	 * all pages/views loaded by child class.
493
+	 *
494
+	 * @abstract
495
+	 * @return void
496
+	 */
497
+	abstract public function admin_notices();
498
+
499
+
500
+	/**
501
+	 * admin_footer_scripts
502
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
503
+	 * will apply to all pages/views loaded by child class.
504
+	 *
505
+	 * @return void
506
+	 */
507
+	abstract public function admin_footer_scripts();
508
+
509
+
510
+	/**
511
+	 * admin_footer
512
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
513
+	 * apply to all pages/views loaded by child class.
514
+	 *
515
+	 * @return void
516
+	 */
517
+	public function admin_footer()
518
+	{
519
+	}
520
+
521
+
522
+	/**
523
+	 * _global_ajax_hooks
524
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
525
+	 * Note: within the ajax callback methods.
526
+	 *
527
+	 * @abstract
528
+	 * @return void
529
+	 */
530
+	protected function _global_ajax_hooks()
531
+	{
532
+		// for lazy loading of metabox content
533
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content']);
534
+
535
+		add_action(
536
+			'wp_ajax_espresso_hide_status_change_notice',
537
+			[$this, 'hideStatusChangeNotice']
538
+		);
539
+		add_action(
540
+			'wp_ajax_nopriv_espresso_hide_status_change_notice',
541
+			[$this, 'hideStatusChangeNotice']
542
+		);
543
+	}
544
+
545
+
546
+	public function ajax_metabox_content()
547
+	{
548
+		$content_id  = $this->request->getRequestParam('contentid', '');
549
+		$content_url = $this->request->getRequestParam('contenturl', '', DataType::URL);
550
+		EE_Admin_Page::cached_rss_display($content_id, $content_url);
551
+		wp_die();
552
+	}
553
+
554
+
555
+	public function hideStatusChangeNotice()
556
+	{
557
+		$response = [];
558
+		try {
559
+			/** @var StatusChangeNotice $status_change_notice */
560
+			$status_change_notice = $this->loader->getShared(
561
+				'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
562
+			);
563
+			$response['success']  = $status_change_notice->dismiss() > -1;
564
+		} catch (Exception $exception) {
565
+			$response['errors'] = $exception->getMessage();
566
+		}
567
+		wp_send_json($response);
568
+	}
569
+
570
+
571
+	/**
572
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
573
+	 *
574
+	 * @return void
575
+	 */
576
+	protected function _before_page_setup()
577
+	{
578
+		// default is to do nothing
579
+	}
580
+
581
+
582
+	/**
583
+	 * Makes sure any things that need to be loaded early get handled.
584
+	 * We also escape early here if the page requested doesn't match the object.
585
+	 *
586
+	 * @final
587
+	 * @return void
588
+	 * @throws EE_Error
589
+	 * @throws InvalidArgumentException
590
+	 * @throws ReflectionException
591
+	 * @throws InvalidDataTypeException
592
+	 * @throws InvalidInterfaceException
593
+	 * @throws Throwable
594
+	 */
595
+	final protected function _page_setup()
596
+	{
597
+		// requires?
598
+		// admin_init stuff - global - we're setting this REALLY early
599
+		// so if EE_Admin pages have to hook into other WP pages they can.
600
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
601
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
602
+		// next verify if we need to load anything...
603
+		$this->_current_page = $this->request->getRequestParam('page', '', DataType::KEY);
604
+		$this->_current_page = $this->request->getRequestParam('current_page', $this->_current_page, DataType::KEY);
605
+		$this->page_folder   = strtolower(
606
+			str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
607
+		);
608
+		global $ee_menu_slugs;
609
+		$ee_menu_slugs = (array) $ee_menu_slugs;
610
+		if (
611
+			! $this->request->isAjax()
612
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
613
+		) {
614
+			return;
615
+		}
616
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
617
+		// we need to copy the action from the second to the first
618
+		$action     = $this->request->getRequestParam('action', '-1', DataType::KEY);
619
+		$action2    = $this->request->getRequestParam('action2', '-1', DataType::KEY);
620
+		$action     = $action !== '-1' ? $action : $action2;
621
+		$req_action = $action !== '-1' ? $action : 'default';
622
+
623
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
624
+		// then let's use the route as the action.
625
+		// This covers cases where we're coming in from a list table that isn't on the default route.
626
+		$route = $this->request->getRequestParam('route');
627
+		$route = $route !== '-1' ? $route : 'default';
628
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
629
+			? $route
630
+			: $req_action;
631
+		$this->_current_view = $this->_req_action;
632
+		$this->_req_nonce    = $this->_req_action . '_nonce';
633
+		$this->_define_page_props();
634
+		$this->_current_page_view_url = add_query_arg(
635
+			['page' => $this->_current_page, 'action' => $this->_current_view],
636
+			$this->_admin_base_url
637
+		);
638
+		// set page configs
639
+		$this->_set_page_routes();
640
+		$this->_set_page_config();
641
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
642
+		if ($this->request->requestParamIsSet('wp_referer')) {
643
+			$wp_referer = $this->request->getRequestParam('wp_referer');
644
+			if ($wp_referer) {
645
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
646
+			}
647
+		}
648
+		// for CPT and other extended functionality.
649
+		// If there is an _extend_page_config_for_cpt
650
+		// then let's run that to modify all the various page configuration arrays.
651
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
652
+			$this->_extend_page_config_for_cpt();
653
+		}
654
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
655
+		$this->_page_routes = apply_filters(
656
+			'FHEE__' . $this->class_name . '__page_setup__page_routes',
657
+			$this->_page_routes,
658
+			$this
659
+		);
660
+		$this->_page_config = apply_filters(
661
+			'FHEE__' . $this->class_name . '__page_setup__page_config',
662
+			$this->_page_config,
663
+			$this
664
+		);
665
+		if ($this->base_class_name !== '') {
666
+			$this->_page_routes = apply_filters(
667
+				'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
668
+				$this->_page_routes,
669
+				$this
670
+			);
671
+			$this->_page_config = apply_filters(
672
+				'FHEE__' . $this->base_class_name . '__page_setup__page_config',
673
+				$this->_page_config,
674
+				$this
675
+			);
676
+		}
677
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
678
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
679
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
680
+			add_action(
681
+				'AHEE__EE_Admin_Page__route_admin_request',
682
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
683
+				10,
684
+				2
685
+			);
686
+		}
687
+		// next route only if routing enabled
688
+		if ($this->_routing && ! $this->request->isAjax()) {
689
+			$this->_verify_routes();
690
+			// next let's just check user_access and kill if no access
691
+			$this->check_user_access();
692
+			if ($this->_is_UI_request) {
693
+				// admin_init stuff - global, all views for this page class, specific view
694
+				add_action('admin_init', [$this, 'admin_init']);
695
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
696
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
697
+				}
698
+			} else {
699
+				// hijack regular WP loading and route admin request immediately
700
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
701
+				$this->route_admin_request();
702
+			}
703
+		}
704
+	}
705
+
706
+
707
+	/**
708
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
709
+	 *
710
+	 * @return void
711
+	 * @throws EE_Error
712
+	 */
713
+	private function _do_other_page_hooks()
714
+	{
715
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
716
+		foreach ($registered_pages as $page) {
717
+			// now let's set up the file name and class that should be present
718
+			$classname = str_replace('.class.php', '', $page);
719
+			// autoloaders should take care of loading file
720
+			if (! class_exists($classname)) {
721
+				$error_msg[] = sprintf(
722
+					esc_html__(
723
+						'Something went wrong with loading the %s admin hooks page.',
724
+						'event_espresso'
725
+					),
726
+					$page
727
+				);
728
+				$error_msg[] = $error_msg[0]
729
+							   . "\r\n"
730
+							   . sprintf(
731
+								   esc_html__(
732
+									   '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',
733
+									   'event_espresso'
734
+								   ),
735
+								   $page,
736
+								   '<br />',
737
+								   '<strong>' . $classname . '</strong>'
738
+							   );
739
+				throw new EE_Error(implode('||', $error_msg));
740
+			}
741
+			// don't load the same class twice
742
+			static $loaded = [];
743
+			if (in_array($classname, $loaded, true)) {
744
+				continue;
745
+			}
746
+			$loaded[] = $classname;
747
+			// notice we are passing the instance of this class to the hook object.
748
+			$this->loader->getShared($classname, [$this]);
749
+		}
750
+	}
751
+
752
+
753
+	/**
754
+	 * @throws ReflectionException
755
+	 * @throws EE_Error
756
+	 */
757
+	public function load_page_dependencies()
758
+	{
759
+		try {
760
+			$this->_load_page_dependencies();
761
+		} catch (EE_Error $e) {
762
+			$e->get_error();
763
+		}
764
+	}
765
+
766
+
767
+	/**
768
+	 * load_page_dependencies
769
+	 * loads things specific to this page class when it's loaded.  Really helps with efficiency.
770
+	 *
771
+	 * @return void
772
+	 * @throws DomainException
773
+	 * @throws EE_Error
774
+	 * @throws InvalidArgumentException
775
+	 * @throws InvalidDataTypeException
776
+	 * @throws InvalidInterfaceException
777
+	 * @throws ReflectionException
778
+	 */
779
+	protected function _load_page_dependencies()
780
+	{
781
+		// let's set the current_screen and screen options to override what WP set
782
+		$this->_current_screen = get_current_screen();
783
+		// load admin_notices - global, page class, and view specific
784
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
785
+		add_action('admin_notices', [$this, 'admin_notices']);
786
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
787
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
788
+		}
789
+		// load network admin_notices - global, page class, and view specific
790
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
791
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
792
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
793
+		}
794
+		// this will save any per_page screen options if they are present
795
+		$this->_set_per_page_screen_options();
796
+		// setup list table properties
797
+		$this->_set_list_table();
798
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
799
+		// However in some cases the metaboxes will need to be added within a route handling callback.
800
+		add_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
801
+		// hack because promos admin was loading the edited promotion object in the metaboxes callback
802
+		// which should NOT be generated on non-UI requests like POST updates/inserts
803
+		if (
804
+			$this->class_name === 'Promotions_Admin_Page'
805
+			&& ($this->_req_action === 'edit' || $this->_req_action === 'create_new')
806
+		) {
807
+			$this->addRegisteredMetaBoxes();
808
+		}
809
+		$this->_add_screen_columns();
810
+		// add screen options - global, page child class, and view specific
811
+		$this->_add_global_screen_options();
812
+		$this->_add_screen_options();
813
+		$add_screen_options = "_add_screen_options_$this->_current_view";
814
+		if (method_exists($this, $add_screen_options)) {
815
+			$this->{$add_screen_options}();
816
+		}
817
+		// add help tab(s) - set via page_config and qtips.
818
+		$this->_add_help_tabs();
819
+		$this->_add_qtips();
820
+		// add feature_pointers - global, page child class, and view specific
821
+		$this->_add_feature_pointers();
822
+		$this->_add_global_feature_pointers();
823
+		$add_feature_pointer = "_add_feature_pointer_$this->_current_view";
824
+		if (method_exists($this, $add_feature_pointer)) {
825
+			$this->{$add_feature_pointer}();
826
+		}
827
+		// enqueue scripts/styles - global, page class, and view specific
828
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 1);
829
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
830
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles']);
831
+		if (method_exists($this, "load_scripts_styles_$this->_current_view")) {
832
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_$this->_current_view"], 15);
833
+		}
834
+		// admin_print_footer_scripts - global, page child class, and view specific.
835
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
836
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
837
+		// is a good use case. Notice the late priority we're giving these
838
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
839
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
840
+		if (method_exists($this, "admin_footer_scripts_$this->_current_view")) {
841
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_$this->_current_view"], 101);
842
+		}
843
+		// admin footer scripts
844
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
845
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
846
+		if (method_exists($this, "admin_footer_$this->_current_view")) {
847
+			add_action('admin_footer', [$this, "admin_footer_$this->_current_view"], 101);
848
+		}
849
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
850
+		// targeted hook
851
+		do_action(
852
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__$this->_req_action"
853
+		);
854
+	}
855
+
856
+
857
+	/**
858
+	 * _set_defaults
859
+	 * This sets some global defaults for class properties.
860
+	 */
861
+	private function _set_defaults()
862
+	{
863
+		// init template args
864
+		$this->set_template_args(
865
+			[
866
+				'admin_page_header'  => '',
867
+				'admin_page_content' => '',
868
+				'post_body_content'  => '',
869
+				'before_list_table'  => '',
870
+				'after_list_table'   => '',
871
+			]
872
+		);
873
+	}
874
+
875
+
876
+	/**
877
+	 * route_admin_request
878
+	 *
879
+	 * @return void
880
+	 * @throws InvalidArgumentException
881
+	 * @throws InvalidInterfaceException
882
+	 * @throws InvalidDataTypeException
883
+	 * @throws EE_Error
884
+	 * @throws ReflectionException
885
+	 * @throws Throwable
886
+	 * @see    _route_admin_request()
887
+	 */
888
+	public function route_admin_request()
889
+	{
890
+		try {
891
+			$this->_route_admin_request();
892
+		} catch (EE_Error $e) {
893
+			$e->get_error();
894
+		}
895
+	}
896
+
897
+
898
+	public function set_wp_page_slug($wp_page_slug)
899
+	{
900
+		$this->_wp_page_slug = $wp_page_slug;
901
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
902
+		if (is_network_admin()) {
903
+			$this->_wp_page_slug .= '-network';
904
+		}
905
+	}
906
+
907
+
908
+	/**
909
+	 * _verify_routes
910
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
911
+	 * we know if we need to drop out.
912
+	 *
913
+	 * @return bool
914
+	 * @throws EE_Error
915
+	 */
916
+	protected function _verify_routes(): bool
917
+	{
918
+		if (! $this->_current_page && ! $this->request->isAjax()) {
919
+			return false;
920
+		}
921
+		// check that the page_routes array is not empty
922
+		if (empty($this->_page_routes)) {
923
+			// user error msg
924
+			$error_msg = sprintf(
925
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
926
+				$this->_admin_page_title
927
+			);
928
+			// developer error msg
929
+			$error_msg .= '||' . $error_msg
930
+						  . esc_html__(
931
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
932
+							  'event_espresso'
933
+						  );
934
+			throw new EE_Error($error_msg);
935
+		}
936
+		// route 'editpost' routes to CPT 'edit' routes
937
+		$alt_edit_route = $this instanceof EE_Admin_Page_CPT ? $this->cpt_editpost_route : 'edit';
938
+		if (
939
+			$this->_req_action === 'editpost'
940
+			&& ! isset($this->_page_routes['editpost'])
941
+			&& isset($this->_page_routes[$alt_edit_route])
942
+		) {
943
+			$this->_req_action = $alt_edit_route;
944
+		}
945
+		// and that the requested page route exists
946
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
947
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
948
+			$this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
949
+		} else {
950
+			// user error msg
951
+			$error_msg = sprintf(
952
+				esc_html__(
953
+					'The requested page route does not exist for the %s admin page.',
954
+					'event_espresso'
955
+				),
956
+				$this->_admin_page_title
957
+			);
958
+			// developer error msg
959
+			$error_msg .= '||' . $error_msg
960
+						  . sprintf(
961
+							  esc_html__(
962
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
963
+								  'event_espresso'
964
+							  ),
965
+							  $this->_req_action
966
+						  );
967
+			throw new EE_Error($error_msg);
968
+		}
969
+		// and that a default route exists
970
+		if (! array_key_exists('default', $this->_page_routes)) {
971
+			// user error msg
972
+			$error_msg = sprintf(
973
+				esc_html__(
974
+					'A default page route has not been set for the % admin page.',
975
+					'event_espresso'
976
+				),
977
+				$this->_admin_page_title
978
+			);
979
+			// developer error msg
980
+			$error_msg .= '||' . $error_msg
981
+						  . esc_html__(
982
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
983
+							  'event_espresso'
984
+						  );
985
+			throw new EE_Error($error_msg);
986
+		}
987
+
988
+		// first lets' catch if the UI request has EVER been set.
989
+		if ($this->_is_UI_request === null) {
990
+			// let's set if this is a UI request or not.
991
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, DataType::BOOL);
992
+			// wait a minute... we might have a noheader in the route array
993
+			$this->_is_UI_request = ! (isset($this->_route['noheader']) && $this->_route['noheader'])
994
+				? $this->_is_UI_request
995
+				: false;
996
+		}
997
+		$this->_set_current_labels();
998
+		return true;
999
+	}
1000
+
1001
+
1002
+	/**
1003
+	 * this method simply verifies a given route and makes sure it's an actual route available for the loaded page
1004
+	 *
1005
+	 * @param string $route the route name we're verifying
1006
+	 * @return bool we'll throw an exception if this isn't a valid route.
1007
+	 * @throws EE_Error
1008
+	 */
1009
+	protected function _verify_route(string $route): bool
1010
+	{
1011
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
1012
+			return true;
1013
+		}
1014
+		// user error msg
1015
+		$error_msg = sprintf(
1016
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1017
+			$this->_admin_page_title
1018
+		);
1019
+		// developer error msg
1020
+		$error_msg .= '||' . $error_msg
1021
+					  . sprintf(
1022
+						  esc_html__(
1023
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1024
+							  'event_espresso'
1025
+						  ),
1026
+						  $route
1027
+					  );
1028
+		throw new EE_Error($error_msg);
1029
+	}
1030
+
1031
+
1032
+	/**
1033
+	 * perform nonce verification
1034
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1035
+	 * using this method (and save retyping!)
1036
+	 *
1037
+	 * @param string $nonce     The nonce sent
1038
+	 * @param string $nonce_ref The nonce reference string (name0)
1039
+	 * @return void
1040
+	 * @throws EE_Error
1041
+	 * @throws InvalidArgumentException
1042
+	 * @throws InvalidDataTypeException
1043
+	 * @throws InvalidInterfaceException
1044
+	 */
1045
+	protected function _verify_nonce(string $nonce, string $nonce_ref)
1046
+	{
1047
+		// verify nonce against expected value
1048
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
1049
+			// these are not the droids you are looking for !!!
1050
+			$msg = sprintf(
1051
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
1052
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1053
+				'</a>'
1054
+			);
1055
+			if (WP_DEBUG) {
1056
+				$msg .= "\n  ";
1057
+				$msg .= sprintf(
1058
+					esc_html__(
1059
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1060
+						'event_espresso'
1061
+					),
1062
+					__CLASS__
1063
+				);
1064
+			}
1065
+			if (! $this->request->isAjax()) {
1066
+				wp_die($msg);
1067
+			}
1068
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1069
+			$this->_return_json();
1070
+		}
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * _route_admin_request()
1076
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1077
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1078
+	 * in the page routes and then will try to load the corresponding method.
1079
+	 *
1080
+	 * @return void
1081
+	 * @throws EE_Error
1082
+	 * @throws InvalidArgumentException
1083
+	 * @throws InvalidDataTypeException
1084
+	 * @throws InvalidInterfaceException
1085
+	 * @throws ReflectionException
1086
+	 * @throws Throwable
1087
+	 */
1088
+	protected function _route_admin_request()
1089
+	{
1090
+		if (! $this->_is_UI_request) {
1091
+			$this->_verify_routes();
1092
+		}
1093
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1094
+		if ($this->_req_action !== 'default' && $nonce_check) {
1095
+			// set nonce from post data
1096
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
1097
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1098
+		}
1099
+		// set the nav_tabs array but ONLY if this is  UI_request
1100
+		if ($this->_is_UI_request) {
1101
+			$this->_set_nav_tabs();
1102
+		}
1103
+		// grab callback function
1104
+		$func = $this->_route['func'] ?? $this->_route;
1105
+		// check if callback has args
1106
+		$args = $this->_route['args'] ?? [];
1107
+
1108
+		// action right before calling route
1109
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1110
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1111
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1112
+		}
1113
+		// strip _wp_http_referer from the server REQUEST_URI
1114
+		// else it grows in length on every submission due to recursion,
1115
+		// ultimately causing a "Request-URI Too Large" error
1116
+		$this->request->unSetRequestParam('_wp_http_referer');
1117
+		$this->request->unSetServerParam('_wp_http_referer');
1118
+		$cleaner_request_uri = remove_query_arg(
1119
+			'_wp_http_referer',
1120
+			wp_unslash($this->request->getServerParam('REQUEST_URI'))
1121
+		);
1122
+		$this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1123
+		$this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1124
+		$route_callback = [];
1125
+		if (! empty($func)) {
1126
+			if (is_array($func) && is_callable($func)) {
1127
+				$route_callback = $func;
1128
+			} elseif (is_string($func)) {
1129
+				if (strpos($func, '::') !== false) {
1130
+					$route_callback = explode('::', $func);
1131
+				} elseif (method_exists($this, $func)) {
1132
+					$route_callback = [$this, $func];
1133
+				} else {
1134
+					$route_callback = $func;
1135
+				}
1136
+			}
1137
+			[$class, $method] = $route_callback;
1138
+			// is it neither a class method NOR a standalone function?
1139
+			if (! is_callable($route_callback)) {
1140
+				// user error msg
1141
+				$error_msg = esc_html__(
1142
+					'An error occurred. The  requested page route could not be found.',
1143
+					'event_espresso'
1144
+				);
1145
+				// developer error msg
1146
+				$error_msg .= '||';
1147
+				$error_msg .= sprintf(
1148
+					esc_html__(
1149
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1150
+						'event_espresso'
1151
+					),
1152
+					$method
1153
+				);
1154
+				throw new DomainException($error_msg);
1155
+			}
1156
+			if ($class !== $this && ! in_array($this, $args)) {
1157
+				// send along this admin page object for access by addons.
1158
+				$args['admin_page'] = $this;
1159
+			}
1160
+
1161
+			call_user_func_array($route_callback, $args);
1162
+		}
1163
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1164
+		// then we need to reset the routing properties to the new route.
1165
+		// 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.
1166
+		if (
1167
+			$this->_is_UI_request === false
1168
+			&& is_array($this->_route)
1169
+			&& ! empty($this->_route['headers_sent_route'])
1170
+		) {
1171
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1172
+		}
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * This method just allows the resetting of page properties in the case where a no headers
1178
+	 * route redirects to a headers route in its route config.
1179
+	 *
1180
+	 * @param string $new_route New (non header) route to redirect to.
1181
+	 * @return void
1182
+	 * @throws ReflectionException
1183
+	 * @throws InvalidArgumentException
1184
+	 * @throws InvalidInterfaceException
1185
+	 * @throws InvalidDataTypeException
1186
+	 * @throws EE_Error
1187
+	 * @throws Throwable
1188
+	 * @since   4.3.0
1189
+	 */
1190
+	protected function _reset_routing_properties(string $new_route)
1191
+	{
1192
+		$this->_is_UI_request = true;
1193
+		// now we set the current route to whatever the headers_sent_route is set at
1194
+		$this->request->setRequestParam('action', $new_route);
1195
+		// rerun page setup
1196
+		$this->_page_setup();
1197
+	}
1198
+
1199
+
1200
+	/**
1201
+	 * _add_query_arg
1202
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1203
+	 *(internally just uses EEH_URL's function with the same name)
1204
+	 *
1205
+	 * @param array  $args
1206
+	 * @param string $url
1207
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1208
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1209
+	 *                                        Example usage: If the current page is:
1210
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1211
+	 *                                        &action=default&event_id=20&month_range=March%202015
1212
+	 *                                        &_wpnonce=5467821
1213
+	 *                                        and you call:
1214
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1215
+	 *                                        array(
1216
+	 *                                        'action' => 'resend_something',
1217
+	 *                                        'page=>espresso_registrations'
1218
+	 *                                        ),
1219
+	 *                                        $some_url,
1220
+	 *                                        true
1221
+	 *                                        );
1222
+	 *                                        It will produce a URL in this structure:
1223
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1224
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1225
+	 *                                        month_range]=March%202015
1226
+	 * @param bool   $exclude_nonce           If true, the nonce will be excluded from the generated nonce.
1227
+	 * @param int    $context
1228
+	 * @return string
1229
+	 */
1230
+	public static function add_query_args_and_nonce(
1231
+		array $args = [],
1232
+		string $url = '',
1233
+		bool $sticky = false,
1234
+		bool $exclude_nonce = false,
1235
+		int $context = EEH_URL::CONTEXT_NONE
1236
+	): string {
1237
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1238
+		if ($sticky) {
1239
+			/** @var RequestInterface $request */
1240
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1241
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1242
+			$request->unSetServerParam('_wp_http_referer', true);
1243
+			foreach ($request->requestParams() as $key => $value) {
1244
+				// do not add nonces
1245
+				if (strpos($key, 'nonce') !== false) {
1246
+					continue;
1247
+				}
1248
+				$args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1249
+			}
1250
+		}
1251
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce, $context);
1252
+	}
1253
+
1254
+
1255
+	/**
1256
+	 * This returns a generated link that will load the related help tab.
1257
+	 *
1258
+	 * @param string $help_tab_id the id for the connected help tab
1259
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1260
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1261
+	 * @return string              generated link
1262
+	 * @uses EEH_Template::get_help_tab_link()
1263
+	 */
1264
+	protected function _get_help_tab_link(string $help_tab_id, string $icon_style = '', string $help_text = ''): string
1265
+	{
1266
+		return EEH_Template::get_help_tab_link(
1267
+			$help_tab_id,
1268
+			$this->page_slug,
1269
+			$this->_req_action,
1270
+			$icon_style,
1271
+			$help_text
1272
+		);
1273
+	}
1274
+
1275
+
1276
+	/**
1277
+	 * _add_help_tabs
1278
+	 * Note child classes define their help tabs within the page_config array.
1279
+	 *
1280
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1281
+	 * @return void
1282
+	 * @throws DomainException
1283
+	 * @throws EE_Error
1284
+	 * @throws ReflectionException
1285
+	 */
1286
+	protected function _add_help_tabs()
1287
+	{
1288
+		if (isset($this->_page_config[ $this->_req_action ])) {
1289
+			$config = $this->_page_config[ $this->_req_action ];
1290
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1291
+			if (is_array($config) && isset($config['help_sidebar'])) {
1292
+				// check that the callback given is valid
1293
+				if (! method_exists($this, $config['help_sidebar'])) {
1294
+					throw new EE_Error(
1295
+						sprintf(
1296
+							esc_html__(
1297
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Double check the spelling and make sure this method exists for the class %s',
1298
+								'event_espresso'
1299
+							),
1300
+							$config['help_sidebar'],
1301
+							$this->class_name
1302
+						)
1303
+					);
1304
+				}
1305
+				$content = apply_filters(
1306
+					'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1307
+					$this->{$config['help_sidebar']}()
1308
+				);
1309
+				$this->_current_screen->set_help_sidebar($content);
1310
+			}
1311
+			if (! isset($config['help_tabs'])) {
1312
+				return;
1313
+			} //no help tabs for this route
1314
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1315
+				// we're here so there ARE help tabs!
1316
+				// make sure we've got what we need
1317
+				if (! isset($cfg['title'])) {
1318
+					throw new EE_Error(
1319
+						esc_html__(
1320
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1321
+							'event_espresso'
1322
+						)
1323
+					);
1324
+				}
1325
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1326
+					throw new EE_Error(
1327
+						esc_html__(
1328
+							'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',
1329
+							'event_espresso'
1330
+						)
1331
+					);
1332
+				}
1333
+				// first priority goes to content.
1334
+				if (! empty($cfg['content'])) {
1335
+					$content = $cfg['content'];
1336
+					// second priority goes to filename
1337
+				} elseif (! empty($cfg['filename'])) {
1338
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1339
+					// 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)
1340
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1341
+															 . basename($this->_get_dir())
1342
+															 . '/help_tabs/'
1343
+															 . $cfg['filename']
1344
+															 . '.help_tab.php' : $file_path;
1345
+					// if file is STILL not readable then let's do an EE_Error so its more graceful than a fatal error.
1346
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1347
+						EE_Error::add_error(
1348
+							sprintf(
1349
+								esc_html__(
1350
+									'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',
1351
+									'event_espresso'
1352
+								),
1353
+								$tab_id,
1354
+								key($config),
1355
+								$file_path
1356
+							),
1357
+							__FILE__,
1358
+							__FUNCTION__,
1359
+							__LINE__
1360
+						);
1361
+						return;
1362
+					}
1363
+					$template_args['admin_page_obj'] = $this;
1364
+					$content                         = EEH_Template::display_template(
1365
+						$file_path,
1366
+						$template_args,
1367
+						true
1368
+					);
1369
+				} else {
1370
+					$content = '';
1371
+				}
1372
+				// check if callback is valid
1373
+				if (
1374
+					empty($content)
1375
+					&& (
1376
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1377
+					)
1378
+				) {
1379
+					EE_Error::add_error(
1380
+						sprintf(
1381
+							esc_html__(
1382
+								'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.',
1383
+								'event_espresso'
1384
+							),
1385
+							$cfg['title']
1386
+						),
1387
+						__FILE__,
1388
+						__FUNCTION__,
1389
+						__LINE__
1390
+					);
1391
+					return;
1392
+				}
1393
+				// setup config array for help tab method
1394
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1395
+				$_ht = [
1396
+					'id'       => $id,
1397
+					'title'    => $cfg['title'],
1398
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1399
+					'content'  => $content,
1400
+				];
1401
+				$this->_current_screen->add_help_tab($_ht);
1402
+			}
1403
+		}
1404
+	}
1405
+
1406
+
1407
+	/**
1408
+	 * This simply sets up any qtips that have been defined in the page config
1409
+	 *
1410
+	 * @return void
1411
+	 * @throws ReflectionException
1412
+	 * @throws EE_Error
1413
+	 */
1414
+	protected function _add_qtips()
1415
+	{
1416
+		if (isset($this->_route_config['qtips'])) {
1417
+			$qtips = (array) $this->_route_config['qtips'];
1418
+			// load qtip loader
1419
+			$path = [
1420
+				$this->_get_dir() . '/qtips/',
1421
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1422
+			];
1423
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1424
+		}
1425
+	}
1426
+
1427
+
1428
+	/**
1429
+	 * _set_nav_tabs
1430
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1431
+	 * wish to add additional tabs or modify accordingly.
1432
+	 *
1433
+	 * @return void
1434
+	 * @throws InvalidArgumentException
1435
+	 * @throws InvalidInterfaceException
1436
+	 * @throws InvalidDataTypeException
1437
+	 */
1438
+	protected function _set_nav_tabs()
1439
+	{
1440
+		$i        = 0;
1441
+		$only_tab = count($this->_page_config) < 2;
1442
+		foreach ($this->_page_config as $slug => $config) {
1443
+			if (! is_array($config) || empty($config['nav'])) {
1444
+				continue;
1445
+			}
1446
+			// no nav tab for this config
1447
+			// check for persistent flag
1448
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1449
+				// nav tab is only to appear when route requested.
1450
+				continue;
1451
+			}
1452
+			if (! $this->check_user_access($slug, true)) {
1453
+				// no nav tab because current user does not have access.
1454
+				continue;
1455
+			}
1456
+			$css_class = $config['css_class'] ?? '';
1457
+			$css_class .= $only_tab ? ' ee-only-tab' : '';
1458
+			$css_class .= " ee-nav-tab__$slug";
1459
+
1460
+			$this->_nav_tabs[ $slug ] = [
1461
+				'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1462
+						['action' => $slug],
1463
+						$this->_admin_base_url
1464
+					),
1465
+				'link_text' => $this->navTabLabel($config['nav'], $slug),
1466
+				'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1467
+				'order'     => $config['nav']['order'] ?? $i,
1468
+			];
1469
+			$i++;
1470
+		}
1471
+		// if $this->_nav_tabs is empty then lets set the default
1472
+		if (empty($this->_nav_tabs)) {
1473
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1474
+				'url'       => $this->_admin_base_url,
1475
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1476
+				'css_class' => 'nav-tab-active',
1477
+				'order'     => 10,
1478
+			];
1479
+		}
1480
+		// now let's sort the tabs according to order
1481
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1482
+	}
1483
+
1484
+
1485
+	private function navTabLabel(array $nav_tab, string $slug): string
1486
+	{
1487
+		$label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1488
+		$icon  = $nav_tab['icon'] ?? null;
1489
+		$icon  = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1490
+		return '
1491 1491
             <span class="ee-admin-screen-tab__label">
1492 1492
                 ' . $icon . '
1493 1493
                 <span class="ee-nav-label__text">' . $label . '</span>
1494 1494
             </span>';
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * _set_current_labels
1500
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1501
-     * property array
1502
-     *
1503
-     * @return void
1504
-     */
1505
-    private function _set_current_labels()
1506
-    {
1507
-        if (isset($this->_route_config['labels'])) {
1508
-            foreach ($this->_route_config['labels'] as $label => $text) {
1509
-                if (is_array($text)) {
1510
-                    foreach ($text as $sublabel => $subtext) {
1511
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1512
-                    }
1513
-                } else {
1514
-                    $this->_labels[ $label ] = $text;
1515
-                }
1516
-            }
1517
-        }
1518
-    }
1519
-
1520
-
1521
-    /**
1522
-     *        verifies user access for this admin page
1523
-     *
1524
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1525
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1526
-     *                               return false if verify fail.
1527
-     * @return bool
1528
-     * @throws InvalidArgumentException
1529
-     * @throws InvalidDataTypeException
1530
-     * @throws InvalidInterfaceException
1531
-     */
1532
-    public function check_user_access(string $route_to_check = '', bool $verify_only = false): bool
1533
-    {
1534
-        // if no route_to_check is passed in then use the current route set via _req_action
1535
-        $action = $route_to_check ?: $this->_req_action;
1536
-        $capability = ! empty($this->_page_routes[ $action ]['capability'])
1537
-            ? $this->_page_routes[ $action ]['capability']
1538
-            : null;
1539
-
1540
-        if (empty($capability)) {
1541
-            $capability = empty($route_to_check) && ! empty($this->_route['capability'])
1542
-                ? $this->_route['capability']
1543
-                : 'manage_options';
1544
-        }
1545
-
1546
-        $id = $this->_route['obj_id'] ?? 0;
1547
-
1548
-        if (
1549
-            ! $this->request->isAjax()
1550
-            && (
1551
-                ! function_exists('is_admin')
1552
-                || ! $this->capabilities->current_user_can($capability, "{$this->page_slug}_$route_to_check", $id)
1553
-            )
1554
-        ) {
1555
-            if ($verify_only) {
1556
-                return false;
1557
-            }
1558
-            if (is_user_logged_in()) {
1559
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1560
-            }
1561
-            return false;
1562
-        }
1563
-        return true;
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * @param string                 $box_id
1569
-     * @param string                 $title
1570
-     * @param callable|string|null   $callback
1571
-     * @param string|array|WP_Screen $screen
1572
-     * @param string                 $context       Post edit screen contexts include 'normal', 'side', and 'advanced'.
1573
-     *                                              Comments screen contexts include 'normal' and 'side'.
1574
-     *                                              Menus meta boxes (accordion sections) all use the 'side' context.
1575
-     * @param string                 $priority      Accepts 'high', 'core', 'default', or 'low'.
1576
-     * @param array|null             $callback_args
1577
-     */
1578
-    protected function addMetaBox(
1579
-        string $box_id,
1580
-        string $title,
1581
-        $callback,
1582
-        $screen,
1583
-        string $context = 'normal',
1584
-        string $priority = 'default',
1585
-        ?array $callback_args = null
1586
-    ) {
1587
-        if (! (is_callable($callback) || ! function_exists($callback))) {
1588
-            return;
1589
-        }
1590
-
1591
-        add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1592
-        add_filter(
1593
-            "postbox_classes_{$this->_wp_page_slug}_$box_id",
1594
-            function ($classes) {
1595
-                $classes[] = 'ee-admin-container';
1596
-                return $classes;
1597
-            }
1598
-        );
1599
-    }
1600
-
1601
-
1602
-    /**
1603
-     * admin_init_global
1604
-     * This runs all the code that we want executed within the WP admin_init hook.
1605
-     * This method executes for ALL EE Admin pages.
1606
-     *
1607
-     * @return void
1608
-     */
1609
-    public function admin_init_global()
1610
-    {
1611
-    }
1612
-
1613
-
1614
-    /**
1615
-     * wp_loaded_global
1616
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1617
-     * EE_Admin page and will execute on every EE Admin Page load
1618
-     *
1619
-     * @return void
1620
-     */
1621
-    public function wp_loaded()
1622
-    {
1623
-    }
1624
-
1625
-
1626
-    /**
1627
-     * admin_notices
1628
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1629
-     * ALL EE_Admin pages.
1630
-     *
1631
-     * @return void
1632
-     */
1633
-    public function admin_notices_global()
1634
-    {
1635
-        $this->_display_no_javascript_warning();
1636
-        $this->_display_espresso_notices();
1637
-    }
1638
-
1639
-
1640
-    public function network_admin_notices_global()
1641
-    {
1642
-        $this->_display_no_javascript_warning();
1643
-        $this->_display_espresso_notices();
1644
-    }
1645
-
1646
-
1647
-    /**
1648
-     * admin_footer_scripts_global
1649
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1650
-     * will apply on ALL EE_Admin pages.
1651
-     *
1652
-     * @return void
1653
-     */
1654
-    public function admin_footer_scripts_global()
1655
-    {
1656
-        $this->_add_admin_page_ajax_loading_img();
1657
-        $this->_add_admin_page_overlay();
1658
-        // if metaboxes are present we need to add the nonce field
1659
-        if (
1660
-            isset($this->_route_config['metaboxes'])
1661
-            || isset($this->_route_config['list_table'])
1662
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1663
-        ) {
1664
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1665
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1666
-        }
1667
-    }
1668
-
1669
-
1670
-    /**
1671
-     * admin_footer_global
1672
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1673
-     * This particular method will apply on ALL EE_Admin Pages.
1674
-     *
1675
-     * @return void
1676
-     */
1677
-    public function admin_footer_global()
1678
-    {
1679
-        // dialog container for dialog helper
1680
-        echo '
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * _set_current_labels
1500
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1501
+	 * property array
1502
+	 *
1503
+	 * @return void
1504
+	 */
1505
+	private function _set_current_labels()
1506
+	{
1507
+		if (isset($this->_route_config['labels'])) {
1508
+			foreach ($this->_route_config['labels'] as $label => $text) {
1509
+				if (is_array($text)) {
1510
+					foreach ($text as $sublabel => $subtext) {
1511
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1512
+					}
1513
+				} else {
1514
+					$this->_labels[ $label ] = $text;
1515
+				}
1516
+			}
1517
+		}
1518
+	}
1519
+
1520
+
1521
+	/**
1522
+	 *        verifies user access for this admin page
1523
+	 *
1524
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1525
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1526
+	 *                               return false if verify fail.
1527
+	 * @return bool
1528
+	 * @throws InvalidArgumentException
1529
+	 * @throws InvalidDataTypeException
1530
+	 * @throws InvalidInterfaceException
1531
+	 */
1532
+	public function check_user_access(string $route_to_check = '', bool $verify_only = false): bool
1533
+	{
1534
+		// if no route_to_check is passed in then use the current route set via _req_action
1535
+		$action = $route_to_check ?: $this->_req_action;
1536
+		$capability = ! empty($this->_page_routes[ $action ]['capability'])
1537
+			? $this->_page_routes[ $action ]['capability']
1538
+			: null;
1539
+
1540
+		if (empty($capability)) {
1541
+			$capability = empty($route_to_check) && ! empty($this->_route['capability'])
1542
+				? $this->_route['capability']
1543
+				: 'manage_options';
1544
+		}
1545
+
1546
+		$id = $this->_route['obj_id'] ?? 0;
1547
+
1548
+		if (
1549
+			! $this->request->isAjax()
1550
+			&& (
1551
+				! function_exists('is_admin')
1552
+				|| ! $this->capabilities->current_user_can($capability, "{$this->page_slug}_$route_to_check", $id)
1553
+			)
1554
+		) {
1555
+			if ($verify_only) {
1556
+				return false;
1557
+			}
1558
+			if (is_user_logged_in()) {
1559
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1560
+			}
1561
+			return false;
1562
+		}
1563
+		return true;
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * @param string                 $box_id
1569
+	 * @param string                 $title
1570
+	 * @param callable|string|null   $callback
1571
+	 * @param string|array|WP_Screen $screen
1572
+	 * @param string                 $context       Post edit screen contexts include 'normal', 'side', and 'advanced'.
1573
+	 *                                              Comments screen contexts include 'normal' and 'side'.
1574
+	 *                                              Menus meta boxes (accordion sections) all use the 'side' context.
1575
+	 * @param string                 $priority      Accepts 'high', 'core', 'default', or 'low'.
1576
+	 * @param array|null             $callback_args
1577
+	 */
1578
+	protected function addMetaBox(
1579
+		string $box_id,
1580
+		string $title,
1581
+		$callback,
1582
+		$screen,
1583
+		string $context = 'normal',
1584
+		string $priority = 'default',
1585
+		?array $callback_args = null
1586
+	) {
1587
+		if (! (is_callable($callback) || ! function_exists($callback))) {
1588
+			return;
1589
+		}
1590
+
1591
+		add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1592
+		add_filter(
1593
+			"postbox_classes_{$this->_wp_page_slug}_$box_id",
1594
+			function ($classes) {
1595
+				$classes[] = 'ee-admin-container';
1596
+				return $classes;
1597
+			}
1598
+		);
1599
+	}
1600
+
1601
+
1602
+	/**
1603
+	 * admin_init_global
1604
+	 * This runs all the code that we want executed within the WP admin_init hook.
1605
+	 * This method executes for ALL EE Admin pages.
1606
+	 *
1607
+	 * @return void
1608
+	 */
1609
+	public function admin_init_global()
1610
+	{
1611
+	}
1612
+
1613
+
1614
+	/**
1615
+	 * wp_loaded_global
1616
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1617
+	 * EE_Admin page and will execute on every EE Admin Page load
1618
+	 *
1619
+	 * @return void
1620
+	 */
1621
+	public function wp_loaded()
1622
+	{
1623
+	}
1624
+
1625
+
1626
+	/**
1627
+	 * admin_notices
1628
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1629
+	 * ALL EE_Admin pages.
1630
+	 *
1631
+	 * @return void
1632
+	 */
1633
+	public function admin_notices_global()
1634
+	{
1635
+		$this->_display_no_javascript_warning();
1636
+		$this->_display_espresso_notices();
1637
+	}
1638
+
1639
+
1640
+	public function network_admin_notices_global()
1641
+	{
1642
+		$this->_display_no_javascript_warning();
1643
+		$this->_display_espresso_notices();
1644
+	}
1645
+
1646
+
1647
+	/**
1648
+	 * admin_footer_scripts_global
1649
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1650
+	 * will apply on ALL EE_Admin pages.
1651
+	 *
1652
+	 * @return void
1653
+	 */
1654
+	public function admin_footer_scripts_global()
1655
+	{
1656
+		$this->_add_admin_page_ajax_loading_img();
1657
+		$this->_add_admin_page_overlay();
1658
+		// if metaboxes are present we need to add the nonce field
1659
+		if (
1660
+			isset($this->_route_config['metaboxes'])
1661
+			|| isset($this->_route_config['list_table'])
1662
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1663
+		) {
1664
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1665
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1666
+		}
1667
+	}
1668
+
1669
+
1670
+	/**
1671
+	 * admin_footer_global
1672
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1673
+	 * This particular method will apply on ALL EE_Admin Pages.
1674
+	 *
1675
+	 * @return void
1676
+	 */
1677
+	public function admin_footer_global()
1678
+	{
1679
+		// dialog container for dialog helper
1680
+		echo '
1681 1681
         <div class="ee-admin-dialog-container auto-hide hidden">
1682 1682
             <div class="ee-notices"></div>
1683 1683
             <div class="ee-admin-dialog-container-inner-content"></div>
1684 1684
         </div>
1685 1685
         <span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>
1686 1686
         <input type="hidden" id="espresso_admin_current_page" value="' . esc_attr($this->_current_page) . '"/>';
1687
-    }
1688
-
1689
-
1690
-    /**
1691
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1692
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1693
-     * help popups then in your templates or your content you set "triggers" for the content using the
1694
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1695
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1696
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1697
-     * for the
1698
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1699
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1700
-     *    'help_trigger_id' => array(
1701
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1702
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1703
-     *    )
1704
-     * );
1705
-     * Then the EE_Admin_Parent will take care of making sure that is set up properly on the correct route.
1706
-     *
1707
-     * @param array $help_array
1708
-     * @param bool  $display
1709
-     * @return string content
1710
-     * @throws DomainException
1711
-     * @throws EE_Error
1712
-     */
1713
-    protected function _set_help_popup_content(array $help_array = [], bool $display = false): string
1714
-    {
1715
-        $content    = '';
1716
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1717
-        // loop through the array and setup content
1718
-        foreach ($help_array as $trigger => $help) {
1719
-            // make sure the array is set up properly
1720
-            if (! isset($help['title'], $help['content'])) {
1721
-                throw new EE_Error(
1722
-                    esc_html__(
1723
-                        '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',
1724
-                        'event_espresso'
1725
-                    )
1726
-                );
1727
-            }
1728
-            // we're good so let's set up the template vars and then assign parsed template content to our content.
1729
-            $template_args = [
1730
-                'help_popup_id'      => $trigger,
1731
-                'help_popup_title'   => $help['title'],
1732
-                'help_popup_content' => $help['content'],
1733
-            ];
1734
-            $content       .= EEH_Template::display_template(
1735
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1736
-                $template_args,
1737
-                true
1738
-            );
1739
-        }
1740
-        if ($display) {
1741
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1742
-            return '';
1743
-        }
1744
-        return $content;
1745
-    }
1746
-
1747
-
1748
-    /**
1749
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1750
-     *
1751
-     * @return array properly formatted array for help popup content
1752
-     * @throws EE_Error
1753
-     */
1754
-    private function _get_help_content(): array
1755
-    {
1756
-        // what is the method we're looking for?
1757
-        $method_name = '_help_popup_content_' . $this->_req_action;
1758
-        // if method doesn't exist let's get out.
1759
-        if (! method_exists($this, $method_name)) {
1760
-            return [];
1761
-        }
1762
-        // k we're good to go let's retrieve the help array
1763
-        $help_array = $this->{$method_name}();
1764
-        // make sure we've got an array!
1765
-        if (! is_array($help_array)) {
1766
-            throw new EE_Error(
1767
-                esc_html__(
1768
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1769
-                    'event_espresso'
1770
-                )
1771
-            );
1772
-        }
1773
-        return $help_array;
1774
-    }
1775
-
1776
-
1777
-    /**
1778
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1779
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1780
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1781
-     *
1782
-     * @param string $trigger_id reference for retrieving the trigger content for the popup
1783
-     * @param bool   $display    if false then we return the trigger string
1784
-     * @param array  $dimensions an array of dimensions for the box (array(h,w))
1785
-     * @return string
1786
-     * @throws DomainException
1787
-     * @throws EE_Error
1788
-     */
1789
-    protected function _set_help_trigger(string $trigger_id, bool $display = true, array $dimensions = ['400', '640'])
1790
-    {
1791
-        if ($this->request->isAjax()) {
1792
-            return '';
1793
-        }
1794
-        // 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
1795
-        $help_array   = $this->_get_help_content();
1796
-        $help_content = '';
1797
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1798
-            $help_array[ $trigger_id ] = [
1799
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1800
-                'content' => esc_html__(
1801
-                    '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.)',
1802
-                    'event_espresso'
1803
-                ),
1804
-            ];
1805
-            $help_content              = $this->_set_help_popup_content($help_array);
1806
-        }
1807
-        $height   = esc_attr($dimensions[0]) ?? 400;
1808
-        $width    = esc_attr($dimensions[1]) ?? 640;
1809
-        $inlineId = esc_attr($trigger_id);
1810
-        // let's setup the trigger
1811
-        $content = "
1687
+	}
1688
+
1689
+
1690
+	/**
1691
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1692
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1693
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1694
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1695
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1696
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1697
+	 * for the
1698
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1699
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1700
+	 *    'help_trigger_id' => array(
1701
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1702
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1703
+	 *    )
1704
+	 * );
1705
+	 * Then the EE_Admin_Parent will take care of making sure that is set up properly on the correct route.
1706
+	 *
1707
+	 * @param array $help_array
1708
+	 * @param bool  $display
1709
+	 * @return string content
1710
+	 * @throws DomainException
1711
+	 * @throws EE_Error
1712
+	 */
1713
+	protected function _set_help_popup_content(array $help_array = [], bool $display = false): string
1714
+	{
1715
+		$content    = '';
1716
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1717
+		// loop through the array and setup content
1718
+		foreach ($help_array as $trigger => $help) {
1719
+			// make sure the array is set up properly
1720
+			if (! isset($help['title'], $help['content'])) {
1721
+				throw new EE_Error(
1722
+					esc_html__(
1723
+						'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',
1724
+						'event_espresso'
1725
+					)
1726
+				);
1727
+			}
1728
+			// we're good so let's set up the template vars and then assign parsed template content to our content.
1729
+			$template_args = [
1730
+				'help_popup_id'      => $trigger,
1731
+				'help_popup_title'   => $help['title'],
1732
+				'help_popup_content' => $help['content'],
1733
+			];
1734
+			$content       .= EEH_Template::display_template(
1735
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1736
+				$template_args,
1737
+				true
1738
+			);
1739
+		}
1740
+		if ($display) {
1741
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1742
+			return '';
1743
+		}
1744
+		return $content;
1745
+	}
1746
+
1747
+
1748
+	/**
1749
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1750
+	 *
1751
+	 * @return array properly formatted array for help popup content
1752
+	 * @throws EE_Error
1753
+	 */
1754
+	private function _get_help_content(): array
1755
+	{
1756
+		// what is the method we're looking for?
1757
+		$method_name = '_help_popup_content_' . $this->_req_action;
1758
+		// if method doesn't exist let's get out.
1759
+		if (! method_exists($this, $method_name)) {
1760
+			return [];
1761
+		}
1762
+		// k we're good to go let's retrieve the help array
1763
+		$help_array = $this->{$method_name}();
1764
+		// make sure we've got an array!
1765
+		if (! is_array($help_array)) {
1766
+			throw new EE_Error(
1767
+				esc_html__(
1768
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1769
+					'event_espresso'
1770
+				)
1771
+			);
1772
+		}
1773
+		return $help_array;
1774
+	}
1775
+
1776
+
1777
+	/**
1778
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1779
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1780
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1781
+	 *
1782
+	 * @param string $trigger_id reference for retrieving the trigger content for the popup
1783
+	 * @param bool   $display    if false then we return the trigger string
1784
+	 * @param array  $dimensions an array of dimensions for the box (array(h,w))
1785
+	 * @return string
1786
+	 * @throws DomainException
1787
+	 * @throws EE_Error
1788
+	 */
1789
+	protected function _set_help_trigger(string $trigger_id, bool $display = true, array $dimensions = ['400', '640'])
1790
+	{
1791
+		if ($this->request->isAjax()) {
1792
+			return '';
1793
+		}
1794
+		// 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
1795
+		$help_array   = $this->_get_help_content();
1796
+		$help_content = '';
1797
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1798
+			$help_array[ $trigger_id ] = [
1799
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1800
+				'content' => esc_html__(
1801
+					'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.)',
1802
+					'event_espresso'
1803
+				),
1804
+			];
1805
+			$help_content              = $this->_set_help_popup_content($help_array);
1806
+		}
1807
+		$height   = esc_attr($dimensions[0]) ?? 400;
1808
+		$width    = esc_attr($dimensions[1]) ?? 640;
1809
+		$inlineId = esc_attr($trigger_id);
1810
+		// let's setup the trigger
1811
+		$content = "
1812 1812
         <a class='ee-dialog' href='?height=$height&width=$width&inlineId=$inlineId' target='_blank'>
1813 1813
             <span class='question ee-help-popup-question'></span>
1814 1814
         </a>";
1815
-        $content .= $help_content;
1816
-        if ($display) {
1817
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1818
-            return '';
1819
-        }
1820
-        return $content;
1821
-    }
1822
-
1823
-
1824
-    /**
1825
-     * _add_global_screen_options
1826
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1827
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1828
-     *
1829
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1830
-     *         see also WP_Screen object documents...
1831
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1832
-     * @abstract
1833
-     * @return void
1834
-     */
1835
-    private function _add_global_screen_options()
1836
-    {
1837
-    }
1838
-
1839
-
1840
-    /**
1841
-     * _add_global_feature_pointers
1842
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1843
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1844
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1845
-     *
1846
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
1847
-     *         extended) also see:
1848
-     * @link   http://eamann.com/tech/wordpress-portland/
1849
-     * @abstract
1850
-     * @return void
1851
-     */
1852
-    private function _add_global_feature_pointers()
1853
-    {
1854
-    }
1855
-
1856
-
1857
-    /**
1858
-     * load_global_scripts_styles
1859
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1860
-     *
1861
-     * @return void
1862
-     */
1863
-    public function load_global_scripts_styles()
1864
-    {
1865
-        // add debugging styles
1866
-        if (WP_DEBUG) {
1867
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1868
-        }
1869
-        // taking care of metaboxes
1870
-        if (
1871
-            empty($this->_cpt_route)
1872
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1873
-        ) {
1874
-            wp_enqueue_script('dashboard');
1875
-        }
1876
-
1877
-        wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1878
-        wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1879
-        // LOCALIZED DATA
1880
-        // localize script for ajax lazy loading
1881
-        wp_localize_script(
1882
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1883
-            'eeLazyLoadingContainers',
1884
-            apply_filters(
1885
-                'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1886
-                ['espresso_news_post_box_content']
1887
-            )
1888
-        );
1889
-        StatusChangeNotice::loadAssets();
1890
-
1891
-        add_filter(
1892
-            'admin_body_class',
1893
-            function ($classes) {
1894
-                if (strpos($classes, 'espresso-admin') === false) {
1895
-                    $classes .= ' espresso-admin';
1896
-                }
1897
-                return $classes;
1898
-            }
1899
-        );
1900
-    }
1901
-
1902
-
1903
-    /**
1904
-     *        admin_footer_scripts_eei18n_js_strings
1905
-     *
1906
-     * @return        void
1907
-     */
1908
-    public function admin_footer_scripts_eei18n_js_strings()
1909
-    {
1910
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1911
-            __(
1912
-                '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!!!',
1913
-                'event_espresso'
1914
-            )
1915
-        );
1916
-        // now add months and days of the week
1917
-        EE_Registry::$i18n_js_strings['January']   = wp_strip_all_tags(__('January', 'event_espresso'));
1918
-        EE_Registry::$i18n_js_strings['February']  = wp_strip_all_tags(__('February', 'event_espresso'));
1919
-        EE_Registry::$i18n_js_strings['March']     = wp_strip_all_tags(__('March', 'event_espresso'));
1920
-        EE_Registry::$i18n_js_strings['April']     = wp_strip_all_tags(__('April', 'event_espresso'));
1921
-        EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1922
-        EE_Registry::$i18n_js_strings['June']      = wp_strip_all_tags(__('June', 'event_espresso'));
1923
-        EE_Registry::$i18n_js_strings['July']      = wp_strip_all_tags(__('July', 'event_espresso'));
1924
-        EE_Registry::$i18n_js_strings['August']    = wp_strip_all_tags(__('August', 'event_espresso'));
1925
-        EE_Registry::$i18n_js_strings['September'] = wp_strip_all_tags(__('September', 'event_espresso'));
1926
-        EE_Registry::$i18n_js_strings['October']   = wp_strip_all_tags(__('October', 'event_espresso'));
1927
-        EE_Registry::$i18n_js_strings['November']  = wp_strip_all_tags(__('November', 'event_espresso'));
1928
-        EE_Registry::$i18n_js_strings['December']  = wp_strip_all_tags(__('December', 'event_espresso'));
1929
-        EE_Registry::$i18n_js_strings['Jan']       = wp_strip_all_tags(__('Jan', 'event_espresso'));
1930
-        EE_Registry::$i18n_js_strings['Feb']       = wp_strip_all_tags(__('Feb', 'event_espresso'));
1931
-        EE_Registry::$i18n_js_strings['Mar']       = wp_strip_all_tags(__('Mar', 'event_espresso'));
1932
-        EE_Registry::$i18n_js_strings['Apr']       = wp_strip_all_tags(__('Apr', 'event_espresso'));
1933
-        EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1934
-        EE_Registry::$i18n_js_strings['Jun']       = wp_strip_all_tags(__('Jun', 'event_espresso'));
1935
-        EE_Registry::$i18n_js_strings['Jul']       = wp_strip_all_tags(__('Jul', 'event_espresso'));
1936
-        EE_Registry::$i18n_js_strings['Aug']       = wp_strip_all_tags(__('Aug', 'event_espresso'));
1937
-        EE_Registry::$i18n_js_strings['Sep']       = wp_strip_all_tags(__('Sep', 'event_espresso'));
1938
-        EE_Registry::$i18n_js_strings['Oct']       = wp_strip_all_tags(__('Oct', 'event_espresso'));
1939
-        EE_Registry::$i18n_js_strings['Nov']       = wp_strip_all_tags(__('Nov', 'event_espresso'));
1940
-        EE_Registry::$i18n_js_strings['Dec']       = wp_strip_all_tags(__('Dec', 'event_espresso'));
1941
-        EE_Registry::$i18n_js_strings['Sunday']    = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1942
-        EE_Registry::$i18n_js_strings['Monday']    = wp_strip_all_tags(__('Monday', 'event_espresso'));
1943
-        EE_Registry::$i18n_js_strings['Tuesday']   = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1944
-        EE_Registry::$i18n_js_strings['Wednesday'] = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1945
-        EE_Registry::$i18n_js_strings['Thursday']  = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1946
-        EE_Registry::$i18n_js_strings['Friday']    = wp_strip_all_tags(__('Friday', 'event_espresso'));
1947
-        EE_Registry::$i18n_js_strings['Saturday']  = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1948
-        EE_Registry::$i18n_js_strings['Sun']       = wp_strip_all_tags(__('Sun', 'event_espresso'));
1949
-        EE_Registry::$i18n_js_strings['Mon']       = wp_strip_all_tags(__('Mon', 'event_espresso'));
1950
-        EE_Registry::$i18n_js_strings['Tue']       = wp_strip_all_tags(__('Tue', 'event_espresso'));
1951
-        EE_Registry::$i18n_js_strings['Wed']       = wp_strip_all_tags(__('Wed', 'event_espresso'));
1952
-        EE_Registry::$i18n_js_strings['Thu']       = wp_strip_all_tags(__('Thu', 'event_espresso'));
1953
-        EE_Registry::$i18n_js_strings['Fri']       = wp_strip_all_tags(__('Fri', 'event_espresso'));
1954
-        EE_Registry::$i18n_js_strings['Sat']       = wp_strip_all_tags(__('Sat', 'event_espresso'));
1955
-    }
1956
-
1957
-
1958
-    /**
1959
-     *        load enhanced xdebug styles for ppl with failing eyesight
1960
-     *
1961
-     * @return        void
1962
-     */
1963
-    public function add_xdebug_style()
1964
-    {
1965
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1966
-    }
1967
-
1968
-
1969
-    /************************/
1970
-    /** LIST TABLE METHODS **/
1971
-    /************************/
1972
-    /**
1973
-     * this sets up the list table if the current view requires it.
1974
-     *
1975
-     * @return void
1976
-     * @throws EE_Error
1977
-     * @throws InvalidArgumentException
1978
-     * @throws InvalidDataTypeException
1979
-     * @throws InvalidInterfaceException
1980
-     */
1981
-    protected function _set_list_table()
1982
-    {
1983
-        // first is this a list_table view?
1984
-        if (! isset($this->_route_config['list_table'])) {
1985
-            return;
1986
-        } //not a list_table view so get out.
1987
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
1988
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
1989
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1990
-            // user error msg
1991
-            $error_msg = esc_html__(
1992
-                'An error occurred. The requested list table views could not be found.',
1993
-                'event_espresso'
1994
-            );
1995
-            // developer error msg
1996
-            $error_msg .= '||'
1997
-                          . sprintf(
1998
-                              esc_html__(
1999
-                                  '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.',
2000
-                                  'event_espresso'
2001
-                              ),
2002
-                              $this->_req_action,
2003
-                              $list_table_view
2004
-                          );
2005
-            throw new EE_Error($error_msg);
2006
-        }
2007
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2008
-        $this->_views = apply_filters(
2009
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2010
-            $this->_views
2011
-        );
2012
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2013
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2014
-        $this->_set_list_table_view();
2015
-        $this->_set_list_table_object();
2016
-    }
2017
-
2018
-
2019
-    /**
2020
-     * set current view for List Table
2021
-     *
2022
-     * @return void
2023
-     */
2024
-    protected function _set_list_table_view()
2025
-    {
2026
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2027
-        $status      = $this->request->getRequestParam('status', null, DataType::KEY);
2028
-        $this->_view = $status && array_key_exists($status, $this->_views)
2029
-            ? $status
2030
-            : $this->_view;
2031
-    }
2032
-
2033
-
2034
-    /**
2035
-     * _set_list_table_object
2036
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2037
-     *
2038
-     * @throws InvalidInterfaceException
2039
-     * @throws InvalidArgumentException
2040
-     * @throws InvalidDataTypeException
2041
-     * @throws EE_Error
2042
-     * @throws InvalidInterfaceException
2043
-     */
2044
-    protected function _set_list_table_object()
2045
-    {
2046
-        if (isset($this->_route_config['list_table'])) {
2047
-            if (! class_exists($this->_route_config['list_table'])) {
2048
-                throw new EE_Error(
2049
-                    sprintf(
2050
-                        esc_html__(
2051
-                            '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.',
2052
-                            'event_espresso'
2053
-                        ),
2054
-                        $this->_route_config['list_table'],
2055
-                        $this->class_name
2056
-                    )
2057
-                );
2058
-            }
2059
-            $this->_list_table_object = $this->loader->getShared(
2060
-                $this->_route_config['list_table'],
2061
-                [
2062
-                    $this,
2063
-                    LoaderFactory::getShared(AdminListTableFilters::class),
2064
-                ]
2065
-            );
2066
-        }
2067
-    }
2068
-
2069
-
2070
-    /**
2071
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2072
-     *
2073
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2074
-     *                                                    urls.  The array should be indexed by the view it is being
2075
-     *                                                    added to.
2076
-     * @return array
2077
-     */
2078
-    public function get_list_table_view_RLs(array $extra_query_args = []): array
2079
-    {
2080
-        $extra_query_args = apply_filters(
2081
-            'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
2082
-            $extra_query_args,
2083
-            $this
2084
-        );
2085
-        // cycle thru views
2086
-        foreach ($this->_views as $key => $view) {
2087
-            $query_args = [];
2088
-            // check for current view
2089
-            $this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2090
-            $query_args['action']          = $this->_req_action;
2091
-            $action_nonce                  = "{$this->_req_action}_nonce";
2092
-            $query_args[ $action_nonce ]   = wp_create_nonce($action_nonce);
2093
-            $query_args['status']          = $view['slug'];
2094
-            // merge any other arguments sent in.
2095
-            if (isset($extra_query_args[ $view['slug'] ])) {
2096
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2097
-            }
2098
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2099
-        }
2100
-        return $this->_views;
2101
-    }
2102
-
2103
-
2104
-    /**
2105
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2106
-     *
2107
-     * @param int $max_entries total number of rows in the table
2108
-     * @return string
2109
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2110
-     *                         WP does it.
2111
-     */
2112
-    protected function _entries_per_page_dropdown(int $max_entries = 0): string
2113
-    {
2114
-        $values   = [10, 25, 50, 100];
2115
-        $per_page = $this->request->getRequestParam('per_page', 10, DataType::INT);
2116
-        if ($max_entries) {
2117
-            $values[] = $max_entries;
2118
-            sort($values);
2119
-        }
2120
-        $entries_per_page_dropdown = '
1815
+		$content .= $help_content;
1816
+		if ($display) {
1817
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1818
+			return '';
1819
+		}
1820
+		return $content;
1821
+	}
1822
+
1823
+
1824
+	/**
1825
+	 * _add_global_screen_options
1826
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1827
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1828
+	 *
1829
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1830
+	 *         see also WP_Screen object documents...
1831
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1832
+	 * @abstract
1833
+	 * @return void
1834
+	 */
1835
+	private function _add_global_screen_options()
1836
+	{
1837
+	}
1838
+
1839
+
1840
+	/**
1841
+	 * _add_global_feature_pointers
1842
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1843
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1844
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1845
+	 *
1846
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
1847
+	 *         extended) also see:
1848
+	 * @link   http://eamann.com/tech/wordpress-portland/
1849
+	 * @abstract
1850
+	 * @return void
1851
+	 */
1852
+	private function _add_global_feature_pointers()
1853
+	{
1854
+	}
1855
+
1856
+
1857
+	/**
1858
+	 * load_global_scripts_styles
1859
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1860
+	 *
1861
+	 * @return void
1862
+	 */
1863
+	public function load_global_scripts_styles()
1864
+	{
1865
+		// add debugging styles
1866
+		if (WP_DEBUG) {
1867
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1868
+		}
1869
+		// taking care of metaboxes
1870
+		if (
1871
+			empty($this->_cpt_route)
1872
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1873
+		) {
1874
+			wp_enqueue_script('dashboard');
1875
+		}
1876
+
1877
+		wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1878
+		wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1879
+		// LOCALIZED DATA
1880
+		// localize script for ajax lazy loading
1881
+		wp_localize_script(
1882
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1883
+			'eeLazyLoadingContainers',
1884
+			apply_filters(
1885
+				'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1886
+				['espresso_news_post_box_content']
1887
+			)
1888
+		);
1889
+		StatusChangeNotice::loadAssets();
1890
+
1891
+		add_filter(
1892
+			'admin_body_class',
1893
+			function ($classes) {
1894
+				if (strpos($classes, 'espresso-admin') === false) {
1895
+					$classes .= ' espresso-admin';
1896
+				}
1897
+				return $classes;
1898
+			}
1899
+		);
1900
+	}
1901
+
1902
+
1903
+	/**
1904
+	 *        admin_footer_scripts_eei18n_js_strings
1905
+	 *
1906
+	 * @return        void
1907
+	 */
1908
+	public function admin_footer_scripts_eei18n_js_strings()
1909
+	{
1910
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1911
+			__(
1912
+				'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!!!',
1913
+				'event_espresso'
1914
+			)
1915
+		);
1916
+		// now add months and days of the week
1917
+		EE_Registry::$i18n_js_strings['January']   = wp_strip_all_tags(__('January', 'event_espresso'));
1918
+		EE_Registry::$i18n_js_strings['February']  = wp_strip_all_tags(__('February', 'event_espresso'));
1919
+		EE_Registry::$i18n_js_strings['March']     = wp_strip_all_tags(__('March', 'event_espresso'));
1920
+		EE_Registry::$i18n_js_strings['April']     = wp_strip_all_tags(__('April', 'event_espresso'));
1921
+		EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1922
+		EE_Registry::$i18n_js_strings['June']      = wp_strip_all_tags(__('June', 'event_espresso'));
1923
+		EE_Registry::$i18n_js_strings['July']      = wp_strip_all_tags(__('July', 'event_espresso'));
1924
+		EE_Registry::$i18n_js_strings['August']    = wp_strip_all_tags(__('August', 'event_espresso'));
1925
+		EE_Registry::$i18n_js_strings['September'] = wp_strip_all_tags(__('September', 'event_espresso'));
1926
+		EE_Registry::$i18n_js_strings['October']   = wp_strip_all_tags(__('October', 'event_espresso'));
1927
+		EE_Registry::$i18n_js_strings['November']  = wp_strip_all_tags(__('November', 'event_espresso'));
1928
+		EE_Registry::$i18n_js_strings['December']  = wp_strip_all_tags(__('December', 'event_espresso'));
1929
+		EE_Registry::$i18n_js_strings['Jan']       = wp_strip_all_tags(__('Jan', 'event_espresso'));
1930
+		EE_Registry::$i18n_js_strings['Feb']       = wp_strip_all_tags(__('Feb', 'event_espresso'));
1931
+		EE_Registry::$i18n_js_strings['Mar']       = wp_strip_all_tags(__('Mar', 'event_espresso'));
1932
+		EE_Registry::$i18n_js_strings['Apr']       = wp_strip_all_tags(__('Apr', 'event_espresso'));
1933
+		EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1934
+		EE_Registry::$i18n_js_strings['Jun']       = wp_strip_all_tags(__('Jun', 'event_espresso'));
1935
+		EE_Registry::$i18n_js_strings['Jul']       = wp_strip_all_tags(__('Jul', 'event_espresso'));
1936
+		EE_Registry::$i18n_js_strings['Aug']       = wp_strip_all_tags(__('Aug', 'event_espresso'));
1937
+		EE_Registry::$i18n_js_strings['Sep']       = wp_strip_all_tags(__('Sep', 'event_espresso'));
1938
+		EE_Registry::$i18n_js_strings['Oct']       = wp_strip_all_tags(__('Oct', 'event_espresso'));
1939
+		EE_Registry::$i18n_js_strings['Nov']       = wp_strip_all_tags(__('Nov', 'event_espresso'));
1940
+		EE_Registry::$i18n_js_strings['Dec']       = wp_strip_all_tags(__('Dec', 'event_espresso'));
1941
+		EE_Registry::$i18n_js_strings['Sunday']    = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1942
+		EE_Registry::$i18n_js_strings['Monday']    = wp_strip_all_tags(__('Monday', 'event_espresso'));
1943
+		EE_Registry::$i18n_js_strings['Tuesday']   = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1944
+		EE_Registry::$i18n_js_strings['Wednesday'] = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1945
+		EE_Registry::$i18n_js_strings['Thursday']  = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1946
+		EE_Registry::$i18n_js_strings['Friday']    = wp_strip_all_tags(__('Friday', 'event_espresso'));
1947
+		EE_Registry::$i18n_js_strings['Saturday']  = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1948
+		EE_Registry::$i18n_js_strings['Sun']       = wp_strip_all_tags(__('Sun', 'event_espresso'));
1949
+		EE_Registry::$i18n_js_strings['Mon']       = wp_strip_all_tags(__('Mon', 'event_espresso'));
1950
+		EE_Registry::$i18n_js_strings['Tue']       = wp_strip_all_tags(__('Tue', 'event_espresso'));
1951
+		EE_Registry::$i18n_js_strings['Wed']       = wp_strip_all_tags(__('Wed', 'event_espresso'));
1952
+		EE_Registry::$i18n_js_strings['Thu']       = wp_strip_all_tags(__('Thu', 'event_espresso'));
1953
+		EE_Registry::$i18n_js_strings['Fri']       = wp_strip_all_tags(__('Fri', 'event_espresso'));
1954
+		EE_Registry::$i18n_js_strings['Sat']       = wp_strip_all_tags(__('Sat', 'event_espresso'));
1955
+	}
1956
+
1957
+
1958
+	/**
1959
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1960
+	 *
1961
+	 * @return        void
1962
+	 */
1963
+	public function add_xdebug_style()
1964
+	{
1965
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1966
+	}
1967
+
1968
+
1969
+	/************************/
1970
+	/** LIST TABLE METHODS **/
1971
+	/************************/
1972
+	/**
1973
+	 * this sets up the list table if the current view requires it.
1974
+	 *
1975
+	 * @return void
1976
+	 * @throws EE_Error
1977
+	 * @throws InvalidArgumentException
1978
+	 * @throws InvalidDataTypeException
1979
+	 * @throws InvalidInterfaceException
1980
+	 */
1981
+	protected function _set_list_table()
1982
+	{
1983
+		// first is this a list_table view?
1984
+		if (! isset($this->_route_config['list_table'])) {
1985
+			return;
1986
+		} //not a list_table view so get out.
1987
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
1988
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
1989
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1990
+			// user error msg
1991
+			$error_msg = esc_html__(
1992
+				'An error occurred. The requested list table views could not be found.',
1993
+				'event_espresso'
1994
+			);
1995
+			// developer error msg
1996
+			$error_msg .= '||'
1997
+						  . sprintf(
1998
+							  esc_html__(
1999
+								  '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.',
2000
+								  'event_espresso'
2001
+							  ),
2002
+							  $this->_req_action,
2003
+							  $list_table_view
2004
+						  );
2005
+			throw new EE_Error($error_msg);
2006
+		}
2007
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2008
+		$this->_views = apply_filters(
2009
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2010
+			$this->_views
2011
+		);
2012
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2013
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2014
+		$this->_set_list_table_view();
2015
+		$this->_set_list_table_object();
2016
+	}
2017
+
2018
+
2019
+	/**
2020
+	 * set current view for List Table
2021
+	 *
2022
+	 * @return void
2023
+	 */
2024
+	protected function _set_list_table_view()
2025
+	{
2026
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2027
+		$status      = $this->request->getRequestParam('status', null, DataType::KEY);
2028
+		$this->_view = $status && array_key_exists($status, $this->_views)
2029
+			? $status
2030
+			: $this->_view;
2031
+	}
2032
+
2033
+
2034
+	/**
2035
+	 * _set_list_table_object
2036
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2037
+	 *
2038
+	 * @throws InvalidInterfaceException
2039
+	 * @throws InvalidArgumentException
2040
+	 * @throws InvalidDataTypeException
2041
+	 * @throws EE_Error
2042
+	 * @throws InvalidInterfaceException
2043
+	 */
2044
+	protected function _set_list_table_object()
2045
+	{
2046
+		if (isset($this->_route_config['list_table'])) {
2047
+			if (! class_exists($this->_route_config['list_table'])) {
2048
+				throw new EE_Error(
2049
+					sprintf(
2050
+						esc_html__(
2051
+							'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.',
2052
+							'event_espresso'
2053
+						),
2054
+						$this->_route_config['list_table'],
2055
+						$this->class_name
2056
+					)
2057
+				);
2058
+			}
2059
+			$this->_list_table_object = $this->loader->getShared(
2060
+				$this->_route_config['list_table'],
2061
+				[
2062
+					$this,
2063
+					LoaderFactory::getShared(AdminListTableFilters::class),
2064
+				]
2065
+			);
2066
+		}
2067
+	}
2068
+
2069
+
2070
+	/**
2071
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2072
+	 *
2073
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2074
+	 *                                                    urls.  The array should be indexed by the view it is being
2075
+	 *                                                    added to.
2076
+	 * @return array
2077
+	 */
2078
+	public function get_list_table_view_RLs(array $extra_query_args = []): array
2079
+	{
2080
+		$extra_query_args = apply_filters(
2081
+			'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
2082
+			$extra_query_args,
2083
+			$this
2084
+		);
2085
+		// cycle thru views
2086
+		foreach ($this->_views as $key => $view) {
2087
+			$query_args = [];
2088
+			// check for current view
2089
+			$this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2090
+			$query_args['action']          = $this->_req_action;
2091
+			$action_nonce                  = "{$this->_req_action}_nonce";
2092
+			$query_args[ $action_nonce ]   = wp_create_nonce($action_nonce);
2093
+			$query_args['status']          = $view['slug'];
2094
+			// merge any other arguments sent in.
2095
+			if (isset($extra_query_args[ $view['slug'] ])) {
2096
+				$query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2097
+			}
2098
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2099
+		}
2100
+		return $this->_views;
2101
+	}
2102
+
2103
+
2104
+	/**
2105
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2106
+	 *
2107
+	 * @param int $max_entries total number of rows in the table
2108
+	 * @return string
2109
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2110
+	 *                         WP does it.
2111
+	 */
2112
+	protected function _entries_per_page_dropdown(int $max_entries = 0): string
2113
+	{
2114
+		$values   = [10, 25, 50, 100];
2115
+		$per_page = $this->request->getRequestParam('per_page', 10, DataType::INT);
2116
+		if ($max_entries) {
2117
+			$values[] = $max_entries;
2118
+			sort($values);
2119
+		}
2120
+		$entries_per_page_dropdown = '
2121 2121
 			<div id="entries-per-page-dv" class="alignleft actions">
2122 2122
 				<label class="hide-if-no-js">
2123 2123
 					Show
2124 2124
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2125
-        foreach ($values as $value) {
2126
-            if ($value < $max_entries) {
2127
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2128
-                $entries_per_page_dropdown .= '
2125
+		foreach ($values as $value) {
2126
+			if ($value < $max_entries) {
2127
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2128
+				$entries_per_page_dropdown .= '
2129 2129
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2130
-            }
2131
-        }
2132
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2133
-        $entries_per_page_dropdown .= '
2130
+			}
2131
+		}
2132
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2133
+		$entries_per_page_dropdown .= '
2134 2134
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2135
-        $entries_per_page_dropdown .= '
2135
+		$entries_per_page_dropdown .= '
2136 2136
 					</select>
2137 2137
 					entries
2138 2138
 				</label>
2139 2139
 				<input id="entries-per-page-btn" class="button button--secondary" type="submit" value="Go" >
2140 2140
 			</div>
2141 2141
 		';
2142
-        return $entries_per_page_dropdown;
2143
-    }
2144
-
2145
-
2146
-    /**
2147
-     *        _set_search_attributes
2148
-     *
2149
-     * @return        void
2150
-     */
2151
-    public function _set_search_attributes()
2152
-    {
2153
-        $this->_template_args['search']['btn_label'] = sprintf(
2154
-            esc_html__('Search %s', 'event_espresso'),
2155
-            empty($this->_search_btn_label) ? $this->page_label
2156
-                : $this->_search_btn_label
2157
-        );
2158
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2159
-    }
2160
-
2161
-
2162
-
2163
-    /*** END LIST TABLE METHODS **/
2164
-
2165
-    /**
2166
-     * @return void
2167
-     * @throws EE_Error
2168
-     */
2169
-    public function addRegisteredMetaBoxes()
2170
-    {
2171
-        remove_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
2172
-        $this->_add_registered_meta_boxes();
2173
-    }
2174
-
2175
-
2176
-    /**
2177
-     * _add_registered_metaboxes
2178
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2179
-     *
2180
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2181
-     * @return void
2182
-     * @throws EE_Error
2183
-     */
2184
-    private function _add_registered_meta_boxes()
2185
-    {
2186
-        // we only add meta boxes if the page_route calls for it
2187
-        if (isset($this->_route_config['metaboxes']) && is_array($this->_route_config['metaboxes'])) {
2188
-            // this simply loops through the callbacks provided
2189
-            // and checks if there is a corresponding callback registered by the child
2190
-            // if there is then we go ahead and process the metabox loader.
2191
-            foreach ($this->_route_config['metaboxes'] as $key => $metabox_callback) {
2192
-                // first check for Closures
2193
-                if ($metabox_callback instanceof Closure) {
2194
-                    $result = $metabox_callback();
2195
-                } elseif (is_callable($metabox_callback)) {
2196
-                    $result = call_user_func($metabox_callback);
2197
-                } elseif (method_exists($this, $metabox_callback)) {
2198
-                    $result = $this->{$metabox_callback}();
2199
-                } else {
2200
-                    $result = false;
2201
-                }
2202
-                if ($result === false) {
2203
-                    // user error msg
2204
-                    $error_msg = esc_html__(
2205
-                        'An error occurred. The  requested metabox could not be found.',
2206
-                        'event_espresso'
2207
-                    );
2208
-                    // developer error msg
2209
-                    $error_msg .= '||'
2210
-                                  . sprintf(
2211
-                                      esc_html__(
2212
-                                          '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.',
2213
-                                          'event_espresso'
2214
-                                      ),
2215
-                                      $metabox_callback
2216
-                                  );
2217
-                    throw new EE_Error($error_msg);
2218
-                }
2219
-                unset($this->_route_config['metaboxes'][ $key ]);
2220
-            }
2221
-        }
2222
-    }
2223
-
2224
-
2225
-    /**
2226
-     * _add_screen_columns
2227
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2228
-     * the dynamic column template and we'll set up the column options for the page.
2229
-     *
2230
-     * @return void
2231
-     */
2232
-    private function _add_screen_columns()
2233
-    {
2234
-        if (
2235
-            isset($this->_route_config['columns'])
2236
-            && is_array($this->_route_config['columns'])
2237
-            && count($this->_route_config['columns']) === 2
2238
-        ) {
2239
-            add_screen_option(
2240
-                'layout_columns',
2241
-                [
2242
-                    'max'     => (int) $this->_route_config['columns'][0],
2243
-                    'default' => (int) $this->_route_config['columns'][1],
2244
-                ]
2245
-            );
2246
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2247
-            $screen_id                                           = $this->_current_screen->id;
2248
-            $screen_columns                                      = (int) get_user_option("screen_layout_$screen_id");
2249
-            $total_columns                                       = ! empty($screen_columns)
2250
-                ? $screen_columns
2251
-                : $this->_route_config['columns'][1];
2252
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2253
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2254
-            $this->_template_args['screen']                      = $this->_current_screen;
2255
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2256
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2257
-            // finally if we don't have has_metaboxes set in the route config
2258
-            // let's make sure it IS set otherwise the necessary hidden fields for this won't be loaded.
2259
-            $this->_route_config['has_metaboxes'] = true;
2260
-        }
2261
-    }
2262
-
2263
-
2264
-
2265
-    /** GLOBALLY AVAILABLE METABOXES **/
2266
-
2267
-
2268
-    /**
2269
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2270
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2271
-     * these get loaded on.
2272
-     */
2273
-    private function _espresso_news_post_box()
2274
-    {
2275
-        $news_box_title = apply_filters(
2276
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2277
-            esc_html__('New @ Event Espresso', 'event_espresso')
2278
-        );
2279
-        $this->addMetaBox(
2280
-            'espresso_news_post_box',
2281
-            $news_box_title,
2282
-            [
2283
-                $this,
2284
-                'espresso_news_post_box',
2285
-            ],
2286
-            $this->_wp_page_slug,
2287
-            'side',
2288
-            'low'
2289
-        );
2290
-    }
2291
-
2292
-
2293
-    /**
2294
-     * Code for setting up espresso ratings request metabox.
2295
-     */
2296
-    protected function _espresso_ratings_request()
2297
-    {
2298
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2299
-            return;
2300
-        }
2301
-        $ratings_box_title = apply_filters(
2302
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2303
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2304
-        );
2305
-        $this->addMetaBox(
2306
-            'espresso_ratings_request',
2307
-            $ratings_box_title,
2308
-            [
2309
-                $this,
2310
-                'espresso_ratings_request',
2311
-            ],
2312
-            $this->_wp_page_slug,
2313
-            'side'
2314
-        );
2315
-    }
2316
-
2317
-
2318
-    /**
2319
-     * Code for setting up espresso ratings request metabox content.
2320
-     *
2321
-     * @throws DomainException
2322
-     */
2323
-    public function espresso_ratings_request()
2324
-    {
2325
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2326
-    }
2327
-
2328
-
2329
-    public static function cached_rss_display(string $rss_id, string $url): bool
2330
-    {
2331
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2332
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2333
-                     . '</p><p class="hide-if-js">'
2334
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2335
-                     . '</p>';
2336
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2337
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2338
-        $post      = '</div>' . "\n";
2339
-        $cache_key = 'ee_rss_' . md5($rss_id);
2340
-        $output    = get_transient($cache_key);
2341
-        if ($output !== false) {
2342
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2343
-            return true;
2344
-        }
2345
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2347
-            return false;
2348
-        }
2349
-        ob_start();
2350
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2351
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2352
-        return true;
2353
-    }
2354
-
2355
-
2356
-    public function espresso_news_post_box()
2357
-    {
2358
-        ?>
2142
+		return $entries_per_page_dropdown;
2143
+	}
2144
+
2145
+
2146
+	/**
2147
+	 *        _set_search_attributes
2148
+	 *
2149
+	 * @return        void
2150
+	 */
2151
+	public function _set_search_attributes()
2152
+	{
2153
+		$this->_template_args['search']['btn_label'] = sprintf(
2154
+			esc_html__('Search %s', 'event_espresso'),
2155
+			empty($this->_search_btn_label) ? $this->page_label
2156
+				: $this->_search_btn_label
2157
+		);
2158
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2159
+	}
2160
+
2161
+
2162
+
2163
+	/*** END LIST TABLE METHODS **/
2164
+
2165
+	/**
2166
+	 * @return void
2167
+	 * @throws EE_Error
2168
+	 */
2169
+	public function addRegisteredMetaBoxes()
2170
+	{
2171
+		remove_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
2172
+		$this->_add_registered_meta_boxes();
2173
+	}
2174
+
2175
+
2176
+	/**
2177
+	 * _add_registered_metaboxes
2178
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2179
+	 *
2180
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2181
+	 * @return void
2182
+	 * @throws EE_Error
2183
+	 */
2184
+	private function _add_registered_meta_boxes()
2185
+	{
2186
+		// we only add meta boxes if the page_route calls for it
2187
+		if (isset($this->_route_config['metaboxes']) && is_array($this->_route_config['metaboxes'])) {
2188
+			// this simply loops through the callbacks provided
2189
+			// and checks if there is a corresponding callback registered by the child
2190
+			// if there is then we go ahead and process the metabox loader.
2191
+			foreach ($this->_route_config['metaboxes'] as $key => $metabox_callback) {
2192
+				// first check for Closures
2193
+				if ($metabox_callback instanceof Closure) {
2194
+					$result = $metabox_callback();
2195
+				} elseif (is_callable($metabox_callback)) {
2196
+					$result = call_user_func($metabox_callback);
2197
+				} elseif (method_exists($this, $metabox_callback)) {
2198
+					$result = $this->{$metabox_callback}();
2199
+				} else {
2200
+					$result = false;
2201
+				}
2202
+				if ($result === false) {
2203
+					// user error msg
2204
+					$error_msg = esc_html__(
2205
+						'An error occurred. The  requested metabox could not be found.',
2206
+						'event_espresso'
2207
+					);
2208
+					// developer error msg
2209
+					$error_msg .= '||'
2210
+								  . sprintf(
2211
+									  esc_html__(
2212
+										  '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.',
2213
+										  'event_espresso'
2214
+									  ),
2215
+									  $metabox_callback
2216
+								  );
2217
+					throw new EE_Error($error_msg);
2218
+				}
2219
+				unset($this->_route_config['metaboxes'][ $key ]);
2220
+			}
2221
+		}
2222
+	}
2223
+
2224
+
2225
+	/**
2226
+	 * _add_screen_columns
2227
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2228
+	 * the dynamic column template and we'll set up the column options for the page.
2229
+	 *
2230
+	 * @return void
2231
+	 */
2232
+	private function _add_screen_columns()
2233
+	{
2234
+		if (
2235
+			isset($this->_route_config['columns'])
2236
+			&& is_array($this->_route_config['columns'])
2237
+			&& count($this->_route_config['columns']) === 2
2238
+		) {
2239
+			add_screen_option(
2240
+				'layout_columns',
2241
+				[
2242
+					'max'     => (int) $this->_route_config['columns'][0],
2243
+					'default' => (int) $this->_route_config['columns'][1],
2244
+				]
2245
+			);
2246
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2247
+			$screen_id                                           = $this->_current_screen->id;
2248
+			$screen_columns                                      = (int) get_user_option("screen_layout_$screen_id");
2249
+			$total_columns                                       = ! empty($screen_columns)
2250
+				? $screen_columns
2251
+				: $this->_route_config['columns'][1];
2252
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2253
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2254
+			$this->_template_args['screen']                      = $this->_current_screen;
2255
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2256
+																   . 'admin_details_metabox_column_wrapper.template.php';
2257
+			// finally if we don't have has_metaboxes set in the route config
2258
+			// let's make sure it IS set otherwise the necessary hidden fields for this won't be loaded.
2259
+			$this->_route_config['has_metaboxes'] = true;
2260
+		}
2261
+	}
2262
+
2263
+
2264
+
2265
+	/** GLOBALLY AVAILABLE METABOXES **/
2266
+
2267
+
2268
+	/**
2269
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2270
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2271
+	 * these get loaded on.
2272
+	 */
2273
+	private function _espresso_news_post_box()
2274
+	{
2275
+		$news_box_title = apply_filters(
2276
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2277
+			esc_html__('New @ Event Espresso', 'event_espresso')
2278
+		);
2279
+		$this->addMetaBox(
2280
+			'espresso_news_post_box',
2281
+			$news_box_title,
2282
+			[
2283
+				$this,
2284
+				'espresso_news_post_box',
2285
+			],
2286
+			$this->_wp_page_slug,
2287
+			'side',
2288
+			'low'
2289
+		);
2290
+	}
2291
+
2292
+
2293
+	/**
2294
+	 * Code for setting up espresso ratings request metabox.
2295
+	 */
2296
+	protected function _espresso_ratings_request()
2297
+	{
2298
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2299
+			return;
2300
+		}
2301
+		$ratings_box_title = apply_filters(
2302
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2303
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2304
+		);
2305
+		$this->addMetaBox(
2306
+			'espresso_ratings_request',
2307
+			$ratings_box_title,
2308
+			[
2309
+				$this,
2310
+				'espresso_ratings_request',
2311
+			],
2312
+			$this->_wp_page_slug,
2313
+			'side'
2314
+		);
2315
+	}
2316
+
2317
+
2318
+	/**
2319
+	 * Code for setting up espresso ratings request metabox content.
2320
+	 *
2321
+	 * @throws DomainException
2322
+	 */
2323
+	public function espresso_ratings_request()
2324
+	{
2325
+		EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2326
+	}
2327
+
2328
+
2329
+	public static function cached_rss_display(string $rss_id, string $url): bool
2330
+	{
2331
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2332
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2333
+					 . '</p><p class="hide-if-js">'
2334
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2335
+					 . '</p>';
2336
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2337
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2338
+		$post      = '</div>' . "\n";
2339
+		$cache_key = 'ee_rss_' . md5($rss_id);
2340
+		$output    = get_transient($cache_key);
2341
+		if ($output !== false) {
2342
+			echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2343
+			return true;
2344
+		}
2345
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
+			echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2347
+			return false;
2348
+		}
2349
+		ob_start();
2350
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2351
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2352
+		return true;
2353
+	}
2354
+
2355
+
2356
+	public function espresso_news_post_box()
2357
+	{
2358
+		?>
2359 2359
 <div class="padding">
2360 2360
 	<div id="espresso_news_post_box_content" class="infolinks">
2361 2361
 		<?php
2362
-                // Get RSS Feed(s)
2363
-                EE_Admin_Page::cached_rss_display(
2364
-                    'espresso_news_post_box_content',
2365
-                    esc_url_raw(
2366
-                        apply_filters(
2367
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2368
-                            'https://eventespresso.com/feed/'
2369
-                        )
2370
-                    )
2371
-                );
2372
-                ?>
2362
+				// Get RSS Feed(s)
2363
+				EE_Admin_Page::cached_rss_display(
2364
+					'espresso_news_post_box_content',
2365
+					esc_url_raw(
2366
+						apply_filters(
2367
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2368
+							'https://eventespresso.com/feed/'
2369
+						)
2370
+					)
2371
+				);
2372
+				?>
2373 2373
 	</div>
2374 2374
 	<?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2375 2375
 </div>
2376 2376
 <?php
2377
-    }
2378
-
2379
-
2380
-    private function _espresso_links_post_box()
2381
-    {
2382
-        // Hiding until we actually have content to put in here...
2383
-        // $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2384
-    }
2385
-
2386
-
2387
-    public function espresso_links_post_box()
2388
-    {
2389
-        // Hiding until we actually have content to put in here...
2390
-        // EEH_Template::display_template(
2391
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2392
-        // );
2393
-    }
2394
-
2395
-
2396
-    protected function _espresso_sponsors_post_box()
2397
-    {
2398
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2399
-            $this->addMetaBox(
2400
-                'espresso_sponsors_post_box',
2401
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2402
-                [$this, 'espresso_sponsors_post_box'],
2403
-                $this->_wp_page_slug,
2404
-                'side'
2405
-            );
2406
-        }
2407
-    }
2408
-
2409
-
2410
-    public function espresso_sponsors_post_box()
2411
-    {
2412
-        EEH_Template::display_template(
2413
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2414
-        );
2415
-    }
2416
-
2417
-
2418
-    /**
2419
-     * if there is [ 'label' => [ 'publishbox' => 'some title' ]]
2420
-     * present in the _page_config array, then we'll use that for the metabox label.
2421
-     * Otherwise we'll just use publish
2422
-     * (publishbox itself could be an array of labels indexed by routes)
2423
-     *
2424
-     * @return string
2425
-     * @since   5.0.0.p
2426
-     */
2427
-    protected function getPublishBoxTitle(): string
2428
-    {
2429
-        $publish_box_title = esc_html__('Publish', 'event_espresso');
2430
-        if (! empty($this->_labels['publishbox'])) {
2431
-            if (is_array($this->_labels['publishbox'])) {
2432
-                $publish_box_title = $this->_labels['publishbox'][ $this->_req_action ] ?? $publish_box_title;
2433
-            } else {
2434
-                $publish_box_title = $this->_labels['publishbox'];
2435
-            }
2436
-        }
2437
-        return apply_filters(
2438
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2439
-            $publish_box_title,
2440
-            $this->_req_action,
2441
-            $this
2442
-        );
2443
-    }
2444
-
2445
-
2446
-    /**
2447
-     * @throws EE_Error
2448
-     */
2449
-    private function _publish_post_box()
2450
-    {
2451
-        $title = $this->getPublishBoxTitle();
2452
-        if (empty($this->_template_args['save_buttons'])) {
2453
-            $this->_set_publish_post_box_vars(sanitize_key($title), "espresso_{$this->page_slug}_editor_overview");
2454
-        } else {
2455
-            $this->addPublishPostMetaBoxHiddenFields(
2456
-                sanitize_key($title),
2457
-                ['type' => 'hidden', 'value' => "espresso_{$this->page_slug}_editor_overview"]
2458
-            );
2459
-        }
2460
-        $this->addMetaBox(
2461
-            "espresso_{$this->page_slug}_editor_overview",
2462
-            $title,
2463
-            [$this, 'editor_overview'],
2464
-            $this->_current_screen->id,
2465
-            'side',
2466
-            'high'
2467
-        );
2468
-    }
2469
-
2470
-
2471
-    public function editor_overview()
2472
-    {
2473
-        /**
2474
-         * @var string $publish_box_extra_content
2475
-         * @var string $publish_hidden_fields
2476
-         * @var string $publish_delete_link
2477
-         * @var string $save_buttons
2478
-         */
2479
-        // if we have extra content set let's add it in if not make sure its empty
2480
-        $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2481
-        echo EEH_Template::display_template(
2482
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2483
-            $this->_template_args,
2484
-            true
2485
-        );
2486
-    }
2487
-
2488
-
2489
-    /** end of globally available metaboxes section **/
2490
-
2491
-
2492
-    /**
2493
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2494
-     * Note: currently there is no validation for this.  However, if you want the delete button, the
2495
-     * save, and save and close buttons to work properly, then you will want to include a
2496
-     * values for the name and id arguments.
2497
-     *
2498
-     * @param string|null $name                     key used for the action ID (i.e. event_id)
2499
-     * @param int|string  $id                       id attached to the item published
2500
-     * @param string|null $delete                   page route callback for the delete action
2501
-     * @param string|null $save_close_redirect_URL  custom URL to redirect to after Save & Close has been completed
2502
-     * @param bool        $both_btns                whether to display BOTH the "Save & Close" and "Save" buttons
2503
-     *                                              or just the "Save" button
2504
-     * @throws EE_Error
2505
-     * @throws InvalidArgumentException
2506
-     * @throws InvalidDataTypeException
2507
-     * @throws InvalidInterfaceException
2508
-     * @todo  Add in validation for name/id arguments.
2509
-     */
2510
-    protected function _set_publish_post_box_vars(
2511
-        ?string $name = '',
2512
-        $id = 0,
2513
-        ?string $delete = '',
2514
-        ?string $save_close_redirect_URL = '',
2515
-        bool $both_btns = true
2516
-    ) {
2517
-        // if Save & Close, use a custom redirect URL or default to the main page?
2518
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2519
-            ? $save_close_redirect_URL
2520
-            : $this->_admin_base_url;
2521
-        // create the Save & Close and Save buttons
2522
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2523
-        // if we have extra content set let's add it in if not make sure its empty
2524
-        $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2525
-        if ($delete && ! empty($id) && empty($this->_template_args['publish_delete_link'])) {
2526
-            // make sure we have a default if just true is sent.
2527
-            $delete                                      = ! empty($delete) ? $delete : 'delete';
2528
-            $this->_template_args['publish_delete_link'] = $this->get_action_link_or_button(
2529
-                $delete,
2530
-                $delete,
2531
-                [$name => $id],
2532
-                'submitdelete deletion button button--outline button--caution'
2533
-            );
2534
-        }
2535
-        if (! isset($this->_template_args['publish_delete_link'])) {
2536
-            $this->_template_args['publish_delete_link'] = '';
2537
-        }
2538
-        if (! empty($name) && ! empty($id)) {
2539
-            $this->addPublishPostMetaBoxHiddenFields($name, ['type' => 'hidden', 'value' => $id]);
2540
-        }
2541
-        $hidden_fields = $this->_generate_admin_form_fields($this->publish_post_meta_box_hidden_fields, 'array');
2542
-        // add hidden fields
2543
-        $this->_template_args['publish_hidden_fields'] = $this->_template_args['publish_hidden_fields'] ?? '';
2544
-        foreach ($hidden_fields as $hidden_field) {
2545
-            $this->_template_args['publish_hidden_fields'] .= $hidden_field['field'] ?? '';
2546
-        }
2547
-    }
2548
-
2549
-
2550
-    /**
2551
-     * @param string|null $name
2552
-     * @param int|string  $id
2553
-     * @param string|null $delete
2554
-     * @param string|null $save_close_redirect_URL
2555
-     * @param bool        $both_btns
2556
-     * @throws EE_Error
2557
-     */
2558
-    public function set_publish_post_box_vars(
2559
-        ?string $name = '',
2560
-        $id = 0,
2561
-        ?string $delete = '',
2562
-        ?string $save_close_redirect_URL = '',
2563
-        bool $both_btns = false
2564
-    ) {
2565
-        $this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2566
-    }
2567
-
2568
-
2569
-    protected function addPublishPostMetaBoxHiddenFields(string $field_name, array $field_attributes)
2570
-    {
2571
-        $this->publish_post_meta_box_hidden_fields[ $field_name ] = $field_attributes;
2572
-    }
2573
-
2574
-
2575
-    /**
2576
-     * displays an error message to ppl who have javascript disabled
2577
-     *
2578
-     * @return void
2579
-     */
2580
-    private function _display_no_javascript_warning()
2581
-    {
2582
-        ?>
2377
+	}
2378
+
2379
+
2380
+	private function _espresso_links_post_box()
2381
+	{
2382
+		// Hiding until we actually have content to put in here...
2383
+		// $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2384
+	}
2385
+
2386
+
2387
+	public function espresso_links_post_box()
2388
+	{
2389
+		// Hiding until we actually have content to put in here...
2390
+		// EEH_Template::display_template(
2391
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2392
+		// );
2393
+	}
2394
+
2395
+
2396
+	protected function _espresso_sponsors_post_box()
2397
+	{
2398
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2399
+			$this->addMetaBox(
2400
+				'espresso_sponsors_post_box',
2401
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2402
+				[$this, 'espresso_sponsors_post_box'],
2403
+				$this->_wp_page_slug,
2404
+				'side'
2405
+			);
2406
+		}
2407
+	}
2408
+
2409
+
2410
+	public function espresso_sponsors_post_box()
2411
+	{
2412
+		EEH_Template::display_template(
2413
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2414
+		);
2415
+	}
2416
+
2417
+
2418
+	/**
2419
+	 * if there is [ 'label' => [ 'publishbox' => 'some title' ]]
2420
+	 * present in the _page_config array, then we'll use that for the metabox label.
2421
+	 * Otherwise we'll just use publish
2422
+	 * (publishbox itself could be an array of labels indexed by routes)
2423
+	 *
2424
+	 * @return string
2425
+	 * @since   5.0.0.p
2426
+	 */
2427
+	protected function getPublishBoxTitle(): string
2428
+	{
2429
+		$publish_box_title = esc_html__('Publish', 'event_espresso');
2430
+		if (! empty($this->_labels['publishbox'])) {
2431
+			if (is_array($this->_labels['publishbox'])) {
2432
+				$publish_box_title = $this->_labels['publishbox'][ $this->_req_action ] ?? $publish_box_title;
2433
+			} else {
2434
+				$publish_box_title = $this->_labels['publishbox'];
2435
+			}
2436
+		}
2437
+		return apply_filters(
2438
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2439
+			$publish_box_title,
2440
+			$this->_req_action,
2441
+			$this
2442
+		);
2443
+	}
2444
+
2445
+
2446
+	/**
2447
+	 * @throws EE_Error
2448
+	 */
2449
+	private function _publish_post_box()
2450
+	{
2451
+		$title = $this->getPublishBoxTitle();
2452
+		if (empty($this->_template_args['save_buttons'])) {
2453
+			$this->_set_publish_post_box_vars(sanitize_key($title), "espresso_{$this->page_slug}_editor_overview");
2454
+		} else {
2455
+			$this->addPublishPostMetaBoxHiddenFields(
2456
+				sanitize_key($title),
2457
+				['type' => 'hidden', 'value' => "espresso_{$this->page_slug}_editor_overview"]
2458
+			);
2459
+		}
2460
+		$this->addMetaBox(
2461
+			"espresso_{$this->page_slug}_editor_overview",
2462
+			$title,
2463
+			[$this, 'editor_overview'],
2464
+			$this->_current_screen->id,
2465
+			'side',
2466
+			'high'
2467
+		);
2468
+	}
2469
+
2470
+
2471
+	public function editor_overview()
2472
+	{
2473
+		/**
2474
+		 * @var string $publish_box_extra_content
2475
+		 * @var string $publish_hidden_fields
2476
+		 * @var string $publish_delete_link
2477
+		 * @var string $save_buttons
2478
+		 */
2479
+		// if we have extra content set let's add it in if not make sure its empty
2480
+		$this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2481
+		echo EEH_Template::display_template(
2482
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2483
+			$this->_template_args,
2484
+			true
2485
+		);
2486
+	}
2487
+
2488
+
2489
+	/** end of globally available metaboxes section **/
2490
+
2491
+
2492
+	/**
2493
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2494
+	 * Note: currently there is no validation for this.  However, if you want the delete button, the
2495
+	 * save, and save and close buttons to work properly, then you will want to include a
2496
+	 * values for the name and id arguments.
2497
+	 *
2498
+	 * @param string|null $name                     key used for the action ID (i.e. event_id)
2499
+	 * @param int|string  $id                       id attached to the item published
2500
+	 * @param string|null $delete                   page route callback for the delete action
2501
+	 * @param string|null $save_close_redirect_URL  custom URL to redirect to after Save & Close has been completed
2502
+	 * @param bool        $both_btns                whether to display BOTH the "Save & Close" and "Save" buttons
2503
+	 *                                              or just the "Save" button
2504
+	 * @throws EE_Error
2505
+	 * @throws InvalidArgumentException
2506
+	 * @throws InvalidDataTypeException
2507
+	 * @throws InvalidInterfaceException
2508
+	 * @todo  Add in validation for name/id arguments.
2509
+	 */
2510
+	protected function _set_publish_post_box_vars(
2511
+		?string $name = '',
2512
+		$id = 0,
2513
+		?string $delete = '',
2514
+		?string $save_close_redirect_URL = '',
2515
+		bool $both_btns = true
2516
+	) {
2517
+		// if Save & Close, use a custom redirect URL or default to the main page?
2518
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2519
+			? $save_close_redirect_URL
2520
+			: $this->_admin_base_url;
2521
+		// create the Save & Close and Save buttons
2522
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2523
+		// if we have extra content set let's add it in if not make sure its empty
2524
+		$this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2525
+		if ($delete && ! empty($id) && empty($this->_template_args['publish_delete_link'])) {
2526
+			// make sure we have a default if just true is sent.
2527
+			$delete                                      = ! empty($delete) ? $delete : 'delete';
2528
+			$this->_template_args['publish_delete_link'] = $this->get_action_link_or_button(
2529
+				$delete,
2530
+				$delete,
2531
+				[$name => $id],
2532
+				'submitdelete deletion button button--outline button--caution'
2533
+			);
2534
+		}
2535
+		if (! isset($this->_template_args['publish_delete_link'])) {
2536
+			$this->_template_args['publish_delete_link'] = '';
2537
+		}
2538
+		if (! empty($name) && ! empty($id)) {
2539
+			$this->addPublishPostMetaBoxHiddenFields($name, ['type' => 'hidden', 'value' => $id]);
2540
+		}
2541
+		$hidden_fields = $this->_generate_admin_form_fields($this->publish_post_meta_box_hidden_fields, 'array');
2542
+		// add hidden fields
2543
+		$this->_template_args['publish_hidden_fields'] = $this->_template_args['publish_hidden_fields'] ?? '';
2544
+		foreach ($hidden_fields as $hidden_field) {
2545
+			$this->_template_args['publish_hidden_fields'] .= $hidden_field['field'] ?? '';
2546
+		}
2547
+	}
2548
+
2549
+
2550
+	/**
2551
+	 * @param string|null $name
2552
+	 * @param int|string  $id
2553
+	 * @param string|null $delete
2554
+	 * @param string|null $save_close_redirect_URL
2555
+	 * @param bool        $both_btns
2556
+	 * @throws EE_Error
2557
+	 */
2558
+	public function set_publish_post_box_vars(
2559
+		?string $name = '',
2560
+		$id = 0,
2561
+		?string $delete = '',
2562
+		?string $save_close_redirect_URL = '',
2563
+		bool $both_btns = false
2564
+	) {
2565
+		$this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2566
+	}
2567
+
2568
+
2569
+	protected function addPublishPostMetaBoxHiddenFields(string $field_name, array $field_attributes)
2570
+	{
2571
+		$this->publish_post_meta_box_hidden_fields[ $field_name ] = $field_attributes;
2572
+	}
2573
+
2574
+
2575
+	/**
2576
+	 * displays an error message to ppl who have javascript disabled
2577
+	 *
2578
+	 * @return void
2579
+	 */
2580
+	private function _display_no_javascript_warning()
2581
+	{
2582
+		?>
2583 2583
 <noscript>
2584 2584
 	<div id="no-js-message" class="error">
2585 2585
 		<p style="font-size:1.3em;">
2586 2586
 			<span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2587 2587
 			<?php esc_html_e(
2588
-                        '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.',
2589
-                        'event_espresso'
2590
-                    ); ?>
2588
+						'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.',
2589
+						'event_espresso'
2590
+					); ?>
2591 2591
 		</p>
2592 2592
 	</div>
2593 2593
 </noscript>
2594 2594
 <?php
2595
-    }
2596
-
2597
-
2598
-    /**
2599
-     * displays espresso success and/or error notices
2600
-     *
2601
-     * @return void
2602
-     */
2603
-    protected function _display_espresso_notices()
2604
-    {
2605
-        $notices = (array) $this->_get_transient(true);
2606
-        foreach ($notices as $notice) {
2607
-            echo $notice ? stripslashes($notice) : '';
2608
-        }
2609
-    }
2610
-
2611
-
2612
-    /**
2613
-     * spinny things pacify the masses
2614
-     *
2615
-     * @return void
2616
-     */
2617
-    protected function _add_admin_page_ajax_loading_img()
2618
-    {
2619
-        ?>
2595
+	}
2596
+
2597
+
2598
+	/**
2599
+	 * displays espresso success and/or error notices
2600
+	 *
2601
+	 * @return void
2602
+	 */
2603
+	protected function _display_espresso_notices()
2604
+	{
2605
+		$notices = (array) $this->_get_transient(true);
2606
+		foreach ($notices as $notice) {
2607
+			echo $notice ? stripslashes($notice) : '';
2608
+		}
2609
+	}
2610
+
2611
+
2612
+	/**
2613
+	 * spinny things pacify the masses
2614
+	 *
2615
+	 * @return void
2616
+	 */
2617
+	protected function _add_admin_page_ajax_loading_img()
2618
+	{
2619
+		?>
2620 2620
 <div id="espresso-ajax-loading" class="ajax-loading-grey">
2621 2621
 	<span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2622
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2622
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2623 2623
 </div>
2624 2624
 <?php
2625
-    }
2625
+	}
2626 2626
 
2627 2627
 
2628
-    /**
2629
-     * add admin page overlay for modal boxes
2630
-     *
2631
-     * @return void
2632
-     */
2633
-    protected function _add_admin_page_overlay()
2634
-    {
2635
-        ?>
2628
+	/**
2629
+	 * add admin page overlay for modal boxes
2630
+	 *
2631
+	 * @return void
2632
+	 */
2633
+	protected function _add_admin_page_overlay()
2634
+	{
2635
+		?>
2636 2636
 <div id="espresso-admin-page-overlay-dv" class=""></div>
2637 2637
 <?php
2638
-    }
2639
-
2640
-
2641
-    /**
2642
-     * facade for $this->addMetaBox()
2643
-     *
2644
-     * @param string   $action        where the metabox gets displayed
2645
-     * @param string   $title         Title of Metabox (output in metabox header)
2646
-     * @param callable $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2647
-     *                                instead of the one created in here.
2648
-     * @param array    $callback_args an array of args supplied for the metabox
2649
-     * @param string   $column        what metabox column
2650
-     * @param string   $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2651
-     * @param bool     $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2652
-     *                                created but just set our own callback for wp's add_meta_box.
2653
-     * @throws DomainException
2654
-     */
2655
-    public function _add_admin_page_meta_box(
2656
-        string $action,
2657
-        string $title,
2658
-        callable $callback,
2659
-        array $callback_args,
2660
-        string $column = 'normal',
2661
-        string $priority = 'high',
2662
-        bool $create_func = true
2663
-    ) {
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
-                echo EEH_Template::display_template(
2675
-                    $metabox['args']['template_path'],
2676
-                    $metabox['args']['template_args'],
2677
-                    true
2678
-                );
2679
-            }
2680
-            : $callback;
2681
-        $this->addMetaBox(
2682
-            str_replace('_', '-', $action) . '-mbox',
2683
-            $title,
2684
-            $call_back_func,
2685
-            $this->_wp_page_slug,
2686
-            $column,
2687
-            $priority,
2688
-            $callback_args
2689
-        );
2690
-    }
2691
-
2692
-
2693
-    /**
2694
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2695
-     *
2696
-     * @throws DomainException
2697
-     * @throws EE_Error
2698
-     * @throws InvalidArgumentException
2699
-     * @throws InvalidDataTypeException
2700
-     * @throws InvalidInterfaceException
2701
-     */
2702
-    public function display_admin_page_with_metabox_columns()
2703
-    {
2704
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2705
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2706
-            $this->_column_template_path,
2707
-            $this->_template_args,
2708
-            true
2709
-        );
2710
-        // the final wrapper
2711
-        $this->admin_page_wrapper();
2712
-    }
2713
-
2714
-
2715
-    /**
2716
-     * generates  HTML wrapper for an admin details page
2717
-     *
2718
-     * @return void
2719
-     * @throws DomainException
2720
-     * @throws EE_Error
2721
-     * @throws InvalidArgumentException
2722
-     * @throws InvalidDataTypeException
2723
-     * @throws InvalidInterfaceException
2724
-     */
2725
-    public function display_admin_page_with_sidebar()
2726
-    {
2727
-        $this->_display_admin_page(true);
2728
-    }
2729
-
2730
-
2731
-    /**
2732
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2733
-     *
2734
-     * @return void
2735
-     * @throws DomainException
2736
-     * @throws EE_Error
2737
-     * @throws InvalidArgumentException
2738
-     * @throws InvalidDataTypeException
2739
-     * @throws InvalidInterfaceException
2740
-     */
2741
-    public function display_admin_page_with_no_sidebar()
2742
-    {
2743
-        $this->_display_admin_page();
2744
-    }
2745
-
2746
-
2747
-    /**
2748
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2749
-     *
2750
-     * @return void
2751
-     * @throws DomainException
2752
-     * @throws EE_Error
2753
-     * @throws InvalidArgumentException
2754
-     * @throws InvalidDataTypeException
2755
-     * @throws InvalidInterfaceException
2756
-     */
2757
-    public function display_about_admin_page()
2758
-    {
2759
-        $this->_display_admin_page(false, true);
2760
-    }
2761
-
2762
-
2763
-    /**
2764
-     * display_admin_page
2765
-     * contains the code for actually displaying an admin page
2766
-     *
2767
-     * @param bool $sidebar true with sidebar, false without
2768
-     * @param bool $about   use the About admin wrapper instead of the default.
2769
-     * @return void
2770
-     * @throws DomainException
2771
-     * @throws EE_Error
2772
-     * @throws InvalidArgumentException
2773
-     * @throws InvalidDataTypeException
2774
-     * @throws InvalidInterfaceException
2775
-     */
2776
-    private function _display_admin_page(bool $sidebar = false, bool $about = false): void
2777
-    {
2778
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2779
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2780
-
2781
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2782
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2783
-        $post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2784
-
2785
-        $this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2786
-                                                  && $this->_req_action !== 'data_reset'
2787
-                                                  && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2788
-                                                  && strpos($post_body_content, 'wp-list-table') === false;
2789
-
2790
-        $this->_template_args['current_page']                 = $this->_wp_page_slug;
2791
-        $this->_template_args['admin_page_wrapper_div_id']    = $this->_cpt_route
2792
-            ? 'poststuff'
2793
-            : 'espresso-default-admin';
2794
-        $this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2795
-                                                                    'event-espresso_page_espresso_',
2796
-                                                                    '',
2797
-                                                                    $this->_wp_page_slug
2798
-                                                                ) . ' ' . $this->_req_action . '-route';
2799
-
2800
-        $template_path = $sidebar
2801
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2802
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2803
-
2804
-        $this->_template_args['is_ajax'] = $this->request->isAjax();
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
-
2814
-        // ensure $post_type and $post are set
2815
-        // to prevent WooCommerce from blowing things up if not using CPT
2816
-        global $post_type, $post;
2817
-        $this->_template_args['post_type'] = $post_type ?? '';
2818
-        $this->_template_args['post']  = $post ?? new WP_Post( (object) [ 'ID' => 0, 'filter' => 'raw' ] );
2819
-
2820
-        $this->_template_args['post_body_content'] = EEH_Template::display_template(
2821
-            EE_ADMIN_TEMPLATE . 'admin_details_wrapper_post_body_content.template.php',
2822
-            $this->_template_args,
2823
-            true
2824
-        );
2825
-
2826
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2827
-            $template_path,
2828
-            $this->_template_args,
2829
-            true
2830
-        );
2831
-        // the final template wrapper
2832
-        $this->admin_page_wrapper($about);
2833
-    }
2834
-
2835
-
2836
-    /**
2837
-     * This is used to display caf preview pages.
2838
-     *
2839
-     * @param string $utm_campaign_source what is the key used for Google Analytics link
2840
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2841
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2842
-     * @return void
2843
-     * @throws DomainException
2844
-     * @throws EE_Error
2845
-     * @throws InvalidArgumentException
2846
-     * @throws InvalidDataTypeException
2847
-     * @throws InvalidInterfaceException
2848
-     * @since 4.3.2
2849
-     */
2850
-    public function display_admin_caf_preview_page(string $utm_campaign_source = '', bool $display_sidebar = true)
2851
-    {
2852
-        // let's generate a default preview action button if there isn't one already present.
2853
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2854
-            'Upgrade to Event Espresso 4 Right Now',
2855
-            'event_espresso'
2856
-        );
2857
-        $buy_now_url                                   = add_query_arg(
2858
-            [
2859
-                'ee_ver'       => 'ee4',
2860
-                'utm_source'   => 'ee4_plugin_admin',
2861
-                'utm_medium'   => 'link',
2862
-                'utm_campaign' => $utm_campaign_source,
2863
-                'utm_content'  => 'buy_now_button',
2864
-            ],
2865
-            'https://eventespresso.com/pricing/'
2866
-        );
2867
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2868
-            ? $this->get_action_link_or_button(
2869
-                '',
2870
-                'buy_now',
2871
-                [],
2872
-                'button button--primary button--big',
2873
-                esc_url_raw($buy_now_url),
2874
-                true
2875
-            )
2876
-            : $this->_template_args['preview_action_button'];
2877
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2878
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2879
-            $this->_template_args,
2880
-            true
2881
-        );
2882
-        $this->_display_admin_page($display_sidebar);
2883
-    }
2884
-
2885
-
2886
-    /**
2887
-     * display_admin_list_table_page_with_sidebar
2888
-     * generates HTML wrapper for an admin_page with list_table
2889
-     *
2890
-     * @return void
2891
-     * @throws DomainException
2892
-     * @throws EE_Error
2893
-     * @throws InvalidArgumentException
2894
-     * @throws InvalidDataTypeException
2895
-     * @throws InvalidInterfaceException
2896
-     */
2897
-    public function display_admin_list_table_page_with_sidebar()
2898
-    {
2899
-        $this->_display_admin_list_table_page(true);
2900
-    }
2901
-
2902
-
2903
-    /**
2904
-     * display_admin_list_table_page_with_no_sidebar
2905
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2906
-     *
2907
-     * @return void
2908
-     * @throws DomainException
2909
-     * @throws EE_Error
2910
-     * @throws InvalidArgumentException
2911
-     * @throws InvalidDataTypeException
2912
-     * @throws InvalidInterfaceException
2913
-     */
2914
-    public function display_admin_list_table_page_with_no_sidebar()
2915
-    {
2916
-        $this->_display_admin_list_table_page();
2917
-    }
2918
-
2919
-
2920
-    /**
2921
-     * generates html wrapper for an admin_list_table page
2922
-     *
2923
-     * @param bool $sidebar whether to display with sidebar or not.
2924
-     * @return void
2925
-     * @throws DomainException
2926
-     * @throws EE_Error
2927
-     * @throws InvalidArgumentException
2928
-     * @throws InvalidDataTypeException
2929
-     * @throws InvalidInterfaceException
2930
-     */
2931
-    private function _display_admin_list_table_page(bool $sidebar = false)
2932
-    {
2933
-        // setup search attributes
2934
-        $this->_set_search_attributes();
2935
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
2936
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2937
-        $this->_template_args['table_url']        = $this->request->isAjax()
2938
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2939
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2940
-        $this->_template_args['list_table']       = $this->_list_table_object;
2941
-        $this->_template_args['current_route']    = $this->_req_action;
2942
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2943
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2944
-        if (! empty($ajax_sorting_callback)) {
2945
-            $sortable_list_table_form_fields = wp_nonce_field(
2946
-                $ajax_sorting_callback . '_nonce',
2947
-                $ajax_sorting_callback . '_nonce',
2948
-                false,
2949
-                false
2950
-            );
2951
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2952
-                                                . $this->page_slug
2953
-                                                . '" />';
2954
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2955
-                                                . $ajax_sorting_callback
2956
-                                                . '" />';
2957
-        } else {
2958
-            $sortable_list_table_form_fields = '';
2959
-        }
2960
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2961
-
2962
-        $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2963
-
2964
-        $nonce_ref          = $this->_req_action . '_nonce';
2965
-        $hidden_form_fields .= '
2638
+	}
2639
+
2640
+
2641
+	/**
2642
+	 * facade for $this->addMetaBox()
2643
+	 *
2644
+	 * @param string   $action        where the metabox gets displayed
2645
+	 * @param string   $title         Title of Metabox (output in metabox header)
2646
+	 * @param callable $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2647
+	 *                                instead of the one created in here.
2648
+	 * @param array    $callback_args an array of args supplied for the metabox
2649
+	 * @param string   $column        what metabox column
2650
+	 * @param string   $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2651
+	 * @param bool     $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2652
+	 *                                created but just set our own callback for wp's add_meta_box.
2653
+	 * @throws DomainException
2654
+	 */
2655
+	public function _add_admin_page_meta_box(
2656
+		string $action,
2657
+		string $title,
2658
+		callable $callback,
2659
+		array $callback_args,
2660
+		string $column = 'normal',
2661
+		string $priority = 'high',
2662
+		bool $create_func = true
2663
+	) {
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
+				echo EEH_Template::display_template(
2675
+					$metabox['args']['template_path'],
2676
+					$metabox['args']['template_args'],
2677
+					true
2678
+				);
2679
+			}
2680
+			: $callback;
2681
+		$this->addMetaBox(
2682
+			str_replace('_', '-', $action) . '-mbox',
2683
+			$title,
2684
+			$call_back_func,
2685
+			$this->_wp_page_slug,
2686
+			$column,
2687
+			$priority,
2688
+			$callback_args
2689
+		);
2690
+	}
2691
+
2692
+
2693
+	/**
2694
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2695
+	 *
2696
+	 * @throws DomainException
2697
+	 * @throws EE_Error
2698
+	 * @throws InvalidArgumentException
2699
+	 * @throws InvalidDataTypeException
2700
+	 * @throws InvalidInterfaceException
2701
+	 */
2702
+	public function display_admin_page_with_metabox_columns()
2703
+	{
2704
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2705
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2706
+			$this->_column_template_path,
2707
+			$this->_template_args,
2708
+			true
2709
+		);
2710
+		// the final wrapper
2711
+		$this->admin_page_wrapper();
2712
+	}
2713
+
2714
+
2715
+	/**
2716
+	 * generates  HTML wrapper for an admin details page
2717
+	 *
2718
+	 * @return void
2719
+	 * @throws DomainException
2720
+	 * @throws EE_Error
2721
+	 * @throws InvalidArgumentException
2722
+	 * @throws InvalidDataTypeException
2723
+	 * @throws InvalidInterfaceException
2724
+	 */
2725
+	public function display_admin_page_with_sidebar()
2726
+	{
2727
+		$this->_display_admin_page(true);
2728
+	}
2729
+
2730
+
2731
+	/**
2732
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2733
+	 *
2734
+	 * @return void
2735
+	 * @throws DomainException
2736
+	 * @throws EE_Error
2737
+	 * @throws InvalidArgumentException
2738
+	 * @throws InvalidDataTypeException
2739
+	 * @throws InvalidInterfaceException
2740
+	 */
2741
+	public function display_admin_page_with_no_sidebar()
2742
+	{
2743
+		$this->_display_admin_page();
2744
+	}
2745
+
2746
+
2747
+	/**
2748
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2749
+	 *
2750
+	 * @return void
2751
+	 * @throws DomainException
2752
+	 * @throws EE_Error
2753
+	 * @throws InvalidArgumentException
2754
+	 * @throws InvalidDataTypeException
2755
+	 * @throws InvalidInterfaceException
2756
+	 */
2757
+	public function display_about_admin_page()
2758
+	{
2759
+		$this->_display_admin_page(false, true);
2760
+	}
2761
+
2762
+
2763
+	/**
2764
+	 * display_admin_page
2765
+	 * contains the code for actually displaying an admin page
2766
+	 *
2767
+	 * @param bool $sidebar true with sidebar, false without
2768
+	 * @param bool $about   use the About admin wrapper instead of the default.
2769
+	 * @return void
2770
+	 * @throws DomainException
2771
+	 * @throws EE_Error
2772
+	 * @throws InvalidArgumentException
2773
+	 * @throws InvalidDataTypeException
2774
+	 * @throws InvalidInterfaceException
2775
+	 */
2776
+	private function _display_admin_page(bool $sidebar = false, bool $about = false): void
2777
+	{
2778
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2779
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2780
+
2781
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2782
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2783
+		$post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2784
+
2785
+		$this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2786
+												  && $this->_req_action !== 'data_reset'
2787
+												  && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2788
+												  && strpos($post_body_content, 'wp-list-table') === false;
2789
+
2790
+		$this->_template_args['current_page']                 = $this->_wp_page_slug;
2791
+		$this->_template_args['admin_page_wrapper_div_id']    = $this->_cpt_route
2792
+			? 'poststuff'
2793
+			: 'espresso-default-admin';
2794
+		$this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2795
+																	'event-espresso_page_espresso_',
2796
+																	'',
2797
+																	$this->_wp_page_slug
2798
+																) . ' ' . $this->_req_action . '-route';
2799
+
2800
+		$template_path = $sidebar
2801
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2802
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2803
+
2804
+		$this->_template_args['is_ajax'] = $this->request->isAjax();
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
+
2814
+		// ensure $post_type and $post are set
2815
+		// to prevent WooCommerce from blowing things up if not using CPT
2816
+		global $post_type, $post;
2817
+		$this->_template_args['post_type'] = $post_type ?? '';
2818
+		$this->_template_args['post']  = $post ?? new WP_Post( (object) [ 'ID' => 0, 'filter' => 'raw' ] );
2819
+
2820
+		$this->_template_args['post_body_content'] = EEH_Template::display_template(
2821
+			EE_ADMIN_TEMPLATE . 'admin_details_wrapper_post_body_content.template.php',
2822
+			$this->_template_args,
2823
+			true
2824
+		);
2825
+
2826
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2827
+			$template_path,
2828
+			$this->_template_args,
2829
+			true
2830
+		);
2831
+		// the final template wrapper
2832
+		$this->admin_page_wrapper($about);
2833
+	}
2834
+
2835
+
2836
+	/**
2837
+	 * This is used to display caf preview pages.
2838
+	 *
2839
+	 * @param string $utm_campaign_source what is the key used for Google Analytics link
2840
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2841
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2842
+	 * @return void
2843
+	 * @throws DomainException
2844
+	 * @throws EE_Error
2845
+	 * @throws InvalidArgumentException
2846
+	 * @throws InvalidDataTypeException
2847
+	 * @throws InvalidInterfaceException
2848
+	 * @since 4.3.2
2849
+	 */
2850
+	public function display_admin_caf_preview_page(string $utm_campaign_source = '', bool $display_sidebar = true)
2851
+	{
2852
+		// let's generate a default preview action button if there isn't one already present.
2853
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2854
+			'Upgrade to Event Espresso 4 Right Now',
2855
+			'event_espresso'
2856
+		);
2857
+		$buy_now_url                                   = add_query_arg(
2858
+			[
2859
+				'ee_ver'       => 'ee4',
2860
+				'utm_source'   => 'ee4_plugin_admin',
2861
+				'utm_medium'   => 'link',
2862
+				'utm_campaign' => $utm_campaign_source,
2863
+				'utm_content'  => 'buy_now_button',
2864
+			],
2865
+			'https://eventespresso.com/pricing/'
2866
+		);
2867
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2868
+			? $this->get_action_link_or_button(
2869
+				'',
2870
+				'buy_now',
2871
+				[],
2872
+				'button button--primary button--big',
2873
+				esc_url_raw($buy_now_url),
2874
+				true
2875
+			)
2876
+			: $this->_template_args['preview_action_button'];
2877
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2878
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2879
+			$this->_template_args,
2880
+			true
2881
+		);
2882
+		$this->_display_admin_page($display_sidebar);
2883
+	}
2884
+
2885
+
2886
+	/**
2887
+	 * display_admin_list_table_page_with_sidebar
2888
+	 * generates HTML wrapper for an admin_page with list_table
2889
+	 *
2890
+	 * @return void
2891
+	 * @throws DomainException
2892
+	 * @throws EE_Error
2893
+	 * @throws InvalidArgumentException
2894
+	 * @throws InvalidDataTypeException
2895
+	 * @throws InvalidInterfaceException
2896
+	 */
2897
+	public function display_admin_list_table_page_with_sidebar()
2898
+	{
2899
+		$this->_display_admin_list_table_page(true);
2900
+	}
2901
+
2902
+
2903
+	/**
2904
+	 * display_admin_list_table_page_with_no_sidebar
2905
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2906
+	 *
2907
+	 * @return void
2908
+	 * @throws DomainException
2909
+	 * @throws EE_Error
2910
+	 * @throws InvalidArgumentException
2911
+	 * @throws InvalidDataTypeException
2912
+	 * @throws InvalidInterfaceException
2913
+	 */
2914
+	public function display_admin_list_table_page_with_no_sidebar()
2915
+	{
2916
+		$this->_display_admin_list_table_page();
2917
+	}
2918
+
2919
+
2920
+	/**
2921
+	 * generates html wrapper for an admin_list_table page
2922
+	 *
2923
+	 * @param bool $sidebar whether to display with sidebar or not.
2924
+	 * @return void
2925
+	 * @throws DomainException
2926
+	 * @throws EE_Error
2927
+	 * @throws InvalidArgumentException
2928
+	 * @throws InvalidDataTypeException
2929
+	 * @throws InvalidInterfaceException
2930
+	 */
2931
+	private function _display_admin_list_table_page(bool $sidebar = false)
2932
+	{
2933
+		// setup search attributes
2934
+		$this->_set_search_attributes();
2935
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
2936
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2937
+		$this->_template_args['table_url']        = $this->request->isAjax()
2938
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2939
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2940
+		$this->_template_args['list_table']       = $this->_list_table_object;
2941
+		$this->_template_args['current_route']    = $this->_req_action;
2942
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2943
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2944
+		if (! empty($ajax_sorting_callback)) {
2945
+			$sortable_list_table_form_fields = wp_nonce_field(
2946
+				$ajax_sorting_callback . '_nonce',
2947
+				$ajax_sorting_callback . '_nonce',
2948
+				false,
2949
+				false
2950
+			);
2951
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2952
+												. $this->page_slug
2953
+												. '" />';
2954
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2955
+												. $ajax_sorting_callback
2956
+												. '" />';
2957
+		} else {
2958
+			$sortable_list_table_form_fields = '';
2959
+		}
2960
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2961
+
2962
+		$hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2963
+
2964
+		$nonce_ref          = $this->_req_action . '_nonce';
2965
+		$hidden_form_fields .= '
2966 2966
             <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2967 2967
 
2968
-        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2969
-        // display message about search results?
2970
-        $search                                    = $this->request->getRequestParam('s');
2971
-        $this->_template_args['before_list_table'] .= ! empty($search)
2972
-            ? '<p class="ee-search-results">' . sprintf(
2973
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2974
-                trim($search, '%')
2975
-            ) . '</p>'
2976
-            : '';
2977
-        // filter before_list_table template arg
2978
-        $this->_template_args['before_list_table'] = apply_filters(
2979
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2980
-            $this->_template_args['before_list_table'],
2981
-            $this->page_slug,
2982
-            $this->request->requestParams(),
2983
-            $this->_req_action
2984
-        );
2985
-        // convert to array and filter again
2986
-        // arrays are easier to inject new items in a specific location,
2987
-        // but would not be backwards compatible, so we have to add a new filter
2988
-        $this->_template_args['before_list_table'] = implode(
2989
-            " \n",
2990
-            (array) apply_filters(
2991
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2992
-                (array) $this->_template_args['before_list_table'],
2993
-                $this->page_slug,
2994
-                $this->request->requestParams(),
2995
-                $this->_req_action
2996
-            )
2997
-        );
2998
-        // filter after_list_table template arg
2999
-        $this->_template_args['after_list_table'] = apply_filters(
3000
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3001
-            $this->_template_args['after_list_table'],
3002
-            $this->page_slug,
3003
-            $this->request->requestParams(),
3004
-            $this->_req_action
3005
-        );
3006
-        // convert to array and filter again
3007
-        // arrays are easier to inject new items in a specific location,
3008
-        // but would not be backwards compatible, so we have to add a new filter
3009
-        $this->_template_args['after_list_table']   = implode(
3010
-            " \n",
3011
-            (array) apply_filters(
3012
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3013
-                (array) $this->_template_args['after_list_table'],
3014
-                $this->page_slug,
3015
-                $this->request->requestParams(),
3016
-                $this->_req_action
3017
-            )
3018
-        );
3019
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3020
-            $template_path,
3021
-            $this->_template_args,
3022
-            true
3023
-        );
3024
-        // the final template wrapper
3025
-        if ($sidebar) {
3026
-            $this->display_admin_page_with_sidebar();
3027
-        } else {
3028
-            $this->display_admin_page_with_no_sidebar();
3029
-        }
3030
-    }
3031
-
3032
-
3033
-    /**
3034
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3035
-     * html string for the legend.
3036
-     * $items are expected in an array in the following format:
3037
-     * $legend_items = array(
3038
-     *        'item_id' => array(
3039
-     *            'icon' => 'http://url_to_icon_being_described.png',
3040
-     *            'desc' => esc_html__('localized description of item');
3041
-     *        )
3042
-     * );
3043
-     *
3044
-     * @param array $items see above for format of array
3045
-     * @return string html string of legend
3046
-     * @throws DomainException
3047
-     */
3048
-    protected function _display_legend(array $items): string
3049
-    {
3050
-        $this->_template_args['items'] = (array) apply_filters(
3051
-            'FHEE__EE_Admin_Page___display_legend__items',
3052
-            $items,
3053
-            $this
3054
-        );
3055
-        /** @var StatusChangeNotice $status_change_notice */
3056
-        $status_change_notice                         = $this->loader->getShared(
3057
-            'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3058
-        );
3059
-        $this->_template_args['status_change_notice'] = $status_change_notice->display(
3060
-            '__admin-legend',
3061
-            $this->page_slug
3062
-        );
3063
-        return EEH_Template::display_template(
3064
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3065
-            $this->_template_args,
3066
-            true
3067
-        );
3068
-    }
3069
-
3070
-
3071
-    /**
3072
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3073
-     * The returned json object is created from an array in the following format:
3074
-     * array(
3075
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3076
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3077
-     *  'notices' => '', // - contains any EE_Error formatted notices
3078
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3079
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3080
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3081
-     *  that might be included in here)
3082
-     * )
3083
-     * The json object is populated by whatever is set in the $_template_args property.
3084
-     *
3085
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3086
-     *                                 instead of displayed.
3087
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3088
-     * @return void
3089
-     * @throws EE_Error
3090
-     * @throws InvalidArgumentException
3091
-     * @throws InvalidDataTypeException
3092
-     * @throws InvalidInterfaceException
3093
-     */
3094
-    protected function _return_json(bool $sticky_notices = false, array $notices_arguments = [])
3095
-    {
3096
-        // make sure any EE_Error notices have been handled.
3097
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3098
-        $data = $this->_template_args['data'] ?? [];
3099
-        unset($this->_template_args['data']);
3100
-        $json = [
3101
-            'error'     => $this->_template_args['error'] ?? false,
3102
-            'success'   => $this->_template_args['success'] ?? false,
3103
-            'errors'    => $this->_template_args['errors'] ?? false,
3104
-            'attention' => $this->_template_args['attention'] ?? false,
3105
-            'notices'   => EE_Error::get_notices(),
3106
-            'content'   => $this->_template_args['admin_page_content'] ?? '',
3107
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3108
-            'isEEajax'  => true,
3109
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3110
-        ];
3111
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3112
-        if (null === error_get_last() || ! headers_sent()) {
3113
-            header('Content-Type: application/json; charset=UTF-8');
3114
-        }
3115
-        echo wp_json_encode($json);
3116
-        exit();
3117
-    }
3118
-
3119
-
3120
-    /**
3121
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3122
-     *
3123
-     * @return void
3124
-     * @throws EE_Error
3125
-     * @throws InvalidArgumentException
3126
-     * @throws InvalidDataTypeException
3127
-     * @throws InvalidInterfaceException
3128
-     */
3129
-    public function return_json()
3130
-    {
3131
-        if ($this->request->isAjax()) {
3132
-            $this->_return_json();
3133
-        } else {
3134
-            throw new EE_Error(
3135
-                sprintf(
3136
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3137
-                    __FUNCTION__
3138
-                )
3139
-            );
3140
-        }
3141
-    }
3142
-
3143
-
3144
-    /**
3145
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3146
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3147
-     *
3148
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3149
-     * @deprecated  5.0.8.p
3150
-     */
3151
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3152
-    {
3153
-        $this->_hook_obj = $hook_obj;
3154
-    }
3155
-
3156
-
3157
-    /**
3158
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3159
-     *
3160
-     * @param bool $about whether to use the special about page wrapper or default.
3161
-     * @return void
3162
-     * @throws DomainException
3163
-     * @throws EE_Error
3164
-     * @throws InvalidArgumentException
3165
-     * @throws InvalidDataTypeException
3166
-     * @throws InvalidInterfaceException
3167
-     */
3168
-    public function admin_page_wrapper(bool $about = false)
3169
-    {
3170
-        $this->_template_args['nav_tabs']         = $this->_get_main_nav_tabs();
3171
-        $this->_template_args['admin_page_title'] = $this->_admin_page_title;
3172
-
3173
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3174
-            "FHEE_before_admin_page_content$this->_current_page$this->_current_view",
3175
-            $this->_template_args['before_admin_page_content'] ?? ''
3176
-        );
3177
-
3178
-        $this->_template_args['after_admin_page_content'] = apply_filters(
3179
-            "FHEE_after_admin_page_content$this->_current_page$this->_current_view",
3180
-            $this->_template_args['after_admin_page_content'] ?? ''
3181
-        );
3182
-        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3183
-
3184
-        if ($this->request->isAjax()) {
3185
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3186
-            // $template_path,
3187
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3188
-                $this->_template_args,
3189
-                true
3190
-            );
3191
-            $this->_return_json();
3192
-        }
3193
-        // load settings page wrapper template
3194
-        $template_path = $about
3195
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3196
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3197
-
3198
-        EEH_Template::display_template($template_path, $this->_template_args);
3199
-    }
3200
-
3201
-
3202
-    /**
3203
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3204
-     *
3205
-     * @return string html
3206
-     * @throws EE_Error
3207
-     */
3208
-    protected function _get_main_nav_tabs(): string
3209
-    {
3210
-        // let's generate the html using the EEH_Tabbed_Content helper.
3211
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3212
-        // (rather than setting in the page_routes array)
3213
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs, $this->page_slug);
3214
-    }
3215
-
3216
-
3217
-    /**
3218
-     *        sort nav tabs
3219
-     *
3220
-     * @param array $a
3221
-     * @param array $b
3222
-     * @return int
3223
-     */
3224
-    private function _sort_nav_tabs(array $a, array $b): int
3225
-    {
3226
-        if ($a['order'] === $b['order']) {
3227
-            return 0;
3228
-        }
3229
-        return ($a['order'] < $b['order']) ? -1 : 1;
3230
-    }
3231
-
3232
-
3233
-    /**
3234
-     * generates HTML for the forms used on admin pages
3235
-     *
3236
-     * @param array  $input_vars - array of input field details
3237
-     * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3238
-     * @param bool   $id
3239
-     * @return array|string
3240
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3241
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3242
-     */
3243
-    protected function _generate_admin_form_fields(
3244
-        array $input_vars = [],
3245
-        string $generator = 'string',
3246
-        bool $id = false
3247
-    ) {
3248
-        return $generator === 'string'
3249
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3250
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3251
-    }
3252
-
3253
-
3254
-    /**
3255
-     * generates the "Save" and "Save & Close" buttons for edit forms
3256
-     *
3257
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3258
-     *                                   Close" button.
3259
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3260
-     *                                   'Save', [1] => 'save & close')
3261
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3262
-     *                                   via the "name" value in the button).  We can also use this to just dump
3263
-     *                                   default actions by submitting some other value.
3264
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Otherwise it
3265
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3266
-     *                                   close (normal form handling).
3267
-     */
3268
-    protected function _set_save_buttons(bool $both = true, array $text = [], array $actions = [], $referrer = null)
3269
-    {
3270
-        $referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3271
-        $button_text   = ! empty($text)
3272
-            ? $text
3273
-            : [
3274
-                esc_html__('Save', 'event_espresso'),
3275
-                esc_html__('Save and Close', 'event_espresso'),
3276
-            ];
3277
-        $default_names = ['save', 'save_and_close'];
3278
-        $buttons       = '';
3279
-        foreach ($button_text as $key => $button) {
3280
-            $ref     = $default_names[ $key ];
3281
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3282
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3283
-                        . 'value="' . $button . '" name="' . $name . '" '
3284
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3285
-            if (! $both) {
3286
-                break;
3287
-            }
3288
-        }
3289
-        // add in a hidden index for the current page (so save and close redirects properly)
3290
-        $buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3291
-                    . $referrer_url
3292
-                    . '" />';
3293
-
3294
-        $this->_template_args['save_buttons'] = $buttons;
3295
-    }
3296
-
3297
-
3298
-    /**
3299
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3300
-     *
3301
-     * @param string $route
3302
-     * @param array  $additional_hidden_fields
3303
-     * @see   $this->_set_add_edit_form_tags() for details on params
3304
-     * @since 4.6.0
3305
-     */
3306
-    public function set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3307
-    {
3308
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3309
-    }
3310
-
3311
-
3312
-    /**
3313
-     * set form open and close tags on add/edit pages.
3314
-     *
3315
-     * @param string $route                    the route you want the form to direct to
3316
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3317
-     * @return void
3318
-     */
3319
-    protected function _set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3320
-    {
3321
-        if (empty($route)) {
3322
-            $user_msg = esc_html__(
3323
-                'An error occurred. No action was set for this page\'s form.',
3324
-                'event_espresso'
3325
-            );
3326
-            $dev_msg  = $user_msg . "\n"
3327
-                        . sprintf(
3328
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3329
-                            __FUNCTION__,
3330
-                            __CLASS__
3331
-                        );
3332
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3333
-        }
3334
-        // open form
3335
-        $action                                            = $this->_admin_base_url;
3336
-        $this->_template_args['before_admin_page_content'] = "
2968
+		$this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2969
+		// display message about search results?
2970
+		$search                                    = $this->request->getRequestParam('s');
2971
+		$this->_template_args['before_list_table'] .= ! empty($search)
2972
+			? '<p class="ee-search-results">' . sprintf(
2973
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2974
+				trim($search, '%')
2975
+			) . '</p>'
2976
+			: '';
2977
+		// filter before_list_table template arg
2978
+		$this->_template_args['before_list_table'] = apply_filters(
2979
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2980
+			$this->_template_args['before_list_table'],
2981
+			$this->page_slug,
2982
+			$this->request->requestParams(),
2983
+			$this->_req_action
2984
+		);
2985
+		// convert to array and filter again
2986
+		// arrays are easier to inject new items in a specific location,
2987
+		// but would not be backwards compatible, so we have to add a new filter
2988
+		$this->_template_args['before_list_table'] = implode(
2989
+			" \n",
2990
+			(array) apply_filters(
2991
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2992
+				(array) $this->_template_args['before_list_table'],
2993
+				$this->page_slug,
2994
+				$this->request->requestParams(),
2995
+				$this->_req_action
2996
+			)
2997
+		);
2998
+		// filter after_list_table template arg
2999
+		$this->_template_args['after_list_table'] = apply_filters(
3000
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3001
+			$this->_template_args['after_list_table'],
3002
+			$this->page_slug,
3003
+			$this->request->requestParams(),
3004
+			$this->_req_action
3005
+		);
3006
+		// convert to array and filter again
3007
+		// arrays are easier to inject new items in a specific location,
3008
+		// but would not be backwards compatible, so we have to add a new filter
3009
+		$this->_template_args['after_list_table']   = implode(
3010
+			" \n",
3011
+			(array) apply_filters(
3012
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3013
+				(array) $this->_template_args['after_list_table'],
3014
+				$this->page_slug,
3015
+				$this->request->requestParams(),
3016
+				$this->_req_action
3017
+			)
3018
+		);
3019
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3020
+			$template_path,
3021
+			$this->_template_args,
3022
+			true
3023
+		);
3024
+		// the final template wrapper
3025
+		if ($sidebar) {
3026
+			$this->display_admin_page_with_sidebar();
3027
+		} else {
3028
+			$this->display_admin_page_with_no_sidebar();
3029
+		}
3030
+	}
3031
+
3032
+
3033
+	/**
3034
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3035
+	 * html string for the legend.
3036
+	 * $items are expected in an array in the following format:
3037
+	 * $legend_items = array(
3038
+	 *        'item_id' => array(
3039
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3040
+	 *            'desc' => esc_html__('localized description of item');
3041
+	 *        )
3042
+	 * );
3043
+	 *
3044
+	 * @param array $items see above for format of array
3045
+	 * @return string html string of legend
3046
+	 * @throws DomainException
3047
+	 */
3048
+	protected function _display_legend(array $items): string
3049
+	{
3050
+		$this->_template_args['items'] = (array) apply_filters(
3051
+			'FHEE__EE_Admin_Page___display_legend__items',
3052
+			$items,
3053
+			$this
3054
+		);
3055
+		/** @var StatusChangeNotice $status_change_notice */
3056
+		$status_change_notice                         = $this->loader->getShared(
3057
+			'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3058
+		);
3059
+		$this->_template_args['status_change_notice'] = $status_change_notice->display(
3060
+			'__admin-legend',
3061
+			$this->page_slug
3062
+		);
3063
+		return EEH_Template::display_template(
3064
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3065
+			$this->_template_args,
3066
+			true
3067
+		);
3068
+	}
3069
+
3070
+
3071
+	/**
3072
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3073
+	 * The returned json object is created from an array in the following format:
3074
+	 * array(
3075
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3076
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3077
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3078
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3079
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3080
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3081
+	 *  that might be included in here)
3082
+	 * )
3083
+	 * The json object is populated by whatever is set in the $_template_args property.
3084
+	 *
3085
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3086
+	 *                                 instead of displayed.
3087
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3088
+	 * @return void
3089
+	 * @throws EE_Error
3090
+	 * @throws InvalidArgumentException
3091
+	 * @throws InvalidDataTypeException
3092
+	 * @throws InvalidInterfaceException
3093
+	 */
3094
+	protected function _return_json(bool $sticky_notices = false, array $notices_arguments = [])
3095
+	{
3096
+		// make sure any EE_Error notices have been handled.
3097
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3098
+		$data = $this->_template_args['data'] ?? [];
3099
+		unset($this->_template_args['data']);
3100
+		$json = [
3101
+			'error'     => $this->_template_args['error'] ?? false,
3102
+			'success'   => $this->_template_args['success'] ?? false,
3103
+			'errors'    => $this->_template_args['errors'] ?? false,
3104
+			'attention' => $this->_template_args['attention'] ?? false,
3105
+			'notices'   => EE_Error::get_notices(),
3106
+			'content'   => $this->_template_args['admin_page_content'] ?? '',
3107
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3108
+			'isEEajax'  => true,
3109
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3110
+		];
3111
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3112
+		if (null === error_get_last() || ! headers_sent()) {
3113
+			header('Content-Type: application/json; charset=UTF-8');
3114
+		}
3115
+		echo wp_json_encode($json);
3116
+		exit();
3117
+	}
3118
+
3119
+
3120
+	/**
3121
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3122
+	 *
3123
+	 * @return void
3124
+	 * @throws EE_Error
3125
+	 * @throws InvalidArgumentException
3126
+	 * @throws InvalidDataTypeException
3127
+	 * @throws InvalidInterfaceException
3128
+	 */
3129
+	public function return_json()
3130
+	{
3131
+		if ($this->request->isAjax()) {
3132
+			$this->_return_json();
3133
+		} else {
3134
+			throw new EE_Error(
3135
+				sprintf(
3136
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3137
+					__FUNCTION__
3138
+				)
3139
+			);
3140
+		}
3141
+	}
3142
+
3143
+
3144
+	/**
3145
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3146
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3147
+	 *
3148
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3149
+	 * @deprecated  5.0.8.p
3150
+	 */
3151
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3152
+	{
3153
+		$this->_hook_obj = $hook_obj;
3154
+	}
3155
+
3156
+
3157
+	/**
3158
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3159
+	 *
3160
+	 * @param bool $about whether to use the special about page wrapper or default.
3161
+	 * @return void
3162
+	 * @throws DomainException
3163
+	 * @throws EE_Error
3164
+	 * @throws InvalidArgumentException
3165
+	 * @throws InvalidDataTypeException
3166
+	 * @throws InvalidInterfaceException
3167
+	 */
3168
+	public function admin_page_wrapper(bool $about = false)
3169
+	{
3170
+		$this->_template_args['nav_tabs']         = $this->_get_main_nav_tabs();
3171
+		$this->_template_args['admin_page_title'] = $this->_admin_page_title;
3172
+
3173
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3174
+			"FHEE_before_admin_page_content$this->_current_page$this->_current_view",
3175
+			$this->_template_args['before_admin_page_content'] ?? ''
3176
+		);
3177
+
3178
+		$this->_template_args['after_admin_page_content'] = apply_filters(
3179
+			"FHEE_after_admin_page_content$this->_current_page$this->_current_view",
3180
+			$this->_template_args['after_admin_page_content'] ?? ''
3181
+		);
3182
+		$this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3183
+
3184
+		if ($this->request->isAjax()) {
3185
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3186
+			// $template_path,
3187
+				EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3188
+				$this->_template_args,
3189
+				true
3190
+			);
3191
+			$this->_return_json();
3192
+		}
3193
+		// load settings page wrapper template
3194
+		$template_path = $about
3195
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3196
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3197
+
3198
+		EEH_Template::display_template($template_path, $this->_template_args);
3199
+	}
3200
+
3201
+
3202
+	/**
3203
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3204
+	 *
3205
+	 * @return string html
3206
+	 * @throws EE_Error
3207
+	 */
3208
+	protected function _get_main_nav_tabs(): string
3209
+	{
3210
+		// let's generate the html using the EEH_Tabbed_Content helper.
3211
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3212
+		// (rather than setting in the page_routes array)
3213
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs, $this->page_slug);
3214
+	}
3215
+
3216
+
3217
+	/**
3218
+	 *        sort nav tabs
3219
+	 *
3220
+	 * @param array $a
3221
+	 * @param array $b
3222
+	 * @return int
3223
+	 */
3224
+	private function _sort_nav_tabs(array $a, array $b): int
3225
+	{
3226
+		if ($a['order'] === $b['order']) {
3227
+			return 0;
3228
+		}
3229
+		return ($a['order'] < $b['order']) ? -1 : 1;
3230
+	}
3231
+
3232
+
3233
+	/**
3234
+	 * generates HTML for the forms used on admin pages
3235
+	 *
3236
+	 * @param array  $input_vars - array of input field details
3237
+	 * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3238
+	 * @param bool   $id
3239
+	 * @return array|string
3240
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3241
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3242
+	 */
3243
+	protected function _generate_admin_form_fields(
3244
+		array $input_vars = [],
3245
+		string $generator = 'string',
3246
+		bool $id = false
3247
+	) {
3248
+		return $generator === 'string'
3249
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3250
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3251
+	}
3252
+
3253
+
3254
+	/**
3255
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3256
+	 *
3257
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3258
+	 *                                   Close" button.
3259
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3260
+	 *                                   'Save', [1] => 'save & close')
3261
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3262
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3263
+	 *                                   default actions by submitting some other value.
3264
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Otherwise it
3265
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3266
+	 *                                   close (normal form handling).
3267
+	 */
3268
+	protected function _set_save_buttons(bool $both = true, array $text = [], array $actions = [], $referrer = null)
3269
+	{
3270
+		$referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3271
+		$button_text   = ! empty($text)
3272
+			? $text
3273
+			: [
3274
+				esc_html__('Save', 'event_espresso'),
3275
+				esc_html__('Save and Close', 'event_espresso'),
3276
+			];
3277
+		$default_names = ['save', 'save_and_close'];
3278
+		$buttons       = '';
3279
+		foreach ($button_text as $key => $button) {
3280
+			$ref     = $default_names[ $key ];
3281
+			$name    = ! empty($actions) ? $actions[ $key ] : $ref;
3282
+			$buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3283
+						. 'value="' . $button . '" name="' . $name . '" '
3284
+						. 'id="' . $this->_current_view . '_' . $ref . '" />';
3285
+			if (! $both) {
3286
+				break;
3287
+			}
3288
+		}
3289
+		// add in a hidden index for the current page (so save and close redirects properly)
3290
+		$buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3291
+					. $referrer_url
3292
+					. '" />';
3293
+
3294
+		$this->_template_args['save_buttons'] = $buttons;
3295
+	}
3296
+
3297
+
3298
+	/**
3299
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3300
+	 *
3301
+	 * @param string $route
3302
+	 * @param array  $additional_hidden_fields
3303
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3304
+	 * @since 4.6.0
3305
+	 */
3306
+	public function set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3307
+	{
3308
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3309
+	}
3310
+
3311
+
3312
+	/**
3313
+	 * set form open and close tags on add/edit pages.
3314
+	 *
3315
+	 * @param string $route                    the route you want the form to direct to
3316
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3317
+	 * @return void
3318
+	 */
3319
+	protected function _set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3320
+	{
3321
+		if (empty($route)) {
3322
+			$user_msg = esc_html__(
3323
+				'An error occurred. No action was set for this page\'s form.',
3324
+				'event_espresso'
3325
+			);
3326
+			$dev_msg  = $user_msg . "\n"
3327
+						. sprintf(
3328
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3329
+							__FUNCTION__,
3330
+							__CLASS__
3331
+						);
3332
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3333
+		}
3334
+		// open form
3335
+		$action                                            = $this->_admin_base_url;
3336
+		$this->_template_args['before_admin_page_content'] = "
3337 3337
             <form name='form' method='post' action='$action' id='{$route}_event_form' class='ee-admin-page-form' >
3338 3338
             ";
3339
-        // add nonce
3340
-        $nonce                                             =
3341
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3342
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3343
-        // add REQUIRED form action
3344
-        $hidden_fields = [
3345
-            'action' => ['type' => 'hidden', 'value' => $route],
3346
-        ];
3347
-        // merge arrays
3348
-        $hidden_fields = is_array($additional_hidden_fields)
3349
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3350
-            : $hidden_fields;
3351
-        // generate form fields
3352
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3353
-        // add fields to form
3354
-        foreach ((array) $form_fields as $form_field) {
3355
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3356
-        }
3357
-        // close form
3358
-        $this->_template_args['after_admin_page_content'] = '</form>';
3359
-    }
3360
-
3361
-
3362
-    /**
3363
-     * Public Wrapper for _redirect_after_action() method since its
3364
-     * discovered it would be useful for external code to have access.
3365
-     *
3366
-     * @param bool|int $success
3367
-     * @param string   $what
3368
-     * @param string   $action_desc
3369
-     * @param array    $query_args
3370
-     * @param bool     $override_overwrite
3371
-     * @throws EE_Error
3372
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3373
-     * @since 4.5.0
3374
-     */
3375
-    public function redirect_after_action(
3376
-        $success = false,
3377
-        string $what = 'item',
3378
-        string $action_desc = 'processed',
3379
-        array $query_args = [],
3380
-        bool $override_overwrite = false
3381
-    ) {
3382
-        $this->_redirect_after_action(
3383
-            $success,
3384
-            $what,
3385
-            $action_desc,
3386
-            $query_args,
3387
-            $override_overwrite
3388
-        );
3389
-    }
3390
-
3391
-
3392
-    /**
3393
-     * Helper method for merging existing request data with the returned redirect url.
3394
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3395
-     * filters are still applied.
3396
-     *
3397
-     * @param array $new_route_data
3398
-     * @return array
3399
-     */
3400
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data): array
3401
-    {
3402
-        foreach ($this->request->requestParams() as $ref => $value) {
3403
-            // unset nonces
3404
-            if (strpos($ref, 'nonce') !== false) {
3405
-                $this->request->unSetRequestParam($ref);
3406
-                continue;
3407
-            }
3408
-            // urlencode values.
3409
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3410
-            $this->request->setRequestParam($ref, $value);
3411
-        }
3412
-        return array_merge($this->request->requestParams(), $new_route_data);
3413
-    }
3414
-
3415
-
3416
-    /**
3417
-     * @param int|float|string $success            - whether success was for two or more records, or just one, or none
3418
-     * @param string           $what               - what the action was performed on
3419
-     * @param string           $action_desc        - what was done ie: updated, deleted, etc
3420
-     * @param array            $query_args         - an array of query_args to be added to the URL to redirect to
3421
-     * @param BOOL             $override_overwrite - by default all EE_Error::success messages are overwritten,
3422
-     *                                             this allows you to override this so that they show.
3423
-     * @return void
3424
-     * @throws EE_Error
3425
-     * @throws InvalidArgumentException
3426
-     * @throws InvalidDataTypeException
3427
-     * @throws InvalidInterfaceException
3428
-     */
3429
-    protected function _redirect_after_action(
3430
-        $success = 0,
3431
-        string $what = 'item',
3432
-        string $action_desc = 'processed',
3433
-        array $query_args = [],
3434
-        bool $override_overwrite = false
3435
-    ) {
3436
-        $notices = EE_Error::get_notices(false);
3437
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3438
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3439
-            EE_Error::overwrite_success();
3440
-        }
3441
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3442
-            // how many records affected ? more than one record ? or just one ?
3443
-            EE_Error::add_success(
3444
-                sprintf(
3445
-                    esc_html(
3446
-                        _n(
3447
-                            'The "%1$s" has been successfully %2$s.',
3448
-                            'The "%1$s" have been successfully %2$s.',
3449
-                            $success,
3450
-                            'event_espresso'
3451
-                        )
3452
-                    ),
3453
-                    $what,
3454
-                    $action_desc
3455
-                ),
3456
-                __FILE__,
3457
-                __FUNCTION__,
3458
-                __LINE__
3459
-            );
3460
-        }
3461
-        // check that $query_args isn't something crazy
3462
-        $query_args = is_array($query_args) ? $query_args : [];
3463
-        /**
3464
-         * Allow injecting actions before the query_args are modified for possible different
3465
-         * redirections on save and close actions
3466
-         *
3467
-         * @param array $query_args       The original query_args array coming into the
3468
-         *                                method.
3469
-         * @since 4.2.0
3470
-         */
3471
-        do_action(
3472
-            "AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_$this->_req_action",
3473
-            $query_args
3474
-        );
3475
-        // set redirect url.
3476
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3477
-        // otherwise we go with whatever is set as the _admin_base_url
3478
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3479
-        // calculate where we're going (if we have a "save and close" button pushed)
3480
-        if (
3481
-            $this->request->requestParamIsSet('save_and_close')
3482
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3483
-        ) {
3484
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3485
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', DataType::URL));
3486
-            // regenerate query args array from referrer URL
3487
-            parse_str($parsed_url['query'], $query_args);
3488
-            // correct page and action will be in the query args now
3489
-            $redirect_url = admin_url('admin.php');
3490
-        }
3491
-        // merge any default query_args set in _default_route_query_args property
3492
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3493
-            $args_to_merge = [];
3494
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3495
-                // is there a wp_referer array in our _default_route_query_args property?
3496
-                if ($query_param === 'wp_referer') {
3497
-                    $query_value = (array) $query_value;
3498
-                    foreach ($query_value as $reference => $value) {
3499
-                        if (strpos($reference, 'nonce') !== false) {
3500
-                            continue;
3501
-                        }
3502
-                        // finally we will override any arguments in the referer with
3503
-                        // what might be set on the _default_route_query_args array.
3504
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3505
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3506
-                        } else {
3507
-                            $args_to_merge[ $reference ] = urlencode($value);
3508
-                        }
3509
-                    }
3510
-                    continue;
3511
-                }
3512
-                $args_to_merge[ $query_param ] = $query_value;
3513
-            }
3514
-            // now let's merge these arguments but override with what was specifically sent in to the
3515
-            // redirect.
3516
-            $query_args = array_merge($args_to_merge, $query_args);
3517
-        }
3518
-        $this->_process_notices($query_args);
3519
-        // generate redirect url
3520
-        // if redirecting to anything other than the main page, add a nonce
3521
-        if (isset($query_args['action'])) {
3522
-            // manually generate wp_nonce and merge that with the query vars
3523
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3524
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3525
-        }
3526
-        // we're adding some hooks and filters in here for processing any things just before redirects
3527
-        // (example: an admin page has done an insert or update and we want to run something after that).
3528
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3529
-        $redirect_url = apply_filters(
3530
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3531
-            EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3532
-            $query_args
3533
-        );
3534
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3535
-        if ($this->request->isAjax()) {
3536
-            $default_data                    = [
3537
-                'close'        => true,
3538
-                'redirect_url' => $redirect_url,
3539
-                'where'        => 'main',
3540
-                'what'         => 'append',
3541
-            ];
3542
-            $this->_template_args['success'] = $success;
3543
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3544
-                $default_data,
3545
-                $this->_template_args['data']
3546
-            ) : $default_data;
3547
-            $this->_return_json();
3548
-        }
3549
-        wp_safe_redirect($redirect_url);
3550
-        exit();
3551
-    }
3552
-
3553
-
3554
-    /**
3555
-     * process any notices before redirecting (or returning ajax request)
3556
-     * This method sets the $this->_template_args['notices'] attribute;
3557
-     *
3558
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3559
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3560
-     *                                  page_routes haven't been defined yet.
3561
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3562
-     *                                  still save a transient for the notice.
3563
-     * @return void
3564
-     * @throws EE_Error
3565
-     * @throws InvalidArgumentException
3566
-     * @throws InvalidDataTypeException
3567
-     * @throws InvalidInterfaceException
3568
-     */
3569
-    protected function _process_notices(
3570
-        array $query_args = [],
3571
-        bool $skip_route_verify = false,
3572
-        bool $sticky_notices = true
3573
-    ) {
3574
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3575
-        if ($this->request->isAjax()) {
3576
-            $notices = EE_Error::get_notices(false);
3577
-            if (empty($this->_template_args['success'])) {
3578
-                $this->_template_args['success'] = $notices['success'] ?? false;
3579
-            }
3580
-            if (empty($this->_template_args['errors'])) {
3581
-                $this->_template_args['errors'] = $notices['errors'] ?? false;
3582
-            }
3583
-            if (empty($this->_template_args['attention'])) {
3584
-                $this->_template_args['attention'] = $notices['attention'] ?? false;
3585
-            }
3586
-        }
3587
-        $this->_template_args['notices'] = EE_Error::get_notices();
3588
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3589
-        if (! $this->request->isAjax() || $sticky_notices) {
3590
-            $route = $query_args['action'] ?? 'default';
3591
-            $this->_add_transient(
3592
-                $route,
3593
-                (array) $this->_template_args['notices'],
3594
-                true,
3595
-                $skip_route_verify
3596
-            );
3597
-        }
3598
-    }
3599
-
3600
-
3601
-    /**
3602
-     * get_action_link_or_button
3603
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3604
-     *
3605
-     * @param string $action        use this to indicate which action the url is generated with.
3606
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3607
-     *                              property.
3608
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3609
-     * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3610
-     * @param string $base_url      If this is not provided
3611
-     *                              the _admin_base_url will be used as the default for the button base_url.
3612
-     *                              Otherwise this value will be used.
3613
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3614
-     * @return string
3615
-     * @throws InvalidArgumentException
3616
-     * @throws InvalidInterfaceException
3617
-     * @throws InvalidDataTypeException
3618
-     * @throws EE_Error
3619
-     */
3620
-    public function get_action_link_or_button(
3621
-        string $action,
3622
-        string $type = 'add',
3623
-        array $extra_request = [],
3624
-        string $class = 'button button--primary',
3625
-        string $base_url = '',
3626
-        bool $exclude_nonce = false
3627
-    ): string {
3628
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3629
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3630
-            throw new EE_Error(
3631
-                sprintf(
3632
-                    esc_html__(
3633
-                        'There is no page route for given action for the button.  This action was given: %s',
3634
-                        'event_espresso'
3635
-                    ),
3636
-                    $action
3637
-                )
3638
-            );
3639
-        }
3640
-        if (! isset($this->_labels['buttons'][ $type ])) {
3641
-            throw new EE_Error(
3642
-                sprintf(
3643
-                    esc_html__(
3644
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3645
-                        'event_espresso'
3646
-                    ),
3647
-                    $type
3648
-                )
3649
-            );
3650
-        }
3651
-        // finally check user access for this button.
3652
-        $has_access = $this->check_user_access($action, true);
3653
-        if (! $has_access) {
3654
-            return '';
3655
-        }
3656
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3657
-        $query_args = [
3658
-            'action' => $action,
3659
-        ];
3660
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3661
-        if (! empty($extra_request)) {
3662
-            $query_args = array_merge($extra_request, $query_args);
3663
-        }
3664
-        $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3665
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3666
-    }
3667
-
3668
-
3669
-    /**
3670
-     * _per_page_screen_option
3671
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3672
-     *
3673
-     * @return void
3674
-     * @throws InvalidArgumentException
3675
-     * @throws InvalidInterfaceException
3676
-     * @throws InvalidDataTypeException
3677
-     */
3678
-    protected function _per_page_screen_option()
3679
-    {
3680
-        $option = 'per_page';
3681
-        $args   = [
3682
-            'label'   => apply_filters(
3683
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3684
-                $this->_admin_page_title,
3685
-                $this
3686
-            ),
3687
-            'default' => (int) apply_filters(
3688
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3689
-                20
3690
-            ),
3691
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3692
-        ];
3693
-        // ONLY add the screen option if the user has access to it.
3694
-        if ($this->check_user_access($this->_current_view, true)) {
3695
-            add_screen_option($option, $args);
3696
-        }
3697
-    }
3698
-
3699
-
3700
-    /**
3701
-     * set_per_page_screen_option
3702
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3703
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3704
-     * admin_menu.
3705
-     *
3706
-     * @return void
3707
-     */
3708
-    private function _set_per_page_screen_options()
3709
-    {
3710
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3711
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3712
-            if (! $user = wp_get_current_user()) {
3713
-                return;
3714
-            }
3715
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', DataType::KEY);
3716
-            if (! $option) {
3717
-                return;
3718
-            }
3719
-            $value      = $this->request->getRequestParam('wp_screen_options[value]', 0, DataType::INT);
3720
-            $map_option = $option;
3721
-            $option     = str_replace('-', '_', $option);
3722
-            switch ($map_option) {
3723
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3724
-                    $max_value = apply_filters(
3725
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3726
-                        999,
3727
-                        $this->_current_page,
3728
-                        $this->_current_view
3729
-                    );
3730
-                    if ($value < 1) {
3731
-                        return;
3732
-                    }
3733
-                    $value = min($value, $max_value);
3734
-                    break;
3735
-                default:
3736
-                    $value = apply_filters(
3737
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3738
-                        false,
3739
-                        $option,
3740
-                        $value
3741
-                    );
3742
-                    if (false === $value) {
3743
-                        return;
3744
-                    }
3745
-                    break;
3746
-            }
3747
-            update_user_meta($user->ID, $option, $value);
3748
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3749
-            exit;
3750
-        }
3751
-    }
3752
-
3753
-
3754
-    /**
3755
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3756
-     *
3757
-     * @param array $data array that will be assigned to template args.
3758
-     */
3759
-    public function set_template_args(array $data)
3760
-    {
3761
-        $this->_template_args = array_merge($this->_template_args, $data);
3762
-    }
3763
-
3764
-
3765
-    public function setAdminPageTitle(string $title)
3766
-    {
3767
-        $this->_admin_page_title = sanitize_text_field($title);
3768
-    }
3769
-
3770
-
3771
-    /**
3772
-     * This makes available the WP transient system for temporarily moving data between routes
3773
-     *
3774
-     * @param string $route             the route that should receive the transient
3775
-     * @param array  $data              the data that gets sent
3776
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise it's just a
3777
-     *                                  normal route transient.
3778
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3779
-     *                                  when we are adding a transient before page_routes have been defined.
3780
-     * @return void
3781
-     * @throws EE_Error
3782
-     */
3783
-    protected function _add_transient(
3784
-        string $route,
3785
-        array $data,
3786
-        bool $notices = false,
3787
-        bool $skip_route_verify = false
3788
-    ) {
3789
-        $user_id = get_current_user_id();
3790
-        if (! $skip_route_verify) {
3791
-            $this->_verify_route($route);
3792
-        }
3793
-        // now let's set the string for what kind of transient we're setting
3794
-        $transient = $notices ? "ee_rte_n_tx_{$route}_$user_id" : "rte_tx_{$route}_$user_id";
3795
-        $data      = $notices ? ['notices' => $data] : $data;
3796
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3797
-        $existing = is_multisite() && is_network_admin()
3798
-            ? get_site_transient($transient)
3799
-            : get_transient($transient);
3800
-        if ($existing) {
3801
-            $data = array_merge($data, (array) $existing);
3802
-        }
3803
-        if (is_multisite() && is_network_admin()) {
3804
-            set_site_transient($transient, $data, 8);
3805
-        } else {
3806
-            set_transient($transient, $data, 8);
3807
-        }
3808
-    }
3809
-
3810
-
3811
-    /**
3812
-     * this retrieves the temporary transient that has been set for moving data between routes.
3813
-     *
3814
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3815
-     * @param string $route
3816
-     * @return mixed data
3817
-     */
3818
-    protected function _get_transient(bool $notices = false, string $route = '')
3819
-    {
3820
-        $user_id   = get_current_user_id();
3821
-        $route     = ! $route ? $this->_req_action : $route;
3822
-        $transient = $notices
3823
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3824
-            : 'rte_tx_' . $route . '_' . $user_id;
3825
-        $data      = is_multisite() && is_network_admin()
3826
-            ? get_site_transient($transient)
3827
-            : get_transient($transient);
3828
-        // delete transient after retrieval (just in case it hasn't expired);
3829
-        if (is_multisite() && is_network_admin()) {
3830
-            delete_site_transient($transient);
3831
-        } else {
3832
-            delete_transient($transient);
3833
-        }
3834
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3835
-    }
3836
-
3837
-
3838
-    /**
3839
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3840
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3841
-     * default route callback on the EE_Admin page you want it run.)
3842
-     *
3843
-     * @return void
3844
-     */
3845
-    protected function _transient_garbage_collection()
3846
-    {
3847
-        global $wpdb;
3848
-        // retrieve all existing transients
3849
-        $query =
3850
-            "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3851
-        if ($results = $wpdb->get_results($query)) {
3852
-            foreach ($results as $result) {
3853
-                $transient = str_replace('_transient_', '', $result->option_name);
3854
-                get_transient($transient);
3855
-                if (is_multisite() && is_network_admin()) {
3856
-                    get_site_transient($transient);
3857
-                }
3858
-            }
3859
-        }
3860
-    }
3861
-
3862
-
3863
-    /**
3864
-     * get_view
3865
-     *
3866
-     * @return string content of _view property
3867
-     */
3868
-    public function get_view(): string
3869
-    {
3870
-        return $this->_view;
3871
-    }
3872
-
3873
-
3874
-    /**
3875
-     * getter for the protected $_views property
3876
-     *
3877
-     * @return array
3878
-     */
3879
-    public function get_views(): array
3880
-    {
3881
-        return $this->_views;
3882
-    }
3883
-
3884
-
3885
-    /**
3886
-     * @param array $views
3887
-     * @return void
3888
-     * @since 5.0.13.p
3889
-     */
3890
-    public function updateViews(array $views)
3891
-    {
3892
-        $this->_views = array_merge($this->_views, $views);
3893
-    }
3894
-
3895
-
3896
-    /**
3897
-    /**
3898
-     * get_current_page
3899
-     *
3900
-     * @return string _current_page property value
3901
-     */
3902
-    public function get_current_page(): string
3903
-    {
3904
-        return $this->_current_page;
3905
-    }
3906
-
3907
-
3908
-    /**
3909
-     * get_current_view
3910
-     *
3911
-     * @return string _current_view property value
3912
-     */
3913
-    public function get_current_view(): string
3914
-    {
3915
-        return $this->_current_view;
3916
-    }
3917
-
3918
-
3919
-    /**
3920
-     * get_current_screen
3921
-     *
3922
-     * @return object The current WP_Screen object
3923
-     */
3924
-    public function get_current_screen()
3925
-    {
3926
-        return $this->_current_screen;
3927
-    }
3928
-
3929
-
3930
-    /**
3931
-     * get_current_page_view_url
3932
-     *
3933
-     * @return string This returns the url for the current_page_view.
3934
-     */
3935
-    public function get_current_page_view_url(): string
3936
-    {
3937
-        return $this->_current_page_view_url;
3938
-    }
3939
-
3940
-
3941
-    /**
3942
-     * just returns the Request
3943
-     *
3944
-     * @return RequestInterface
3945
-     */
3946
-    public function get_request(): ?RequestInterface
3947
-    {
3948
-        return $this->request;
3949
-    }
3950
-
3951
-
3952
-    /**
3953
-     * just returns the _req_data property
3954
-     *
3955
-     * @return array
3956
-     */
3957
-    public function get_request_data(): array
3958
-    {
3959
-        return $this->request->requestParams();
3960
-    }
3961
-
3962
-
3963
-    /**
3964
-     * returns the _req_data protected property
3965
-     *
3966
-     * @return string
3967
-     */
3968
-    public function get_req_action(): string
3969
-    {
3970
-        return $this->_req_action;
3971
-    }
3972
-
3973
-
3974
-    /**
3975
-     * @return bool  value of $_is_caf property
3976
-     */
3977
-    public function is_caf(): bool
3978
-    {
3979
-        return $this->_is_caf;
3980
-    }
3981
-
3982
-
3983
-    /**
3984
-     * @return array
3985
-     */
3986
-    public function default_espresso_metaboxes(): array
3987
-    {
3988
-        return $this->_default_espresso_metaboxes;
3989
-    }
3990
-
3991
-
3992
-    /**
3993
-     * @return string
3994
-     */
3995
-    public function admin_base_url(): string
3996
-    {
3997
-        return $this->_admin_base_url;
3998
-    }
3999
-
4000
-
4001
-    /**
4002
-     * @return string
4003
-     */
4004
-    public function wp_page_slug(): string
4005
-    {
4006
-        return $this->_wp_page_slug;
4007
-    }
4008
-
4009
-
4010
-    /**
4011
-     * updates  espresso configuration settings
4012
-     *
4013
-     * @param string                   $tab
4014
-     * @param EE_Config_Base|EE_Config $config
4015
-     * @param string                   $file file where error occurred
4016
-     * @param string                   $func function  where error occurred
4017
-     * @param string                   $line line no where error occurred
4018
-     * @return bool
4019
-     */
4020
-    protected function _update_espresso_configuration(
4021
-        string $tab,
4022
-        $config,
4023
-        string $file = '',
4024
-        string $func = '',
4025
-        string $line = ''
4026
-    ): bool {
4027
-        // remove any options that are NOT going to be saved with the config settings.
4028
-        if (isset($config->core->ee_ueip_optin)) {
4029
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4030
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4031
-            update_option('ee_ueip_has_notified', true);
4032
-        }
4033
-        // and save it (note we're also doing the network save here)
4034
-        $net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
4035
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4036
-        if ($config_saved && $net_saved) {
4037
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4038
-            return true;
4039
-        }
4040
-        EE_Error::add_error(
4041
-            sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab),
4042
-            $file,
4043
-            $func,
4044
-            $line
4045
-        );
4046
-        return false;
4047
-    }
4048
-
4049
-
4050
-    /**
4051
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4052
-     *
4053
-     * @return array
4054
-     */
4055
-    public function get_yes_no_values(): array
4056
-    {
4057
-        return $this->_yes_no_values;
4058
-    }
4059
-
4060
-
4061
-    /**
4062
-     * @return string
4063
-     * @throws ReflectionException
4064
-     * @since 5.0.0.p
4065
-     */
4066
-    protected function _get_dir(): string
4067
-    {
4068
-        $reflector = new ReflectionClass($this->class_name);
4069
-        return dirname($reflector->getFileName());
4070
-    }
4071
-
4072
-
4073
-    /**
4074
-     * A helper for getting a "next link".
4075
-     *
4076
-     * @param string $url   The url to link to
4077
-     * @param string $class The class to use.
4078
-     * @return string
4079
-     */
4080
-    protected function _next_link(string $url, string $class = 'dashicons dashicons-arrow-right'): string
4081
-    {
4082
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4083
-    }
4084
-
4085
-
4086
-    /**
4087
-     * A helper for getting a "previous link".
4088
-     *
4089
-     * @param string $url   The url to link to
4090
-     * @param string $class The class to use.
4091
-     * @return string
4092
-     */
4093
-    protected function _previous_link(string $url, string $class = 'dashicons dashicons-arrow-left'): string
4094
-    {
4095
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4096
-    }
4097
-
4098
-
4099
-
4100
-
4101
-
4102
-
4103
-
4104
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4105
-
4106
-
4107
-    /**
4108
-     * This processes a request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4109
-     * 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
4110
-     * _req_data array.
4111
-     *
4112
-     * @return bool success/fail
4113
-     * @throws EE_Error
4114
-     * @throws InvalidArgumentException
4115
-     * @throws ReflectionException
4116
-     * @throws InvalidDataTypeException
4117
-     * @throws InvalidInterfaceException
4118
-     */
4119
-    protected function _process_resend_registration(): bool
4120
-    {
4121
-        $this->_template_args['success'] = EED_Messages::process_resend($this->request->requestParams());
4122
-        do_action(
4123
-            'AHEE__EE_Admin_Page___process_resend_registration',
4124
-            $this->_template_args['success'],
4125
-            $this->request->requestParams()
4126
-        );
4127
-        return $this->_template_args['success'];
4128
-    }
4129
-
4130
-
4131
-    /**
4132
-     * This automatically processes any payment message notifications when manual payment has been applied.
4133
-     *
4134
-     * @param EE_Payment $payment
4135
-     * @return bool success/fail
4136
-     */
4137
-    protected function _process_payment_notification(EE_Payment $payment): bool
4138
-    {
4139
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4140
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4141
-        $this->_template_args['success'] = apply_filters(
4142
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4143
-            false,
4144
-            $payment
4145
-        );
4146
-        return $this->_template_args['success'];
4147
-    }
4148
-
4149
-
4150
-    /**
4151
-     * @param EEM_Base      $entity_model
4152
-     * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4153
-     * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4154
-     * @param string        $delete_column  name of the field that denotes whether entity is trashed
4155
-     * @param callable|null $callback       called after entity is trashed, restored, or deleted
4156
-     * @return int|float
4157
-     * @throws EE_Error
4158
-     */
4159
-    protected function trashRestoreDeleteEntities(
4160
-        EEM_Base $entity_model,
4161
-        string $entity_PK_name,
4162
-        string $action = EE_Admin_List_Table::ACTION_DELETE,
4163
-        string $delete_column = '',
4164
-        ?callable $callback = null
4165
-    ) {
4166
-        $entity_PK      = $entity_model->get_primary_key_field();
4167
-        $entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4168
-        $entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4169
-        // grab ID if deleting a single entity
4170
-        if ($this->request->requestParamIsSet($entity_PK_name)) {
4171
-            $ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4172
-            return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4173
-        }
4174
-        // or grab checkbox array if bulk deleting
4175
-        $checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4176
-        if (empty($checkboxes)) {
4177
-            return 0;
4178
-        }
4179
-        $success = 0;
4180
-        $IDs     = array_keys($checkboxes);
4181
-        // cycle thru bulk action checkboxes
4182
-        foreach ($IDs as $ID) {
4183
-            // increment $success
4184
-            if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4185
-                $success++;
4186
-            }
4187
-        }
4188
-        $count = (int) count($checkboxes);
4189
-        // if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4190
-        // otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4191
-        return $success === $count ? $count : $success / $count;
4192
-    }
4193
-
4194
-
4195
-    /**
4196
-     * @param EE_Primary_Key_Field_Base $entity_PK
4197
-     * @return string
4198
-     * @throws EE_Error
4199
-     * @since   4.10.30.p
4200
-     */
4201
-    private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4202
-    {
4203
-        $entity_PK_type = $entity_PK->getSchemaType();
4204
-        switch ($entity_PK_type) {
4205
-            case 'boolean':
4206
-                return DataType::BOOL;
4207
-            case 'integer':
4208
-                return DataType::INT;
4209
-            case 'number':
4210
-                return DataType::FLOAT;
4211
-            case 'string':
4212
-                return DataType::STRING;
4213
-        }
4214
-        throw new RuntimeException(
4215
-            sprintf(
4216
-                esc_html__(
4217
-                    '"%1$s" is an invalid schema type for the %2$s primary key.',
4218
-                    'event_espresso'
4219
-                ),
4220
-                $entity_PK_type,
4221
-                $entity_PK->get_name()
4222
-            )
4223
-        );
4224
-    }
4225
-
4226
-
4227
-    /**
4228
-     * @param EEM_Base      $entity_model
4229
-     * @param int|string    $entity_ID
4230
-     * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4231
-     * @param string        $delete_column name of the field that denotes whether entity is trashed
4232
-     * @param callable|null $callback      called after entity is trashed, restored, or deleted
4233
-     * @return bool
4234
-     */
4235
-    protected function trashRestoreDeleteEntity(
4236
-        EEM_Base $entity_model,
4237
-        $entity_ID,
4238
-        string $action,
4239
-        string $delete_column,
4240
-        ?callable $callback = null
4241
-    ): bool {
4242
-        $entity_ID = absint($entity_ID);
4243
-        if (! $entity_ID) {
4244
-            $this->trashRestoreDeleteError($action, $entity_model);
4245
-        }
4246
-        $result = 0;
4247
-        try {
4248
-            $entity = $entity_model->get_one_by_ID($entity_ID);
4249
-            if (! $entity instanceof EE_Base_Class) {
4250
-                throw new DomainException(
4251
-                    sprintf(
4252
-                        esc_html__(
4253
-                            'Missing or invalid %1$s entity with ID of "%2$s" returned from db.',
4254
-                            'event_espresso'
4255
-                        ),
4256
-                        str_replace('EEM_', '', $entity_model->get_this_model_name()),
4257
-                        $entity_ID
4258
-                    )
4259
-                );
4260
-            }
4261
-            switch ($action) {
4262
-                case EE_Admin_List_Table::ACTION_DELETE:
4263
-                    $result = (bool) $entity->delete_permanently();
4264
-                    break;
4265
-                case EE_Admin_List_Table::ACTION_RESTORE:
4266
-                    $result = $entity->delete_or_restore(false);
4267
-                    break;
4268
-                case EE_Admin_List_Table::ACTION_TRASH:
4269
-                    $result = $entity->delete_or_restore();
4270
-                    break;
4271
-            }
4272
-        } catch (Exception $exception) {
4273
-            $this->trashRestoreDeleteError($action, $entity_model, $exception);
4274
-        }
4275
-        if (is_callable($callback)) {
4276
-            call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4277
-        }
4278
-        return $result;
4279
-    }
4280
-
4281
-
4282
-    /**
4283
-     * @param EEM_Base $entity_model
4284
-     * @param string   $delete_column
4285
-     * @since 4.10.30.p
4286
-     */
4287
-    private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4288
-    {
4289
-        if (empty($delete_column)) {
4290
-            throw new DomainException(
4291
-                sprintf(
4292
-                    esc_html__(
4293
-                        'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4294
-                        'event_espresso'
4295
-                    ),
4296
-                    $entity_model->get_this_model_name()
4297
-                )
4298
-            );
4299
-        }
4300
-        if (! $entity_model->has_field($delete_column)) {
4301
-            throw new DomainException(
4302
-                sprintf(
4303
-                    esc_html__(
4304
-                        'The %1$s field does not exist on the %2$s model.',
4305
-                        'event_espresso'
4306
-                    ),
4307
-                    $delete_column,
4308
-                    $entity_model->get_this_model_name()
4309
-                )
4310
-            );
4311
-        }
4312
-    }
4313
-
4314
-
4315
-    /**
4316
-     * @param EEM_Base       $entity_model
4317
-     * @param Exception|null $exception
4318
-     * @param string         $action
4319
-     * @since 4.10.30.p
4320
-     */
4321
-    private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, Exception $exception = null)
4322
-    {
4323
-        if ($exception instanceof Exception) {
4324
-            throw new RuntimeException(
4325
-                sprintf(
4326
-                    esc_html__(
4327
-                        'Could not %1$s the %2$s because the following error occurred: %3$s',
4328
-                        'event_espresso'
4329
-                    ),
4330
-                    $action,
4331
-                    $entity_model->get_this_model_name(),
4332
-                    $exception->getMessage()
4333
-                )
4334
-            );
4335
-        }
4336
-        throw new RuntimeException(
4337
-            sprintf(
4338
-                esc_html__(
4339
-                    'Could not %1$s the %2$s because an invalid ID was received.',
4340
-                    'event_espresso'
4341
-                ),
4342
-                $action,
4343
-                $entity_model->get_this_model_name()
4344
-            )
4345
-        );
4346
-    }
3339
+		// add nonce
3340
+		$nonce                                             =
3341
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3342
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3343
+		// add REQUIRED form action
3344
+		$hidden_fields = [
3345
+			'action' => ['type' => 'hidden', 'value' => $route],
3346
+		];
3347
+		// merge arrays
3348
+		$hidden_fields = is_array($additional_hidden_fields)
3349
+			? array_merge($hidden_fields, $additional_hidden_fields)
3350
+			: $hidden_fields;
3351
+		// generate form fields
3352
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3353
+		// add fields to form
3354
+		foreach ((array) $form_fields as $form_field) {
3355
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3356
+		}
3357
+		// close form
3358
+		$this->_template_args['after_admin_page_content'] = '</form>';
3359
+	}
3360
+
3361
+
3362
+	/**
3363
+	 * Public Wrapper for _redirect_after_action() method since its
3364
+	 * discovered it would be useful for external code to have access.
3365
+	 *
3366
+	 * @param bool|int $success
3367
+	 * @param string   $what
3368
+	 * @param string   $action_desc
3369
+	 * @param array    $query_args
3370
+	 * @param bool     $override_overwrite
3371
+	 * @throws EE_Error
3372
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3373
+	 * @since 4.5.0
3374
+	 */
3375
+	public function redirect_after_action(
3376
+		$success = false,
3377
+		string $what = 'item',
3378
+		string $action_desc = 'processed',
3379
+		array $query_args = [],
3380
+		bool $override_overwrite = false
3381
+	) {
3382
+		$this->_redirect_after_action(
3383
+			$success,
3384
+			$what,
3385
+			$action_desc,
3386
+			$query_args,
3387
+			$override_overwrite
3388
+		);
3389
+	}
3390
+
3391
+
3392
+	/**
3393
+	 * Helper method for merging existing request data with the returned redirect url.
3394
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3395
+	 * filters are still applied.
3396
+	 *
3397
+	 * @param array $new_route_data
3398
+	 * @return array
3399
+	 */
3400
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data): array
3401
+	{
3402
+		foreach ($this->request->requestParams() as $ref => $value) {
3403
+			// unset nonces
3404
+			if (strpos($ref, 'nonce') !== false) {
3405
+				$this->request->unSetRequestParam($ref);
3406
+				continue;
3407
+			}
3408
+			// urlencode values.
3409
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3410
+			$this->request->setRequestParam($ref, $value);
3411
+		}
3412
+		return array_merge($this->request->requestParams(), $new_route_data);
3413
+	}
3414
+
3415
+
3416
+	/**
3417
+	 * @param int|float|string $success            - whether success was for two or more records, or just one, or none
3418
+	 * @param string           $what               - what the action was performed on
3419
+	 * @param string           $action_desc        - what was done ie: updated, deleted, etc
3420
+	 * @param array            $query_args         - an array of query_args to be added to the URL to redirect to
3421
+	 * @param BOOL             $override_overwrite - by default all EE_Error::success messages are overwritten,
3422
+	 *                                             this allows you to override this so that they show.
3423
+	 * @return void
3424
+	 * @throws EE_Error
3425
+	 * @throws InvalidArgumentException
3426
+	 * @throws InvalidDataTypeException
3427
+	 * @throws InvalidInterfaceException
3428
+	 */
3429
+	protected function _redirect_after_action(
3430
+		$success = 0,
3431
+		string $what = 'item',
3432
+		string $action_desc = 'processed',
3433
+		array $query_args = [],
3434
+		bool $override_overwrite = false
3435
+	) {
3436
+		$notices = EE_Error::get_notices(false);
3437
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3438
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3439
+			EE_Error::overwrite_success();
3440
+		}
3441
+		if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3442
+			// how many records affected ? more than one record ? or just one ?
3443
+			EE_Error::add_success(
3444
+				sprintf(
3445
+					esc_html(
3446
+						_n(
3447
+							'The "%1$s" has been successfully %2$s.',
3448
+							'The "%1$s" have been successfully %2$s.',
3449
+							$success,
3450
+							'event_espresso'
3451
+						)
3452
+					),
3453
+					$what,
3454
+					$action_desc
3455
+				),
3456
+				__FILE__,
3457
+				__FUNCTION__,
3458
+				__LINE__
3459
+			);
3460
+		}
3461
+		// check that $query_args isn't something crazy
3462
+		$query_args = is_array($query_args) ? $query_args : [];
3463
+		/**
3464
+		 * Allow injecting actions before the query_args are modified for possible different
3465
+		 * redirections on save and close actions
3466
+		 *
3467
+		 * @param array $query_args       The original query_args array coming into the
3468
+		 *                                method.
3469
+		 * @since 4.2.0
3470
+		 */
3471
+		do_action(
3472
+			"AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_$this->_req_action",
3473
+			$query_args
3474
+		);
3475
+		// set redirect url.
3476
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3477
+		// otherwise we go with whatever is set as the _admin_base_url
3478
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3479
+		// calculate where we're going (if we have a "save and close" button pushed)
3480
+		if (
3481
+			$this->request->requestParamIsSet('save_and_close')
3482
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3483
+		) {
3484
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3485
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', DataType::URL));
3486
+			// regenerate query args array from referrer URL
3487
+			parse_str($parsed_url['query'], $query_args);
3488
+			// correct page and action will be in the query args now
3489
+			$redirect_url = admin_url('admin.php');
3490
+		}
3491
+		// merge any default query_args set in _default_route_query_args property
3492
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3493
+			$args_to_merge = [];
3494
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3495
+				// is there a wp_referer array in our _default_route_query_args property?
3496
+				if ($query_param === 'wp_referer') {
3497
+					$query_value = (array) $query_value;
3498
+					foreach ($query_value as $reference => $value) {
3499
+						if (strpos($reference, 'nonce') !== false) {
3500
+							continue;
3501
+						}
3502
+						// finally we will override any arguments in the referer with
3503
+						// what might be set on the _default_route_query_args array.
3504
+						if (isset($this->_default_route_query_args[ $reference ])) {
3505
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3506
+						} else {
3507
+							$args_to_merge[ $reference ] = urlencode($value);
3508
+						}
3509
+					}
3510
+					continue;
3511
+				}
3512
+				$args_to_merge[ $query_param ] = $query_value;
3513
+			}
3514
+			// now let's merge these arguments but override with what was specifically sent in to the
3515
+			// redirect.
3516
+			$query_args = array_merge($args_to_merge, $query_args);
3517
+		}
3518
+		$this->_process_notices($query_args);
3519
+		// generate redirect url
3520
+		// if redirecting to anything other than the main page, add a nonce
3521
+		if (isset($query_args['action'])) {
3522
+			// manually generate wp_nonce and merge that with the query vars
3523
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3524
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3525
+		}
3526
+		// we're adding some hooks and filters in here for processing any things just before redirects
3527
+		// (example: an admin page has done an insert or update and we want to run something after that).
3528
+		do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3529
+		$redirect_url = apply_filters(
3530
+			'FHEE_redirect_' . $this->class_name . $this->_req_action,
3531
+			EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3532
+			$query_args
3533
+		);
3534
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3535
+		if ($this->request->isAjax()) {
3536
+			$default_data                    = [
3537
+				'close'        => true,
3538
+				'redirect_url' => $redirect_url,
3539
+				'where'        => 'main',
3540
+				'what'         => 'append',
3541
+			];
3542
+			$this->_template_args['success'] = $success;
3543
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3544
+				$default_data,
3545
+				$this->_template_args['data']
3546
+			) : $default_data;
3547
+			$this->_return_json();
3548
+		}
3549
+		wp_safe_redirect($redirect_url);
3550
+		exit();
3551
+	}
3552
+
3553
+
3554
+	/**
3555
+	 * process any notices before redirecting (or returning ajax request)
3556
+	 * This method sets the $this->_template_args['notices'] attribute;
3557
+	 *
3558
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3559
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3560
+	 *                                  page_routes haven't been defined yet.
3561
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3562
+	 *                                  still save a transient for the notice.
3563
+	 * @return void
3564
+	 * @throws EE_Error
3565
+	 * @throws InvalidArgumentException
3566
+	 * @throws InvalidDataTypeException
3567
+	 * @throws InvalidInterfaceException
3568
+	 */
3569
+	protected function _process_notices(
3570
+		array $query_args = [],
3571
+		bool $skip_route_verify = false,
3572
+		bool $sticky_notices = true
3573
+	) {
3574
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3575
+		if ($this->request->isAjax()) {
3576
+			$notices = EE_Error::get_notices(false);
3577
+			if (empty($this->_template_args['success'])) {
3578
+				$this->_template_args['success'] = $notices['success'] ?? false;
3579
+			}
3580
+			if (empty($this->_template_args['errors'])) {
3581
+				$this->_template_args['errors'] = $notices['errors'] ?? false;
3582
+			}
3583
+			if (empty($this->_template_args['attention'])) {
3584
+				$this->_template_args['attention'] = $notices['attention'] ?? false;
3585
+			}
3586
+		}
3587
+		$this->_template_args['notices'] = EE_Error::get_notices();
3588
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3589
+		if (! $this->request->isAjax() || $sticky_notices) {
3590
+			$route = $query_args['action'] ?? 'default';
3591
+			$this->_add_transient(
3592
+				$route,
3593
+				(array) $this->_template_args['notices'],
3594
+				true,
3595
+				$skip_route_verify
3596
+			);
3597
+		}
3598
+	}
3599
+
3600
+
3601
+	/**
3602
+	 * get_action_link_or_button
3603
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3604
+	 *
3605
+	 * @param string $action        use this to indicate which action the url is generated with.
3606
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3607
+	 *                              property.
3608
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3609
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3610
+	 * @param string $base_url      If this is not provided
3611
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3612
+	 *                              Otherwise this value will be used.
3613
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3614
+	 * @return string
3615
+	 * @throws InvalidArgumentException
3616
+	 * @throws InvalidInterfaceException
3617
+	 * @throws InvalidDataTypeException
3618
+	 * @throws EE_Error
3619
+	 */
3620
+	public function get_action_link_or_button(
3621
+		string $action,
3622
+		string $type = 'add',
3623
+		array $extra_request = [],
3624
+		string $class = 'button button--primary',
3625
+		string $base_url = '',
3626
+		bool $exclude_nonce = false
3627
+	): string {
3628
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3629
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3630
+			throw new EE_Error(
3631
+				sprintf(
3632
+					esc_html__(
3633
+						'There is no page route for given action for the button.  This action was given: %s',
3634
+						'event_espresso'
3635
+					),
3636
+					$action
3637
+				)
3638
+			);
3639
+		}
3640
+		if (! isset($this->_labels['buttons'][ $type ])) {
3641
+			throw new EE_Error(
3642
+				sprintf(
3643
+					esc_html__(
3644
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3645
+						'event_espresso'
3646
+					),
3647
+					$type
3648
+				)
3649
+			);
3650
+		}
3651
+		// finally check user access for this button.
3652
+		$has_access = $this->check_user_access($action, true);
3653
+		if (! $has_access) {
3654
+			return '';
3655
+		}
3656
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3657
+		$query_args = [
3658
+			'action' => $action,
3659
+		];
3660
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3661
+		if (! empty($extra_request)) {
3662
+			$query_args = array_merge($extra_request, $query_args);
3663
+		}
3664
+		$url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3665
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3666
+	}
3667
+
3668
+
3669
+	/**
3670
+	 * _per_page_screen_option
3671
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3672
+	 *
3673
+	 * @return void
3674
+	 * @throws InvalidArgumentException
3675
+	 * @throws InvalidInterfaceException
3676
+	 * @throws InvalidDataTypeException
3677
+	 */
3678
+	protected function _per_page_screen_option()
3679
+	{
3680
+		$option = 'per_page';
3681
+		$args   = [
3682
+			'label'   => apply_filters(
3683
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3684
+				$this->_admin_page_title,
3685
+				$this
3686
+			),
3687
+			'default' => (int) apply_filters(
3688
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3689
+				20
3690
+			),
3691
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3692
+		];
3693
+		// ONLY add the screen option if the user has access to it.
3694
+		if ($this->check_user_access($this->_current_view, true)) {
3695
+			add_screen_option($option, $args);
3696
+		}
3697
+	}
3698
+
3699
+
3700
+	/**
3701
+	 * set_per_page_screen_option
3702
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3703
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3704
+	 * admin_menu.
3705
+	 *
3706
+	 * @return void
3707
+	 */
3708
+	private function _set_per_page_screen_options()
3709
+	{
3710
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3711
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3712
+			if (! $user = wp_get_current_user()) {
3713
+				return;
3714
+			}
3715
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', DataType::KEY);
3716
+			if (! $option) {
3717
+				return;
3718
+			}
3719
+			$value      = $this->request->getRequestParam('wp_screen_options[value]', 0, DataType::INT);
3720
+			$map_option = $option;
3721
+			$option     = str_replace('-', '_', $option);
3722
+			switch ($map_option) {
3723
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3724
+					$max_value = apply_filters(
3725
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3726
+						999,
3727
+						$this->_current_page,
3728
+						$this->_current_view
3729
+					);
3730
+					if ($value < 1) {
3731
+						return;
3732
+					}
3733
+					$value = min($value, $max_value);
3734
+					break;
3735
+				default:
3736
+					$value = apply_filters(
3737
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3738
+						false,
3739
+						$option,
3740
+						$value
3741
+					);
3742
+					if (false === $value) {
3743
+						return;
3744
+					}
3745
+					break;
3746
+			}
3747
+			update_user_meta($user->ID, $option, $value);
3748
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3749
+			exit;
3750
+		}
3751
+	}
3752
+
3753
+
3754
+	/**
3755
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3756
+	 *
3757
+	 * @param array $data array that will be assigned to template args.
3758
+	 */
3759
+	public function set_template_args(array $data)
3760
+	{
3761
+		$this->_template_args = array_merge($this->_template_args, $data);
3762
+	}
3763
+
3764
+
3765
+	public function setAdminPageTitle(string $title)
3766
+	{
3767
+		$this->_admin_page_title = sanitize_text_field($title);
3768
+	}
3769
+
3770
+
3771
+	/**
3772
+	 * This makes available the WP transient system for temporarily moving data between routes
3773
+	 *
3774
+	 * @param string $route             the route that should receive the transient
3775
+	 * @param array  $data              the data that gets sent
3776
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise it's just a
3777
+	 *                                  normal route transient.
3778
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3779
+	 *                                  when we are adding a transient before page_routes have been defined.
3780
+	 * @return void
3781
+	 * @throws EE_Error
3782
+	 */
3783
+	protected function _add_transient(
3784
+		string $route,
3785
+		array $data,
3786
+		bool $notices = false,
3787
+		bool $skip_route_verify = false
3788
+	) {
3789
+		$user_id = get_current_user_id();
3790
+		if (! $skip_route_verify) {
3791
+			$this->_verify_route($route);
3792
+		}
3793
+		// now let's set the string for what kind of transient we're setting
3794
+		$transient = $notices ? "ee_rte_n_tx_{$route}_$user_id" : "rte_tx_{$route}_$user_id";
3795
+		$data      = $notices ? ['notices' => $data] : $data;
3796
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3797
+		$existing = is_multisite() && is_network_admin()
3798
+			? get_site_transient($transient)
3799
+			: get_transient($transient);
3800
+		if ($existing) {
3801
+			$data = array_merge($data, (array) $existing);
3802
+		}
3803
+		if (is_multisite() && is_network_admin()) {
3804
+			set_site_transient($transient, $data, 8);
3805
+		} else {
3806
+			set_transient($transient, $data, 8);
3807
+		}
3808
+	}
3809
+
3810
+
3811
+	/**
3812
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3813
+	 *
3814
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3815
+	 * @param string $route
3816
+	 * @return mixed data
3817
+	 */
3818
+	protected function _get_transient(bool $notices = false, string $route = '')
3819
+	{
3820
+		$user_id   = get_current_user_id();
3821
+		$route     = ! $route ? $this->_req_action : $route;
3822
+		$transient = $notices
3823
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3824
+			: 'rte_tx_' . $route . '_' . $user_id;
3825
+		$data      = is_multisite() && is_network_admin()
3826
+			? get_site_transient($transient)
3827
+			: get_transient($transient);
3828
+		// delete transient after retrieval (just in case it hasn't expired);
3829
+		if (is_multisite() && is_network_admin()) {
3830
+			delete_site_transient($transient);
3831
+		} else {
3832
+			delete_transient($transient);
3833
+		}
3834
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3835
+	}
3836
+
3837
+
3838
+	/**
3839
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3840
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3841
+	 * default route callback on the EE_Admin page you want it run.)
3842
+	 *
3843
+	 * @return void
3844
+	 */
3845
+	protected function _transient_garbage_collection()
3846
+	{
3847
+		global $wpdb;
3848
+		// retrieve all existing transients
3849
+		$query =
3850
+			"SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3851
+		if ($results = $wpdb->get_results($query)) {
3852
+			foreach ($results as $result) {
3853
+				$transient = str_replace('_transient_', '', $result->option_name);
3854
+				get_transient($transient);
3855
+				if (is_multisite() && is_network_admin()) {
3856
+					get_site_transient($transient);
3857
+				}
3858
+			}
3859
+		}
3860
+	}
3861
+
3862
+
3863
+	/**
3864
+	 * get_view
3865
+	 *
3866
+	 * @return string content of _view property
3867
+	 */
3868
+	public function get_view(): string
3869
+	{
3870
+		return $this->_view;
3871
+	}
3872
+
3873
+
3874
+	/**
3875
+	 * getter for the protected $_views property
3876
+	 *
3877
+	 * @return array
3878
+	 */
3879
+	public function get_views(): array
3880
+	{
3881
+		return $this->_views;
3882
+	}
3883
+
3884
+
3885
+	/**
3886
+	 * @param array $views
3887
+	 * @return void
3888
+	 * @since 5.0.13.p
3889
+	 */
3890
+	public function updateViews(array $views)
3891
+	{
3892
+		$this->_views = array_merge($this->_views, $views);
3893
+	}
3894
+
3895
+
3896
+	/**
3897
+    /**
3898
+	 * get_current_page
3899
+	 *
3900
+	 * @return string _current_page property value
3901
+	 */
3902
+	public function get_current_page(): string
3903
+	{
3904
+		return $this->_current_page;
3905
+	}
3906
+
3907
+
3908
+	/**
3909
+	 * get_current_view
3910
+	 *
3911
+	 * @return string _current_view property value
3912
+	 */
3913
+	public function get_current_view(): string
3914
+	{
3915
+		return $this->_current_view;
3916
+	}
3917
+
3918
+
3919
+	/**
3920
+	 * get_current_screen
3921
+	 *
3922
+	 * @return object The current WP_Screen object
3923
+	 */
3924
+	public function get_current_screen()
3925
+	{
3926
+		return $this->_current_screen;
3927
+	}
3928
+
3929
+
3930
+	/**
3931
+	 * get_current_page_view_url
3932
+	 *
3933
+	 * @return string This returns the url for the current_page_view.
3934
+	 */
3935
+	public function get_current_page_view_url(): string
3936
+	{
3937
+		return $this->_current_page_view_url;
3938
+	}
3939
+
3940
+
3941
+	/**
3942
+	 * just returns the Request
3943
+	 *
3944
+	 * @return RequestInterface
3945
+	 */
3946
+	public function get_request(): ?RequestInterface
3947
+	{
3948
+		return $this->request;
3949
+	}
3950
+
3951
+
3952
+	/**
3953
+	 * just returns the _req_data property
3954
+	 *
3955
+	 * @return array
3956
+	 */
3957
+	public function get_request_data(): array
3958
+	{
3959
+		return $this->request->requestParams();
3960
+	}
3961
+
3962
+
3963
+	/**
3964
+	 * returns the _req_data protected property
3965
+	 *
3966
+	 * @return string
3967
+	 */
3968
+	public function get_req_action(): string
3969
+	{
3970
+		return $this->_req_action;
3971
+	}
3972
+
3973
+
3974
+	/**
3975
+	 * @return bool  value of $_is_caf property
3976
+	 */
3977
+	public function is_caf(): bool
3978
+	{
3979
+		return $this->_is_caf;
3980
+	}
3981
+
3982
+
3983
+	/**
3984
+	 * @return array
3985
+	 */
3986
+	public function default_espresso_metaboxes(): array
3987
+	{
3988
+		return $this->_default_espresso_metaboxes;
3989
+	}
3990
+
3991
+
3992
+	/**
3993
+	 * @return string
3994
+	 */
3995
+	public function admin_base_url(): string
3996
+	{
3997
+		return $this->_admin_base_url;
3998
+	}
3999
+
4000
+
4001
+	/**
4002
+	 * @return string
4003
+	 */
4004
+	public function wp_page_slug(): string
4005
+	{
4006
+		return $this->_wp_page_slug;
4007
+	}
4008
+
4009
+
4010
+	/**
4011
+	 * updates  espresso configuration settings
4012
+	 *
4013
+	 * @param string                   $tab
4014
+	 * @param EE_Config_Base|EE_Config $config
4015
+	 * @param string                   $file file where error occurred
4016
+	 * @param string                   $func function  where error occurred
4017
+	 * @param string                   $line line no where error occurred
4018
+	 * @return bool
4019
+	 */
4020
+	protected function _update_espresso_configuration(
4021
+		string $tab,
4022
+		$config,
4023
+		string $file = '',
4024
+		string $func = '',
4025
+		string $line = ''
4026
+	): bool {
4027
+		// remove any options that are NOT going to be saved with the config settings.
4028
+		if (isset($config->core->ee_ueip_optin)) {
4029
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4030
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4031
+			update_option('ee_ueip_has_notified', true);
4032
+		}
4033
+		// and save it (note we're also doing the network save here)
4034
+		$net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
4035
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4036
+		if ($config_saved && $net_saved) {
4037
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4038
+			return true;
4039
+		}
4040
+		EE_Error::add_error(
4041
+			sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab),
4042
+			$file,
4043
+			$func,
4044
+			$line
4045
+		);
4046
+		return false;
4047
+	}
4048
+
4049
+
4050
+	/**
4051
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4052
+	 *
4053
+	 * @return array
4054
+	 */
4055
+	public function get_yes_no_values(): array
4056
+	{
4057
+		return $this->_yes_no_values;
4058
+	}
4059
+
4060
+
4061
+	/**
4062
+	 * @return string
4063
+	 * @throws ReflectionException
4064
+	 * @since 5.0.0.p
4065
+	 */
4066
+	protected function _get_dir(): string
4067
+	{
4068
+		$reflector = new ReflectionClass($this->class_name);
4069
+		return dirname($reflector->getFileName());
4070
+	}
4071
+
4072
+
4073
+	/**
4074
+	 * A helper for getting a "next link".
4075
+	 *
4076
+	 * @param string $url   The url to link to
4077
+	 * @param string $class The class to use.
4078
+	 * @return string
4079
+	 */
4080
+	protected function _next_link(string $url, string $class = 'dashicons dashicons-arrow-right'): string
4081
+	{
4082
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4083
+	}
4084
+
4085
+
4086
+	/**
4087
+	 * A helper for getting a "previous link".
4088
+	 *
4089
+	 * @param string $url   The url to link to
4090
+	 * @param string $class The class to use.
4091
+	 * @return string
4092
+	 */
4093
+	protected function _previous_link(string $url, string $class = 'dashicons dashicons-arrow-left'): string
4094
+	{
4095
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4096
+	}
4097
+
4098
+
4099
+
4100
+
4101
+
4102
+
4103
+
4104
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4105
+
4106
+
4107
+	/**
4108
+	 * This processes a request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4109
+	 * 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
4110
+	 * _req_data array.
4111
+	 *
4112
+	 * @return bool success/fail
4113
+	 * @throws EE_Error
4114
+	 * @throws InvalidArgumentException
4115
+	 * @throws ReflectionException
4116
+	 * @throws InvalidDataTypeException
4117
+	 * @throws InvalidInterfaceException
4118
+	 */
4119
+	protected function _process_resend_registration(): bool
4120
+	{
4121
+		$this->_template_args['success'] = EED_Messages::process_resend($this->request->requestParams());
4122
+		do_action(
4123
+			'AHEE__EE_Admin_Page___process_resend_registration',
4124
+			$this->_template_args['success'],
4125
+			$this->request->requestParams()
4126
+		);
4127
+		return $this->_template_args['success'];
4128
+	}
4129
+
4130
+
4131
+	/**
4132
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4133
+	 *
4134
+	 * @param EE_Payment $payment
4135
+	 * @return bool success/fail
4136
+	 */
4137
+	protected function _process_payment_notification(EE_Payment $payment): bool
4138
+	{
4139
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4140
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4141
+		$this->_template_args['success'] = apply_filters(
4142
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4143
+			false,
4144
+			$payment
4145
+		);
4146
+		return $this->_template_args['success'];
4147
+	}
4148
+
4149
+
4150
+	/**
4151
+	 * @param EEM_Base      $entity_model
4152
+	 * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4153
+	 * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4154
+	 * @param string        $delete_column  name of the field that denotes whether entity is trashed
4155
+	 * @param callable|null $callback       called after entity is trashed, restored, or deleted
4156
+	 * @return int|float
4157
+	 * @throws EE_Error
4158
+	 */
4159
+	protected function trashRestoreDeleteEntities(
4160
+		EEM_Base $entity_model,
4161
+		string $entity_PK_name,
4162
+		string $action = EE_Admin_List_Table::ACTION_DELETE,
4163
+		string $delete_column = '',
4164
+		?callable $callback = null
4165
+	) {
4166
+		$entity_PK      = $entity_model->get_primary_key_field();
4167
+		$entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4168
+		$entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4169
+		// grab ID if deleting a single entity
4170
+		if ($this->request->requestParamIsSet($entity_PK_name)) {
4171
+			$ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4172
+			return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4173
+		}
4174
+		// or grab checkbox array if bulk deleting
4175
+		$checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4176
+		if (empty($checkboxes)) {
4177
+			return 0;
4178
+		}
4179
+		$success = 0;
4180
+		$IDs     = array_keys($checkboxes);
4181
+		// cycle thru bulk action checkboxes
4182
+		foreach ($IDs as $ID) {
4183
+			// increment $success
4184
+			if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4185
+				$success++;
4186
+			}
4187
+		}
4188
+		$count = (int) count($checkboxes);
4189
+		// if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4190
+		// otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4191
+		return $success === $count ? $count : $success / $count;
4192
+	}
4193
+
4194
+
4195
+	/**
4196
+	 * @param EE_Primary_Key_Field_Base $entity_PK
4197
+	 * @return string
4198
+	 * @throws EE_Error
4199
+	 * @since   4.10.30.p
4200
+	 */
4201
+	private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4202
+	{
4203
+		$entity_PK_type = $entity_PK->getSchemaType();
4204
+		switch ($entity_PK_type) {
4205
+			case 'boolean':
4206
+				return DataType::BOOL;
4207
+			case 'integer':
4208
+				return DataType::INT;
4209
+			case 'number':
4210
+				return DataType::FLOAT;
4211
+			case 'string':
4212
+				return DataType::STRING;
4213
+		}
4214
+		throw new RuntimeException(
4215
+			sprintf(
4216
+				esc_html__(
4217
+					'"%1$s" is an invalid schema type for the %2$s primary key.',
4218
+					'event_espresso'
4219
+				),
4220
+				$entity_PK_type,
4221
+				$entity_PK->get_name()
4222
+			)
4223
+		);
4224
+	}
4225
+
4226
+
4227
+	/**
4228
+	 * @param EEM_Base      $entity_model
4229
+	 * @param int|string    $entity_ID
4230
+	 * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4231
+	 * @param string        $delete_column name of the field that denotes whether entity is trashed
4232
+	 * @param callable|null $callback      called after entity is trashed, restored, or deleted
4233
+	 * @return bool
4234
+	 */
4235
+	protected function trashRestoreDeleteEntity(
4236
+		EEM_Base $entity_model,
4237
+		$entity_ID,
4238
+		string $action,
4239
+		string $delete_column,
4240
+		?callable $callback = null
4241
+	): bool {
4242
+		$entity_ID = absint($entity_ID);
4243
+		if (! $entity_ID) {
4244
+			$this->trashRestoreDeleteError($action, $entity_model);
4245
+		}
4246
+		$result = 0;
4247
+		try {
4248
+			$entity = $entity_model->get_one_by_ID($entity_ID);
4249
+			if (! $entity instanceof EE_Base_Class) {
4250
+				throw new DomainException(
4251
+					sprintf(
4252
+						esc_html__(
4253
+							'Missing or invalid %1$s entity with ID of "%2$s" returned from db.',
4254
+							'event_espresso'
4255
+						),
4256
+						str_replace('EEM_', '', $entity_model->get_this_model_name()),
4257
+						$entity_ID
4258
+					)
4259
+				);
4260
+			}
4261
+			switch ($action) {
4262
+				case EE_Admin_List_Table::ACTION_DELETE:
4263
+					$result = (bool) $entity->delete_permanently();
4264
+					break;
4265
+				case EE_Admin_List_Table::ACTION_RESTORE:
4266
+					$result = $entity->delete_or_restore(false);
4267
+					break;
4268
+				case EE_Admin_List_Table::ACTION_TRASH:
4269
+					$result = $entity->delete_or_restore();
4270
+					break;
4271
+			}
4272
+		} catch (Exception $exception) {
4273
+			$this->trashRestoreDeleteError($action, $entity_model, $exception);
4274
+		}
4275
+		if (is_callable($callback)) {
4276
+			call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4277
+		}
4278
+		return $result;
4279
+	}
4280
+
4281
+
4282
+	/**
4283
+	 * @param EEM_Base $entity_model
4284
+	 * @param string   $delete_column
4285
+	 * @since 4.10.30.p
4286
+	 */
4287
+	private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4288
+	{
4289
+		if (empty($delete_column)) {
4290
+			throw new DomainException(
4291
+				sprintf(
4292
+					esc_html__(
4293
+						'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4294
+						'event_espresso'
4295
+					),
4296
+					$entity_model->get_this_model_name()
4297
+				)
4298
+			);
4299
+		}
4300
+		if (! $entity_model->has_field($delete_column)) {
4301
+			throw new DomainException(
4302
+				sprintf(
4303
+					esc_html__(
4304
+						'The %1$s field does not exist on the %2$s model.',
4305
+						'event_espresso'
4306
+					),
4307
+					$delete_column,
4308
+					$entity_model->get_this_model_name()
4309
+				)
4310
+			);
4311
+		}
4312
+	}
4313
+
4314
+
4315
+	/**
4316
+	 * @param EEM_Base       $entity_model
4317
+	 * @param Exception|null $exception
4318
+	 * @param string         $action
4319
+	 * @since 4.10.30.p
4320
+	 */
4321
+	private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, Exception $exception = null)
4322
+	{
4323
+		if ($exception instanceof Exception) {
4324
+			throw new RuntimeException(
4325
+				sprintf(
4326
+					esc_html__(
4327
+						'Could not %1$s the %2$s because the following error occurred: %3$s',
4328
+						'event_espresso'
4329
+					),
4330
+					$action,
4331
+					$entity_model->get_this_model_name(),
4332
+					$exception->getMessage()
4333
+				)
4334
+			);
4335
+		}
4336
+		throw new RuntimeException(
4337
+			sprintf(
4338
+				esc_html__(
4339
+					'Could not %1$s the %2$s because an invalid ID was received.',
4340
+					'event_espresso'
4341
+				),
4342
+				$action,
4343
+				$entity_model->get_this_model_name()
4344
+			)
4345
+		);
4346
+	}
4347 4347
 }
Please login to merge, or discard this patch.
Spacing   +173 added lines, -173 removed lines patch added patch discarded remove patch
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
 
246 246
     public function capabilities(): EE_Capabilities
247 247
     {
248
-        if (! $this->capabilities instanceof EE_Capabilities) {
248
+        if ( ! $this->capabilities instanceof EE_Capabilities) {
249 249
             $this->capabilities = $this->loader->getShared(EE_Capabilities::class);
250 250
         }
251 251
         return $this->capabilities;
@@ -609,7 +609,7 @@  discard block
 block discarded – undo
609 609
         $ee_menu_slugs = (array) $ee_menu_slugs;
610 610
         if (
611 611
             ! $this->request->isAjax()
612
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
612
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
613 613
         ) {
614 614
             return;
615 615
         }
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
             ? $route
630 630
             : $req_action;
631 631
         $this->_current_view = $this->_req_action;
632
-        $this->_req_nonce    = $this->_req_action . '_nonce';
632
+        $this->_req_nonce    = $this->_req_action.'_nonce';
633 633
         $this->_define_page_props();
634 634
         $this->_current_page_view_url = add_query_arg(
635 635
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -653,33 +653,33 @@  discard block
 block discarded – undo
653 653
         }
654 654
         // filter routes and page_config so addons can add their stuff. Filtering done per class
655 655
         $this->_page_routes = apply_filters(
656
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
656
+            'FHEE__'.$this->class_name.'__page_setup__page_routes',
657 657
             $this->_page_routes,
658 658
             $this
659 659
         );
660 660
         $this->_page_config = apply_filters(
661
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
661
+            'FHEE__'.$this->class_name.'__page_setup__page_config',
662 662
             $this->_page_config,
663 663
             $this
664 664
         );
665 665
         if ($this->base_class_name !== '') {
666 666
             $this->_page_routes = apply_filters(
667
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
667
+                'FHEE__'.$this->base_class_name.'__page_setup__page_routes',
668 668
                 $this->_page_routes,
669 669
                 $this
670 670
             );
671 671
             $this->_page_config = apply_filters(
672
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
672
+                'FHEE__'.$this->base_class_name.'__page_setup__page_config',
673 673
                 $this->_page_config,
674 674
                 $this
675 675
             );
676 676
         }
677 677
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
678 678
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
679
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
679
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
680 680
             add_action(
681 681
                 'AHEE__EE_Admin_Page__route_admin_request',
682
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
682
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
683 683
                 10,
684 684
                 2
685 685
             );
@@ -692,8 +692,8 @@  discard block
 block discarded – undo
692 692
             if ($this->_is_UI_request) {
693 693
                 // admin_init stuff - global, all views for this page class, specific view
694 694
                 add_action('admin_init', [$this, 'admin_init']);
695
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
696
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
695
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
696
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
697 697
                 }
698 698
             } else {
699 699
                 // hijack regular WP loading and route admin request immediately
@@ -712,12 +712,12 @@  discard block
 block discarded – undo
712 712
      */
713 713
     private function _do_other_page_hooks()
714 714
     {
715
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
715
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
716 716
         foreach ($registered_pages as $page) {
717 717
             // now let's set up the file name and class that should be present
718 718
             $classname = str_replace('.class.php', '', $page);
719 719
             // autoloaders should take care of loading file
720
-            if (! class_exists($classname)) {
720
+            if ( ! class_exists($classname)) {
721 721
                 $error_msg[] = sprintf(
722 722
                     esc_html__(
723 723
                         'Something went wrong with loading the %s admin hooks page.',
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
                                    ),
735 735
                                    $page,
736 736
                                    '<br />',
737
-                                   '<strong>' . $classname . '</strong>'
737
+                                   '<strong>'.$classname.'</strong>'
738 738
                                );
739 739
                 throw new EE_Error(implode('||', $error_msg));
740 740
             }
@@ -783,13 +783,13 @@  discard block
 block discarded – undo
783 783
         // load admin_notices - global, page class, and view specific
784 784
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
785 785
         add_action('admin_notices', [$this, 'admin_notices']);
786
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
787
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
786
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
787
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
788 788
         }
789 789
         // load network admin_notices - global, page class, and view specific
790 790
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
791
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
792
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
791
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
792
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
793 793
         }
794 794
         // this will save any per_page screen options if they are present
795 795
         $this->_set_per_page_screen_options();
@@ -915,7 +915,7 @@  discard block
 block discarded – undo
915 915
      */
916 916
     protected function _verify_routes(): bool
917 917
     {
918
-        if (! $this->_current_page && ! $this->request->isAjax()) {
918
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
919 919
             return false;
920 920
         }
921 921
         // check that the page_routes array is not empty
@@ -926,7 +926,7 @@  discard block
 block discarded – undo
926 926
                 $this->_admin_page_title
927 927
             );
928 928
             // developer error msg
929
-            $error_msg .= '||' . $error_msg
929
+            $error_msg .= '||'.$error_msg
930 930
                           . esc_html__(
931 931
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
932 932
                               'event_espresso'
@@ -944,8 +944,8 @@  discard block
 block discarded – undo
944 944
         }
945 945
         // and that the requested page route exists
946 946
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
947
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
948
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
947
+            $this->_route        = $this->_page_routes[$this->_req_action];
948
+            $this->_route_config = $this->_page_config[$this->_req_action] ?? [];
949 949
         } else {
950 950
             // user error msg
951 951
             $error_msg = sprintf(
@@ -956,7 +956,7 @@  discard block
 block discarded – undo
956 956
                 $this->_admin_page_title
957 957
             );
958 958
             // developer error msg
959
-            $error_msg .= '||' . $error_msg
959
+            $error_msg .= '||'.$error_msg
960 960
                           . sprintf(
961 961
                               esc_html__(
962 962
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -967,7 +967,7 @@  discard block
 block discarded – undo
967 967
             throw new EE_Error($error_msg);
968 968
         }
969 969
         // and that a default route exists
970
-        if (! array_key_exists('default', $this->_page_routes)) {
970
+        if ( ! array_key_exists('default', $this->_page_routes)) {
971 971
             // user error msg
972 972
             $error_msg = sprintf(
973 973
                 esc_html__(
@@ -977,7 +977,7 @@  discard block
 block discarded – undo
977 977
                 $this->_admin_page_title
978 978
             );
979 979
             // developer error msg
980
-            $error_msg .= '||' . $error_msg
980
+            $error_msg .= '||'.$error_msg
981 981
                           . esc_html__(
982 982
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
983 983
                               'event_espresso'
@@ -1017,7 +1017,7 @@  discard block
 block discarded – undo
1017 1017
             $this->_admin_page_title
1018 1018
         );
1019 1019
         // developer error msg
1020
-        $error_msg .= '||' . $error_msg
1020
+        $error_msg .= '||'.$error_msg
1021 1021
                       . sprintf(
1022 1022
                           esc_html__(
1023 1023
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -1045,7 +1045,7 @@  discard block
 block discarded – undo
1045 1045
     protected function _verify_nonce(string $nonce, string $nonce_ref)
1046 1046
     {
1047 1047
         // verify nonce against expected value
1048
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1048
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
1049 1049
             // these are not the droids you are looking for !!!
1050 1050
             $msg = sprintf(
1051 1051
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -1062,7 +1062,7 @@  discard block
 block discarded – undo
1062 1062
                     __CLASS__
1063 1063
                 );
1064 1064
             }
1065
-            if (! $this->request->isAjax()) {
1065
+            if ( ! $this->request->isAjax()) {
1066 1066
                 wp_die($msg);
1067 1067
             }
1068 1068
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -1087,7 +1087,7 @@  discard block
 block discarded – undo
1087 1087
      */
1088 1088
     protected function _route_admin_request()
1089 1089
     {
1090
-        if (! $this->_is_UI_request) {
1090
+        if ( ! $this->_is_UI_request) {
1091 1091
             $this->_verify_routes();
1092 1092
         }
1093 1093
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -1107,7 +1107,7 @@  discard block
 block discarded – undo
1107 1107
 
1108 1108
         // action right before calling route
1109 1109
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1110
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1110
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1111 1111
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1112 1112
         }
1113 1113
         // strip _wp_http_referer from the server REQUEST_URI
@@ -1122,7 +1122,7 @@  discard block
 block discarded – undo
1122 1122
         $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1123 1123
         $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1124 1124
         $route_callback = [];
1125
-        if (! empty($func)) {
1125
+        if ( ! empty($func)) {
1126 1126
             if (is_array($func) && is_callable($func)) {
1127 1127
                 $route_callback = $func;
1128 1128
             } elseif (is_string($func)) {
@@ -1136,7 +1136,7 @@  discard block
 block discarded – undo
1136 1136
             }
1137 1137
             [$class, $method] = $route_callback;
1138 1138
             // is it neither a class method NOR a standalone function?
1139
-            if (! is_callable($route_callback)) {
1139
+            if ( ! is_callable($route_callback)) {
1140 1140
                 // user error msg
1141 1141
                 $error_msg = esc_html__(
1142 1142
                     'An error occurred. The  requested page route could not be found.',
@@ -1245,7 +1245,7 @@  discard block
 block discarded – undo
1245 1245
                 if (strpos($key, 'nonce') !== false) {
1246 1246
                     continue;
1247 1247
                 }
1248
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1248
+                $args['wp_referer['.$key.']'] = is_string($value) ? htmlspecialchars($value) : $value;
1249 1249
             }
1250 1250
         }
1251 1251
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce, $context);
@@ -1285,12 +1285,12 @@  discard block
 block discarded – undo
1285 1285
      */
1286 1286
     protected function _add_help_tabs()
1287 1287
     {
1288
-        if (isset($this->_page_config[ $this->_req_action ])) {
1289
-            $config = $this->_page_config[ $this->_req_action ];
1288
+        if (isset($this->_page_config[$this->_req_action])) {
1289
+            $config = $this->_page_config[$this->_req_action];
1290 1290
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1291 1291
             if (is_array($config) && isset($config['help_sidebar'])) {
1292 1292
                 // check that the callback given is valid
1293
-                if (! method_exists($this, $config['help_sidebar'])) {
1293
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1294 1294
                     throw new EE_Error(
1295 1295
                         sprintf(
1296 1296
                             esc_html__(
@@ -1303,18 +1303,18 @@  discard block
 block discarded – undo
1303 1303
                     );
1304 1304
                 }
1305 1305
                 $content = apply_filters(
1306
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1306
+                    'FHEE__'.$this->class_name.'__add_help_tabs__help_sidebar',
1307 1307
                     $this->{$config['help_sidebar']}()
1308 1308
                 );
1309 1309
                 $this->_current_screen->set_help_sidebar($content);
1310 1310
             }
1311
-            if (! isset($config['help_tabs'])) {
1311
+            if ( ! isset($config['help_tabs'])) {
1312 1312
                 return;
1313 1313
             } //no help tabs for this route
1314 1314
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1315 1315
                 // we're here so there ARE help tabs!
1316 1316
                 // make sure we've got what we need
1317
-                if (! isset($cfg['title'])) {
1317
+                if ( ! isset($cfg['title'])) {
1318 1318
                     throw new EE_Error(
1319 1319
                         esc_html__(
1320 1320
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1322,7 +1322,7 @@  discard block
 block discarded – undo
1322 1322
                         )
1323 1323
                     );
1324 1324
                 }
1325
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1325
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1326 1326
                     throw new EE_Error(
1327 1327
                         esc_html__(
1328 1328
                             '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',
@@ -1331,11 +1331,11 @@  discard block
 block discarded – undo
1331 1331
                     );
1332 1332
                 }
1333 1333
                 // first priority goes to content.
1334
-                if (! empty($cfg['content'])) {
1334
+                if ( ! empty($cfg['content'])) {
1335 1335
                     $content = $cfg['content'];
1336 1336
                     // second priority goes to filename
1337
-                } elseif (! empty($cfg['filename'])) {
1338
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1337
+                } elseif ( ! empty($cfg['filename'])) {
1338
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1339 1339
                     // 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)
1340 1340
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1341 1341
                                                              . basename($this->_get_dir())
@@ -1343,7 +1343,7 @@  discard block
 block discarded – undo
1343 1343
                                                              . $cfg['filename']
1344 1344
                                                              . '.help_tab.php' : $file_path;
1345 1345
                     // if file is STILL not readable then let's do an EE_Error so its more graceful than a fatal error.
1346
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1346
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1347 1347
                         EE_Error::add_error(
1348 1348
                             sprintf(
1349 1349
                                 esc_html__(
@@ -1391,7 +1391,7 @@  discard block
 block discarded – undo
1391 1391
                     return;
1392 1392
                 }
1393 1393
                 // setup config array for help tab method
1394
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1394
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1395 1395
                 $_ht = [
1396 1396
                     'id'       => $id,
1397 1397
                     'title'    => $cfg['title'],
@@ -1417,8 +1417,8 @@  discard block
 block discarded – undo
1417 1417
             $qtips = (array) $this->_route_config['qtips'];
1418 1418
             // load qtip loader
1419 1419
             $path = [
1420
-                $this->_get_dir() . '/qtips/',
1421
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1420
+                $this->_get_dir().'/qtips/',
1421
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1422 1422
             ];
1423 1423
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1424 1424
         }
@@ -1440,7 +1440,7 @@  discard block
 block discarded – undo
1440 1440
         $i        = 0;
1441 1441
         $only_tab = count($this->_page_config) < 2;
1442 1442
         foreach ($this->_page_config as $slug => $config) {
1443
-            if (! is_array($config) || empty($config['nav'])) {
1443
+            if ( ! is_array($config) || empty($config['nav'])) {
1444 1444
                 continue;
1445 1445
             }
1446 1446
             // no nav tab for this config
@@ -1449,7 +1449,7 @@  discard block
 block discarded – undo
1449 1449
                 // nav tab is only to appear when route requested.
1450 1450
                 continue;
1451 1451
             }
1452
-            if (! $this->check_user_access($slug, true)) {
1452
+            if ( ! $this->check_user_access($slug, true)) {
1453 1453
                 // no nav tab because current user does not have access.
1454 1454
                 continue;
1455 1455
             }
@@ -1457,20 +1457,20 @@  discard block
 block discarded – undo
1457 1457
             $css_class .= $only_tab ? ' ee-only-tab' : '';
1458 1458
             $css_class .= " ee-nav-tab__$slug";
1459 1459
 
1460
-            $this->_nav_tabs[ $slug ] = [
1460
+            $this->_nav_tabs[$slug] = [
1461 1461
                 'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1462 1462
                         ['action' => $slug],
1463 1463
                         $this->_admin_base_url
1464 1464
                     ),
1465 1465
                 'link_text' => $this->navTabLabel($config['nav'], $slug),
1466
-                'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1466
+                'css_class' => $this->_req_action === $slug ? $css_class.' nav-tab-active' : $css_class,
1467 1467
                 'order'     => $config['nav']['order'] ?? $i,
1468 1468
             ];
1469 1469
             $i++;
1470 1470
         }
1471 1471
         // if $this->_nav_tabs is empty then lets set the default
1472 1472
         if (empty($this->_nav_tabs)) {
1473
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1473
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1474 1474
                 'url'       => $this->_admin_base_url,
1475 1475
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1476 1476
                 'css_class' => 'nav-tab-active',
@@ -1486,11 +1486,11 @@  discard block
 block discarded – undo
1486 1486
     {
1487 1487
         $label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1488 1488
         $icon  = $nav_tab['icon'] ?? null;
1489
-        $icon  = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1489
+        $icon  = $icon ? '<span class="dashicons '.$icon.'"></span>' : '';
1490 1490
         return '
1491 1491
             <span class="ee-admin-screen-tab__label">
1492
-                ' . $icon . '
1493
-                <span class="ee-nav-label__text">' . $label . '</span>
1492
+                ' . $icon.'
1493
+                <span class="ee-nav-label__text">' . $label.'</span>
1494 1494
             </span>';
1495 1495
     }
1496 1496
 
@@ -1508,10 +1508,10 @@  discard block
 block discarded – undo
1508 1508
             foreach ($this->_route_config['labels'] as $label => $text) {
1509 1509
                 if (is_array($text)) {
1510 1510
                     foreach ($text as $sublabel => $subtext) {
1511
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1511
+                        $this->_labels[$label][$sublabel] = $subtext;
1512 1512
                     }
1513 1513
                 } else {
1514
-                    $this->_labels[ $label ] = $text;
1514
+                    $this->_labels[$label] = $text;
1515 1515
                 }
1516 1516
             }
1517 1517
         }
@@ -1533,8 +1533,8 @@  discard block
 block discarded – undo
1533 1533
     {
1534 1534
         // if no route_to_check is passed in then use the current route set via _req_action
1535 1535
         $action = $route_to_check ?: $this->_req_action;
1536
-        $capability = ! empty($this->_page_routes[ $action ]['capability'])
1537
-            ? $this->_page_routes[ $action ]['capability']
1536
+        $capability = ! empty($this->_page_routes[$action]['capability'])
1537
+            ? $this->_page_routes[$action]['capability']
1538 1538
             : null;
1539 1539
 
1540 1540
         if (empty($capability)) {
@@ -1584,14 +1584,14 @@  discard block
 block discarded – undo
1584 1584
         string $priority = 'default',
1585 1585
         ?array $callback_args = null
1586 1586
     ) {
1587
-        if (! (is_callable($callback) || ! function_exists($callback))) {
1587
+        if ( ! (is_callable($callback) || ! function_exists($callback))) {
1588 1588
             return;
1589 1589
         }
1590 1590
 
1591 1591
         add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1592 1592
         add_filter(
1593 1593
             "postbox_classes_{$this->_wp_page_slug}_$box_id",
1594
-            function ($classes) {
1594
+            function($classes) {
1595 1595
                 $classes[] = 'ee-admin-container';
1596 1596
                 return $classes;
1597 1597
             }
@@ -1682,8 +1682,8 @@  discard block
 block discarded – undo
1682 1682
             <div class="ee-notices"></div>
1683 1683
             <div class="ee-admin-dialog-container-inner-content"></div>
1684 1684
         </div>
1685
-        <span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>
1686
-        <input type="hidden" id="espresso_admin_current_page" value="' . esc_attr($this->_current_page) . '"/>';
1685
+        <span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()).'</span>
1686
+        <input type="hidden" id="espresso_admin_current_page" value="' . esc_attr($this->_current_page).'"/>';
1687 1687
     }
1688 1688
 
1689 1689
 
@@ -1717,7 +1717,7 @@  discard block
 block discarded – undo
1717 1717
         // loop through the array and setup content
1718 1718
         foreach ($help_array as $trigger => $help) {
1719 1719
             // make sure the array is set up properly
1720
-            if (! isset($help['title'], $help['content'])) {
1720
+            if ( ! isset($help['title'], $help['content'])) {
1721 1721
                 throw new EE_Error(
1722 1722
                     esc_html__(
1723 1723
                         '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',
@@ -1731,8 +1731,8 @@  discard block
 block discarded – undo
1731 1731
                 'help_popup_title'   => $help['title'],
1732 1732
                 'help_popup_content' => $help['content'],
1733 1733
             ];
1734
-            $content       .= EEH_Template::display_template(
1735
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1734
+            $content .= EEH_Template::display_template(
1735
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1736 1736
                 $template_args,
1737 1737
                 true
1738 1738
             );
@@ -1754,15 +1754,15 @@  discard block
 block discarded – undo
1754 1754
     private function _get_help_content(): array
1755 1755
     {
1756 1756
         // what is the method we're looking for?
1757
-        $method_name = '_help_popup_content_' . $this->_req_action;
1757
+        $method_name = '_help_popup_content_'.$this->_req_action;
1758 1758
         // if method doesn't exist let's get out.
1759
-        if (! method_exists($this, $method_name)) {
1759
+        if ( ! method_exists($this, $method_name)) {
1760 1760
             return [];
1761 1761
         }
1762 1762
         // k we're good to go let's retrieve the help array
1763 1763
         $help_array = $this->{$method_name}();
1764 1764
         // make sure we've got an array!
1765
-        if (! is_array($help_array)) {
1765
+        if ( ! is_array($help_array)) {
1766 1766
             throw new EE_Error(
1767 1767
                 esc_html__(
1768 1768
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1794,15 +1794,15 @@  discard block
 block discarded – undo
1794 1794
         // 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
1795 1795
         $help_array   = $this->_get_help_content();
1796 1796
         $help_content = '';
1797
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1798
-            $help_array[ $trigger_id ] = [
1797
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1798
+            $help_array[$trigger_id] = [
1799 1799
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1800 1800
                 'content' => esc_html__(
1801 1801
                     '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.)',
1802 1802
                     'event_espresso'
1803 1803
                 ),
1804 1804
             ];
1805
-            $help_content              = $this->_set_help_popup_content($help_array);
1805
+            $help_content = $this->_set_help_popup_content($help_array);
1806 1806
         }
1807 1807
         $height   = esc_attr($dimensions[0]) ?? 400;
1808 1808
         $width    = esc_attr($dimensions[1]) ?? 640;
@@ -1890,7 +1890,7 @@  discard block
 block discarded – undo
1890 1890
 
1891 1891
         add_filter(
1892 1892
             'admin_body_class',
1893
-            function ($classes) {
1893
+            function($classes) {
1894 1894
                 if (strpos($classes, 'espresso-admin') === false) {
1895 1895
                     $classes .= ' espresso-admin';
1896 1896
                 }
@@ -1981,12 +1981,12 @@  discard block
 block discarded – undo
1981 1981
     protected function _set_list_table()
1982 1982
     {
1983 1983
         // first is this a list_table view?
1984
-        if (! isset($this->_route_config['list_table'])) {
1984
+        if ( ! isset($this->_route_config['list_table'])) {
1985 1985
             return;
1986 1986
         } //not a list_table view so get out.
1987 1987
         // list table functions are per view specific (because some admin pages might have more than one list table!)
1988
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
1989
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1988
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
1989
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1990 1990
             // user error msg
1991 1991
             $error_msg = esc_html__(
1992 1992
                 'An error occurred. The requested list table views could not be found.',
@@ -2006,10 +2006,10 @@  discard block
 block discarded – undo
2006 2006
         }
2007 2007
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2008 2008
         $this->_views = apply_filters(
2009
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2009
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2010 2010
             $this->_views
2011 2011
         );
2012
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2012
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2013 2013
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2014 2014
         $this->_set_list_table_view();
2015 2015
         $this->_set_list_table_object();
@@ -2044,7 +2044,7 @@  discard block
 block discarded – undo
2044 2044
     protected function _set_list_table_object()
2045 2045
     {
2046 2046
         if (isset($this->_route_config['list_table'])) {
2047
-            if (! class_exists($this->_route_config['list_table'])) {
2047
+            if ( ! class_exists($this->_route_config['list_table'])) {
2048 2048
                 throw new EE_Error(
2049 2049
                     sprintf(
2050 2050
                         esc_html__(
@@ -2086,16 +2086,16 @@  discard block
 block discarded – undo
2086 2086
         foreach ($this->_views as $key => $view) {
2087 2087
             $query_args = [];
2088 2088
             // check for current view
2089
-            $this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2089
+            $this->_views[$key]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2090 2090
             $query_args['action']          = $this->_req_action;
2091 2091
             $action_nonce                  = "{$this->_req_action}_nonce";
2092
-            $query_args[ $action_nonce ]   = wp_create_nonce($action_nonce);
2092
+            $query_args[$action_nonce]   = wp_create_nonce($action_nonce);
2093 2093
             $query_args['status']          = $view['slug'];
2094 2094
             // merge any other arguments sent in.
2095
-            if (isset($extra_query_args[ $view['slug'] ])) {
2096
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2095
+            if (isset($extra_query_args[$view['slug']])) {
2096
+                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2097 2097
             }
2098
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2098
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2099 2099
         }
2100 2100
         return $this->_views;
2101 2101
     }
@@ -2124,14 +2124,14 @@  discard block
 block discarded – undo
2124 2124
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2125 2125
         foreach ($values as $value) {
2126 2126
             if ($value < $max_entries) {
2127
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2127
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2128 2128
                 $entries_per_page_dropdown .= '
2129
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2129
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2130 2130
             }
2131 2131
         }
2132
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2132
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2133 2133
         $entries_per_page_dropdown .= '
2134
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2134
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2135 2135
         $entries_per_page_dropdown .= '
2136 2136
 					</select>
2137 2137
 					entries
@@ -2155,7 +2155,7 @@  discard block
 block discarded – undo
2155 2155
             empty($this->_search_btn_label) ? $this->page_label
2156 2156
                 : $this->_search_btn_label
2157 2157
         );
2158
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2158
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2159 2159
     }
2160 2160
 
2161 2161
 
@@ -2216,7 +2216,7 @@  discard block
 block discarded – undo
2216 2216
                                   );
2217 2217
                     throw new EE_Error($error_msg);
2218 2218
                 }
2219
-                unset($this->_route_config['metaboxes'][ $key ]);
2219
+                unset($this->_route_config['metaboxes'][$key]);
2220 2220
             }
2221 2221
         }
2222 2222
     }
@@ -2249,7 +2249,7 @@  discard block
 block discarded – undo
2249 2249
             $total_columns                                       = ! empty($screen_columns)
2250 2250
                 ? $screen_columns
2251 2251
                 : $this->_route_config['columns'][1];
2252
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2252
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2253 2253
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2254 2254
             $this->_template_args['screen']                      = $this->_current_screen;
2255 2255
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2295,7 +2295,7 @@  discard block
 block discarded – undo
2295 2295
      */
2296 2296
     protected function _espresso_ratings_request()
2297 2297
     {
2298
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2298
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2299 2299
             return;
2300 2300
         }
2301 2301
         $ratings_box_title = apply_filters(
@@ -2322,28 +2322,28 @@  discard block
 block discarded – undo
2322 2322
      */
2323 2323
     public function espresso_ratings_request()
2324 2324
     {
2325
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2325
+        EEH_Template::display_template(EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php');
2326 2326
     }
2327 2327
 
2328 2328
 
2329 2329
     public static function cached_rss_display(string $rss_id, string $url): bool
2330 2330
     {
2331
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2331
+        $loading = '<p class="widget-loading hide-if-no-js">'
2332 2332
                      . esc_html__('Loading&#8230;', 'event_espresso')
2333 2333
                      . '</p><p class="hide-if-js">'
2334 2334
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2335 2335
                      . '</p>';
2336
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2337
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2338
-        $post      = '</div>' . "\n";
2339
-        $cache_key = 'ee_rss_' . md5($rss_id);
2336
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2337
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2338
+        $post      = '</div>'."\n";
2339
+        $cache_key = 'ee_rss_'.md5($rss_id);
2340 2340
         $output    = get_transient($cache_key);
2341 2341
         if ($output !== false) {
2342
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2342
+            echo wp_kses($pre.$output.$post, AllowedTags::getWithFormTags());
2343 2343
             return true;
2344 2344
         }
2345
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2345
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
+            echo wp_kses($pre.$loading.$post, AllowedTags::getWithFormTags());
2347 2347
             return false;
2348 2348
         }
2349 2349
         ob_start();
@@ -2410,7 +2410,7 @@  discard block
 block discarded – undo
2410 2410
     public function espresso_sponsors_post_box()
2411 2411
     {
2412 2412
         EEH_Template::display_template(
2413
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2413
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2414 2414
         );
2415 2415
     }
2416 2416
 
@@ -2427,9 +2427,9 @@  discard block
 block discarded – undo
2427 2427
     protected function getPublishBoxTitle(): string
2428 2428
     {
2429 2429
         $publish_box_title = esc_html__('Publish', 'event_espresso');
2430
-        if (! empty($this->_labels['publishbox'])) {
2430
+        if ( ! empty($this->_labels['publishbox'])) {
2431 2431
             if (is_array($this->_labels['publishbox'])) {
2432
-                $publish_box_title = $this->_labels['publishbox'][ $this->_req_action ] ?? $publish_box_title;
2432
+                $publish_box_title = $this->_labels['publishbox'][$this->_req_action] ?? $publish_box_title;
2433 2433
             } else {
2434 2434
                 $publish_box_title = $this->_labels['publishbox'];
2435 2435
             }
@@ -2479,7 +2479,7 @@  discard block
 block discarded – undo
2479 2479
         // if we have extra content set let's add it in if not make sure its empty
2480 2480
         $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2481 2481
         echo EEH_Template::display_template(
2482
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2482
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2483 2483
             $this->_template_args,
2484 2484
             true
2485 2485
         );
@@ -2532,10 +2532,10 @@  discard block
 block discarded – undo
2532 2532
                 'submitdelete deletion button button--outline button--caution'
2533 2533
             );
2534 2534
         }
2535
-        if (! isset($this->_template_args['publish_delete_link'])) {
2535
+        if ( ! isset($this->_template_args['publish_delete_link'])) {
2536 2536
             $this->_template_args['publish_delete_link'] = '';
2537 2537
         }
2538
-        if (! empty($name) && ! empty($id)) {
2538
+        if ( ! empty($name) && ! empty($id)) {
2539 2539
             $this->addPublishPostMetaBoxHiddenFields($name, ['type' => 'hidden', 'value' => $id]);
2540 2540
         }
2541 2541
         $hidden_fields = $this->_generate_admin_form_fields($this->publish_post_meta_box_hidden_fields, 'array');
@@ -2568,7 +2568,7 @@  discard block
 block discarded – undo
2568 2568
 
2569 2569
     protected function addPublishPostMetaBoxHiddenFields(string $field_name, array $field_attributes)
2570 2570
     {
2571
-        $this->publish_post_meta_box_hidden_fields[ $field_name ] = $field_attributes;
2571
+        $this->publish_post_meta_box_hidden_fields[$field_name] = $field_attributes;
2572 2572
     }
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
                 echo EEH_Template::display_template(
2675 2675
                     $metabox['args']['template_path'],
2676 2676
                     $metabox['args']['template_args'],
@@ -2679,7 +2679,7 @@  discard block
 block discarded – undo
2679 2679
             }
2680 2680
             : $callback;
2681 2681
         $this->addMetaBox(
2682
-            str_replace('_', '-', $action) . '-mbox',
2682
+            str_replace('_', '-', $action).'-mbox',
2683 2683
             $title,
2684 2684
             $call_back_func,
2685 2685
             $this->_wp_page_slug,
@@ -2795,15 +2795,15 @@  discard block
 block discarded – undo
2795 2795
                                                                     'event-espresso_page_espresso_',
2796 2796
                                                                     '',
2797 2797
                                                                     $this->_wp_page_slug
2798
-                                                                ) . ' ' . $this->_req_action . '-route';
2798
+                                                                ).' '.$this->_req_action.'-route';
2799 2799
 
2800 2800
         $template_path = $sidebar
2801 2801
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2802
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2802
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2803 2803
 
2804 2804
         $this->_template_args['is_ajax'] = $this->request->isAjax();
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
 
@@ -2815,10 +2815,10 @@  discard block
 block discarded – undo
2815 2815
         // to prevent WooCommerce from blowing things up if not using CPT
2816 2816
         global $post_type, $post;
2817 2817
         $this->_template_args['post_type'] = $post_type ?? '';
2818
-        $this->_template_args['post']  = $post ?? new WP_Post( (object) [ 'ID' => 0, 'filter' => 'raw' ] );
2818
+        $this->_template_args['post'] = $post ?? new WP_Post((object) ['ID' => 0, 'filter' => 'raw']);
2819 2819
 
2820 2820
         $this->_template_args['post_body_content'] = EEH_Template::display_template(
2821
-            EE_ADMIN_TEMPLATE . 'admin_details_wrapper_post_body_content.template.php',
2821
+            EE_ADMIN_TEMPLATE.'admin_details_wrapper_post_body_content.template.php',
2822 2822
             $this->_template_args,
2823 2823
             true
2824 2824
         );
@@ -2850,11 +2850,11 @@  discard block
 block discarded – undo
2850 2850
     public function display_admin_caf_preview_page(string $utm_campaign_source = '', bool $display_sidebar = true)
2851 2851
     {
2852 2852
         // let's generate a default preview action button if there isn't one already present.
2853
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2853
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2854 2854
             'Upgrade to Event Espresso 4 Right Now',
2855 2855
             'event_espresso'
2856 2856
         );
2857
-        $buy_now_url                                   = add_query_arg(
2857
+        $buy_now_url = add_query_arg(
2858 2858
             [
2859 2859
                 'ee_ver'       => 'ee4',
2860 2860
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2874,8 +2874,8 @@  discard block
 block discarded – undo
2874 2874
                 true
2875 2875
             )
2876 2876
             : $this->_template_args['preview_action_button'];
2877
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2878
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2877
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2878
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2879 2879
             $this->_template_args,
2880 2880
             true
2881 2881
         );
@@ -2933,7 +2933,7 @@  discard block
 block discarded – undo
2933 2933
         // setup search attributes
2934 2934
         $this->_set_search_attributes();
2935 2935
         $this->_template_args['current_page']     = $this->_wp_page_slug;
2936
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2936
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
2937 2937
         $this->_template_args['table_url']        = $this->request->isAjax()
2938 2938
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2939 2939
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -2941,10 +2941,10 @@  discard block
 block discarded – undo
2941 2941
         $this->_template_args['current_route']    = $this->_req_action;
2942 2942
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2943 2943
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2944
-        if (! empty($ajax_sorting_callback)) {
2944
+        if ( ! empty($ajax_sorting_callback)) {
2945 2945
             $sortable_list_table_form_fields = wp_nonce_field(
2946
-                $ajax_sorting_callback . '_nonce',
2947
-                $ajax_sorting_callback . '_nonce',
2946
+                $ajax_sorting_callback.'_nonce',
2947
+                $ajax_sorting_callback.'_nonce',
2948 2948
                 false,
2949 2949
                 false
2950 2950
             );
@@ -2961,18 +2961,18 @@  discard block
 block discarded – undo
2961 2961
 
2962 2962
         $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2963 2963
 
2964
-        $nonce_ref          = $this->_req_action . '_nonce';
2964
+        $nonce_ref          = $this->_req_action.'_nonce';
2965 2965
         $hidden_form_fields .= '
2966
-            <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2966
+            <input type="hidden" name="' . $nonce_ref.'" value="'.wp_create_nonce($nonce_ref).'">';
2967 2967
 
2968 2968
         $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2969 2969
         // display message about search results?
2970
-        $search                                    = $this->request->getRequestParam('s');
2970
+        $search = $this->request->getRequestParam('s');
2971 2971
         $this->_template_args['before_list_table'] .= ! empty($search)
2972
-            ? '<p class="ee-search-results">' . sprintf(
2972
+            ? '<p class="ee-search-results">'.sprintf(
2973 2973
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2974 2974
                 trim($search, '%')
2975
-            ) . '</p>'
2975
+            ).'</p>'
2976 2976
             : '';
2977 2977
         // filter before_list_table template arg
2978 2978
         $this->_template_args['before_list_table'] = apply_filters(
@@ -3006,7 +3006,7 @@  discard block
 block discarded – undo
3006 3006
         // convert to array and filter again
3007 3007
         // arrays are easier to inject new items in a specific location,
3008 3008
         // but would not be backwards compatible, so we have to add a new filter
3009
-        $this->_template_args['after_list_table']   = implode(
3009
+        $this->_template_args['after_list_table'] = implode(
3010 3010
             " \n",
3011 3011
             (array) apply_filters(
3012 3012
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -3061,7 +3061,7 @@  discard block
 block discarded – undo
3061 3061
             $this->page_slug
3062 3062
         );
3063 3063
         return EEH_Template::display_template(
3064
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3064
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3065 3065
             $this->_template_args,
3066 3066
             true
3067 3067
         );
@@ -3184,7 +3184,7 @@  discard block
 block discarded – undo
3184 3184
         if ($this->request->isAjax()) {
3185 3185
             $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3186 3186
             // $template_path,
3187
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3187
+                EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php',
3188 3188
                 $this->_template_args,
3189 3189
                 true
3190 3190
             );
@@ -3193,7 +3193,7 @@  discard block
 block discarded – undo
3193 3193
         // load settings page wrapper template
3194 3194
         $template_path = $about
3195 3195
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3196
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3196
+            : EE_ADMIN_TEMPLATE.'admin_wrapper.template.php';
3197 3197
 
3198 3198
         EEH_Template::display_template($template_path, $this->_template_args);
3199 3199
     }
@@ -3277,12 +3277,12 @@  discard block
 block discarded – undo
3277 3277
         $default_names = ['save', 'save_and_close'];
3278 3278
         $buttons       = '';
3279 3279
         foreach ($button_text as $key => $button) {
3280
-            $ref     = $default_names[ $key ];
3281
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3282
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3283
-                        . 'value="' . $button . '" name="' . $name . '" '
3284
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3285
-            if (! $both) {
3280
+            $ref     = $default_names[$key];
3281
+            $name    = ! empty($actions) ? $actions[$key] : $ref;
3282
+            $buttons .= '<input type="submit" class="button button--primary '.$ref.'" '
3283
+                        . 'value="'.$button.'" name="'.$name.'" '
3284
+                        . 'id="'.$this->_current_view.'_'.$ref.'" />';
3285
+            if ( ! $both) {
3286 3286
                 break;
3287 3287
             }
3288 3288
         }
@@ -3323,13 +3323,13 @@  discard block
 block discarded – undo
3323 3323
                 'An error occurred. No action was set for this page\'s form.',
3324 3324
                 'event_espresso'
3325 3325
             );
3326
-            $dev_msg  = $user_msg . "\n"
3326
+            $dev_msg = $user_msg."\n"
3327 3327
                         . sprintf(
3328 3328
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3329 3329
                             __FUNCTION__,
3330 3330
                             __CLASS__
3331 3331
                         );
3332
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3332
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3333 3333
         }
3334 3334
         // open form
3335 3335
         $action                                            = $this->_admin_base_url;
@@ -3337,9 +3337,9 @@  discard block
 block discarded – undo
3337 3337
             <form name='form' method='post' action='$action' id='{$route}_event_form' class='ee-admin-page-form' >
3338 3338
             ";
3339 3339
         // add nonce
3340
-        $nonce                                             =
3341
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3342
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3340
+        $nonce =
3341
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3342
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3343 3343
         // add REQUIRED form action
3344 3344
         $hidden_fields = [
3345 3345
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3352,7 +3352,7 @@  discard block
 block discarded – undo
3352 3352
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3353 3353
         // add fields to form
3354 3354
         foreach ((array) $form_fields as $form_field) {
3355
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3355
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3356 3356
         }
3357 3357
         // close form
3358 3358
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3435,10 +3435,10 @@  discard block
 block discarded – undo
3435 3435
     ) {
3436 3436
         $notices = EE_Error::get_notices(false);
3437 3437
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3438
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3438
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3439 3439
             EE_Error::overwrite_success();
3440 3440
         }
3441
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3441
+        if ( ! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3442 3442
             // how many records affected ? more than one record ? or just one ?
3443 3443
             EE_Error::add_success(
3444 3444
                 sprintf(
@@ -3489,7 +3489,7 @@  discard block
 block discarded – undo
3489 3489
             $redirect_url = admin_url('admin.php');
3490 3490
         }
3491 3491
         // merge any default query_args set in _default_route_query_args property
3492
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3492
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3493 3493
             $args_to_merge = [];
3494 3494
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3495 3495
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3501,15 +3501,15 @@  discard block
 block discarded – undo
3501 3501
                         }
3502 3502
                         // finally we will override any arguments in the referer with
3503 3503
                         // what might be set on the _default_route_query_args array.
3504
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3505
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3504
+                        if (isset($this->_default_route_query_args[$reference])) {
3505
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3506 3506
                         } else {
3507
-                            $args_to_merge[ $reference ] = urlencode($value);
3507
+                            $args_to_merge[$reference] = urlencode($value);
3508 3508
                         }
3509 3509
                     }
3510 3510
                     continue;
3511 3511
                 }
3512
-                $args_to_merge[ $query_param ] = $query_value;
3512
+                $args_to_merge[$query_param] = $query_value;
3513 3513
             }
3514 3514
             // now let's merge these arguments but override with what was specifically sent in to the
3515 3515
             // redirect.
@@ -3521,19 +3521,19 @@  discard block
 block discarded – undo
3521 3521
         if (isset($query_args['action'])) {
3522 3522
             // manually generate wp_nonce and merge that with the query vars
3523 3523
             // becuz the wp_nonce_url function wrecks havoc on some vars
3524
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3524
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3525 3525
         }
3526 3526
         // we're adding some hooks and filters in here for processing any things just before redirects
3527 3527
         // (example: an admin page has done an insert or update and we want to run something after that).
3528
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3528
+        do_action('AHEE_redirect_'.$this->class_name.$this->_req_action, $query_args);
3529 3529
         $redirect_url = apply_filters(
3530
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3530
+            'FHEE_redirect_'.$this->class_name.$this->_req_action,
3531 3531
             EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3532 3532
             $query_args
3533 3533
         );
3534 3534
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3535 3535
         if ($this->request->isAjax()) {
3536
-            $default_data                    = [
3536
+            $default_data = [
3537 3537
                 'close'        => true,
3538 3538
                 'redirect_url' => $redirect_url,
3539 3539
                 'where'        => 'main',
@@ -3586,7 +3586,7 @@  discard block
 block discarded – undo
3586 3586
         }
3587 3587
         $this->_template_args['notices'] = EE_Error::get_notices();
3588 3588
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3589
-        if (! $this->request->isAjax() || $sticky_notices) {
3589
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3590 3590
             $route = $query_args['action'] ?? 'default';
3591 3591
             $this->_add_transient(
3592 3592
                 $route,
@@ -3626,7 +3626,7 @@  discard block
 block discarded – undo
3626 3626
         bool $exclude_nonce = false
3627 3627
     ): string {
3628 3628
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3629
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3629
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3630 3630
             throw new EE_Error(
3631 3631
                 sprintf(
3632 3632
                     esc_html__(
@@ -3637,7 +3637,7 @@  discard block
 block discarded – undo
3637 3637
                 )
3638 3638
             );
3639 3639
         }
3640
-        if (! isset($this->_labels['buttons'][ $type ])) {
3640
+        if ( ! isset($this->_labels['buttons'][$type])) {
3641 3641
             throw new EE_Error(
3642 3642
                 sprintf(
3643 3643
                     esc_html__(
@@ -3650,7 +3650,7 @@  discard block
 block discarded – undo
3650 3650
         }
3651 3651
         // finally check user access for this button.
3652 3652
         $has_access = $this->check_user_access($action, true);
3653
-        if (! $has_access) {
3653
+        if ( ! $has_access) {
3654 3654
             return '';
3655 3655
         }
3656 3656
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3658,11 +3658,11 @@  discard block
 block discarded – undo
3658 3658
             'action' => $action,
3659 3659
         ];
3660 3660
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3661
-        if (! empty($extra_request)) {
3661
+        if ( ! empty($extra_request)) {
3662 3662
             $query_args = array_merge($extra_request, $query_args);
3663 3663
         }
3664 3664
         $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3665
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3665
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3666 3666
     }
3667 3667
 
3668 3668
 
@@ -3688,7 +3688,7 @@  discard block
 block discarded – undo
3688 3688
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3689 3689
                 20
3690 3690
             ),
3691
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3691
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3692 3692
         ];
3693 3693
         // ONLY add the screen option if the user has access to it.
3694 3694
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3709,18 +3709,18 @@  discard block
 block discarded – undo
3709 3709
     {
3710 3710
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3711 3711
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3712
-            if (! $user = wp_get_current_user()) {
3712
+            if ( ! $user = wp_get_current_user()) {
3713 3713
                 return;
3714 3714
             }
3715 3715
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', DataType::KEY);
3716
-            if (! $option) {
3716
+            if ( ! $option) {
3717 3717
                 return;
3718 3718
             }
3719 3719
             $value      = $this->request->getRequestParam('wp_screen_options[value]', 0, DataType::INT);
3720 3720
             $map_option = $option;
3721 3721
             $option     = str_replace('-', '_', $option);
3722 3722
             switch ($map_option) {
3723
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3723
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3724 3724
                     $max_value = apply_filters(
3725 3725
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3726 3726
                         999,
@@ -3787,7 +3787,7 @@  discard block
 block discarded – undo
3787 3787
         bool $skip_route_verify = false
3788 3788
     ) {
3789 3789
         $user_id = get_current_user_id();
3790
-        if (! $skip_route_verify) {
3790
+        if ( ! $skip_route_verify) {
3791 3791
             $this->_verify_route($route);
3792 3792
         }
3793 3793
         // now let's set the string for what kind of transient we're setting
@@ -3820,8 +3820,8 @@  discard block
 block discarded – undo
3820 3820
         $user_id   = get_current_user_id();
3821 3821
         $route     = ! $route ? $this->_req_action : $route;
3822 3822
         $transient = $notices
3823
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3824
-            : 'rte_tx_' . $route . '_' . $user_id;
3823
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3824
+            : 'rte_tx_'.$route.'_'.$user_id;
3825 3825
         $data      = is_multisite() && is_network_admin()
3826 3826
             ? get_site_transient($transient)
3827 3827
             : get_transient($transient);
@@ -4079,7 +4079,7 @@  discard block
 block discarded – undo
4079 4079
      */
4080 4080
     protected function _next_link(string $url, string $class = 'dashicons dashicons-arrow-right'): string
4081 4081
     {
4082
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4082
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4083 4083
     }
4084 4084
 
4085 4085
 
@@ -4092,7 +4092,7 @@  discard block
 block discarded – undo
4092 4092
      */
4093 4093
     protected function _previous_link(string $url, string $class = 'dashicons dashicons-arrow-left'): string
4094 4094
     {
4095
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4095
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4096 4096
     }
4097 4097
 
4098 4098
 
@@ -4240,13 +4240,13 @@  discard block
 block discarded – undo
4240 4240
         ?callable $callback = null
4241 4241
     ): bool {
4242 4242
         $entity_ID = absint($entity_ID);
4243
-        if (! $entity_ID) {
4243
+        if ( ! $entity_ID) {
4244 4244
             $this->trashRestoreDeleteError($action, $entity_model);
4245 4245
         }
4246 4246
         $result = 0;
4247 4247
         try {
4248 4248
             $entity = $entity_model->get_one_by_ID($entity_ID);
4249
-            if (! $entity instanceof EE_Base_Class) {
4249
+            if ( ! $entity instanceof EE_Base_Class) {
4250 4250
                 throw new DomainException(
4251 4251
                     sprintf(
4252 4252
                         esc_html__(
@@ -4297,7 +4297,7 @@  discard block
 block discarded – undo
4297 4297
                 )
4298 4298
             );
4299 4299
         }
4300
-        if (! $entity_model->has_field($delete_column)) {
4300
+        if ( ! $entity_model->has_field($delete_column)) {
4301 4301
             throw new DomainException(
4302 4302
                 sprintf(
4303 4303
                     esc_html__(
Please login to merge, or discard this patch.
core/libraries/payment_methods/EE_Payment_Method_Manager.lib.php 2 patches
Indentation   +584 added lines, -584 removed lines patch added patch discarded remove patch
@@ -16,588 +16,588 @@
 block discarded – undo
16 16
  */
17 17
 class EE_Payment_Method_Manager implements ResettableInterface
18 18
 {
19
-    /**
20
-     * prefix added to all payment method capabilities names
21
-     */
22
-    const CAPABILITIES_PREFIX = 'ee_payment_method_';
23
-
24
-    private static ?EE_Payment_Method_Manager $_instance = null;
25
-
26
-    /**
27
-     * @var boolean
28
-     */
29
-    protected bool $payment_method_caps_initialized = false;
30
-
31
-    /**
32
-     * @var string[] keys are class names without 'EE_PMT_', values are their filepaths
33
-     */
34
-    protected array $_payment_method_types = [];
35
-
36
-    /**
37
-     * @var EE_PMT_Base[]
38
-     */
39
-    protected array $payment_method_objects = [];
40
-
41
-
42
-    /**
43
-     * EE_Payment_Method_Manager constructor.
44
-     *
45
-     * @throws DomainException
46
-     */
47
-    public function __construct()
48
-    {
49
-        // if in admin lets ensure caps are set.
50
-        if (is_admin()) {
51
-            $this->_register_payment_methods();
52
-            // add PM caps when EE_Capabilities is initialized
53
-            add_action(
54
-                'AHEE__EE_Capabilities__init_caps__before_initialization',
55
-                [$this, 'initializePaymentMethodCaps']
56
-            );
57
-            // plus any time they get reset
58
-            add_filter(
59
-                'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
60
-                [$this, 'addPaymentMethodCapsDuringReset']
61
-            );
62
-        }
63
-        add_action('http_api_curl', ['EE_Payment_Method_Manager', 'curlRequestsToPaypalUseTls'], 10, 3);
64
-    }
65
-
66
-
67
-    /**
68
-     * @singleton method used to instantiate class object
69
-     * @return EE_Payment_Method_Manager instance
70
-     * @throws DomainException
71
-     * @throws EE_Error
72
-     * @throws ReflectionException
73
-     */
74
-    public static function instance(): EE_Payment_Method_Manager
75
-    {
76
-        // check if class object is instantiated, and instantiated properly
77
-        if (! self::$_instance instanceof EE_Payment_Method_Manager) {
78
-            EE_Registry::instance()->load_lib('PMT_Base');
79
-            self::$_instance = new self();
80
-        }
81
-        return self::$_instance;
82
-    }
83
-
84
-
85
-    /**
86
-     * Resets the instance and returns a new one
87
-     *
88
-     * @return EE_Payment_Method_Manager
89
-     * @throws DomainException
90
-     * @throws EE_Error
91
-     * @throws ReflectionException
92
-     */
93
-    public static function reset(): EE_Payment_Method_Manager
94
-    {
95
-        self::$_instance = null;
96
-        return self::instance();
97
-    }
98
-
99
-
100
-    /**
101
-     * Force posts to PayPal to use TLS v1.2. See:
102
-     * https://core.trac.wordpress.org/ticket/36320
103
-     * https://core.trac.wordpress.org/ticket/34924#comment:15
104
-     * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
105
-     * This will affect PayPal standard, pro, express, and Payflow.
106
-     *
107
-     * @param $handle
108
-     * @param $r
109
-     * @param $url
110
-     */
111
-    public static function curlRequestsToPaypalUseTls($handle, $r, $url)
112
-    {
113
-        if (strpos($url, 'https://') !== false && strpos($url, '.paypal.com') !== false) {
114
-            // Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
115
-            // instead of the constant because it might not be defined
116
-            curl_setopt($handle, CURLOPT_SSLVERSION, 6);
117
-        }
118
-    }
119
-
120
-
121
-    /**
122
-     * If necessary, re-register payment methods
123
-     *
124
-     * @param boolean $force_recheck whether to recheck for payment method types,
125
-     *                               or just re-use the PMTs we found last time we checked during this request (if
126
-     *                               we have not yet checked during this request, then we need to check anyways)
127
-     */
128
-    public function maybe_register_payment_methods(bool $force_recheck = false)
129
-    {
130
-        if (! $this->_payment_method_types || $force_recheck) {
131
-            $this->_register_payment_methods();
132
-        }
133
-    }
134
-
135
-
136
-    /**
137
-     * register_payment_methods
138
-     *
139
-     * @return array
140
-     */
141
-    protected function _register_payment_methods(): array
142
-    {
143
-        // grab list of installed modules
144
-        $pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
145
-        // filter list of modules to register
146
-        $pm_to_register = apply_filters(
147
-            'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
148
-            $pm_to_register
149
-        );
150
-        // remove any duplicates if that should happen for some reason
151
-        $pm_to_register = array_unique($pm_to_register);
152
-        // loop through folders
153
-        foreach ($pm_to_register as $pm_path) {
154
-            $this->register_payment_method($pm_path);
155
-        }
156
-        do_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods');
157
-        // filter list of installed modules
158
-        // keep them organized alphabetically by the payment method type's name
159
-        ksort($this->_payment_method_types);
160
-        return apply_filters(
161
-            'FHEE__EE_Payment_Method_Manager__register_payment_methods__installed_payment_methods',
162
-            $this->_payment_method_types
163
-        );
164
-    }
165
-
166
-
167
-    /**
168
-     * register_payment_method- makes core aware of this payment method
169
-     *
170
-     * @param string $payment_method_path - full path up to and including payment method folder
171
-     * @return boolean
172
-     */
173
-    public function register_payment_method(string $payment_method_path = ''): bool
174
-    {
175
-        do_action('AHEE__EE_Payment_Method_Manager__register_payment_method__begin', $payment_method_path);
176
-        $module_ext = '.pm.php';
177
-        // make all separators match
178
-        $payment_method_path = rtrim(str_replace('/\\', '/', $payment_method_path), '/');
179
-        // grab and sanitize module name
180
-        $module_dir = basename($payment_method_path);
181
-        // create class name from module directory name
182
-        $module = str_replace(['_', ' '], [' ', '_'], $module_dir);
183
-        // add class prefix
184
-        $module_class = 'EE_PMT_' . $module;
185
-        // does the module exist ?
186
-        if (! is_readable($payment_method_path . '/' . $module_class . $module_ext)) {
187
-            $msg = sprintf(
188
-                esc_html__(
189
-                    'The requested %s payment method file could not be found or is not readable due to file permissions.',
190
-                    'event_espresso'
191
-                ),
192
-                $module
193
-            );
194
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
195
-            return false;
196
-        }
197
-        // load the module class file
198
-        require_once($payment_method_path . '/' . $module_class . $module_ext);
199
-        // verify that class exists
200
-        if (! class_exists($module_class)) {
201
-            $msg = sprintf(
202
-                esc_html__('The requested %s module class does not exist.', 'event_espresso'),
203
-                $module_class
204
-            );
205
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
206
-            return false;
207
-        }
208
-        // add to array of registered modules
209
-        $this->_payment_method_types[ $module ] = $payment_method_path . '/' . $module_class . $module_ext;
210
-        return true;
211
-    }
212
-
213
-
214
-    /**
215
-     * Checks if a payment method has been registered, and if so includes it
216
-     *
217
-     * @param string  $payment_method_name like 'PayPal_Pro', (ie class name without the prefix 'EEPM_')
218
-     * @param boolean $force_recheck       whether to force re-checking for new payment method types
219
-     * @return boolean
220
-     */
221
-    public function payment_method_type_exists(string $payment_method_name, bool $force_recheck = false): bool
222
-    {
223
-        if (
224
-            $force_recheck
225
-            || empty($this->_payment_method_types)
226
-            || ! isset($this->_payment_method_types[ $payment_method_name ])
227
-        ) {
228
-            $this->maybe_register_payment_methods($force_recheck);
229
-        }
230
-        if (isset($this->_payment_method_types[ $payment_method_name ])) {
231
-            require_once($this->_payment_method_types[ $payment_method_name ]);
232
-            return true;
233
-        }
234
-        return false;
235
-    }
236
-
237
-
238
-    /**
239
-     * Returns all the class names of the various payment method types
240
-     *
241
-     * @param boolean $with_prefixes TRUE: get payment method type class names; false just their 'names'
242
-     *                               (what you'd find in wp_esp_payment_method.PMD_type)
243
-     * @param boolean $force_recheck whether to force re-checking for new payment method types
244
-     * @return array
245
-     */
246
-    public function payment_method_type_names(bool $with_prefixes = false, bool $force_recheck = false): array
247
-    {
248
-        $this->maybe_register_payment_methods($force_recheck);
249
-        if ($with_prefixes) {
250
-            $classnames      = array_keys($this->_payment_method_types);
251
-            $payment_methods = [];
252
-            foreach ($classnames as $classname) {
253
-                $payment_methods[] = $this->payment_method_class_from_type($classname);
254
-            }
255
-            return $payment_methods;
256
-        }
257
-        return array_keys($this->_payment_method_types);
258
-    }
259
-
260
-
261
-    /**
262
-     * Gets an object of each payment method type, none of which are bound to a
263
-     * payment method instance
264
-     *
265
-     * @param boolean $force_recheck whether to force re-checking for new payment method types
266
-     * @return EE_PMT_Base[]
267
-     */
268
-    public function payment_method_types(bool $force_recheck = false): array
269
-    {
270
-        if ($force_recheck || empty($this->payment_method_objects)) {
271
-            $this->maybe_register_payment_methods($force_recheck);
272
-            foreach ($this->payment_method_type_names(true) as $classname) {
273
-                if (! isset($this->payment_method_objects[ $classname ])) {
274
-                    $this->payment_method_objects[ $classname ] = new $classname();
275
-                }
276
-            }
277
-        }
278
-        return $this->payment_method_objects;
279
-    }
280
-
281
-
282
-    /**
283
-     * Changes the payment method's class name into the payment method type's name
284
-     * (as used on the payment method's table's PMD_type field)
285
-     *
286
-     * @param string $classname
287
-     * @return string
288
-     */
289
-    public function payment_method_type_sans_class_prefix(string $classname): string
290
-    {
291
-        return str_replace('EE_PMT_', '', $classname);
292
-    }
293
-
294
-
295
-    /**
296
-     * Does the opposite of payment-method_type_sans_prefix
297
-     *
298
-     * @param string $type
299
-     * @return string
300
-     */
301
-    public function payment_method_class_from_type(string $type): string
302
-    {
303
-        return 'EE_PMT_' . $type;
304
-    }
305
-
306
-
307
-    /**
308
-     * Activates a payment method of the given type.
309
-     *
310
-     * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
311
-     * @return EE_Payment_Method
312
-     * @throws InvalidDataTypeException
313
-     * @throws EE_Error
314
-     * @throws ReflectionException
315
-     */
316
-    public function activate_a_payment_method_of_type(string $payment_method_type): EE_Payment_Method
317
-    {
318
-        $this->maybe_register_payment_methods();
319
-        $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
320
-        if (! $payment_method instanceof EE_Payment_Method) {
321
-            $pm_type_class = $this->payment_method_class_from_type($payment_method_type);
322
-            if (class_exists($pm_type_class)) {
323
-                /** @var $pm_type_obj EE_PMT_Base */
324
-                $pm_type_obj    = new $pm_type_class();
325
-                $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
326
-                if (! $payment_method) {
327
-                    $payment_method = $this->create_payment_method_of_type($pm_type_obj);
328
-                }
329
-                $payment_method->set_type($payment_method_type);
330
-                $this->initialize_payment_method($payment_method);
331
-            } else {
332
-                throw new EE_Error(
333
-                    sprintf(
334
-                        esc_html__(
335
-                            'There is no payment method of type %1$s, so it could not be activated',
336
-                            'event_espresso'
337
-                        ),
338
-                        $pm_type_class
339
-                    )
340
-                );
341
-            }
342
-        }
343
-        $payment_method->set_active();
344
-        $payment_method->save();
345
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
346
-        // if this was the invoice message type, make sure users can view their invoices
347
-        if (
348
-            $payment_method->type() === 'Invoice'
349
-            && (
350
-            ! EEH_MSG_Template::is_mt_active('invoice')
351
-            )
352
-        ) {
353
-            $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
354
-            /** @type EE_Message_Resource_Manager $message_resource_manager */
355
-            $message_resource_manager->ensure_message_type_is_active('invoice', 'html');
356
-            new PersistentAdminNotice(
357
-                'invoice_pm_requirements_notice',
358
-                sprintf(
359
-                    esc_html__(
360
-                        'The Invoice payment method has been activated. It requires the %1$sinvoice message%2$s type to be active, so it was automatically activated for you.',
361
-                        'event_espresso'
362
-                    ),
363
-                    '<a href="' . admin_url('admin.php?page=espresso_messages&action=settings') . '">',
364
-                    '</a>'
365
-                ),
366
-                true
367
-            );
368
-        }
369
-        return $payment_method;
370
-    }
371
-
372
-
373
-    /**
374
-     * Creates a payment method of the specified type. Does not save it.
375
-     *
376
-     * @param EE_PMT_Base $pm_type_obj
377
-     * @return EE_Payment_Method
378
-     * @throws EE_Error*@throws ReflectionException
379
-     * @throws ReflectionException
380
-     * @global WP_User    $current_user
381
-     */
382
-    public function create_payment_method_of_type(EE_PMT_Base $pm_type_obj): EE_Payment_Method
383
-    {
384
-        global $current_user;
385
-        return EE_Payment_Method::new_instance(
386
-            [
387
-                'PMD_type'       => $pm_type_obj->system_name(),
388
-                'PMD_name'       => $pm_type_obj->defaultFrontendName(),
389
-                'PMD_admin_name' => $pm_type_obj->pretty_name(),
390
-                'PMD_slug'       => $pm_type_obj->system_name(),// automatically converted to slug
391
-                'PMD_wp_user'    => $current_user->ID,
392
-                'PMD_order'      => EEM_Payment_Method::instance()->count(
393
-                    [['PMD_type' => ['!=', 'Admin_Only']]]
394
-                ) * 10,
395
-            ]
396
-        );
397
-    }
398
-
399
-
400
-    /**
401
-     * Sets the initial payment method properties (including extra meta)
402
-     *
403
-     * @param EE_Payment_Method $payment_method
404
-     * @return EE_Payment_Method
405
-     * @throws EE_Error
406
-     * @throws ReflectionException
407
-     */
408
-    public function initialize_payment_method(EE_Payment_Method $payment_method): EE_Payment_Method
409
-    {
410
-        $pm_type_obj = $payment_method->type_obj();
411
-        $payment_method->set_description($pm_type_obj->default_description());
412
-        if (! $payment_method->button_url()) {
413
-            $payment_method->set_button_url($pm_type_obj->default_button_url());
414
-        }
415
-        // now add setup its default extra meta properties
416
-        $extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
417
-        if (! empty($extra_metas)) {
418
-            // verify the payment method has an ID before adding extra meta
419
-            if (! $payment_method->ID()) {
420
-                $payment_method->save();
421
-            }
422
-            foreach ($extra_metas as $meta_name => $input) {
423
-                $payment_method->update_extra_meta($meta_name, $input->raw_value());
424
-            }
425
-        }
426
-        return $payment_method;
427
-    }
428
-
429
-
430
-    /**
431
-     * Makes sure the payment method is related to the specified payment method
432
-     *
433
-     * @param EE_Payment_Method $payment_method
434
-     * @return EE_Payment_Method
435
-     * @deprecated in 4.9.40 because the currency payment method table is being deprecated
436
-     */
437
-    public function set_usable_currencies_on_payment_method(EE_Payment_Method $payment_method): EE_Payment_Method
438
-    {
439
-        EE_Error::doing_it_wrong(
440
-            'EE_Payment_Method_Manager::set_usable_currencies_on_payment_method',
441
-            esc_html__(
442
-                'We no longer define what currencies are usable by payment methods. Its not used nor efficient.',
443
-                'event_espresso'
444
-            ),
445
-            '4.9.40'
446
-        );
447
-        return $payment_method;
448
-    }
449
-
450
-
451
-    /**
452
-     * Deactivates a payment method of the given payment method slug.
453
-     *
454
-     * @param string $payment_method_slug The slug for the payment method to deactivate.
455
-     * @return int count of rows updated.
456
-     * @throws EE_Error
457
-     * @throws ReflectionException
458
-     */
459
-    public function deactivate_payment_method(string $payment_method_slug): int
460
-    {
461
-        EE_Log::instance()->log(
462
-            __FILE__,
463
-            __FUNCTION__,
464
-            sprintf(
465
-                esc_html__(
466
-                    'Payment method with slug %1$s is being deactivated by site admin',
467
-                    'event_espresso'
468
-                ),
469
-                $payment_method_slug
470
-            ),
471
-            'payment_method_change'
472
-        );
473
-        $count_updated = EEM_Payment_Method::instance()->update(
474
-            ['PMD_scope' => []],
475
-            [['PMD_slug' => $payment_method_slug]]
476
-        );
477
-        do_action(
478
-            'AHEE__EE_Payment_Method_Manager__deactivate_payment_method__after_deactivating_payment_method',
479
-            $payment_method_slug,
480
-            $count_updated
481
-        );
482
-        return $count_updated;
483
-    }
484
-
485
-
486
-    /**
487
-     * initializes payment method access caps via EE_Capabilities::init_role_caps()
488
-     * upon EE_Payment_Method_Manager construction
489
-     *
490
-     * @throws EE_Error
491
-     * @throws DomainException
492
-     */
493
-    public function initializePaymentMethodCaps()
494
-    {
495
-        // don't do this twice
496
-        if ($this->payment_method_caps_initialized) {
497
-            return;
498
-        }
499
-        EE_Capabilities::instance()->addCaps(
500
-            $this->getPaymentMethodCaps()
501
-        );
502
-        $this->payment_method_caps_initialized = true;
503
-    }
504
-
505
-
506
-    /**
507
-     * array  of dynamic payment method access caps.
508
-     * at the time of writing, october 20 2014, these are the caps added:
509
-     *  ee_payment_method_admin_only
510
-     *  ee_payment_method_aim
511
-     *  ee_payment_method_bank
512
-     *  ee_payment_method_check
513
-     *  ee_payment_method_invoice
514
-     *  ee_payment_method_mijireh
515
-     *  ee_payment_method_paypal_pro
516
-     *  ee_payment_method_paypal_standard
517
-     * Any other payment methods added to core or via addons will also get
518
-     * their related capability automatically added too, so long as they are
519
-     * registered properly using EE_Register_Payment_Method::register()
520
-     *
521
-     * @return array
522
-     * @throws DomainException
523
-     */
524
-    protected function getPaymentMethodCaps(): array
525
-    {
526
-        $caps = [];
527
-        foreach ($this->payment_method_type_names() as $payment_method_name) {
528
-            $caps = $this->addPaymentMethodCap($payment_method_name, $caps);
529
-        }
530
-        return $caps;
531
-    }
532
-
533
-
534
-    /**
535
-     * @param string $payment_method_name
536
-     * @param array  $payment_method_caps
537
-     * @param string $role
538
-     * @return array
539
-     * @throws DomainException
540
-     */
541
-    public function addPaymentMethodCap(
542
-        string $payment_method_name,
543
-        array $payment_method_caps,
544
-        string $role = 'administrator'
545
-    ): array {
546
-        if (empty($payment_method_name)) {
547
-            throw new DomainException(
548
-                esc_html__(
549
-                    'The name of a payment method must be specified to add capabilities.',
550
-                    'event_espresso'
551
-                )
552
-            );
553
-        }
554
-        if (empty($role)) {
555
-            throw new DomainException(
556
-                sprintf(
557
-                    esc_html__(
558
-                        'No role was supplied while trying to add capabilities for the %1$s payment method.',
559
-                        'event_espresso'
560
-                    ),
561
-                    $payment_method_name
562
-                )
563
-            );
564
-        }
565
-        if (! isset($payment_method_caps[ $role ])) {
566
-            $payment_method_caps[ $role ] = [];
567
-        }
568
-        $payment_method_caps[ $role ][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX
569
-                                          . strtolower($payment_method_name);
570
-        return $payment_method_caps;
571
-    }
572
-
573
-
574
-    /**
575
-     * callback for FHEE__EE_Capabilities__init_role_caps__caps_map filter
576
-     * to add dynamic payment method access caps when capabilities are reset
577
-     * (or if that filter is called and PM caps are not already set)
578
-     *
579
-     * @param array $caps capabilities being filtered
580
-     * @param bool  $reset
581
-     * @return array
582
-     * @throws DomainException
583
-     */
584
-    public function addPaymentMethodCapsDuringReset(array $caps, bool $reset = false): array
585
-    {
586
-        if ($reset || ! $this->payment_method_caps_initialized) {
587
-            $this->payment_method_caps_initialized = true;
588
-            $caps                                  = array_merge_recursive($caps, $this->getPaymentMethodCaps());
589
-        }
590
-        return $caps;
591
-    }
592
-
593
-
594
-    /**
595
-     * @param $caps
596
-     * @return mixed
597
-     * @deprecated 4.9.42
598
-     */
599
-    public function add_payment_method_caps($caps)
600
-    {
601
-        return $caps;
602
-    }
19
+	/**
20
+	 * prefix added to all payment method capabilities names
21
+	 */
22
+	const CAPABILITIES_PREFIX = 'ee_payment_method_';
23
+
24
+	private static ?EE_Payment_Method_Manager $_instance = null;
25
+
26
+	/**
27
+	 * @var boolean
28
+	 */
29
+	protected bool $payment_method_caps_initialized = false;
30
+
31
+	/**
32
+	 * @var string[] keys are class names without 'EE_PMT_', values are their filepaths
33
+	 */
34
+	protected array $_payment_method_types = [];
35
+
36
+	/**
37
+	 * @var EE_PMT_Base[]
38
+	 */
39
+	protected array $payment_method_objects = [];
40
+
41
+
42
+	/**
43
+	 * EE_Payment_Method_Manager constructor.
44
+	 *
45
+	 * @throws DomainException
46
+	 */
47
+	public function __construct()
48
+	{
49
+		// if in admin lets ensure caps are set.
50
+		if (is_admin()) {
51
+			$this->_register_payment_methods();
52
+			// add PM caps when EE_Capabilities is initialized
53
+			add_action(
54
+				'AHEE__EE_Capabilities__init_caps__before_initialization',
55
+				[$this, 'initializePaymentMethodCaps']
56
+			);
57
+			// plus any time they get reset
58
+			add_filter(
59
+				'FHEE__EE_Capabilities__addCaps__capabilities_to_add',
60
+				[$this, 'addPaymentMethodCapsDuringReset']
61
+			);
62
+		}
63
+		add_action('http_api_curl', ['EE_Payment_Method_Manager', 'curlRequestsToPaypalUseTls'], 10, 3);
64
+	}
65
+
66
+
67
+	/**
68
+	 * @singleton method used to instantiate class object
69
+	 * @return EE_Payment_Method_Manager instance
70
+	 * @throws DomainException
71
+	 * @throws EE_Error
72
+	 * @throws ReflectionException
73
+	 */
74
+	public static function instance(): EE_Payment_Method_Manager
75
+	{
76
+		// check if class object is instantiated, and instantiated properly
77
+		if (! self::$_instance instanceof EE_Payment_Method_Manager) {
78
+			EE_Registry::instance()->load_lib('PMT_Base');
79
+			self::$_instance = new self();
80
+		}
81
+		return self::$_instance;
82
+	}
83
+
84
+
85
+	/**
86
+	 * Resets the instance and returns a new one
87
+	 *
88
+	 * @return EE_Payment_Method_Manager
89
+	 * @throws DomainException
90
+	 * @throws EE_Error
91
+	 * @throws ReflectionException
92
+	 */
93
+	public static function reset(): EE_Payment_Method_Manager
94
+	{
95
+		self::$_instance = null;
96
+		return self::instance();
97
+	}
98
+
99
+
100
+	/**
101
+	 * Force posts to PayPal to use TLS v1.2. See:
102
+	 * https://core.trac.wordpress.org/ticket/36320
103
+	 * https://core.trac.wordpress.org/ticket/34924#comment:15
104
+	 * https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1914&viewlocale=en_US
105
+	 * This will affect PayPal standard, pro, express, and Payflow.
106
+	 *
107
+	 * @param $handle
108
+	 * @param $r
109
+	 * @param $url
110
+	 */
111
+	public static function curlRequestsToPaypalUseTls($handle, $r, $url)
112
+	{
113
+		if (strpos($url, 'https://') !== false && strpos($url, '.paypal.com') !== false) {
114
+			// Use the value of the constant CURL_SSLVERSION_TLSv1 = 1
115
+			// instead of the constant because it might not be defined
116
+			curl_setopt($handle, CURLOPT_SSLVERSION, 6);
117
+		}
118
+	}
119
+
120
+
121
+	/**
122
+	 * If necessary, re-register payment methods
123
+	 *
124
+	 * @param boolean $force_recheck whether to recheck for payment method types,
125
+	 *                               or just re-use the PMTs we found last time we checked during this request (if
126
+	 *                               we have not yet checked during this request, then we need to check anyways)
127
+	 */
128
+	public function maybe_register_payment_methods(bool $force_recheck = false)
129
+	{
130
+		if (! $this->_payment_method_types || $force_recheck) {
131
+			$this->_register_payment_methods();
132
+		}
133
+	}
134
+
135
+
136
+	/**
137
+	 * register_payment_methods
138
+	 *
139
+	 * @return array
140
+	 */
141
+	protected function _register_payment_methods(): array
142
+	{
143
+		// grab list of installed modules
144
+		$pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
145
+		// filter list of modules to register
146
+		$pm_to_register = apply_filters(
147
+			'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
148
+			$pm_to_register
149
+		);
150
+		// remove any duplicates if that should happen for some reason
151
+		$pm_to_register = array_unique($pm_to_register);
152
+		// loop through folders
153
+		foreach ($pm_to_register as $pm_path) {
154
+			$this->register_payment_method($pm_path);
155
+		}
156
+		do_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods');
157
+		// filter list of installed modules
158
+		// keep them organized alphabetically by the payment method type's name
159
+		ksort($this->_payment_method_types);
160
+		return apply_filters(
161
+			'FHEE__EE_Payment_Method_Manager__register_payment_methods__installed_payment_methods',
162
+			$this->_payment_method_types
163
+		);
164
+	}
165
+
166
+
167
+	/**
168
+	 * register_payment_method- makes core aware of this payment method
169
+	 *
170
+	 * @param string $payment_method_path - full path up to and including payment method folder
171
+	 * @return boolean
172
+	 */
173
+	public function register_payment_method(string $payment_method_path = ''): bool
174
+	{
175
+		do_action('AHEE__EE_Payment_Method_Manager__register_payment_method__begin', $payment_method_path);
176
+		$module_ext = '.pm.php';
177
+		// make all separators match
178
+		$payment_method_path = rtrim(str_replace('/\\', '/', $payment_method_path), '/');
179
+		// grab and sanitize module name
180
+		$module_dir = basename($payment_method_path);
181
+		// create class name from module directory name
182
+		$module = str_replace(['_', ' '], [' ', '_'], $module_dir);
183
+		// add class prefix
184
+		$module_class = 'EE_PMT_' . $module;
185
+		// does the module exist ?
186
+		if (! is_readable($payment_method_path . '/' . $module_class . $module_ext)) {
187
+			$msg = sprintf(
188
+				esc_html__(
189
+					'The requested %s payment method file could not be found or is not readable due to file permissions.',
190
+					'event_espresso'
191
+				),
192
+				$module
193
+			);
194
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
195
+			return false;
196
+		}
197
+		// load the module class file
198
+		require_once($payment_method_path . '/' . $module_class . $module_ext);
199
+		// verify that class exists
200
+		if (! class_exists($module_class)) {
201
+			$msg = sprintf(
202
+				esc_html__('The requested %s module class does not exist.', 'event_espresso'),
203
+				$module_class
204
+			);
205
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
206
+			return false;
207
+		}
208
+		// add to array of registered modules
209
+		$this->_payment_method_types[ $module ] = $payment_method_path . '/' . $module_class . $module_ext;
210
+		return true;
211
+	}
212
+
213
+
214
+	/**
215
+	 * Checks if a payment method has been registered, and if so includes it
216
+	 *
217
+	 * @param string  $payment_method_name like 'PayPal_Pro', (ie class name without the prefix 'EEPM_')
218
+	 * @param boolean $force_recheck       whether to force re-checking for new payment method types
219
+	 * @return boolean
220
+	 */
221
+	public function payment_method_type_exists(string $payment_method_name, bool $force_recheck = false): bool
222
+	{
223
+		if (
224
+			$force_recheck
225
+			|| empty($this->_payment_method_types)
226
+			|| ! isset($this->_payment_method_types[ $payment_method_name ])
227
+		) {
228
+			$this->maybe_register_payment_methods($force_recheck);
229
+		}
230
+		if (isset($this->_payment_method_types[ $payment_method_name ])) {
231
+			require_once($this->_payment_method_types[ $payment_method_name ]);
232
+			return true;
233
+		}
234
+		return false;
235
+	}
236
+
237
+
238
+	/**
239
+	 * Returns all the class names of the various payment method types
240
+	 *
241
+	 * @param boolean $with_prefixes TRUE: get payment method type class names; false just their 'names'
242
+	 *                               (what you'd find in wp_esp_payment_method.PMD_type)
243
+	 * @param boolean $force_recheck whether to force re-checking for new payment method types
244
+	 * @return array
245
+	 */
246
+	public function payment_method_type_names(bool $with_prefixes = false, bool $force_recheck = false): array
247
+	{
248
+		$this->maybe_register_payment_methods($force_recheck);
249
+		if ($with_prefixes) {
250
+			$classnames      = array_keys($this->_payment_method_types);
251
+			$payment_methods = [];
252
+			foreach ($classnames as $classname) {
253
+				$payment_methods[] = $this->payment_method_class_from_type($classname);
254
+			}
255
+			return $payment_methods;
256
+		}
257
+		return array_keys($this->_payment_method_types);
258
+	}
259
+
260
+
261
+	/**
262
+	 * Gets an object of each payment method type, none of which are bound to a
263
+	 * payment method instance
264
+	 *
265
+	 * @param boolean $force_recheck whether to force re-checking for new payment method types
266
+	 * @return EE_PMT_Base[]
267
+	 */
268
+	public function payment_method_types(bool $force_recheck = false): array
269
+	{
270
+		if ($force_recheck || empty($this->payment_method_objects)) {
271
+			$this->maybe_register_payment_methods($force_recheck);
272
+			foreach ($this->payment_method_type_names(true) as $classname) {
273
+				if (! isset($this->payment_method_objects[ $classname ])) {
274
+					$this->payment_method_objects[ $classname ] = new $classname();
275
+				}
276
+			}
277
+		}
278
+		return $this->payment_method_objects;
279
+	}
280
+
281
+
282
+	/**
283
+	 * Changes the payment method's class name into the payment method type's name
284
+	 * (as used on the payment method's table's PMD_type field)
285
+	 *
286
+	 * @param string $classname
287
+	 * @return string
288
+	 */
289
+	public function payment_method_type_sans_class_prefix(string $classname): string
290
+	{
291
+		return str_replace('EE_PMT_', '', $classname);
292
+	}
293
+
294
+
295
+	/**
296
+	 * Does the opposite of payment-method_type_sans_prefix
297
+	 *
298
+	 * @param string $type
299
+	 * @return string
300
+	 */
301
+	public function payment_method_class_from_type(string $type): string
302
+	{
303
+		return 'EE_PMT_' . $type;
304
+	}
305
+
306
+
307
+	/**
308
+	 * Activates a payment method of the given type.
309
+	 *
310
+	 * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
311
+	 * @return EE_Payment_Method
312
+	 * @throws InvalidDataTypeException
313
+	 * @throws EE_Error
314
+	 * @throws ReflectionException
315
+	 */
316
+	public function activate_a_payment_method_of_type(string $payment_method_type): EE_Payment_Method
317
+	{
318
+		$this->maybe_register_payment_methods();
319
+		$payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
320
+		if (! $payment_method instanceof EE_Payment_Method) {
321
+			$pm_type_class = $this->payment_method_class_from_type($payment_method_type);
322
+			if (class_exists($pm_type_class)) {
323
+				/** @var $pm_type_obj EE_PMT_Base */
324
+				$pm_type_obj    = new $pm_type_class();
325
+				$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
326
+				if (! $payment_method) {
327
+					$payment_method = $this->create_payment_method_of_type($pm_type_obj);
328
+				}
329
+				$payment_method->set_type($payment_method_type);
330
+				$this->initialize_payment_method($payment_method);
331
+			} else {
332
+				throw new EE_Error(
333
+					sprintf(
334
+						esc_html__(
335
+							'There is no payment method of type %1$s, so it could not be activated',
336
+							'event_espresso'
337
+						),
338
+						$pm_type_class
339
+					)
340
+				);
341
+			}
342
+		}
343
+		$payment_method->set_active();
344
+		$payment_method->save();
345
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
346
+		// if this was the invoice message type, make sure users can view their invoices
347
+		if (
348
+			$payment_method->type() === 'Invoice'
349
+			&& (
350
+			! EEH_MSG_Template::is_mt_active('invoice')
351
+			)
352
+		) {
353
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
354
+			/** @type EE_Message_Resource_Manager $message_resource_manager */
355
+			$message_resource_manager->ensure_message_type_is_active('invoice', 'html');
356
+			new PersistentAdminNotice(
357
+				'invoice_pm_requirements_notice',
358
+				sprintf(
359
+					esc_html__(
360
+						'The Invoice payment method has been activated. It requires the %1$sinvoice message%2$s type to be active, so it was automatically activated for you.',
361
+						'event_espresso'
362
+					),
363
+					'<a href="' . admin_url('admin.php?page=espresso_messages&action=settings') . '">',
364
+					'</a>'
365
+				),
366
+				true
367
+			);
368
+		}
369
+		return $payment_method;
370
+	}
371
+
372
+
373
+	/**
374
+	 * Creates a payment method of the specified type. Does not save it.
375
+	 *
376
+	 * @param EE_PMT_Base $pm_type_obj
377
+	 * @return EE_Payment_Method
378
+	 * @throws EE_Error*@throws ReflectionException
379
+	 * @throws ReflectionException
380
+	 * @global WP_User    $current_user
381
+	 */
382
+	public function create_payment_method_of_type(EE_PMT_Base $pm_type_obj): EE_Payment_Method
383
+	{
384
+		global $current_user;
385
+		return EE_Payment_Method::new_instance(
386
+			[
387
+				'PMD_type'       => $pm_type_obj->system_name(),
388
+				'PMD_name'       => $pm_type_obj->defaultFrontendName(),
389
+				'PMD_admin_name' => $pm_type_obj->pretty_name(),
390
+				'PMD_slug'       => $pm_type_obj->system_name(),// automatically converted to slug
391
+				'PMD_wp_user'    => $current_user->ID,
392
+				'PMD_order'      => EEM_Payment_Method::instance()->count(
393
+					[['PMD_type' => ['!=', 'Admin_Only']]]
394
+				) * 10,
395
+			]
396
+		);
397
+	}
398
+
399
+
400
+	/**
401
+	 * Sets the initial payment method properties (including extra meta)
402
+	 *
403
+	 * @param EE_Payment_Method $payment_method
404
+	 * @return EE_Payment_Method
405
+	 * @throws EE_Error
406
+	 * @throws ReflectionException
407
+	 */
408
+	public function initialize_payment_method(EE_Payment_Method $payment_method): EE_Payment_Method
409
+	{
410
+		$pm_type_obj = $payment_method->type_obj();
411
+		$payment_method->set_description($pm_type_obj->default_description());
412
+		if (! $payment_method->button_url()) {
413
+			$payment_method->set_button_url($pm_type_obj->default_button_url());
414
+		}
415
+		// now add setup its default extra meta properties
416
+		$extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
417
+		if (! empty($extra_metas)) {
418
+			// verify the payment method has an ID before adding extra meta
419
+			if (! $payment_method->ID()) {
420
+				$payment_method->save();
421
+			}
422
+			foreach ($extra_metas as $meta_name => $input) {
423
+				$payment_method->update_extra_meta($meta_name, $input->raw_value());
424
+			}
425
+		}
426
+		return $payment_method;
427
+	}
428
+
429
+
430
+	/**
431
+	 * Makes sure the payment method is related to the specified payment method
432
+	 *
433
+	 * @param EE_Payment_Method $payment_method
434
+	 * @return EE_Payment_Method
435
+	 * @deprecated in 4.9.40 because the currency payment method table is being deprecated
436
+	 */
437
+	public function set_usable_currencies_on_payment_method(EE_Payment_Method $payment_method): EE_Payment_Method
438
+	{
439
+		EE_Error::doing_it_wrong(
440
+			'EE_Payment_Method_Manager::set_usable_currencies_on_payment_method',
441
+			esc_html__(
442
+				'We no longer define what currencies are usable by payment methods. Its not used nor efficient.',
443
+				'event_espresso'
444
+			),
445
+			'4.9.40'
446
+		);
447
+		return $payment_method;
448
+	}
449
+
450
+
451
+	/**
452
+	 * Deactivates a payment method of the given payment method slug.
453
+	 *
454
+	 * @param string $payment_method_slug The slug for the payment method to deactivate.
455
+	 * @return int count of rows updated.
456
+	 * @throws EE_Error
457
+	 * @throws ReflectionException
458
+	 */
459
+	public function deactivate_payment_method(string $payment_method_slug): int
460
+	{
461
+		EE_Log::instance()->log(
462
+			__FILE__,
463
+			__FUNCTION__,
464
+			sprintf(
465
+				esc_html__(
466
+					'Payment method with slug %1$s is being deactivated by site admin',
467
+					'event_espresso'
468
+				),
469
+				$payment_method_slug
470
+			),
471
+			'payment_method_change'
472
+		);
473
+		$count_updated = EEM_Payment_Method::instance()->update(
474
+			['PMD_scope' => []],
475
+			[['PMD_slug' => $payment_method_slug]]
476
+		);
477
+		do_action(
478
+			'AHEE__EE_Payment_Method_Manager__deactivate_payment_method__after_deactivating_payment_method',
479
+			$payment_method_slug,
480
+			$count_updated
481
+		);
482
+		return $count_updated;
483
+	}
484
+
485
+
486
+	/**
487
+	 * initializes payment method access caps via EE_Capabilities::init_role_caps()
488
+	 * upon EE_Payment_Method_Manager construction
489
+	 *
490
+	 * @throws EE_Error
491
+	 * @throws DomainException
492
+	 */
493
+	public function initializePaymentMethodCaps()
494
+	{
495
+		// don't do this twice
496
+		if ($this->payment_method_caps_initialized) {
497
+			return;
498
+		}
499
+		EE_Capabilities::instance()->addCaps(
500
+			$this->getPaymentMethodCaps()
501
+		);
502
+		$this->payment_method_caps_initialized = true;
503
+	}
504
+
505
+
506
+	/**
507
+	 * array  of dynamic payment method access caps.
508
+	 * at the time of writing, october 20 2014, these are the caps added:
509
+	 *  ee_payment_method_admin_only
510
+	 *  ee_payment_method_aim
511
+	 *  ee_payment_method_bank
512
+	 *  ee_payment_method_check
513
+	 *  ee_payment_method_invoice
514
+	 *  ee_payment_method_mijireh
515
+	 *  ee_payment_method_paypal_pro
516
+	 *  ee_payment_method_paypal_standard
517
+	 * Any other payment methods added to core or via addons will also get
518
+	 * their related capability automatically added too, so long as they are
519
+	 * registered properly using EE_Register_Payment_Method::register()
520
+	 *
521
+	 * @return array
522
+	 * @throws DomainException
523
+	 */
524
+	protected function getPaymentMethodCaps(): array
525
+	{
526
+		$caps = [];
527
+		foreach ($this->payment_method_type_names() as $payment_method_name) {
528
+			$caps = $this->addPaymentMethodCap($payment_method_name, $caps);
529
+		}
530
+		return $caps;
531
+	}
532
+
533
+
534
+	/**
535
+	 * @param string $payment_method_name
536
+	 * @param array  $payment_method_caps
537
+	 * @param string $role
538
+	 * @return array
539
+	 * @throws DomainException
540
+	 */
541
+	public function addPaymentMethodCap(
542
+		string $payment_method_name,
543
+		array $payment_method_caps,
544
+		string $role = 'administrator'
545
+	): array {
546
+		if (empty($payment_method_name)) {
547
+			throw new DomainException(
548
+				esc_html__(
549
+					'The name of a payment method must be specified to add capabilities.',
550
+					'event_espresso'
551
+				)
552
+			);
553
+		}
554
+		if (empty($role)) {
555
+			throw new DomainException(
556
+				sprintf(
557
+					esc_html__(
558
+						'No role was supplied while trying to add capabilities for the %1$s payment method.',
559
+						'event_espresso'
560
+					),
561
+					$payment_method_name
562
+				)
563
+			);
564
+		}
565
+		if (! isset($payment_method_caps[ $role ])) {
566
+			$payment_method_caps[ $role ] = [];
567
+		}
568
+		$payment_method_caps[ $role ][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX
569
+										  . strtolower($payment_method_name);
570
+		return $payment_method_caps;
571
+	}
572
+
573
+
574
+	/**
575
+	 * callback for FHEE__EE_Capabilities__init_role_caps__caps_map filter
576
+	 * to add dynamic payment method access caps when capabilities are reset
577
+	 * (or if that filter is called and PM caps are not already set)
578
+	 *
579
+	 * @param array $caps capabilities being filtered
580
+	 * @param bool  $reset
581
+	 * @return array
582
+	 * @throws DomainException
583
+	 */
584
+	public function addPaymentMethodCapsDuringReset(array $caps, bool $reset = false): array
585
+	{
586
+		if ($reset || ! $this->payment_method_caps_initialized) {
587
+			$this->payment_method_caps_initialized = true;
588
+			$caps                                  = array_merge_recursive($caps, $this->getPaymentMethodCaps());
589
+		}
590
+		return $caps;
591
+	}
592
+
593
+
594
+	/**
595
+	 * @param $caps
596
+	 * @return mixed
597
+	 * @deprecated 4.9.42
598
+	 */
599
+	public function add_payment_method_caps($caps)
600
+	{
601
+		return $caps;
602
+	}
603 603
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
     public static function instance(): EE_Payment_Method_Manager
75 75
     {
76 76
         // check if class object is instantiated, and instantiated properly
77
-        if (! self::$_instance instanceof EE_Payment_Method_Manager) {
77
+        if ( ! self::$_instance instanceof EE_Payment_Method_Manager) {
78 78
             EE_Registry::instance()->load_lib('PMT_Base');
79 79
             self::$_instance = new self();
80 80
         }
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
      */
128 128
     public function maybe_register_payment_methods(bool $force_recheck = false)
129 129
     {
130
-        if (! $this->_payment_method_types || $force_recheck) {
130
+        if ( ! $this->_payment_method_types || $force_recheck) {
131 131
             $this->_register_payment_methods();
132 132
         }
133 133
     }
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
     protected function _register_payment_methods(): array
142 142
     {
143 143
         // grab list of installed modules
144
-        $pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
144
+        $pm_to_register = glob(EE_PAYMENT_METHODS.'*', GLOB_ONLYDIR);
145 145
         // filter list of modules to register
146 146
         $pm_to_register = apply_filters(
147 147
             'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
@@ -181,9 +181,9 @@  discard block
 block discarded – undo
181 181
         // create class name from module directory name
182 182
         $module = str_replace(['_', ' '], [' ', '_'], $module_dir);
183 183
         // add class prefix
184
-        $module_class = 'EE_PMT_' . $module;
184
+        $module_class = 'EE_PMT_'.$module;
185 185
         // does the module exist ?
186
-        if (! is_readable($payment_method_path . '/' . $module_class . $module_ext)) {
186
+        if ( ! is_readable($payment_method_path.'/'.$module_class.$module_ext)) {
187 187
             $msg = sprintf(
188 188
                 esc_html__(
189 189
                     'The requested %s payment method file could not be found or is not readable due to file permissions.',
@@ -191,22 +191,22 @@  discard block
 block discarded – undo
191 191
                 ),
192 192
                 $module
193 193
             );
194
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
194
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
195 195
             return false;
196 196
         }
197 197
         // load the module class file
198
-        require_once($payment_method_path . '/' . $module_class . $module_ext);
198
+        require_once($payment_method_path.'/'.$module_class.$module_ext);
199 199
         // verify that class exists
200
-        if (! class_exists($module_class)) {
200
+        if ( ! class_exists($module_class)) {
201 201
             $msg = sprintf(
202 202
                 esc_html__('The requested %s module class does not exist.', 'event_espresso'),
203 203
                 $module_class
204 204
             );
205
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
205
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
206 206
             return false;
207 207
         }
208 208
         // add to array of registered modules
209
-        $this->_payment_method_types[ $module ] = $payment_method_path . '/' . $module_class . $module_ext;
209
+        $this->_payment_method_types[$module] = $payment_method_path.'/'.$module_class.$module_ext;
210 210
         return true;
211 211
     }
212 212
 
@@ -223,12 +223,12 @@  discard block
 block discarded – undo
223 223
         if (
224 224
             $force_recheck
225 225
             || empty($this->_payment_method_types)
226
-            || ! isset($this->_payment_method_types[ $payment_method_name ])
226
+            || ! isset($this->_payment_method_types[$payment_method_name])
227 227
         ) {
228 228
             $this->maybe_register_payment_methods($force_recheck);
229 229
         }
230
-        if (isset($this->_payment_method_types[ $payment_method_name ])) {
231
-            require_once($this->_payment_method_types[ $payment_method_name ]);
230
+        if (isset($this->_payment_method_types[$payment_method_name])) {
231
+            require_once($this->_payment_method_types[$payment_method_name]);
232 232
             return true;
233 233
         }
234 234
         return false;
@@ -270,8 +270,8 @@  discard block
 block discarded – undo
270 270
         if ($force_recheck || empty($this->payment_method_objects)) {
271 271
             $this->maybe_register_payment_methods($force_recheck);
272 272
             foreach ($this->payment_method_type_names(true) as $classname) {
273
-                if (! isset($this->payment_method_objects[ $classname ])) {
274
-                    $this->payment_method_objects[ $classname ] = new $classname();
273
+                if ( ! isset($this->payment_method_objects[$classname])) {
274
+                    $this->payment_method_objects[$classname] = new $classname();
275 275
                 }
276 276
             }
277 277
         }
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
      */
301 301
     public function payment_method_class_from_type(string $type): string
302 302
     {
303
-        return 'EE_PMT_' . $type;
303
+        return 'EE_PMT_'.$type;
304 304
     }
305 305
 
306 306
 
@@ -317,13 +317,13 @@  discard block
 block discarded – undo
317 317
     {
318 318
         $this->maybe_register_payment_methods();
319 319
         $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
320
-        if (! $payment_method instanceof EE_Payment_Method) {
320
+        if ( ! $payment_method instanceof EE_Payment_Method) {
321 321
             $pm_type_class = $this->payment_method_class_from_type($payment_method_type);
322 322
             if (class_exists($pm_type_class)) {
323 323
                 /** @var $pm_type_obj EE_PMT_Base */
324 324
                 $pm_type_obj    = new $pm_type_class();
325 325
                 $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
326
-                if (! $payment_method) {
326
+                if ( ! $payment_method) {
327 327
                     $payment_method = $this->create_payment_method_of_type($pm_type_obj);
328 328
                 }
329 329
                 $payment_method->set_type($payment_method_type);
@@ -360,7 +360,7 @@  discard block
 block discarded – undo
360 360
                         'The Invoice payment method has been activated. It requires the %1$sinvoice message%2$s type to be active, so it was automatically activated for you.',
361 361
                         'event_espresso'
362 362
                     ),
363
-                    '<a href="' . admin_url('admin.php?page=espresso_messages&action=settings') . '">',
363
+                    '<a href="'.admin_url('admin.php?page=espresso_messages&action=settings').'">',
364 364
                     '</a>'
365 365
                 ),
366 366
                 true
@@ -387,7 +387,7 @@  discard block
 block discarded – undo
387 387
                 'PMD_type'       => $pm_type_obj->system_name(),
388 388
                 'PMD_name'       => $pm_type_obj->defaultFrontendName(),
389 389
                 'PMD_admin_name' => $pm_type_obj->pretty_name(),
390
-                'PMD_slug'       => $pm_type_obj->system_name(),// automatically converted to slug
390
+                'PMD_slug'       => $pm_type_obj->system_name(), // automatically converted to slug
391 391
                 'PMD_wp_user'    => $current_user->ID,
392 392
                 'PMD_order'      => EEM_Payment_Method::instance()->count(
393 393
                     [['PMD_type' => ['!=', 'Admin_Only']]]
@@ -409,14 +409,14 @@  discard block
 block discarded – undo
409 409
     {
410 410
         $pm_type_obj = $payment_method->type_obj();
411 411
         $payment_method->set_description($pm_type_obj->default_description());
412
-        if (! $payment_method->button_url()) {
412
+        if ( ! $payment_method->button_url()) {
413 413
             $payment_method->set_button_url($pm_type_obj->default_button_url());
414 414
         }
415 415
         // now add setup its default extra meta properties
416 416
         $extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
417
-        if (! empty($extra_metas)) {
417
+        if ( ! empty($extra_metas)) {
418 418
             // verify the payment method has an ID before adding extra meta
419
-            if (! $payment_method->ID()) {
419
+            if ( ! $payment_method->ID()) {
420 420
                 $payment_method->save();
421 421
             }
422 422
             foreach ($extra_metas as $meta_name => $input) {
@@ -562,10 +562,10 @@  discard block
 block discarded – undo
562 562
                 )
563 563
             );
564 564
         }
565
-        if (! isset($payment_method_caps[ $role ])) {
566
-            $payment_method_caps[ $role ] = [];
565
+        if ( ! isset($payment_method_caps[$role])) {
566
+            $payment_method_caps[$role] = [];
567 567
         }
568
-        $payment_method_caps[ $role ][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX
568
+        $payment_method_caps[$role][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX
569 569
                                           . strtolower($payment_method_name);
570 570
         return $payment_method_caps;
571 571
     }
Please login to merge, or discard this patch.
core/domain/services/wp_queries/EventListQuery.php 2 patches
Indentation   +179 added lines, -179 removed lines patch added patch discarded remove patch
@@ -16,183 +16,183 @@
 block discarded – undo
16 16
  */
17 17
 class EventListQuery extends WP_Query
18 18
 {
19
-    private ?string $title = '';
20
-
21
-    private int $limit = 10;
22
-
23
-    private ?string $css_class = '';
24
-
25
-    private bool $show_expired = false;
26
-
27
-    private ?string $month = '';
28
-
29
-    private ?string $category_slug = '';
30
-
31
-    /**
32
-     * @var array|string|null
33
-     */
34
-    private $order_by =[];
35
-
36
-    private ?string $sort = '';
37
-
38
-    private bool $show_title = true;
39
-
40
-
41
-    /**
42
-     * EE_Event_List_Query Constructor     *
43
-     *
44
-     * @param array $args
45
-     */
46
-    public function __construct($args = [])
47
-    {
48
-        $args = $this->parseArgs((array) $args);
49
-        $this->setupEventQueryHelper();
50
-        $this->setupFilters();
51
-        $args = $this->getQueryArgs($args);
52
-        // run the query
53
-        parent::__construct($args);
54
-    }
55
-
56
-
57
-    /**
58
-     * @param array $args
59
-     * @return array
60
-     */
61
-    private function parseArgs(array $args): array
62
-    {
63
-        // incoming args could be a mix of WP query args + EE shortcode args
64
-        foreach ($args as $property => $value) {
65
-            // if the arg is a property of this class, then it's an EE shortcode arg
66
-            if (property_exists($this, $property) && ! property_exists('WP_Query', $property)) {
67
-                // get the property type
68
-                $type = gettype($this->{$property});
69
-                // set the property value
70
-                switch ($type) {
71
-                    case 'integer':
72
-                        $this->{$property} = absint($value);
73
-                        break;
74
-                    case 'boolean':
75
-                        $this->{$property} = filter_var($value, FILTER_VALIDATE_BOOLEAN);
76
-                        break;
77
-                    case 'string':
78
-                        $this->{$property} = sanitize_text_field($value);
79
-                        break;
80
-                    default:
81
-                        $this->{$property} = $value;
82
-                        break;
83
-                }
84
-                // then remove it from the array of args that will later be passed to WP_Query()
85
-                unset($args[ $property ]);
86
-            }
87
-        }
88
-        return $args;
89
-    }
90
-
91
-
92
-    private function setupEventQueryHelper()
93
-    {
94
-        // add query filters
95
-        EEH_Event_Query::add_query_filters();
96
-        // set params that will get used by the filters
97
-        EEH_Event_Query::set_query_params(
98
-            $this->month,
99
-            $this->category_slug,
100
-            $this->show_expired,
101
-            $this->order_by,
102
-            $this->sort
103
-        );
104
-    }
105
-
106
-
107
-    private function setupFilters()
108
-    {
109
-        // first off, let's remove any filters from previous queries
110
-        remove_filter(
111
-            'FHEE__archive_espresso_events_template__show_header',
112
-            [$this, 'show_event_list_title']
113
-        );
114
-        remove_filter(
115
-            'FHEE__archive_espresso_events_template__upcoming_events_h1',
116
-            [$this, 'event_list_title']
117
-        );
118
-        remove_all_filters('FHEE__content_espresso_events__event_class');
119
-        // Event List Title ?
120
-        add_filter(
121
-            'FHEE__archive_espresso_events_template__show_header',
122
-            [$this, 'show_event_list_title']
123
-        );
124
-        add_filter(
125
-            'FHEE__archive_espresso_events_template__upcoming_events_h1',
126
-            [$this, 'event_list_title']
127
-        );
128
-        // add the css class
129
-        add_filter(
130
-            'FHEE__content_espresso_events__event_class',
131
-            [$this, 'event_list_css']
132
-        );
133
-    }
134
-
135
-
136
-    private function getQueryArgs(array $args): array
137
-    {
138
-        // the current "page" we are viewing
139
-        $paged = max(1, get_query_var('paged'));
140
-        // Force these args
141
-        return array_merge(
142
-            $args,
143
-            [
144
-                'post_type'              => EspressoPostType::EVENTS,
145
-                'posts_per_page'         => $this->limit,
146
-                'update_post_term_cache' => false,
147
-                'update_post_meta_cache' => false,
148
-                'paged'                  => $paged,
149
-                'offset'                 => ($paged - 1) * $this->limit,
150
-            ]
151
-        );
152
-    }
153
-
154
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
155
-
156
-
157
-    /**
158
-     * show_event_list_title
159
-     *
160
-     * @return boolean
161
-     */
162
-    public function show_event_list_title(): bool
163
-    {
164
-        return filter_var($this->show_title, FILTER_VALIDATE_BOOLEAN);
165
-    }
166
-
167
-
168
-    /**
169
-     * callback for FHEE__archive_espresso_events_template__upcoming_events_h1 filter
170
-     *
171
-     * @param string $event_list_title
172
-     * @return    string
173
-     */
174
-    public function event_list_title(string $event_list_title = ''): string
175
-    {
176
-        if (! empty($this->title)) {
177
-            return $this->title;
178
-        }
179
-        return $event_list_title;
180
-    }
181
-
182
-
183
-    /**
184
-     * callback for FHEE__content_espresso_events__event_class filter
185
-     *
186
-     * @param string $event_list_css
187
-     * @return string
188
-     */
189
-    public function event_list_css(string $event_list_css = ''): string
190
-    {
191
-        $event_list_css .= ! empty($event_list_css) ? ' ' : '';
192
-        $event_list_css .= ! empty($this->css_class) ? $this->css_class : '';
193
-        $event_list_css .= ! empty($event_list_css) ? ' ' : '';
194
-        $event_list_css .= ! empty($this->category_slug) ? $this->category_slug : '';
195
-        return $event_list_css;
196
-    }
197
-    // phpcs:enable
19
+	private ?string $title = '';
20
+
21
+	private int $limit = 10;
22
+
23
+	private ?string $css_class = '';
24
+
25
+	private bool $show_expired = false;
26
+
27
+	private ?string $month = '';
28
+
29
+	private ?string $category_slug = '';
30
+
31
+	/**
32
+	 * @var array|string|null
33
+	 */
34
+	private $order_by =[];
35
+
36
+	private ?string $sort = '';
37
+
38
+	private bool $show_title = true;
39
+
40
+
41
+	/**
42
+	 * EE_Event_List_Query Constructor     *
43
+	 *
44
+	 * @param array $args
45
+	 */
46
+	public function __construct($args = [])
47
+	{
48
+		$args = $this->parseArgs((array) $args);
49
+		$this->setupEventQueryHelper();
50
+		$this->setupFilters();
51
+		$args = $this->getQueryArgs($args);
52
+		// run the query
53
+		parent::__construct($args);
54
+	}
55
+
56
+
57
+	/**
58
+	 * @param array $args
59
+	 * @return array
60
+	 */
61
+	private function parseArgs(array $args): array
62
+	{
63
+		// incoming args could be a mix of WP query args + EE shortcode args
64
+		foreach ($args as $property => $value) {
65
+			// if the arg is a property of this class, then it's an EE shortcode arg
66
+			if (property_exists($this, $property) && ! property_exists('WP_Query', $property)) {
67
+				// get the property type
68
+				$type = gettype($this->{$property});
69
+				// set the property value
70
+				switch ($type) {
71
+					case 'integer':
72
+						$this->{$property} = absint($value);
73
+						break;
74
+					case 'boolean':
75
+						$this->{$property} = filter_var($value, FILTER_VALIDATE_BOOLEAN);
76
+						break;
77
+					case 'string':
78
+						$this->{$property} = sanitize_text_field($value);
79
+						break;
80
+					default:
81
+						$this->{$property} = $value;
82
+						break;
83
+				}
84
+				// then remove it from the array of args that will later be passed to WP_Query()
85
+				unset($args[ $property ]);
86
+			}
87
+		}
88
+		return $args;
89
+	}
90
+
91
+
92
+	private function setupEventQueryHelper()
93
+	{
94
+		// add query filters
95
+		EEH_Event_Query::add_query_filters();
96
+		// set params that will get used by the filters
97
+		EEH_Event_Query::set_query_params(
98
+			$this->month,
99
+			$this->category_slug,
100
+			$this->show_expired,
101
+			$this->order_by,
102
+			$this->sort
103
+		);
104
+	}
105
+
106
+
107
+	private function setupFilters()
108
+	{
109
+		// first off, let's remove any filters from previous queries
110
+		remove_filter(
111
+			'FHEE__archive_espresso_events_template__show_header',
112
+			[$this, 'show_event_list_title']
113
+		);
114
+		remove_filter(
115
+			'FHEE__archive_espresso_events_template__upcoming_events_h1',
116
+			[$this, 'event_list_title']
117
+		);
118
+		remove_all_filters('FHEE__content_espresso_events__event_class');
119
+		// Event List Title ?
120
+		add_filter(
121
+			'FHEE__archive_espresso_events_template__show_header',
122
+			[$this, 'show_event_list_title']
123
+		);
124
+		add_filter(
125
+			'FHEE__archive_espresso_events_template__upcoming_events_h1',
126
+			[$this, 'event_list_title']
127
+		);
128
+		// add the css class
129
+		add_filter(
130
+			'FHEE__content_espresso_events__event_class',
131
+			[$this, 'event_list_css']
132
+		);
133
+	}
134
+
135
+
136
+	private function getQueryArgs(array $args): array
137
+	{
138
+		// the current "page" we are viewing
139
+		$paged = max(1, get_query_var('paged'));
140
+		// Force these args
141
+		return array_merge(
142
+			$args,
143
+			[
144
+				'post_type'              => EspressoPostType::EVENTS,
145
+				'posts_per_page'         => $this->limit,
146
+				'update_post_term_cache' => false,
147
+				'update_post_meta_cache' => false,
148
+				'paged'                  => $paged,
149
+				'offset'                 => ($paged - 1) * $this->limit,
150
+			]
151
+		);
152
+	}
153
+
154
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
155
+
156
+
157
+	/**
158
+	 * show_event_list_title
159
+	 *
160
+	 * @return boolean
161
+	 */
162
+	public function show_event_list_title(): bool
163
+	{
164
+		return filter_var($this->show_title, FILTER_VALIDATE_BOOLEAN);
165
+	}
166
+
167
+
168
+	/**
169
+	 * callback for FHEE__archive_espresso_events_template__upcoming_events_h1 filter
170
+	 *
171
+	 * @param string $event_list_title
172
+	 * @return    string
173
+	 */
174
+	public function event_list_title(string $event_list_title = ''): string
175
+	{
176
+		if (! empty($this->title)) {
177
+			return $this->title;
178
+		}
179
+		return $event_list_title;
180
+	}
181
+
182
+
183
+	/**
184
+	 * callback for FHEE__content_espresso_events__event_class filter
185
+	 *
186
+	 * @param string $event_list_css
187
+	 * @return string
188
+	 */
189
+	public function event_list_css(string $event_list_css = ''): string
190
+	{
191
+		$event_list_css .= ! empty($event_list_css) ? ' ' : '';
192
+		$event_list_css .= ! empty($this->css_class) ? $this->css_class : '';
193
+		$event_list_css .= ! empty($event_list_css) ? ' ' : '';
194
+		$event_list_css .= ! empty($this->category_slug) ? $this->category_slug : '';
195
+		return $event_list_css;
196
+	}
197
+	// phpcs:enable
198 198
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
     /**
32 32
      * @var array|string|null
33 33
      */
34
-    private $order_by =[];
34
+    private $order_by = [];
35 35
 
36 36
     private ?string $sort = '';
37 37
 
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
                         break;
83 83
                 }
84 84
                 // then remove it from the array of args that will later be passed to WP_Query()
85
-                unset($args[ $property ]);
85
+                unset($args[$property]);
86 86
             }
87 87
         }
88 88
         return $args;
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
      */
174 174
     public function event_list_title(string $event_list_title = ''): string
175 175
     {
176
-        if (! empty($this->title)) {
176
+        if ( ! empty($this->title)) {
177 177
             return $this->title;
178 178
         }
179 179
         return $event_list_title;
Please login to merge, or discard this patch.