Completed
Branch dev (fc935c)
by
unknown
22:17 queued 15:01
created
services/admin/registrations/list_table/csv_reports/PaymentsInfoCSV.php 1 patch
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -11,23 +11,23 @@
 block discarded – undo
11 11
  */
12 12
 class PaymentsInfoCSV
13 13
 {
14
-    /**
15
-     * Extracts payment information using the payment records
16
-     *
17
-     * @param array $payments_info
18
-     * @return array
19
-     */
20
-    public static function extractPaymentInfo(array $payments_info): array
21
-    {
22
-        $payment_methods = [];
23
-        $gateway_txn_ids_etc = [];
24
-        $payment_times = [];
25
-        foreach ($payments_info as $payment_method_and_gateway_txn_id) {
26
-            $payment_methods[] = $payment_method_and_gateway_txn_id['name']
27
-                                 ?? esc_html__('Unknown', 'event_espresso');
28
-            $gateway_txn_ids_etc[] = $payment_method_and_gateway_txn_id['gateway_txn_id'] ?? '';
29
-            $payment_times[] = $payment_method_and_gateway_txn_id['payment_time'] ?? '';
30
-        }
31
-        return [$payment_methods, $gateway_txn_ids_etc, $payment_times];
32
-    }
14
+	/**
15
+	 * Extracts payment information using the payment records
16
+	 *
17
+	 * @param array $payments_info
18
+	 * @return array
19
+	 */
20
+	public static function extractPaymentInfo(array $payments_info): array
21
+	{
22
+		$payment_methods = [];
23
+		$gateway_txn_ids_etc = [];
24
+		$payment_times = [];
25
+		foreach ($payments_info as $payment_method_and_gateway_txn_id) {
26
+			$payment_methods[] = $payment_method_and_gateway_txn_id['name']
27
+								 ?? esc_html__('Unknown', 'event_espresso');
28
+			$gateway_txn_ids_etc[] = $payment_method_and_gateway_txn_id['gateway_txn_id'] ?? '';
29
+			$payment_times[] = $payment_method_and_gateway_txn_id['payment_time'] ?? '';
30
+		}
31
+		return [$payment_methods, $gateway_txn_ids_etc, $payment_times];
32
+	}
33 33
 }
Please login to merge, or discard this patch.
services/admin/registrations/list_table/csv_reports/RegistrationCSV.php 2 patches
Indentation   +63 added lines, -63 removed lines patch added patch discarded remove patch
@@ -17,67 +17,67 @@
 block discarded – undo
17 17
  */
18 18
 class RegistrationCSV
19 19
 {
20
-    /**
21
-     * Adds registration columns to the CSV row
22
-     *
23
-     * @param array $fields
24
-     * @param array $reg_row
25
-     * @param array $data
26
-     * @return array
27
-     * @throws EE_Error
28
-     * @throws ReflectionException
29
-     */
30
-    public static function addRegistrationColumns(array $fields, array $reg_row, array $data): array
31
-    {
32
-        $reg_model = EEM_Registration::instance();
33
-        foreach ($fields as $field_name) {
34
-            $field = $reg_model->field_settings_for($field_name);
35
-            switch ($field_name) {
36
-                case 'REG_final_price':
37
-                    $value = EEH_Export::prepare_value_from_db_for_display(
38
-                        $reg_model,
39
-                        $field_name,
40
-                        $reg_row['Registration.REG_final_price'],
41
-                        'localized_float'
42
-                    );
43
-                    break;
44
-                case 'REG_count':
45
-                    $value = sprintf(
46
-                        /* translators: 1: number of registration in group (REG_count), 2: registration group size (REG_group_size) */
47
-                        esc_html__('%1$s of %2$s', 'event_espresso'),
48
-                        EEH_Export::prepare_value_from_db_for_display(
49
-                            $reg_model,
50
-                            'REG_count',
51
-                            $reg_row['Registration.REG_count']
52
-                        ),
53
-                        EEH_Export::prepare_value_from_db_for_display(
54
-                            $reg_model,
55
-                            'REG_group_size',
56
-                            $reg_row['Registration.REG_group_size']
57
-                        )
58
-                    );
59
-                    break;
60
-                case 'REG_date':
61
-                    $value = EEH_Export::prepare_value_from_db_for_display(
62
-                        $reg_model,
63
-                        $field_name,
64
-                        $reg_row['Registration.REG_date'],
65
-                        'no_html'
66
-                    );
67
-                    break;
68
-                default:
69
-                    $value = EEH_Export::prepare_value_from_db_for_display(
70
-                        $reg_model,
71
-                        $field_name,
72
-                        $reg_row[ $field->get_qualified_column() ]
73
-                    );
74
-            }
75
-            $data[ EEH_Export::get_column_name_for_field($field) ] = $value;
76
-            if ($field_name == 'REG_final_price') {
77
-                // add a column named Currency after the final price
78
-                $data[ esc_html__("Currency", "event_espresso") ] = EE_Config::instance()->currency->code;
79
-            }
80
-        }
81
-        return $data;
82
-    }
20
+	/**
21
+	 * Adds registration columns to the CSV row
22
+	 *
23
+	 * @param array $fields
24
+	 * @param array $reg_row
25
+	 * @param array $data
26
+	 * @return array
27
+	 * @throws EE_Error
28
+	 * @throws ReflectionException
29
+	 */
30
+	public static function addRegistrationColumns(array $fields, array $reg_row, array $data): array
31
+	{
32
+		$reg_model = EEM_Registration::instance();
33
+		foreach ($fields as $field_name) {
34
+			$field = $reg_model->field_settings_for($field_name);
35
+			switch ($field_name) {
36
+				case 'REG_final_price':
37
+					$value = EEH_Export::prepare_value_from_db_for_display(
38
+						$reg_model,
39
+						$field_name,
40
+						$reg_row['Registration.REG_final_price'],
41
+						'localized_float'
42
+					);
43
+					break;
44
+				case 'REG_count':
45
+					$value = sprintf(
46
+						/* translators: 1: number of registration in group (REG_count), 2: registration group size (REG_group_size) */
47
+						esc_html__('%1$s of %2$s', 'event_espresso'),
48
+						EEH_Export::prepare_value_from_db_for_display(
49
+							$reg_model,
50
+							'REG_count',
51
+							$reg_row['Registration.REG_count']
52
+						),
53
+						EEH_Export::prepare_value_from_db_for_display(
54
+							$reg_model,
55
+							'REG_group_size',
56
+							$reg_row['Registration.REG_group_size']
57
+						)
58
+					);
59
+					break;
60
+				case 'REG_date':
61
+					$value = EEH_Export::prepare_value_from_db_for_display(
62
+						$reg_model,
63
+						$field_name,
64
+						$reg_row['Registration.REG_date'],
65
+						'no_html'
66
+					);
67
+					break;
68
+				default:
69
+					$value = EEH_Export::prepare_value_from_db_for_display(
70
+						$reg_model,
71
+						$field_name,
72
+						$reg_row[ $field->get_qualified_column() ]
73
+					);
74
+			}
75
+			$data[ EEH_Export::get_column_name_for_field($field) ] = $value;
76
+			if ($field_name == 'REG_final_price') {
77
+				// add a column named Currency after the final price
78
+				$data[ esc_html__("Currency", "event_espresso") ] = EE_Config::instance()->currency->code;
79
+			}
80
+		}
81
+		return $data;
82
+	}
83 83
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -69,13 +69,13 @@
 block discarded – undo
69 69
                     $value = EEH_Export::prepare_value_from_db_for_display(
70 70
                         $reg_model,
71 71
                         $field_name,
72
-                        $reg_row[ $field->get_qualified_column() ]
72
+                        $reg_row[$field->get_qualified_column()]
73 73
                     );
74 74
             }
75
-            $data[ EEH_Export::get_column_name_for_field($field) ] = $value;
75
+            $data[EEH_Export::get_column_name_for_field($field)] = $value;
76 76
             if ($field_name == 'REG_final_price') {
77 77
                 // add a column named Currency after the final price
78
-                $data[ esc_html__("Currency", "event_espresso") ] = EE_Config::instance()->currency->code;
78
+                $data[esc_html__("Currency", "event_espresso")] = EE_Config::instance()->currency->code;
79 79
             }
80 80
         }
81 81
         return $data;
Please login to merge, or discard this patch.
domain/services/admin/registrations/list_table/csv_reports/AttendeeCSV.php 2 patches
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -18,53 +18,53 @@
 block discarded – undo
18 18
  */
19 19
 class AttendeeCSV
20 20
 {
21
-    /**
22
-     * Adds attendee columns to the CSV row
23
-     *
24
-     * @param array $fields
25
-     * @param array $reg_row
26
-     * @param array $data
27
-     * @return array
28
-     * @throws EE_Error
29
-     * @throws ReflectionException
30
-     */
31
-    public static function addAttendeeColumns(array $fields, array $reg_row, array $data): array
32
-    {
33
-        $att_model = EEM_Attendee::instance();
34
-        $state_model   = EEM_State::instance();
35
-        $country_model = EEM_Country::instance();
36
-        foreach ($fields as $field_name) {
37
-            $field_obj = $att_model->field_settings_for($field_name);
38
-            if ($reg_row['Attendee_CPT.ID']) {
39
-                switch ($field_name) {
40
-                    case 'STA_ID':
41
-                        $value = $state_model->get_var(
42
-                            [
43
-                                ['STA_ID' => $reg_row['Attendee_Meta.STA_ID']]
44
-                            ],
45
-                            'STA_name'
46
-                        );
47
-                        break;
48
-                    case 'CNT_ISO':
49
-                        $value = $country_model->get_var(
50
-                            [
51
-                                ['CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO']]
52
-                            ],
53
-                            'CNT_name'
54
-                        );
55
-                        break;
56
-                    default:
57
-                        $value = EEH_Export::prepare_value_from_db_for_display(
58
-                            $att_model,
59
-                            $field_name,
60
-                            $reg_row[ $field_obj->get_qualified_column() ]
61
-                        );
62
-                }
63
-            } else {
64
-                $value = '';
65
-            }
66
-            $data[ EEH_Export::get_column_name_for_field($field_obj) ] = $value;
67
-        }
68
-        return $data;
69
-    }
21
+	/**
22
+	 * Adds attendee columns to the CSV row
23
+	 *
24
+	 * @param array $fields
25
+	 * @param array $reg_row
26
+	 * @param array $data
27
+	 * @return array
28
+	 * @throws EE_Error
29
+	 * @throws ReflectionException
30
+	 */
31
+	public static function addAttendeeColumns(array $fields, array $reg_row, array $data): array
32
+	{
33
+		$att_model = EEM_Attendee::instance();
34
+		$state_model   = EEM_State::instance();
35
+		$country_model = EEM_Country::instance();
36
+		foreach ($fields as $field_name) {
37
+			$field_obj = $att_model->field_settings_for($field_name);
38
+			if ($reg_row['Attendee_CPT.ID']) {
39
+				switch ($field_name) {
40
+					case 'STA_ID':
41
+						$value = $state_model->get_var(
42
+							[
43
+								['STA_ID' => $reg_row['Attendee_Meta.STA_ID']]
44
+							],
45
+							'STA_name'
46
+						);
47
+						break;
48
+					case 'CNT_ISO':
49
+						$value = $country_model->get_var(
50
+							[
51
+								['CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO']]
52
+							],
53
+							'CNT_name'
54
+						);
55
+						break;
56
+					default:
57
+						$value = EEH_Export::prepare_value_from_db_for_display(
58
+							$att_model,
59
+							$field_name,
60
+							$reg_row[ $field_obj->get_qualified_column() ]
61
+						);
62
+				}
63
+			} else {
64
+				$value = '';
65
+			}
66
+			$data[ EEH_Export::get_column_name_for_field($field_obj) ] = $value;
67
+		}
68
+		return $data;
69
+	}
70 70
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -57,13 +57,13 @@
 block discarded – undo
57 57
                         $value = EEH_Export::prepare_value_from_db_for_display(
58 58
                             $att_model,
59 59
                             $field_name,
60
-                            $reg_row[ $field_obj->get_qualified_column() ]
60
+                            $reg_row[$field_obj->get_qualified_column()]
61 61
                         );
62 62
                 }
63 63
             } else {
64 64
                 $value = '';
65 65
             }
66
-            $data[ EEH_Export::get_column_name_for_field($field_obj) ] = $value;
66
+            $data[EEH_Export::get_column_name_for_field($field_obj)] = $value;
67 67
         }
68 68
         return $data;
69 69
     }
Please login to merge, or discard this patch.
domain/services/admin/registrations/list_table/csv_reports/AnswersCSV.php 2 patches
Indentation   +53 added lines, -53 removed lines patch added patch discarded remove patch
@@ -18,59 +18,59 @@
 block discarded – undo
18 18
  */
19 19
 class AnswersCSV
20 20
 {
21
-    /**
22
-     * Add question / answer columns to the CSV row
23
-     *
24
-     * @param array $reg_row
25
-     * @param array $data
26
-     * @param array $question_labels
27
-     * @return array
28
-     * @throws EE_Error
29
-     * @throws ReflectionException
30
-     */
31
-    public static function addAnswerColumns(array $reg_row, array $data, array $question_labels): array
32
-    {
33
-        $answer_model = EEM_Answer::instance();
34
-        $qst_model = EEM_Question::instance();
35
-        $state_model = EEM_State::instance();
36
-        // make sure each registration has the same questions in the same order
37
-        foreach ($question_labels as $question_label) {
38
-            if (! isset($data[ $question_label ])) {
39
-                $data[ $question_label ] = null;
40
-            }
41
-        }
42
-        $answers = $answer_model->get_all_wpdb_results([
43
-            ['REG_ID' => $reg_row['Registration.REG_ID']],
44
-            'force_join' => ['Question'],
45
-        ]);
46
-        // now fill out the questions THEY answered
47
-        foreach ($answers as $answer_row) {
48
-            if ($answer_row['Question.QST_system']) {
49
-                // it's an answer to a system question. That was already displayed as part of the attendee
50
-                // fields, so don't write it out again thanks.
51
-                continue;
52
-            }
21
+	/**
22
+	 * Add question / answer columns to the CSV row
23
+	 *
24
+	 * @param array $reg_row
25
+	 * @param array $data
26
+	 * @param array $question_labels
27
+	 * @return array
28
+	 * @throws EE_Error
29
+	 * @throws ReflectionException
30
+	 */
31
+	public static function addAnswerColumns(array $reg_row, array $data, array $question_labels): array
32
+	{
33
+		$answer_model = EEM_Answer::instance();
34
+		$qst_model = EEM_Question::instance();
35
+		$state_model = EEM_State::instance();
36
+		// make sure each registration has the same questions in the same order
37
+		foreach ($question_labels as $question_label) {
38
+			if (! isset($data[ $question_label ])) {
39
+				$data[ $question_label ] = null;
40
+			}
41
+		}
42
+		$answers = $answer_model->get_all_wpdb_results([
43
+			['REG_ID' => $reg_row['Registration.REG_ID']],
44
+			'force_join' => ['Question'],
45
+		]);
46
+		// now fill out the questions THEY answered
47
+		foreach ($answers as $answer_row) {
48
+			if ($answer_row['Question.QST_system']) {
49
+				// it's an answer to a system question. That was already displayed as part of the attendee
50
+				// fields, so don't write it out again thanks.
51
+				continue;
52
+			}
53 53
 
54
-            $question_label = $answer_row['Question.QST_ID']
55
-                ? EEH_Export::prepare_value_from_db_for_display(
56
-                    $qst_model,
57
-                    'QST_admin_label',
58
-                    $answer_row['Question.QST_admin_label']
59
-                )
60
-                : sprintf(esc_html__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']);
54
+			$question_label = $answer_row['Question.QST_ID']
55
+				? EEH_Export::prepare_value_from_db_for_display(
56
+					$qst_model,
57
+					'QST_admin_label',
58
+					$answer_row['Question.QST_admin_label']
59
+				)
60
+				: sprintf(esc_html__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']);
61 61
 
62
-            $data[ $question_label ] = isset($answer_row['Question.QST_type'])
63
-                                       && $answer_row['Question.QST_type'] === EEM_Question::QST_type_state
64
-                ? $state_model->get_state_name_by_ID($answer_row['Answer.ANS_value'])
65
-                // this isn't for html, so don't show html entities
66
-                : html_entity_decode(
67
-                    EEH_Export::prepare_value_from_db_for_display(
68
-                        $answer_model,
69
-                        'ANS_value',
70
-                        $answer_row['Answer.ANS_value']
71
-                    )
72
-                );
73
-        }
74
-        return $data;
75
-    }
62
+			$data[ $question_label ] = isset($answer_row['Question.QST_type'])
63
+									   && $answer_row['Question.QST_type'] === EEM_Question::QST_type_state
64
+				? $state_model->get_state_name_by_ID($answer_row['Answer.ANS_value'])
65
+				// this isn't for html, so don't show html entities
66
+				: html_entity_decode(
67
+					EEH_Export::prepare_value_from_db_for_display(
68
+						$answer_model,
69
+						'ANS_value',
70
+						$answer_row['Answer.ANS_value']
71
+					)
72
+				);
73
+		}
74
+		return $data;
75
+	}
76 76
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -35,8 +35,8 @@  discard block
 block discarded – undo
35 35
         $state_model = EEM_State::instance();
36 36
         // make sure each registration has the same questions in the same order
37 37
         foreach ($question_labels as $question_label) {
38
-            if (! isset($data[ $question_label ])) {
39
-                $data[ $question_label ] = null;
38
+            if ( ! isset($data[$question_label])) {
39
+                $data[$question_label] = null;
40 40
             }
41 41
         }
42 42
         $answers = $answer_model->get_all_wpdb_results([
@@ -59,7 +59,7 @@  discard block
 block discarded – undo
59 59
                 )
60 60
                 : sprintf(esc_html__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']);
61 61
 
62
-            $data[ $question_label ] = isset($answer_row['Question.QST_type'])
62
+            $data[$question_label] = isset($answer_row['Question.QST_type'])
63 63
                                        && $answer_row['Question.QST_type'] === EEM_Question::QST_type_state
64 64
                 ? $state_model->get_state_name_by_ID($answer_row['Answer.ANS_value'])
65 65
                 // this isn't for html, so don't show html entities
Please login to merge, or discard this patch.
domain/services/admin/registrations/list_table/csv_reports/CheckinsCSV.php 1 patch
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -16,57 +16,57 @@
 block discarded – undo
16 16
  */
17 17
 class CheckinsCSV
18 18
 {
19
-    /**
20
-     * Returns datetime label
21
-     *
22
-     * @param EE_Datetime $datetime
23
-     * @return string
24
-     * @throws EE_Error
25
-     * @throws ReflectionException
26
-     */
27
-    public static function getDatetimeLabel(EE_Datetime $datetime): string
28
-    {
29
-        if (trim($datetime->get('DTT_name'))) {
30
-            /* translators: 1: datetime name, 2: datetime ID */
31
-            return sprintf(
32
-                esc_html__('Check-ins for %1$s - ID: %2$s', 'event_espresso'),
33
-                esc_html($datetime->get('DTT_name')),
34
-                esc_html($datetime->get('DTT_ID'))
35
-            );
36
-        }
19
+	/**
20
+	 * Returns datetime label
21
+	 *
22
+	 * @param EE_Datetime $datetime
23
+	 * @return string
24
+	 * @throws EE_Error
25
+	 * @throws ReflectionException
26
+	 */
27
+	public static function getDatetimeLabel(EE_Datetime $datetime): string
28
+	{
29
+		if (trim($datetime->get('DTT_name'))) {
30
+			/* translators: 1: datetime name, 2: datetime ID */
31
+			return sprintf(
32
+				esc_html__('Check-ins for %1$s - ID: %2$s', 'event_espresso'),
33
+				esc_html($datetime->get('DTT_name')),
34
+				esc_html($datetime->get('DTT_ID'))
35
+			);
36
+		}
37 37
 
38
-        /* translators: %s: datetime ID */
39
-        return sprintf(
40
-            esc_html__('ID: %1$s', 'event_espresso'),
41
-            esc_html($datetime->get('DTT_ID'))
42
-        );
43
-    }
38
+		/* translators: %s: datetime ID */
39
+		return sprintf(
40
+			esc_html__('ID: %1$s', 'event_espresso'),
41
+			esc_html($datetime->get('DTT_ID'))
42
+		);
43
+	}
44 44
 
45 45
 
46
-    /**
47
-     * Returns checkin value using checkin status and datetime
48
-     *
49
-     * @param EE_Checkin|null $checkin
50
-     * @return string|null
51
-     * @throws EE_Error
52
-     * @throws ReflectionException
53
-     */
54
-    public static function getCheckinValue(?EE_Checkin $checkin): ?string
55
-    {
56
-        if ($checkin instanceof EE_Checkin && $checkin->get('CHK_in') === true) {
57
-            /* translators: 1: check-in timestamp */
58
-            return sprintf(
59
-                esc_html__('IN: %1$s', 'event_espresso'),
60
-                $checkin->get_datetime('CHK_timestamp', 'Y-m-d', 'g:i a')
61
-            );
62
-        } elseif ($checkin instanceof EE_Checkin && $checkin->get('CHK_in') === false) {
63
-            /* translators: 1: check-in timestamp */
64
-            return sprintf(
65
-                esc_html__('OUT: %1$s', 'event_espresso'),
66
-                $checkin->get_datetime('CHK_timestamp', 'Y-m-d', 'g:i a')
67
-            );
68
-        }
46
+	/**
47
+	 * Returns checkin value using checkin status and datetime
48
+	 *
49
+	 * @param EE_Checkin|null $checkin
50
+	 * @return string|null
51
+	 * @throws EE_Error
52
+	 * @throws ReflectionException
53
+	 */
54
+	public static function getCheckinValue(?EE_Checkin $checkin): ?string
55
+	{
56
+		if ($checkin instanceof EE_Checkin && $checkin->get('CHK_in') === true) {
57
+			/* translators: 1: check-in timestamp */
58
+			return sprintf(
59
+				esc_html__('IN: %1$s', 'event_espresso'),
60
+				$checkin->get_datetime('CHK_timestamp', 'Y-m-d', 'g:i a')
61
+			);
62
+		} elseif ($checkin instanceof EE_Checkin && $checkin->get('CHK_in') === false) {
63
+			/* translators: 1: check-in timestamp */
64
+			return sprintf(
65
+				esc_html__('OUT: %1$s', 'event_espresso'),
66
+				$checkin->get_datetime('CHK_timestamp', 'Y-m-d', 'g:i a')
67
+			);
68
+		}
69 69
 
70
-        return '';
71
-    }
70
+		return '';
71
+	}
72 72
 }
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/RegistrationsReport.php 2 patches
Indentation   +576 added lines, -576 removed lines patch added patch discarded remove patch
@@ -42,580 +42,580 @@
 block discarded – undo
42 42
  */
43 43
 class RegistrationsReport extends JobHandlerFile
44 44
 {
45
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
46
-    // phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
47
-    /**
48
-     * Performs any necessary setup for starting the job. This is also a good
49
-     * place to setup the $job_arguments which will be used for subsequent HTTP requests
50
-     * when continue_job will be called
51
-     *
52
-     * @param JobParameters $job_parameters
53
-     * @return JobStepResponse
54
-     * @throws BatchRequestException
55
-     * @throws EE_Error
56
-     * @throws ReflectionException
57
-     */
58
-    public function create_job(JobParameters $job_parameters)
59
-    {
60
-        $event_id = absint($job_parameters->request_datum('EVT_ID', '0'));
61
-        $DTT_ID   = absint($job_parameters->request_datum('DTT_ID', '0'));
62
-        if (! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
63
-            throw new BatchRequestException(
64
-                esc_html__('You do not have permission to view registrations', 'event_espresso')
65
-            );
66
-        }
67
-        $filepath = $this->create_file_from_job_with_name(
68
-            $job_parameters->job_id(),
69
-            $this->get_filename()
70
-        );
71
-        $job_parameters->add_extra_data('filepath', $filepath);
72
-        if ($job_parameters->request_datum('use_filters', false)) {
73
-            $query_params = maybe_unserialize($job_parameters->request_datum('filters', []));
74
-        } else {
75
-            $query_params = apply_filters(
76
-                'FHEE__EE_Export__report_registration_for_event',
77
-                [
78
-                    [
79
-                        'OR' => [
80
-                            // don't include registrations from failed or abandoned transactions...
81
-                            'Transaction.STS_ID' => [
82
-                                'NOT IN',
83
-                                [
84
-                                    EEM_Transaction::failed_status_code,
85
-                                    EEM_Transaction::abandoned_status_code,
86
-                                ],
87
-                            ],
88
-                            // unless the registration is approved,
89
-                            // in which case include it regardless of transaction status
90
-                            'STS_ID' => EEM_Registration::status_id_approved,
91
-                        ],
92
-                        'Ticket.TKT_deleted' => ['IN', [true, false]],
93
-                    ],
94
-                    'order_by'   => ['Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'],
95
-                    'force_join' => ['Transaction', 'Ticket', 'Attendee'],
96
-                    'caps'       => EEM_Base::caps_read_admin,
97
-                ],
98
-                $event_id
99
-            );
100
-            if ($event_id) {
101
-                $query_params[0]['EVT_ID'] = $event_id;
102
-            } else {
103
-                $query_params['force_join'][] = 'Event';
104
-            }
105
-        }
106
-
107
-        if (! isset($query_params['force_join'])) {
108
-            $query_params['force_join'] = ['Event', 'Transaction', 'Ticket', 'Attendee'];
109
-        }
110
-        $job_parameters->add_extra_data('query_params', $query_params);
111
-        $question_labels = $this->_get_question_labels($query_params);
112
-        $job_parameters->add_extra_data('question_labels', $question_labels);
113
-        $job_parameters->set_job_size($this->count_units_to_process($query_params));
114
-        // we need to set the header columns
115
-        // but to do that we need to process one row so that we can extract ALL of the column headers
116
-        $csv_data_for_row = $this->get_csv_data_for(
117
-            $event_id,
118
-            0,
119
-            1,
120
-            $question_labels,
121
-            $query_params,
122
-            $DTT_ID
123
-        );
124
-        // but we don't want to write any actual data yet...
125
-        // so let's blank out all of the values for that first row
126
-        array_walk(
127
-            $csv_data_for_row[0],
128
-            function (&$value) {
129
-                $value = null;
130
-            }
131
-        );
132
-
133
-        EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true, true);
134
-        $this->updateTextHeader(
135
-            esc_html__('Registrations report started successfully...', 'event_espresso')
136
-        );
137
-        return new JobStepResponse($job_parameters, $this->feedback);
138
-    }
139
-
140
-
141
-    /**
142
-     * Gets the filename
143
-     *
144
-     * @return string
145
-     */
146
-    protected function get_filename(): string
147
-    {
148
-        return apply_filters(
149
-            'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__get_filename',
150
-            sprintf(
151
-                'event-espresso-registrations-%s.csv',
152
-                str_replace([':', ' '], '-', current_time('mysql'))
153
-            )
154
-        );
155
-    }
156
-
157
-
158
-    /**
159
-     * Gets the questions which are to be used for this report,
160
-     * so they can be remembered for later
161
-     *
162
-     * @param array $registration_query_params
163
-     * @return array question admin labels to be used for this report
164
-     * @throws EE_Error
165
-     * @throws ReflectionException
166
-     */
167
-    protected function _get_question_labels(array $registration_query_params): array
168
-    {
169
-        $where                 = $registration_query_params[0] ?? null;
170
-        $question_query_params = [];
171
-        if ($where !== null) {
172
-            $question_query_params = [
173
-                $this->_change_registration_where_params_to_question_where_params($registration_query_params[0]),
174
-            ];
175
-        }
176
-        // Make sure it's not a system question
177
-        $question_query_params[0]['OR*not-system-questions'] = [
178
-            'QST_system'      => '',
179
-            'QST_system*null' => ['IS_NULL']
180
-        ];
181
-        if (
182
-            apply_filters(
183
-                'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport___get_question_labels__only_include_answered_questions',
184
-                false,
185
-                $registration_query_params
186
-            )
187
-        ) {
188
-            $question_query_params[0]['Answer.ANS_ID'] = ['IS_NOT_NULL'];
189
-        }
190
-        $question_query_params['group_by'] = ['QST_ID'];
191
-        return array_unique(EEM_Question::instance()->get_col($question_query_params, 'QST_admin_label'));
192
-    }
193
-
194
-
195
-    /**
196
-     * Takes where params meant for registrations and changes them to work for questions
197
-     *
198
-     * @param array $reg_where_params
199
-     * @return array
200
-     * @throws EE_Error
201
-     * @throws ReflectionException
202
-     */
203
-    protected function _change_registration_where_params_to_question_where_params(array $reg_where_params): array
204
-    {
205
-        $question_where_params = [];
206
-        foreach ($reg_where_params as $key => $val) {
207
-            if (EEM_Registration::instance()->is_logic_query_param_key($key)) {
208
-                $question_where_params[ $key ] =
209
-                    $this->_change_registration_where_params_to_question_where_params($val);
210
-            } else {
211
-                // it's a normal where condition
212
-                $question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
213
-            }
214
-        }
215
-        return $question_where_params;
216
-    }
217
-
218
-
219
-    /**
220
-     * Performs another step of the job
221
-     *
222
-     * @param JobParameters $job_parameters
223
-     * @param int           $batch_size
224
-     * @return JobStepResponse
225
-     * @throws EE_Error
226
-     * @throws ReflectionException
227
-     */
228
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
229
-    {
230
-        if ($job_parameters->units_processed() < $job_parameters->job_size()) {
231
-            $csv_data = $this->get_csv_data_for(
232
-                (int) $job_parameters->request_datum('EVT_ID', '0'),
233
-                $job_parameters->units_processed(),
234
-                $batch_size,
235
-                $job_parameters->extra_datum('question_labels'),
236
-                $job_parameters->extra_datum('query_params'),
237
-                (int) $job_parameters->request_datum('DTT_ID', '0')
238
-            );
239
-            EEH_Export::write_data_array_to_csv(
240
-                $job_parameters->extra_datum('filepath'),
241
-                $csv_data,
242
-                false
243
-            );
244
-            $units_processed = count($csv_data);
245
-            if ($units_processed) {
246
-                $job_parameters->mark_processed($units_processed);
247
-                $this->updateText(
248
-                    sprintf(
249
-                        esc_html__('Wrote %1$s rows to report CSV file...', 'event_espresso'),
250
-                        $units_processed
251
-                    )
252
-                );
253
-            }
254
-        }
255
-        $extra_response_data = ['file_url' => ''];
256
-        if ($job_parameters->units_processed() >= $job_parameters->job_size()) {
257
-            $job_parameters->set_status(JobParameters::status_complete);
258
-            $extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
259
-            $this->displayJobFinalResults($job_parameters);
260
-        } else {
261
-            $job_parameters->set_status(JobParameters::status_continue);
262
-        }
263
-        return new JobStepResponse($job_parameters, $this->feedback, $extra_response_data);
264
-    }
265
-
266
-
267
-    /**
268
-     * Gets the csv data for a batch of registrations
269
-     *
270
-     * @param int|null $event_id
271
-     * @param int      $offset
272
-     * @param int      $limit
273
-     * @param array    $question_labels the IDs for all the questions which were answered by someone in this selection
274
-     * @param array    $query_params    for using where querying the model
275
-     * @param int      $DTT_ID
276
-     * @return array top-level keys are numeric, next-level keys are column headers
277
-     * @throws EE_Error
278
-     * @throws ReflectionException
279
-     */
280
-    public function get_csv_data_for(
281
-        ?int $event_id,
282
-        int $offset,
283
-        int $limit,
284
-        array $question_labels,
285
-        array $query_params,
286
-        int $DTT_ID = 0
287
-    ): array {
288
-        $reg_fields_to_include = [
289
-            'TXN_ID',
290
-            'ATT_ID',
291
-            'REG_ID',
292
-            'REG_date',
293
-            'REG_code',
294
-            'REG_count',
295
-            'REG_final_price',
296
-        ];
297
-        $att_fields_to_include = [
298
-            'ATT_fname',
299
-            'ATT_lname',
300
-            'ATT_email',
301
-            'ATT_address',
302
-            'ATT_address2',
303
-            'ATT_city',
304
-            'STA_ID',
305
-            'CNT_ISO',
306
-            'ATT_zip',
307
-            'ATT_phone',
308
-        ];
309
-
310
-        // get models
311
-        $event_model   = EEM_Event::instance();
312
-        $date_model    = EEM_Datetime::instance();
313
-        $ticket_model  = EEM_Ticket::instance();
314
-        $txn_model     = EEM_Transaction::instance();
315
-        $reg_model     = EEM_Registration::instance();
316
-        $pay_model     = EEM_Payment::instance();
317
-        $status_model  = EEM_Status::instance();
318
-
319
-        $registrations_csv_ready_array = [];
320
-        $query_params['limit']         = [$offset, $limit];
321
-        $registration_rows             = $reg_model->get_all_wpdb_results($query_params);
322
-
323
-        foreach ($registration_rows as $reg_row) {
324
-            if (! is_array($reg_row)) {
325
-                continue;
326
-            }
327
-            $reg_csv_array = [];
328
-            // registration ID
329
-            $reg_id_field = $reg_model->field_settings_for('REG_ID');
330
-            $reg_csv_array[ EEH_Export::get_column_name_for_field($reg_id_field) ] =
331
-                EEH_Export::prepare_value_from_db_for_display(
332
-                    $reg_model,
333
-                    'REG_ID',
334
-                    $reg_row[ $reg_id_field->get_qualified_column() ]
335
-                );
336
-            // ALL registrations, or is list filtered to just one?
337
-            if (! $event_id) {
338
-                // ALL registrations, so get each event's name and ID
339
-                $reg_csv_array[ esc_html__('Event', 'event_espresso') ] = sprintf(
340
-                    /* translators: 1: event name, 2: event ID */
341
-                    esc_html__('%1$s (%2$s)', 'event_espresso'),
342
-                    EEH_Export::prepare_value_from_db_for_display(
343
-                        $event_model,
344
-                        'EVT_name',
345
-                        $reg_row['Event_CPT.post_title']
346
-                    ),
347
-                    $reg_row['Event_CPT.ID']
348
-                );
349
-            }
350
-            // add attendee columns
351
-            $reg_csv_array = AttendeeCSV::addAttendeeColumns($att_fields_to_include, $reg_row, $reg_csv_array);
352
-            // add registration columns
353
-            $reg_csv_array = RegistrationCSV::addRegistrationColumns($reg_fields_to_include, $reg_row, $reg_csv_array);
354
-            // get pretty status
355
-            $stati = $status_model->localized_status(
356
-                [
357
-                    $reg_row['Registration.STS_ID']     => esc_html__('unknown', 'event_espresso'),
358
-                    $reg_row['TransactionTable.STS_ID'] => esc_html__('unknown', 'event_espresso'),
359
-                ],
360
-                false,
361
-                'sentence'
362
-            );
363
-            $is_primary_reg = $reg_row['Registration.REG_count'] == '1';
364
-
365
-            $reg_csv_array[ esc_html__('Registration Status', 'event_espresso') ] =
366
-                $stati[ $reg_row['Registration.STS_ID'] ];
367
-            // get pretty transaction status
368
-            $reg_csv_array[ esc_html__('Transaction Status', 'event_espresso') ]     =
369
-                $stati[ $reg_row['TransactionTable.STS_ID'] ];
370
-            $reg_csv_array[ esc_html__('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
371
-                ? EEH_Export::prepare_value_from_db_for_display(
372
-                    $txn_model,
373
-                    'TXN_total',
374
-                    $reg_row['TransactionTable.TXN_total'],
375
-                    'localized_float'
376
-                )
377
-                : '0.00';
378
-
379
-            $reg_csv_array[ esc_html__('Amount Paid', 'event_espresso') ]            = $is_primary_reg
380
-                ? EEH_Export::prepare_value_from_db_for_display(
381
-                    $txn_model,
382
-                    'TXN_paid',
383
-                    $reg_row['TransactionTable.TXN_paid'],
384
-                    'localized_float'
385
-                )
386
-                : '0.00';
387
-
388
-            $payment_methods                                                                  = [];
389
-            $gateway_txn_ids_etc                                                              = [];
390
-            $payment_times                                                                    = [];
391
-            if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) {
392
-                $payments_info = $pay_model->get_all_wpdb_results(
393
-                    [
394
-                        [
395
-                            'TXN_ID' => $reg_row['TransactionTable.TXN_ID'],
396
-                            'STS_ID' => EEM_Payment::status_id_approved,
397
-                        ],
398
-                        'force_join' => ['Payment_Method'],
399
-                    ],
400
-                    ARRAY_A,
401
-                    'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time'
402
-                );
403
-                [$payment_methods, $gateway_txn_ids_etc, $payment_times] = PaymentsInfoCSV::extractPaymentInfo(
404
-                    $payments_info
405
-                );
406
-            }
407
-
408
-            $reg_csv_array[ esc_html__('Payment Date(s)', 'event_espresso') ] = implode(
409
-                ',',
410
-                $payment_times
411
-            );
412
-
413
-            $reg_csv_array[ esc_html__('Payment Method(s)', 'event_espresso') ] = implode(
414
-                ',',
415
-                $payment_methods
416
-            );
417
-
418
-            $reg_csv_array[ esc_html__('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
419
-                ',',
420
-                $gateway_txn_ids_etc
421
-            );
422
-
423
-            $ticket_name      = esc_html__('Unknown', 'event_espresso');
424
-            $datetime_strings = [esc_html__('Unknown', 'event_espresso')];
425
-            if ($reg_row['Ticket.TKT_ID']) {
426
-                $ticket_name       = EEH_Export::prepare_value_from_db_for_display(
427
-                    $ticket_model,
428
-                    'TKT_name',
429
-                    $reg_row['Ticket.TKT_name']
430
-                );
431
-                $datetime_strings = [];
432
-                $datetimes        = $date_model->get_all_wpdb_results(
433
-                    [
434
-                        ['Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']],
435
-                        'order_by'                 => ['DTT_EVT_start' => 'ASC'],
436
-                        'default_where_conditions' => 'none',
437
-                    ]
438
-                );
439
-                foreach ($datetimes as $datetime) {
440
-                    $datetime_strings[] = EEH_Export::prepare_value_from_db_for_display(
441
-                        $date_model,
442
-                        'DTT_EVT_start',
443
-                        $datetime['Datetime.DTT_EVT_start']
444
-                    );
445
-                }
446
-            }
447
-
448
-            $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
449
-
450
-
451
-            $reg_csv_array[ esc_html__('Ticket Datetimes', 'event_espresso') ] = implode(
452
-                ', ',
453
-                $datetime_strings
454
-            );
455
-
456
-            // add answer columns
457
-            $reg_csv_array = AnswersCSV::addAnswerColumns($reg_row, $reg_csv_array, $question_labels);
458
-            // Include check-in data
459
-            if ($event_id && $DTT_ID) {
460
-                // get whether or not the user has checked in
461
-                $reg_csv_array[ esc_html__('Datetime Check-ins #', 'event_espresso') ] =
462
-                    $reg_model->count_related(
463
-                        $reg_row['Registration.REG_ID'],
464
-                        'Checkin',
465
-                        [
466
-                            [
467
-                                'DTT_ID' => $DTT_ID
468
-                            ]
469
-                        ]
470
-                    );
471
-                /** @var EE_Datetime $datetime */
472
-                $datetime     = $date_model->get_one_by_ID($DTT_ID);
473
-                $checkin_rows = EEM_Checkin::instance()->get_all(
474
-                    [
475
-                        [
476
-                            'REG_ID' => $reg_row['Registration.REG_ID'],
477
-                            'DTT_ID' => $datetime->get('DTT_ID'),
478
-                        ],
479
-                    ]
480
-                );
481
-                $checkins     = [];
482
-                foreach ($checkin_rows as $checkin_row) {
483
-                    /** @var EE_Checkin $checkin_row */
484
-                    $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
485
-                    if ($checkin_value) {
486
-                        $checkins[] = $checkin_value;
487
-                    }
488
-                }
489
-                $datetime_name                   = CheckinsCSV::getDatetimeLabel($datetime);
490
-                $reg_csv_array[ $datetime_name ] = implode(' --- ', $checkins);
491
-            } elseif ($event_id) {
492
-                // get whether or not the user has checked in
493
-                $reg_csv_array[ esc_html__('Event Check-ins #', 'event_espresso') ] =
494
-                    $reg_model->count_related(
495
-                        $reg_row['Registration.REG_ID'],
496
-                        'Checkin'
497
-                    );
498
-
499
-                $datetimes = $date_model->get_all(
500
-                    [
501
-                        [
502
-                            'Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID'],
503
-                        ],
504
-                        'order_by'                 => ['DTT_EVT_start' => 'ASC'],
505
-                        'default_where_conditions' => 'none',
506
-                    ]
507
-                );
508
-                foreach ($datetimes as $datetime) {
509
-                    if (! $datetime instanceof EE_Datetime) {
510
-                        continue;
511
-                    }
512
-
513
-                    /** @var EE_Checkin $checkin_row */
514
-                    $checkin_row = EEM_Checkin::instance()->get_one(
515
-                        [
516
-                            [
517
-                                'REG_ID' => $reg_row['Registration.REG_ID'],
518
-                                'DTT_ID' => $datetime->get('DTT_ID'),
519
-                            ],
520
-                            'limit'    => 1,
521
-                            'order_by' => [
522
-                                'CHK_ID' => 'DESC'
523
-                            ]
524
-                        ]
525
-                    );
526
-
527
-                    $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
528
-                    $datetime_name = CheckinsCSV::getDatetimeLabel($datetime);
529
-
530
-                    $reg_csv_array[ $datetime_name ] = $checkin_value;
531
-                }
532
-            }
533
-            /**
534
-             * Filter to change the contents of each row of the registrations report CSV file.
535
-             * This can be used to add or remote columns from the CSV file, or change their values.
536
-             * Note when using: all rows in the CSV should have the same columns.
537
-             *
538
-             * @param array $reg_csv_array keys are the column names, values are their cell values
539
-             * @param array $reg_row       one entry from EEM_Registration::get_all_wpdb_results()
540
-             */
541
-            $registrations_csv_ready_array[] = apply_filters(
542
-                'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array',
543
-                $reg_csv_array,
544
-                $reg_row
545
-            );
546
-        }
547
-        // if we couldn't export anything, we want to at least show the column headers
548
-        if (empty($registrations_csv_ready_array)) {
549
-            $reg_csv_array               = [];
550
-            $model_and_fields_to_include = [
551
-                'Registration' => $reg_fields_to_include,
552
-                'Attendee'     => $att_fields_to_include,
553
-            ];
554
-            foreach ($model_and_fields_to_include as $model_name => $field_list) {
555
-                $model = EE_Registry::instance()->load_model($model_name);
556
-                foreach ($field_list as $field_name) {
557
-                    $field                                                          =
558
-                        $model->field_settings_for($field_name);
559
-                    $reg_csv_array[ EEH_Export::get_column_name_for_field($field) ] = null;
560
-                }
561
-            }
562
-            $registrations_csv_ready_array[] = $reg_csv_array;
563
-        }
564
-        return $registrations_csv_ready_array;
565
-    }
566
-
567
-
568
-    /**
569
-     * Counts total unit to process
570
-     *
571
-     * @param array $query_params
572
-     * @return int
573
-     * @throws EE_Error
574
-     * @throws ReflectionException
575
-     */
576
-    public function count_units_to_process(array $query_params): int
577
-    {
578
-        return EEM_Registration::instance()->count(
579
-            array_diff_key(
580
-                $query_params,
581
-                array_flip(
582
-                    ['limit']
583
-                )
584
-            )
585
-        );
586
-    }
587
-
588
-
589
-    /**
590
-     * Performs any clean-up logic when we know the job is completed.
591
-     * In this case, we delete the temporary file
592
-     *
593
-     * @param JobParameters $job_parameters
594
-     * @return JobStepResponse
595
-     */
596
-    public function cleanup_job(JobParameters $job_parameters)
597
-    {
598
-        $this->updateText(esc_html__('File Generation complete and downloaded', 'event_espresso'));
599
-
600
-        $this->_file_helper->delete(
601
-            EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
602
-            true,
603
-            'd'
604
-        );
605
-        $this->updateText(esc_html__('Cleaned up temporary file', 'event_espresso'));
606
-        $this->updateText(
607
-            $this->infoWrapper(
608
-                sprintf(
609
-                    esc_html__(
610
-                        'If not automatically redirected in %1$s seconds, click here to return to the %2$sRegistrations List Table%3$s',
611
-                        'event_espresso'
612
-                    ),
613
-                    '<span id="ee-redirect-timer">10</span>',
614
-                    '<a href="' . $job_parameters->request_datum('return_url') . '">',
615
-                    '</a>'
616
-                )
617
-            )
618
-        );
619
-        return new JobStepResponse($job_parameters, $this->feedback);
620
-    }
45
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
46
+	// phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
47
+	/**
48
+	 * Performs any necessary setup for starting the job. This is also a good
49
+	 * place to setup the $job_arguments which will be used for subsequent HTTP requests
50
+	 * when continue_job will be called
51
+	 *
52
+	 * @param JobParameters $job_parameters
53
+	 * @return JobStepResponse
54
+	 * @throws BatchRequestException
55
+	 * @throws EE_Error
56
+	 * @throws ReflectionException
57
+	 */
58
+	public function create_job(JobParameters $job_parameters)
59
+	{
60
+		$event_id = absint($job_parameters->request_datum('EVT_ID', '0'));
61
+		$DTT_ID   = absint($job_parameters->request_datum('DTT_ID', '0'));
62
+		if (! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
63
+			throw new BatchRequestException(
64
+				esc_html__('You do not have permission to view registrations', 'event_espresso')
65
+			);
66
+		}
67
+		$filepath = $this->create_file_from_job_with_name(
68
+			$job_parameters->job_id(),
69
+			$this->get_filename()
70
+		);
71
+		$job_parameters->add_extra_data('filepath', $filepath);
72
+		if ($job_parameters->request_datum('use_filters', false)) {
73
+			$query_params = maybe_unserialize($job_parameters->request_datum('filters', []));
74
+		} else {
75
+			$query_params = apply_filters(
76
+				'FHEE__EE_Export__report_registration_for_event',
77
+				[
78
+					[
79
+						'OR' => [
80
+							// don't include registrations from failed or abandoned transactions...
81
+							'Transaction.STS_ID' => [
82
+								'NOT IN',
83
+								[
84
+									EEM_Transaction::failed_status_code,
85
+									EEM_Transaction::abandoned_status_code,
86
+								],
87
+							],
88
+							// unless the registration is approved,
89
+							// in which case include it regardless of transaction status
90
+							'STS_ID' => EEM_Registration::status_id_approved,
91
+						],
92
+						'Ticket.TKT_deleted' => ['IN', [true, false]],
93
+					],
94
+					'order_by'   => ['Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'],
95
+					'force_join' => ['Transaction', 'Ticket', 'Attendee'],
96
+					'caps'       => EEM_Base::caps_read_admin,
97
+				],
98
+				$event_id
99
+			);
100
+			if ($event_id) {
101
+				$query_params[0]['EVT_ID'] = $event_id;
102
+			} else {
103
+				$query_params['force_join'][] = 'Event';
104
+			}
105
+		}
106
+
107
+		if (! isset($query_params['force_join'])) {
108
+			$query_params['force_join'] = ['Event', 'Transaction', 'Ticket', 'Attendee'];
109
+		}
110
+		$job_parameters->add_extra_data('query_params', $query_params);
111
+		$question_labels = $this->_get_question_labels($query_params);
112
+		$job_parameters->add_extra_data('question_labels', $question_labels);
113
+		$job_parameters->set_job_size($this->count_units_to_process($query_params));
114
+		// we need to set the header columns
115
+		// but to do that we need to process one row so that we can extract ALL of the column headers
116
+		$csv_data_for_row = $this->get_csv_data_for(
117
+			$event_id,
118
+			0,
119
+			1,
120
+			$question_labels,
121
+			$query_params,
122
+			$DTT_ID
123
+		);
124
+		// but we don't want to write any actual data yet...
125
+		// so let's blank out all of the values for that first row
126
+		array_walk(
127
+			$csv_data_for_row[0],
128
+			function (&$value) {
129
+				$value = null;
130
+			}
131
+		);
132
+
133
+		EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true, true);
134
+		$this->updateTextHeader(
135
+			esc_html__('Registrations report started successfully...', 'event_espresso')
136
+		);
137
+		return new JobStepResponse($job_parameters, $this->feedback);
138
+	}
139
+
140
+
141
+	/**
142
+	 * Gets the filename
143
+	 *
144
+	 * @return string
145
+	 */
146
+	protected function get_filename(): string
147
+	{
148
+		return apply_filters(
149
+			'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__get_filename',
150
+			sprintf(
151
+				'event-espresso-registrations-%s.csv',
152
+				str_replace([':', ' '], '-', current_time('mysql'))
153
+			)
154
+		);
155
+	}
156
+
157
+
158
+	/**
159
+	 * Gets the questions which are to be used for this report,
160
+	 * so they can be remembered for later
161
+	 *
162
+	 * @param array $registration_query_params
163
+	 * @return array question admin labels to be used for this report
164
+	 * @throws EE_Error
165
+	 * @throws ReflectionException
166
+	 */
167
+	protected function _get_question_labels(array $registration_query_params): array
168
+	{
169
+		$where                 = $registration_query_params[0] ?? null;
170
+		$question_query_params = [];
171
+		if ($where !== null) {
172
+			$question_query_params = [
173
+				$this->_change_registration_where_params_to_question_where_params($registration_query_params[0]),
174
+			];
175
+		}
176
+		// Make sure it's not a system question
177
+		$question_query_params[0]['OR*not-system-questions'] = [
178
+			'QST_system'      => '',
179
+			'QST_system*null' => ['IS_NULL']
180
+		];
181
+		if (
182
+			apply_filters(
183
+				'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport___get_question_labels__only_include_answered_questions',
184
+				false,
185
+				$registration_query_params
186
+			)
187
+		) {
188
+			$question_query_params[0]['Answer.ANS_ID'] = ['IS_NOT_NULL'];
189
+		}
190
+		$question_query_params['group_by'] = ['QST_ID'];
191
+		return array_unique(EEM_Question::instance()->get_col($question_query_params, 'QST_admin_label'));
192
+	}
193
+
194
+
195
+	/**
196
+	 * Takes where params meant for registrations and changes them to work for questions
197
+	 *
198
+	 * @param array $reg_where_params
199
+	 * @return array
200
+	 * @throws EE_Error
201
+	 * @throws ReflectionException
202
+	 */
203
+	protected function _change_registration_where_params_to_question_where_params(array $reg_where_params): array
204
+	{
205
+		$question_where_params = [];
206
+		foreach ($reg_where_params as $key => $val) {
207
+			if (EEM_Registration::instance()->is_logic_query_param_key($key)) {
208
+				$question_where_params[ $key ] =
209
+					$this->_change_registration_where_params_to_question_where_params($val);
210
+			} else {
211
+				// it's a normal where condition
212
+				$question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
213
+			}
214
+		}
215
+		return $question_where_params;
216
+	}
217
+
218
+
219
+	/**
220
+	 * Performs another step of the job
221
+	 *
222
+	 * @param JobParameters $job_parameters
223
+	 * @param int           $batch_size
224
+	 * @return JobStepResponse
225
+	 * @throws EE_Error
226
+	 * @throws ReflectionException
227
+	 */
228
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
229
+	{
230
+		if ($job_parameters->units_processed() < $job_parameters->job_size()) {
231
+			$csv_data = $this->get_csv_data_for(
232
+				(int) $job_parameters->request_datum('EVT_ID', '0'),
233
+				$job_parameters->units_processed(),
234
+				$batch_size,
235
+				$job_parameters->extra_datum('question_labels'),
236
+				$job_parameters->extra_datum('query_params'),
237
+				(int) $job_parameters->request_datum('DTT_ID', '0')
238
+			);
239
+			EEH_Export::write_data_array_to_csv(
240
+				$job_parameters->extra_datum('filepath'),
241
+				$csv_data,
242
+				false
243
+			);
244
+			$units_processed = count($csv_data);
245
+			if ($units_processed) {
246
+				$job_parameters->mark_processed($units_processed);
247
+				$this->updateText(
248
+					sprintf(
249
+						esc_html__('Wrote %1$s rows to report CSV file...', 'event_espresso'),
250
+						$units_processed
251
+					)
252
+				);
253
+			}
254
+		}
255
+		$extra_response_data = ['file_url' => ''];
256
+		if ($job_parameters->units_processed() >= $job_parameters->job_size()) {
257
+			$job_parameters->set_status(JobParameters::status_complete);
258
+			$extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
259
+			$this->displayJobFinalResults($job_parameters);
260
+		} else {
261
+			$job_parameters->set_status(JobParameters::status_continue);
262
+		}
263
+		return new JobStepResponse($job_parameters, $this->feedback, $extra_response_data);
264
+	}
265
+
266
+
267
+	/**
268
+	 * Gets the csv data for a batch of registrations
269
+	 *
270
+	 * @param int|null $event_id
271
+	 * @param int      $offset
272
+	 * @param int      $limit
273
+	 * @param array    $question_labels the IDs for all the questions which were answered by someone in this selection
274
+	 * @param array    $query_params    for using where querying the model
275
+	 * @param int      $DTT_ID
276
+	 * @return array top-level keys are numeric, next-level keys are column headers
277
+	 * @throws EE_Error
278
+	 * @throws ReflectionException
279
+	 */
280
+	public function get_csv_data_for(
281
+		?int $event_id,
282
+		int $offset,
283
+		int $limit,
284
+		array $question_labels,
285
+		array $query_params,
286
+		int $DTT_ID = 0
287
+	): array {
288
+		$reg_fields_to_include = [
289
+			'TXN_ID',
290
+			'ATT_ID',
291
+			'REG_ID',
292
+			'REG_date',
293
+			'REG_code',
294
+			'REG_count',
295
+			'REG_final_price',
296
+		];
297
+		$att_fields_to_include = [
298
+			'ATT_fname',
299
+			'ATT_lname',
300
+			'ATT_email',
301
+			'ATT_address',
302
+			'ATT_address2',
303
+			'ATT_city',
304
+			'STA_ID',
305
+			'CNT_ISO',
306
+			'ATT_zip',
307
+			'ATT_phone',
308
+		];
309
+
310
+		// get models
311
+		$event_model   = EEM_Event::instance();
312
+		$date_model    = EEM_Datetime::instance();
313
+		$ticket_model  = EEM_Ticket::instance();
314
+		$txn_model     = EEM_Transaction::instance();
315
+		$reg_model     = EEM_Registration::instance();
316
+		$pay_model     = EEM_Payment::instance();
317
+		$status_model  = EEM_Status::instance();
318
+
319
+		$registrations_csv_ready_array = [];
320
+		$query_params['limit']         = [$offset, $limit];
321
+		$registration_rows             = $reg_model->get_all_wpdb_results($query_params);
322
+
323
+		foreach ($registration_rows as $reg_row) {
324
+			if (! is_array($reg_row)) {
325
+				continue;
326
+			}
327
+			$reg_csv_array = [];
328
+			// registration ID
329
+			$reg_id_field = $reg_model->field_settings_for('REG_ID');
330
+			$reg_csv_array[ EEH_Export::get_column_name_for_field($reg_id_field) ] =
331
+				EEH_Export::prepare_value_from_db_for_display(
332
+					$reg_model,
333
+					'REG_ID',
334
+					$reg_row[ $reg_id_field->get_qualified_column() ]
335
+				);
336
+			// ALL registrations, or is list filtered to just one?
337
+			if (! $event_id) {
338
+				// ALL registrations, so get each event's name and ID
339
+				$reg_csv_array[ esc_html__('Event', 'event_espresso') ] = sprintf(
340
+					/* translators: 1: event name, 2: event ID */
341
+					esc_html__('%1$s (%2$s)', 'event_espresso'),
342
+					EEH_Export::prepare_value_from_db_for_display(
343
+						$event_model,
344
+						'EVT_name',
345
+						$reg_row['Event_CPT.post_title']
346
+					),
347
+					$reg_row['Event_CPT.ID']
348
+				);
349
+			}
350
+			// add attendee columns
351
+			$reg_csv_array = AttendeeCSV::addAttendeeColumns($att_fields_to_include, $reg_row, $reg_csv_array);
352
+			// add registration columns
353
+			$reg_csv_array = RegistrationCSV::addRegistrationColumns($reg_fields_to_include, $reg_row, $reg_csv_array);
354
+			// get pretty status
355
+			$stati = $status_model->localized_status(
356
+				[
357
+					$reg_row['Registration.STS_ID']     => esc_html__('unknown', 'event_espresso'),
358
+					$reg_row['TransactionTable.STS_ID'] => esc_html__('unknown', 'event_espresso'),
359
+				],
360
+				false,
361
+				'sentence'
362
+			);
363
+			$is_primary_reg = $reg_row['Registration.REG_count'] == '1';
364
+
365
+			$reg_csv_array[ esc_html__('Registration Status', 'event_espresso') ] =
366
+				$stati[ $reg_row['Registration.STS_ID'] ];
367
+			// get pretty transaction status
368
+			$reg_csv_array[ esc_html__('Transaction Status', 'event_espresso') ]     =
369
+				$stati[ $reg_row['TransactionTable.STS_ID'] ];
370
+			$reg_csv_array[ esc_html__('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
371
+				? EEH_Export::prepare_value_from_db_for_display(
372
+					$txn_model,
373
+					'TXN_total',
374
+					$reg_row['TransactionTable.TXN_total'],
375
+					'localized_float'
376
+				)
377
+				: '0.00';
378
+
379
+			$reg_csv_array[ esc_html__('Amount Paid', 'event_espresso') ]            = $is_primary_reg
380
+				? EEH_Export::prepare_value_from_db_for_display(
381
+					$txn_model,
382
+					'TXN_paid',
383
+					$reg_row['TransactionTable.TXN_paid'],
384
+					'localized_float'
385
+				)
386
+				: '0.00';
387
+
388
+			$payment_methods                                                                  = [];
389
+			$gateway_txn_ids_etc                                                              = [];
390
+			$payment_times                                                                    = [];
391
+			if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) {
392
+				$payments_info = $pay_model->get_all_wpdb_results(
393
+					[
394
+						[
395
+							'TXN_ID' => $reg_row['TransactionTable.TXN_ID'],
396
+							'STS_ID' => EEM_Payment::status_id_approved,
397
+						],
398
+						'force_join' => ['Payment_Method'],
399
+					],
400
+					ARRAY_A,
401
+					'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time'
402
+				);
403
+				[$payment_methods, $gateway_txn_ids_etc, $payment_times] = PaymentsInfoCSV::extractPaymentInfo(
404
+					$payments_info
405
+				);
406
+			}
407
+
408
+			$reg_csv_array[ esc_html__('Payment Date(s)', 'event_espresso') ] = implode(
409
+				',',
410
+				$payment_times
411
+			);
412
+
413
+			$reg_csv_array[ esc_html__('Payment Method(s)', 'event_espresso') ] = implode(
414
+				',',
415
+				$payment_methods
416
+			);
417
+
418
+			$reg_csv_array[ esc_html__('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
419
+				',',
420
+				$gateway_txn_ids_etc
421
+			);
422
+
423
+			$ticket_name      = esc_html__('Unknown', 'event_espresso');
424
+			$datetime_strings = [esc_html__('Unknown', 'event_espresso')];
425
+			if ($reg_row['Ticket.TKT_ID']) {
426
+				$ticket_name       = EEH_Export::prepare_value_from_db_for_display(
427
+					$ticket_model,
428
+					'TKT_name',
429
+					$reg_row['Ticket.TKT_name']
430
+				);
431
+				$datetime_strings = [];
432
+				$datetimes        = $date_model->get_all_wpdb_results(
433
+					[
434
+						['Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']],
435
+						'order_by'                 => ['DTT_EVT_start' => 'ASC'],
436
+						'default_where_conditions' => 'none',
437
+					]
438
+				);
439
+				foreach ($datetimes as $datetime) {
440
+					$datetime_strings[] = EEH_Export::prepare_value_from_db_for_display(
441
+						$date_model,
442
+						'DTT_EVT_start',
443
+						$datetime['Datetime.DTT_EVT_start']
444
+					);
445
+				}
446
+			}
447
+
448
+			$reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
449
+
450
+
451
+			$reg_csv_array[ esc_html__('Ticket Datetimes', 'event_espresso') ] = implode(
452
+				', ',
453
+				$datetime_strings
454
+			);
455
+
456
+			// add answer columns
457
+			$reg_csv_array = AnswersCSV::addAnswerColumns($reg_row, $reg_csv_array, $question_labels);
458
+			// Include check-in data
459
+			if ($event_id && $DTT_ID) {
460
+				// get whether or not the user has checked in
461
+				$reg_csv_array[ esc_html__('Datetime Check-ins #', 'event_espresso') ] =
462
+					$reg_model->count_related(
463
+						$reg_row['Registration.REG_ID'],
464
+						'Checkin',
465
+						[
466
+							[
467
+								'DTT_ID' => $DTT_ID
468
+							]
469
+						]
470
+					);
471
+				/** @var EE_Datetime $datetime */
472
+				$datetime     = $date_model->get_one_by_ID($DTT_ID);
473
+				$checkin_rows = EEM_Checkin::instance()->get_all(
474
+					[
475
+						[
476
+							'REG_ID' => $reg_row['Registration.REG_ID'],
477
+							'DTT_ID' => $datetime->get('DTT_ID'),
478
+						],
479
+					]
480
+				);
481
+				$checkins     = [];
482
+				foreach ($checkin_rows as $checkin_row) {
483
+					/** @var EE_Checkin $checkin_row */
484
+					$checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
485
+					if ($checkin_value) {
486
+						$checkins[] = $checkin_value;
487
+					}
488
+				}
489
+				$datetime_name                   = CheckinsCSV::getDatetimeLabel($datetime);
490
+				$reg_csv_array[ $datetime_name ] = implode(' --- ', $checkins);
491
+			} elseif ($event_id) {
492
+				// get whether or not the user has checked in
493
+				$reg_csv_array[ esc_html__('Event Check-ins #', 'event_espresso') ] =
494
+					$reg_model->count_related(
495
+						$reg_row['Registration.REG_ID'],
496
+						'Checkin'
497
+					);
498
+
499
+				$datetimes = $date_model->get_all(
500
+					[
501
+						[
502
+							'Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID'],
503
+						],
504
+						'order_by'                 => ['DTT_EVT_start' => 'ASC'],
505
+						'default_where_conditions' => 'none',
506
+					]
507
+				);
508
+				foreach ($datetimes as $datetime) {
509
+					if (! $datetime instanceof EE_Datetime) {
510
+						continue;
511
+					}
512
+
513
+					/** @var EE_Checkin $checkin_row */
514
+					$checkin_row = EEM_Checkin::instance()->get_one(
515
+						[
516
+							[
517
+								'REG_ID' => $reg_row['Registration.REG_ID'],
518
+								'DTT_ID' => $datetime->get('DTT_ID'),
519
+							],
520
+							'limit'    => 1,
521
+							'order_by' => [
522
+								'CHK_ID' => 'DESC'
523
+							]
524
+						]
525
+					);
526
+
527
+					$checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
528
+					$datetime_name = CheckinsCSV::getDatetimeLabel($datetime);
529
+
530
+					$reg_csv_array[ $datetime_name ] = $checkin_value;
531
+				}
532
+			}
533
+			/**
534
+			 * Filter to change the contents of each row of the registrations report CSV file.
535
+			 * This can be used to add or remote columns from the CSV file, or change their values.
536
+			 * Note when using: all rows in the CSV should have the same columns.
537
+			 *
538
+			 * @param array $reg_csv_array keys are the column names, values are their cell values
539
+			 * @param array $reg_row       one entry from EEM_Registration::get_all_wpdb_results()
540
+			 */
541
+			$registrations_csv_ready_array[] = apply_filters(
542
+				'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array',
543
+				$reg_csv_array,
544
+				$reg_row
545
+			);
546
+		}
547
+		// if we couldn't export anything, we want to at least show the column headers
548
+		if (empty($registrations_csv_ready_array)) {
549
+			$reg_csv_array               = [];
550
+			$model_and_fields_to_include = [
551
+				'Registration' => $reg_fields_to_include,
552
+				'Attendee'     => $att_fields_to_include,
553
+			];
554
+			foreach ($model_and_fields_to_include as $model_name => $field_list) {
555
+				$model = EE_Registry::instance()->load_model($model_name);
556
+				foreach ($field_list as $field_name) {
557
+					$field                                                          =
558
+						$model->field_settings_for($field_name);
559
+					$reg_csv_array[ EEH_Export::get_column_name_for_field($field) ] = null;
560
+				}
561
+			}
562
+			$registrations_csv_ready_array[] = $reg_csv_array;
563
+		}
564
+		return $registrations_csv_ready_array;
565
+	}
566
+
567
+
568
+	/**
569
+	 * Counts total unit to process
570
+	 *
571
+	 * @param array $query_params
572
+	 * @return int
573
+	 * @throws EE_Error
574
+	 * @throws ReflectionException
575
+	 */
576
+	public function count_units_to_process(array $query_params): int
577
+	{
578
+		return EEM_Registration::instance()->count(
579
+			array_diff_key(
580
+				$query_params,
581
+				array_flip(
582
+					['limit']
583
+				)
584
+			)
585
+		);
586
+	}
587
+
588
+
589
+	/**
590
+	 * Performs any clean-up logic when we know the job is completed.
591
+	 * In this case, we delete the temporary file
592
+	 *
593
+	 * @param JobParameters $job_parameters
594
+	 * @return JobStepResponse
595
+	 */
596
+	public function cleanup_job(JobParameters $job_parameters)
597
+	{
598
+		$this->updateText(esc_html__('File Generation complete and downloaded', 'event_espresso'));
599
+
600
+		$this->_file_helper->delete(
601
+			EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
602
+			true,
603
+			'd'
604
+		);
605
+		$this->updateText(esc_html__('Cleaned up temporary file', 'event_espresso'));
606
+		$this->updateText(
607
+			$this->infoWrapper(
608
+				sprintf(
609
+					esc_html__(
610
+						'If not automatically redirected in %1$s seconds, click here to return to the %2$sRegistrations List Table%3$s',
611
+						'event_espresso'
612
+					),
613
+					'<span id="ee-redirect-timer">10</span>',
614
+					'<a href="' . $job_parameters->request_datum('return_url') . '">',
615
+					'</a>'
616
+				)
617
+			)
618
+		);
619
+		return new JobStepResponse($job_parameters, $this->feedback);
620
+	}
621 621
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -59,7 +59,7 @@  discard block
 block discarded – undo
59 59
     {
60 60
         $event_id = absint($job_parameters->request_datum('EVT_ID', '0'));
61 61
         $DTT_ID   = absint($job_parameters->request_datum('DTT_ID', '0'));
62
-        if (! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
62
+        if ( ! EE_Capabilities::instance()->current_user_can('ee_read_registrations', 'generating_report')) {
63 63
             throw new BatchRequestException(
64 64
                 esc_html__('You do not have permission to view registrations', 'event_espresso')
65 65
             );
@@ -104,7 +104,7 @@  discard block
 block discarded – undo
104 104
             }
105 105
         }
106 106
 
107
-        if (! isset($query_params['force_join'])) {
107
+        if ( ! isset($query_params['force_join'])) {
108 108
             $query_params['force_join'] = ['Event', 'Transaction', 'Ticket', 'Attendee'];
109 109
         }
110 110
         $job_parameters->add_extra_data('query_params', $query_params);
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
         // so let's blank out all of the values for that first row
126 126
         array_walk(
127 127
             $csv_data_for_row[0],
128
-            function (&$value) {
128
+            function(&$value) {
129 129
                 $value = null;
130 130
             }
131 131
         );
@@ -205,11 +205,11 @@  discard block
 block discarded – undo
205 205
         $question_where_params = [];
206 206
         foreach ($reg_where_params as $key => $val) {
207 207
             if (EEM_Registration::instance()->is_logic_query_param_key($key)) {
208
-                $question_where_params[ $key ] =
208
+                $question_where_params[$key] =
209 209
                     $this->_change_registration_where_params_to_question_where_params($val);
210 210
             } else {
211 211
                 // it's a normal where condition
212
-                $question_where_params[ 'Question_Group.Event.Registration.' . $key ] = $val;
212
+                $question_where_params['Question_Group.Event.Registration.'.$key] = $val;
213 213
             }
214 214
         }
215 215
         return $question_where_params;
@@ -321,22 +321,22 @@  discard block
 block discarded – undo
321 321
         $registration_rows             = $reg_model->get_all_wpdb_results($query_params);
322 322
 
323 323
         foreach ($registration_rows as $reg_row) {
324
-            if (! is_array($reg_row)) {
324
+            if ( ! is_array($reg_row)) {
325 325
                 continue;
326 326
             }
327 327
             $reg_csv_array = [];
328 328
             // registration ID
329 329
             $reg_id_field = $reg_model->field_settings_for('REG_ID');
330
-            $reg_csv_array[ EEH_Export::get_column_name_for_field($reg_id_field) ] =
330
+            $reg_csv_array[EEH_Export::get_column_name_for_field($reg_id_field)] =
331 331
                 EEH_Export::prepare_value_from_db_for_display(
332 332
                     $reg_model,
333 333
                     'REG_ID',
334
-                    $reg_row[ $reg_id_field->get_qualified_column() ]
334
+                    $reg_row[$reg_id_field->get_qualified_column()]
335 335
                 );
336 336
             // ALL registrations, or is list filtered to just one?
337
-            if (! $event_id) {
337
+            if ( ! $event_id) {
338 338
                 // ALL registrations, so get each event's name and ID
339
-                $reg_csv_array[ esc_html__('Event', 'event_espresso') ] = sprintf(
339
+                $reg_csv_array[esc_html__('Event', 'event_espresso')] = sprintf(
340 340
                     /* translators: 1: event name, 2: event ID */
341 341
                     esc_html__('%1$s (%2$s)', 'event_espresso'),
342 342
                     EEH_Export::prepare_value_from_db_for_display(
@@ -362,12 +362,12 @@  discard block
 block discarded – undo
362 362
             );
363 363
             $is_primary_reg = $reg_row['Registration.REG_count'] == '1';
364 364
 
365
-            $reg_csv_array[ esc_html__('Registration Status', 'event_espresso') ] =
366
-                $stati[ $reg_row['Registration.STS_ID'] ];
365
+            $reg_csv_array[esc_html__('Registration Status', 'event_espresso')] =
366
+                $stati[$reg_row['Registration.STS_ID']];
367 367
             // get pretty transaction status
368
-            $reg_csv_array[ esc_html__('Transaction Status', 'event_espresso') ]     =
369
-                $stati[ $reg_row['TransactionTable.STS_ID'] ];
370
-            $reg_csv_array[ esc_html__('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg
368
+            $reg_csv_array[esc_html__('Transaction Status', 'event_espresso')]     =
369
+                $stati[$reg_row['TransactionTable.STS_ID']];
370
+            $reg_csv_array[esc_html__('Transaction Amount Due', 'event_espresso')] = $is_primary_reg
371 371
                 ? EEH_Export::prepare_value_from_db_for_display(
372 372
                     $txn_model,
373 373
                     'TXN_total',
@@ -376,7 +376,7 @@  discard block
 block discarded – undo
376 376
                 )
377 377
                 : '0.00';
378 378
 
379
-            $reg_csv_array[ esc_html__('Amount Paid', 'event_espresso') ]            = $is_primary_reg
379
+            $reg_csv_array[esc_html__('Amount Paid', 'event_espresso')] = $is_primary_reg
380 380
                 ? EEH_Export::prepare_value_from_db_for_display(
381 381
                     $txn_model,
382 382
                     'TXN_paid',
@@ -405,17 +405,17 @@  discard block
 block discarded – undo
405 405
                 );
406 406
             }
407 407
 
408
-            $reg_csv_array[ esc_html__('Payment Date(s)', 'event_espresso') ] = implode(
408
+            $reg_csv_array[esc_html__('Payment Date(s)', 'event_espresso')] = implode(
409 409
                 ',',
410 410
                 $payment_times
411 411
             );
412 412
 
413
-            $reg_csv_array[ esc_html__('Payment Method(s)', 'event_espresso') ] = implode(
413
+            $reg_csv_array[esc_html__('Payment Method(s)', 'event_espresso')] = implode(
414 414
                 ',',
415 415
                 $payment_methods
416 416
             );
417 417
 
418
-            $reg_csv_array[ esc_html__('Gateway Transaction ID(s)', 'event_espresso') ] = implode(
418
+            $reg_csv_array[esc_html__('Gateway Transaction ID(s)', 'event_espresso')] = implode(
419 419
                 ',',
420 420
                 $gateway_txn_ids_etc
421 421
             );
@@ -423,7 +423,7 @@  discard block
 block discarded – undo
423 423
             $ticket_name      = esc_html__('Unknown', 'event_espresso');
424 424
             $datetime_strings = [esc_html__('Unknown', 'event_espresso')];
425 425
             if ($reg_row['Ticket.TKT_ID']) {
426
-                $ticket_name       = EEH_Export::prepare_value_from_db_for_display(
426
+                $ticket_name = EEH_Export::prepare_value_from_db_for_display(
427 427
                     $ticket_model,
428 428
                     'TKT_name',
429 429
                     $reg_row['Ticket.TKT_name']
@@ -445,10 +445,10 @@  discard block
 block discarded – undo
445 445
                 }
446 446
             }
447 447
 
448
-            $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name;
448
+            $reg_csv_array[$ticket_model->field_settings_for('TKT_name')->get_nicename()] = $ticket_name;
449 449
 
450 450
 
451
-            $reg_csv_array[ esc_html__('Ticket Datetimes', 'event_espresso') ] = implode(
451
+            $reg_csv_array[esc_html__('Ticket Datetimes', 'event_espresso')] = implode(
452 452
                 ', ',
453 453
                 $datetime_strings
454 454
             );
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
             // Include check-in data
459 459
             if ($event_id && $DTT_ID) {
460 460
                 // get whether or not the user has checked in
461
-                $reg_csv_array[ esc_html__('Datetime Check-ins #', 'event_espresso') ] =
461
+                $reg_csv_array[esc_html__('Datetime Check-ins #', 'event_espresso')] =
462 462
                     $reg_model->count_related(
463 463
                         $reg_row['Registration.REG_ID'],
464 464
                         'Checkin',
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
                         ],
479 479
                     ]
480 480
                 );
481
-                $checkins     = [];
481
+                $checkins = [];
482 482
                 foreach ($checkin_rows as $checkin_row) {
483 483
                     /** @var EE_Checkin $checkin_row */
484 484
                     $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
@@ -487,10 +487,10 @@  discard block
 block discarded – undo
487 487
                     }
488 488
                 }
489 489
                 $datetime_name                   = CheckinsCSV::getDatetimeLabel($datetime);
490
-                $reg_csv_array[ $datetime_name ] = implode(' --- ', $checkins);
490
+                $reg_csv_array[$datetime_name] = implode(' --- ', $checkins);
491 491
             } elseif ($event_id) {
492 492
                 // get whether or not the user has checked in
493
-                $reg_csv_array[ esc_html__('Event Check-ins #', 'event_espresso') ] =
493
+                $reg_csv_array[esc_html__('Event Check-ins #', 'event_espresso')] =
494 494
                     $reg_model->count_related(
495 495
                         $reg_row['Registration.REG_ID'],
496 496
                         'Checkin'
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
                     ]
507 507
                 );
508 508
                 foreach ($datetimes as $datetime) {
509
-                    if (! $datetime instanceof EE_Datetime) {
509
+                    if ( ! $datetime instanceof EE_Datetime) {
510 510
                         continue;
511 511
                     }
512 512
 
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
                     $checkin_value = CheckinsCSV::getCheckinValue($checkin_row);
528 528
                     $datetime_name = CheckinsCSV::getDatetimeLabel($datetime);
529 529
 
530
-                    $reg_csv_array[ $datetime_name ] = $checkin_value;
530
+                    $reg_csv_array[$datetime_name] = $checkin_value;
531 531
                 }
532 532
             }
533 533
             /**
@@ -556,7 +556,7 @@  discard block
 block discarded – undo
556 556
                 foreach ($field_list as $field_name) {
557 557
                     $field                                                          =
558 558
                         $model->field_settings_for($field_name);
559
-                    $reg_csv_array[ EEH_Export::get_column_name_for_field($field) ] = null;
559
+                    $reg_csv_array[EEH_Export::get_column_name_for_field($field)] = null;
560 560
                 }
561 561
             }
562 562
             $registrations_csv_ready_array[] = $reg_csv_array;
@@ -611,7 +611,7 @@  discard block
 block discarded – undo
611 611
                         'event_espresso'
612 612
                     ),
613 613
                     '<span id="ee-redirect-timer">10</span>',
614
-                    '<a href="' . $job_parameters->request_datum('return_url') . '">',
614
+                    '<a href="'.$job_parameters->request_datum('return_url').'">',
615 615
                     '</a>'
616 616
                 )
617 617
             )
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4180 added lines, -4180 removed lines patch added patch discarded remove patch
@@ -22,4264 +22,4264 @@
 block discarded – undo
22 22
  */
23 23
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
24 24
 {
25
-    /**
26
-     * @var EE_Admin_Config
27
-     */
28
-    protected $admin_config;
25
+	/**
26
+	 * @var EE_Admin_Config
27
+	 */
28
+	protected $admin_config;
29 29
 
30
-    /**
31
-     * @var LoaderInterface
32
-     */
33
-    protected $loader;
30
+	/**
31
+	 * @var LoaderInterface
32
+	 */
33
+	protected $loader;
34 34
 
35
-    /**
36
-     * @var RequestInterface
37
-     */
38
-    protected $request;
35
+	/**
36
+	 * @var RequestInterface
37
+	 */
38
+	protected $request;
39 39
 
40
-    // set in _init_page_props()
41
-    public $page_slug;
40
+	// set in _init_page_props()
41
+	public $page_slug;
42 42
 
43
-    public $page_label;
43
+	public $page_label;
44 44
 
45
-    public $page_folder;
45
+	public $page_folder;
46 46
 
47
-    // set in define_page_props()
48
-    protected $_admin_base_url;
47
+	// set in define_page_props()
48
+	protected $_admin_base_url;
49 49
 
50
-    protected $_admin_base_path;
50
+	protected $_admin_base_path;
51 51
 
52
-    protected $_admin_page_title;
52
+	protected $_admin_page_title;
53 53
 
54
-    protected $_labels;
54
+	protected $_labels;
55 55
 
56 56
 
57
-    // set early within EE_Admin_Init
58
-    protected $_wp_page_slug;
57
+	// set early within EE_Admin_Init
58
+	protected $_wp_page_slug;
59 59
 
60
-    // nav tabs
61
-    protected $_nav_tabs;
60
+	// nav tabs
61
+	protected $_nav_tabs;
62 62
 
63
-    protected $_default_nav_tab_name;
63
+	protected $_default_nav_tab_name;
64 64
 
65 65
 
66
-    // template variables (used by templates)
67
-    protected $_template_path;
66
+	// template variables (used by templates)
67
+	protected $_template_path;
68 68
 
69
-    protected $_column_template_path;
69
+	protected $_column_template_path;
70 70
 
71
-    /**
72
-     * @var array $_template_args
73
-     */
74
-    protected $_template_args = [];
71
+	/**
72
+	 * @var array $_template_args
73
+	 */
74
+	protected $_template_args = [];
75 75
 
76
-    /**
77
-     * this will hold the list table object for a given view.
78
-     *
79
-     * @var EE_Admin_List_Table $_list_table_object
80
-     */
81
-    protected $_list_table_object;
76
+	/**
77
+	 * this will hold the list table object for a given view.
78
+	 *
79
+	 * @var EE_Admin_List_Table $_list_table_object
80
+	 */
81
+	protected $_list_table_object;
82 82
 
83
-    // boolean
84
-    protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
83
+	// boolean
84
+	protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
85 85
 
86
-    protected $_routing;
86
+	protected $_routing;
87 87
 
88
-    // list table args
89
-    protected $_view;
88
+	// list table args
89
+	protected $_view;
90 90
 
91
-    protected $_views;
91
+	protected $_views;
92 92
 
93 93
 
94
-    // action => method pairs used for routing incoming requests
95
-    protected $_page_routes;
94
+	// action => method pairs used for routing incoming requests
95
+	protected $_page_routes;
96 96
 
97
-    /**
98
-     * @var array $_page_config
99
-     */
100
-    protected $_page_config;
97
+	/**
98
+	 * @var array $_page_config
99
+	 */
100
+	protected $_page_config;
101 101
 
102
-    /**
103
-     * the current page route and route config
104
-     *
105
-     * @var string $_route
106
-     */
107
-    protected $_route;
102
+	/**
103
+	 * the current page route and route config
104
+	 *
105
+	 * @var string $_route
106
+	 */
107
+	protected $_route;
108 108
 
109
-    /**
110
-     * @var string $_cpt_route
111
-     */
112
-    protected $_cpt_route;
109
+	/**
110
+	 * @var string $_cpt_route
111
+	 */
112
+	protected $_cpt_route;
113 113
 
114
-    /**
115
-     * @var array $_route_config
116
-     */
117
-    protected $_route_config;
114
+	/**
115
+	 * @var array $_route_config
116
+	 */
117
+	protected $_route_config;
118 118
 
119
-    /**
120
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
121
-     * actions.
122
-     *
123
-     * @since 4.6.x
124
-     * @var array.
125
-     */
126
-    protected $_default_route_query_args;
119
+	/**
120
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
121
+	 * actions.
122
+	 *
123
+	 * @since 4.6.x
124
+	 * @var array.
125
+	 */
126
+	protected $_default_route_query_args;
127 127
 
128
-    // set via request page and action args.
129
-    protected $_current_page;
128
+	// set via request page and action args.
129
+	protected $_current_page;
130 130
 
131
-    protected $_current_view;
131
+	protected $_current_view;
132 132
 
133
-    protected $_current_page_view_url;
133
+	protected $_current_page_view_url;
134 134
 
135
-    /**
136
-     * unprocessed value for the 'action' request param (default '')
137
-     *
138
-     * @var string
139
-     */
140
-    protected $raw_req_action = '';
135
+	/**
136
+	 * unprocessed value for the 'action' request param (default '')
137
+	 *
138
+	 * @var string
139
+	 */
140
+	protected $raw_req_action = '';
141 141
 
142
-    /**
143
-     * unprocessed value for the 'page' request param (default '')
144
-     *
145
-     * @var string
146
-     */
147
-    protected $raw_req_page = '';
148
-
149
-    /**
150
-     * sanitized request action (and nonce)
151
-     *
152
-     * @var string
153
-     */
154
-    protected $_req_action = '';
155
-
156
-    /**
157
-     * sanitized request action nonce
158
-     *
159
-     * @var string
160
-     */
161
-    protected $_req_nonce = '';
162
-
163
-    /**
164
-     * @var string
165
-     */
166
-    protected $_search_btn_label = '';
167
-
168
-    /**
169
-     * @var string
170
-     */
171
-    protected $_search_box_callback = '';
172
-
173
-    /**
174
-     * @var WP_Screen
175
-     */
176
-    protected $_current_screen;
177
-
178
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
179
-    protected $_hook_obj;
180
-
181
-    // for holding incoming request data
182
-    protected $_req_data = [];
183
-
184
-    // yes / no array for admin form fields
185
-    protected $_yes_no_values = [];
186
-
187
-    // some default things shared by all child classes
188
-    protected $_default_espresso_metaboxes = [
189
-        '_espresso_news_post_box',
190
-        '_espresso_links_post_box',
191
-        '_espresso_ratings_request',
192
-        '_espresso_sponsors_post_box',
193
-    ];
194
-
195
-    /**
196
-     * @var EE_Registry
197
-     */
198
-    protected $EE;
199
-
200
-
201
-    /**
202
-     * This is just a property that flags whether the given route is a caffeinated route or not.
203
-     *
204
-     * @var boolean
205
-     */
206
-    protected $_is_caf = false;
207
-
208
-    /**
209
-     * whether or not initializePage() has run
210
-     *
211
-     * @var boolean
212
-     */
213
-    protected $initialized = false;
214
-
215
-    /**
216
-     * @var FeatureFlags
217
-     */
218
-    protected $feature;
219
-
220
-
221
-    /**
222
-     * @var string
223
-     */
224
-    protected $class_name;
225
-
226
-    /**
227
-     * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
228
-     * then this would be the parent classname: Events_Admin_Page
229
-     *
230
-     * @var string
231
-     */
232
-    protected $base_class_name;
233
-
234
-
235
-    /**
236
-     * @Constructor
237
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
238
-     * @throws InvalidArgumentException
239
-     * @throws InvalidDataTypeException
240
-     * @throws InvalidInterfaceException
241
-     * @throws ReflectionException
242
-     */
243
-    public function __construct($routing = true)
244
-    {
245
-        $this->loader = LoaderFactory::getLoader();
246
-        $this->admin_config = $this->loader->getShared('EE_Admin_Config');
247
-        $this->feature = $this->loader->getShared(FeatureFlags::class);
248
-        $this->request = $this->loader->getShared(RequestInterface::class);
249
-        // routing enabled?
250
-        $this->_routing = $routing;
251
-
252
-        $this->class_name = get_class($this);
253
-        $this->base_class_name = strpos($this->class_name, 'Extend_') === 0
254
-            ? str_replace('Extend_', '', $this->class_name)
255
-            : '';
256
-
257
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
258
-            $this->_is_caf = true;
259
-        }
260
-        $this->_yes_no_values = [
261
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
262
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
263
-        ];
264
-        // set the _req_data property.
265
-        $this->_req_data = $this->request->requestParams();
266
-    }
267
-
268
-
269
-    /**
270
-     * @return EE_Admin_Config
271
-     */
272
-    public function adminConfig(): EE_Admin_Config
273
-    {
274
-        return $this->admin_config;
275
-    }
276
-
277
-
278
-    /**
279
-     * @return FeatureFlags
280
-     */
281
-    public function feature(): FeatureFlags
282
-    {
283
-        return $this->feature;
284
-    }
285
-
286
-
287
-    /**
288
-     * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
289
-     * for child classes that needed to set properties prior to these methods getting called,
290
-     * but also needed the parent class to have its construction completed as well.
291
-     * Bottom line is that constructors should ONLY be used for setting initial properties
292
-     * and any complex initialization logic should only run after instantiation is complete.
293
-     *
294
-     * This method gets called immediately after construction from within
295
-     *      EE_Admin_Page_Init::_initialize_admin_page()
296
-     *
297
-     * @throws EE_Error
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     * @throws ReflectionException
302
-     * @since $VID:$
303
-     */
304
-    public function initializePage()
305
-    {
306
-        if ($this->initialized) {
307
-            return;
308
-        }
309
-        // set initial page props (child method)
310
-        $this->_init_page_props();
311
-        // set global defaults
312
-        $this->_set_defaults();
313
-        // set early because incoming requests could be ajax related and we need to register those hooks.
314
-        $this->_global_ajax_hooks();
315
-        $this->_ajax_hooks();
316
-        // other_page_hooks have to be early too.
317
-        $this->_do_other_page_hooks();
318
-        // set up page dependencies
319
-        $this->_before_page_setup();
320
-        $this->_page_setup();
321
-        $this->initialized = true;
322
-    }
323
-
324
-
325
-    /**
326
-     * _init_page_props
327
-     * Child classes use to set at least the following properties:
328
-     * $page_slug.
329
-     * $page_label.
330
-     *
331
-     * @abstract
332
-     * @return void
333
-     */
334
-    abstract protected function _init_page_props();
335
-
336
-
337
-    /**
338
-     * _ajax_hooks
339
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
340
-     * Note: within the ajax callback methods.
341
-     *
342
-     * @abstract
343
-     * @return void
344
-     */
345
-    abstract protected function _ajax_hooks();
346
-
347
-
348
-    /**
349
-     * _define_page_props
350
-     * child classes define page properties in here.  Must include at least:
351
-     * $_admin_base_url = base_url for all admin pages
352
-     * $_admin_page_title = default admin_page_title for admin pages
353
-     * $_labels = array of default labels for various automatically generated elements:
354
-     *    array(
355
-     *        'buttons' => array(
356
-     *            'add' => esc_html__('label for add new button'),
357
-     *            'edit' => esc_html__('label for edit button'),
358
-     *            'delete' => esc_html__('label for delete button')
359
-     *            )
360
-     *        )
361
-     *
362
-     * @abstract
363
-     * @return void
364
-     */
365
-    abstract protected function _define_page_props();
366
-
367
-
368
-    /**
369
-     * _set_page_routes
370
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
371
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
372
-     * have a 'default' route. Here's the format
373
-     * $this->_page_routes = array(
374
-     *        'default' => array(
375
-     *            'func' => '_default_method_handling_route',
376
-     *            'args' => array('array','of','args'),
377
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
378
-     *            ajax request, backend processing)
379
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
380
-     *            headers route after.  The string you enter here should match the defined route reference for a
381
-     *            headers sent route.
382
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
383
-     *            this route.
384
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
385
-     *            checks).
386
-     *        ),
387
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
388
-     *        handling method.
389
-     *        )
390
-     * )
391
-     *
392
-     * @abstract
393
-     * @return void
394
-     */
395
-    abstract protected function _set_page_routes();
396
-
397
-
398
-    /**
399
-     * _set_page_config
400
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
401
-     * array corresponds to the page_route for the loaded page. Format:
402
-     * $this->_page_config = array(
403
-     *        'default' => array(
404
-     *            'labels' => array(
405
-     *                'buttons' => array(
406
-     *                    'add' => esc_html__('label for adding item'),
407
-     *                    'edit' => esc_html__('label for editing item'),
408
-     *                    'delete' => esc_html__('label for deleting item')
409
-     *                ),
410
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
411
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
412
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
413
-     *            _define_page_props() method
414
-     *            'nav' => array(
415
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
416
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
417
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
418
-     *                'order' => 10, //required to indicate tab position.
419
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
420
-     *                displayed then add this parameter.
421
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
422
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
423
-     *            metaboxes set for eventespresso admin pages.
424
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
425
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
426
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
427
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
428
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
429
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
430
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
431
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
432
-     *            want to display.
433
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
434
-     *                'tab_id' => array(
435
-     *                    'title' => 'tab_title',
436
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
437
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
438
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
439
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
440
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
441
-     *                    attempt to use the callback which should match the name of a method in the class
442
-     *                    ),
443
-     *                'tab2_id' => array(
444
-     *                    'title' => 'tab2 title',
445
-     *                    'filename' => 'file_name_2'
446
-     *                    'callback' => 'callback_method_for_content',
447
-     *                 ),
448
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
449
-     *            help tab area on an admin page. @return void
450
-     *
451
-     * @abstract
452
-     */
453
-    abstract protected function _set_page_config();
454
-
455
-
456
-    /**
457
-     * _add_screen_options
458
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
459
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
460
-     * to a particular view.
461
-     *
462
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
463
-     *         see also WP_Screen object documents...
464
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
465
-     * @abstract
466
-     * @return void
467
-     */
468
-    abstract protected function _add_screen_options();
469
-
470
-
471
-    /**
472
-     * _add_feature_pointers
473
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
474
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
475
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
476
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
477
-     * extended) also see:
478
-     *
479
-     * @link   http://eamann.com/tech/wordpress-portland/
480
-     * @abstract
481
-     * @return void
482
-     */
483
-    abstract protected function _add_feature_pointers();
484
-
485
-
486
-    /**
487
-     * load_scripts_styles
488
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
489
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
490
-     * scripts/styles per view by putting them in a dynamic function in this format
491
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
492
-     *
493
-     * @abstract
494
-     * @return void
495
-     */
496
-    abstract public function load_scripts_styles();
497
-
498
-
499
-    /**
500
-     * admin_init
501
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
502
-     * all pages/views loaded by child class.
503
-     *
504
-     * @abstract
505
-     * @return void
506
-     */
507
-    abstract public function admin_init();
508
-
509
-
510
-    /**
511
-     * admin_notices
512
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
513
-     * all pages/views loaded by child class.
514
-     *
515
-     * @abstract
516
-     * @return void
517
-     */
518
-    abstract public function admin_notices();
519
-
520
-
521
-    /**
522
-     * admin_footer_scripts
523
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
524
-     * will apply to all pages/views loaded by child class.
525
-     *
526
-     * @return void
527
-     */
528
-    abstract public function admin_footer_scripts();
529
-
530
-
531
-    /**
532
-     * admin_footer
533
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
534
-     * apply to all pages/views loaded by child class.
535
-     *
536
-     * @return void
537
-     */
538
-    public function admin_footer()
539
-    {
540
-    }
541
-
542
-
543
-    /**
544
-     * _global_ajax_hooks
545
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
546
-     * Note: within the ajax callback methods.
547
-     *
548
-     * @abstract
549
-     * @return void
550
-     */
551
-    protected function _global_ajax_hooks()
552
-    {
553
-        // for lazy loading of metabox content
554
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
555
-
556
-        add_action(
557
-            'wp_ajax_espresso_hide_status_change_notice',
558
-            [$this, 'hideStatusChangeNotice']
559
-        );
560
-        add_action(
561
-            'wp_ajax_nopriv_espresso_hide_status_change_notice',
562
-            [$this, 'hideStatusChangeNotice']
563
-        );
564
-    }
565
-
566
-
567
-    public function ajax_metabox_content()
568
-    {
569
-        $content_id  = $this->request->getRequestParam('contentid', '');
570
-        $content_url = $this->request->getRequestParam('contenturl', '', 'url');
571
-        EE_Admin_Page::cached_rss_display($content_id, $content_url);
572
-        wp_die();
573
-    }
574
-
575
-
576
-    public function hideStatusChangeNotice()
577
-    {
578
-        $response = [];
579
-        try {
580
-            /** @var StatusChangeNotice $status_change_notice */
581
-            $status_change_notice = $this->loader->getShared(
582
-                'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
583
-            );
584
-            $response['success'] = $status_change_notice->dismiss() > -1;
585
-        } catch (Exception $exception) {
586
-            $response['errors'] = $exception->getMessage();
587
-        }
588
-        echo wp_json_encode($response);
589
-        exit();
590
-    }
591
-
592
-
593
-    /**
594
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
595
-     *
596
-     * @return void
597
-     */
598
-    protected function _before_page_setup()
599
-    {
600
-        // default is to do nothing
601
-    }
602
-
603
-
604
-    /**
605
-     * Makes sure any things that need to be loaded early get handled.
606
-     * We also escape early here if the page requested doesn't match the object.
607
-     *
608
-     * @final
609
-     * @return void
610
-     * @throws EE_Error
611
-     * @throws InvalidArgumentException
612
-     * @throws ReflectionException
613
-     * @throws InvalidDataTypeException
614
-     * @throws InvalidInterfaceException
615
-     */
616
-    final protected function _page_setup()
617
-    {
618
-        // requires?
619
-        // admin_init stuff - global - we're setting this REALLY early
620
-        // so if EE_Admin pages have to hook into other WP pages they can.
621
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
622
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
623
-        // next verify if we need to load anything...
624
-        $this->_current_page = $this->request->getRequestParam('page', '', 'key');
625
-        $this->page_folder   = strtolower(
626
-            str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
627
-        );
628
-        global $ee_menu_slugs;
629
-        $ee_menu_slugs = (array) $ee_menu_slugs;
630
-        if (
631
-            ! $this->request->isAjax()
632
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
633
-        ) {
634
-            return;
635
-        }
636
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
637
-        // we need to copy the action from the second to the first
638
-        $action     = $this->request->getRequestParam('action', '-1', 'key');
639
-        $action2    = $this->request->getRequestParam('action2', '-1', 'key');
640
-        $action     = $action !== '-1' ? $action : $action2;
641
-        $req_action = $action !== '-1' ? $action : 'default';
642
-
643
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
644
-        // then let's use the route as the action.
645
-        // This covers cases where we're coming in from a list table that isn't on the default route.
646
-        $route = $this->request->getRequestParam('route');
647
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
648
-            ? $route
649
-            : $req_action;
650
-
651
-        $this->_current_view = $this->_req_action;
652
-        $this->_req_nonce    = $this->_req_action . '_nonce';
653
-        $this->_define_page_props();
654
-        $this->_current_page_view_url = add_query_arg(
655
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
656
-            $this->_admin_base_url
657
-        );
658
-        // set page configs
659
-        $this->_set_page_routes();
660
-        $this->_set_page_config();
661
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
662
-        if ($this->request->requestParamIsSet('wp_referer')) {
663
-            $wp_referer = $this->request->getRequestParam('wp_referer');
664
-            if ($wp_referer) {
665
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
666
-            }
667
-        }
668
-        // for caffeinated and other extended functionality.
669
-        //  If there is a _extend_page_config method
670
-        // then let's run that to modify the all the various page configuration arrays
671
-        if (method_exists($this, '_extend_page_config')) {
672
-            $this->_extend_page_config();
673
-        }
674
-        // for CPT and other extended functionality.
675
-        // If there is an _extend_page_config_for_cpt
676
-        // then let's run that to modify all the various page configuration arrays.
677
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
678
-            $this->_extend_page_config_for_cpt();
679
-        }
680
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
681
-        $this->_page_routes = apply_filters(
682
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
683
-            $this->_page_routes,
684
-            $this
685
-        );
686
-        $this->_page_config = apply_filters(
687
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
688
-            $this->_page_config,
689
-            $this
690
-        );
691
-        if ($this->base_class_name !== '') {
692
-            $this->_page_routes = apply_filters(
693
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
694
-                $this->_page_routes,
695
-                $this
696
-            );
697
-            $this->_page_config = apply_filters(
698
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
699
-                $this->_page_config,
700
-                $this
701
-            );
702
-        }
703
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
706
-            add_action(
707
-                'AHEE__EE_Admin_Page__route_admin_request',
708
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
709
-                10,
710
-                2
711
-            );
712
-        }
713
-        // next route only if routing enabled
714
-        if ($this->_routing && ! $this->request->isAjax()) {
715
-            $this->_verify_routes();
716
-            // next let's just check user_access and kill if no access
717
-            $this->check_user_access();
718
-            if ($this->_is_UI_request) {
719
-                // admin_init stuff - global, all views for this page class, specific view
720
-                add_action('admin_init', [$this, 'admin_init'], 10);
721
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
723
-                }
724
-            } else {
725
-                // hijack regular WP loading and route admin request immediately
726
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
727
-                $this->route_admin_request();
728
-            }
729
-        }
730
-    }
731
-
732
-
733
-    /**
734
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
735
-     *
736
-     * @return void
737
-     * @throws EE_Error
738
-     */
739
-    private function _do_other_page_hooks()
740
-    {
741
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
742
-        foreach ($registered_pages as $page) {
743
-            // now let's setup the file name and class that should be present
744
-            $classname = str_replace('.class.php', '', $page);
745
-            // autoloaders should take care of loading file
746
-            if (! class_exists($classname)) {
747
-                $error_msg[] = sprintf(
748
-                    esc_html__(
749
-                        'Something went wrong with loading the %s admin hooks page.',
750
-                        'event_espresso'
751
-                    ),
752
-                    $page
753
-                );
754
-                $error_msg[] = $error_msg[0]
755
-                               . "\r\n"
756
-                               . sprintf(
757
-                                   esc_html__(
758
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
759
-                                       'event_espresso'
760
-                                   ),
761
-                                   $page,
762
-                                   '<br />',
763
-                                   '<strong>' . $classname . '</strong>'
764
-                               );
765
-                throw new EE_Error(implode('||', $error_msg));
766
-            }
767
-            // notice we are passing the instance of this class to the hook object.
768
-            $this->loader->getShared($classname, [$this]);
769
-        }
770
-    }
771
-
772
-
773
-    /**
774
-     * @throws ReflectionException
775
-     * @throws EE_Error
776
-     */
777
-    public function load_page_dependencies()
778
-    {
779
-        try {
780
-            $this->_load_page_dependencies();
781
-        } catch (EE_Error $e) {
782
-            $e->get_error();
783
-        }
784
-    }
785
-
786
-
787
-    /**
788
-     * load_page_dependencies
789
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
790
-     *
791
-     * @return void
792
-     * @throws DomainException
793
-     * @throws EE_Error
794
-     * @throws InvalidArgumentException
795
-     * @throws InvalidDataTypeException
796
-     * @throws InvalidInterfaceException
797
-     */
798
-    protected function _load_page_dependencies()
799
-    {
800
-        // let's set the current_screen and screen options to override what WP set
801
-        $this->_current_screen = get_current_screen();
802
-        // load admin_notices - global, page class, and view specific
803
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804
-        add_action('admin_notices', [$this, 'admin_notices'], 10);
805
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
807
-        }
808
-        // load network admin_notices - global, page class, and view specific
809
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
812
-        }
813
-        // this will save any per_page screen options if they are present
814
-        $this->_set_per_page_screen_options();
815
-        // setup list table properties
816
-        $this->_set_list_table();
817
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
818
-        // However in some cases the metaboxes will need to be added within a route handling callback.
819
-        $this->_add_registered_meta_boxes();
820
-        $this->_add_screen_columns();
821
-        // add screen options - global, page child class, and view specific
822
-        $this->_add_global_screen_options();
823
-        $this->_add_screen_options();
824
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
825
-        if (method_exists($this, $add_screen_options)) {
826
-            $this->{$add_screen_options}();
827
-        }
828
-        // add help tab(s) - set via page_config and qtips.
829
-        $this->_add_help_tabs();
830
-        $this->_add_qtips();
831
-        // add feature_pointers - global, page child class, and view specific
832
-        $this->_add_feature_pointers();
833
-        $this->_add_global_feature_pointers();
834
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
835
-        if (method_exists($this, $add_feature_pointer)) {
836
-            $this->{$add_feature_pointer}();
837
-        }
838
-        // enqueue scripts/styles - global, page class, and view specific
839
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
840
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
841
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
842
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
843
-        }
844
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
845
-        // admin_print_footer_scripts - global, page child class, and view specific.
846
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
847
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
848
-        // is a good use case. Notice the late priority we're giving these
849
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
850
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
851
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
852
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
853
-        }
854
-        // admin footer scripts
855
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
856
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
857
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
858
-            add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
859
-        }
860
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
861
-        // targeted hook
862
-        do_action(
863
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
864
-        );
865
-    }
866
-
867
-
868
-    /**
869
-     * _set_defaults
870
-     * This sets some global defaults for class properties.
871
-     */
872
-    private function _set_defaults()
873
-    {
874
-        $this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
875
-        $this->_event                = $this->_template_path = $this->_column_template_path = null;
876
-        $this->_nav_tabs             = $this->_views = $this->_page_routes = [];
877
-        $this->_page_config          = $this->_default_route_query_args = [];
878
-        $this->_default_nav_tab_name = 'overview';
879
-        // init template args
880
-        $this->_template_args = [
881
-            'admin_page_header'  => '',
882
-            'admin_page_content' => '',
883
-            'post_body_content'  => '',
884
-            'before_list_table'  => '',
885
-            'after_list_table'   => '',
886
-        ];
887
-    }
888
-
889
-
890
-    /**
891
-     * route_admin_request
892
-     *
893
-     * @return void
894
-     * @throws InvalidArgumentException
895
-     * @throws InvalidInterfaceException
896
-     * @throws InvalidDataTypeException
897
-     * @throws EE_Error
898
-     * @throws ReflectionException
899
-     * @see    _route_admin_request()
900
-     */
901
-    public function route_admin_request()
902
-    {
903
-        try {
904
-            $this->_route_admin_request();
905
-        } catch (EE_Error $e) {
906
-            $e->get_error();
907
-        }
908
-    }
909
-
910
-
911
-    public function set_wp_page_slug($wp_page_slug)
912
-    {
913
-        $this->_wp_page_slug = $wp_page_slug;
914
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
915
-        if (is_network_admin()) {
916
-            $this->_wp_page_slug .= '-network';
917
-        }
918
-    }
919
-
920
-
921
-    /**
922
-     * _verify_routes
923
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
924
-     * we know if we need to drop out.
925
-     *
926
-     * @return bool
927
-     * @throws EE_Error
928
-     */
929
-    protected function _verify_routes()
930
-    {
931
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
-        if (! $this->_current_page && ! $this->request->isAjax()) {
933
-            return false;
934
-        }
935
-        $this->_route = false;
936
-        // check that the page_routes array is not empty
937
-        if (empty($this->_page_routes)) {
938
-            // user error msg
939
-            $error_msg = sprintf(
940
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
941
-                $this->_admin_page_title
942
-            );
943
-            // developer error msg
944
-            $error_msg .= '||' . $error_msg
945
-                          . esc_html__(
946
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947
-                              'event_espresso'
948
-                          );
949
-            throw new EE_Error($error_msg);
950
-        }
951
-        // and that the requested page route exists
952
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
954
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
955
-        } else {
956
-            // user error msg
957
-            $error_msg = sprintf(
958
-                esc_html__(
959
-                    'The requested page route does not exist for the %s admin page.',
960
-                    'event_espresso'
961
-                ),
962
-                $this->_admin_page_title
963
-            );
964
-            // developer error msg
965
-            $error_msg .= '||' . $error_msg
966
-                          . sprintf(
967
-                              esc_html__(
968
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
969
-                                  'event_espresso'
970
-                              ),
971
-                              $this->_req_action
972
-                          );
973
-            throw new EE_Error($error_msg);
974
-        }
975
-        // and that a default route exists
976
-        if (! array_key_exists('default', $this->_page_routes)) {
977
-            // user error msg
978
-            $error_msg = sprintf(
979
-                esc_html__(
980
-                    'A default page route has not been set for the % admin page.',
981
-                    'event_espresso'
982
-                ),
983
-                $this->_admin_page_title
984
-            );
985
-            // developer error msg
986
-            $error_msg .= '||' . $error_msg
987
-                          . esc_html__(
988
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989
-                              'event_espresso'
990
-                          );
991
-            throw new EE_Error($error_msg);
992
-        }
993
-
994
-        // first lets' catch if the UI request has EVER been set.
995
-        if ($this->_is_UI_request === null) {
996
-            // lets set if this is a UI request or not.
997
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
998
-            // wait a minute... we might have a noheader in the route array
999
-            $this->_is_UI_request = ! (
1000
-                is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
1001
-            )
1002
-                ? $this->_is_UI_request
1003
-                : false;
1004
-        }
1005
-        $this->_set_current_labels();
1006
-        return true;
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1012
-     *
1013
-     * @param string $route the route name we're verifying
1014
-     * @return bool we'll throw an exception if this isn't a valid route.
1015
-     * @throws EE_Error
1016
-     */
1017
-    protected function _verify_route($route)
1018
-    {
1019
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
1020
-            return true;
1021
-        }
1022
-        // user error msg
1023
-        $error_msg = sprintf(
1024
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1025
-            $this->_admin_page_title
1026
-        );
1027
-        // developer error msg
1028
-        $error_msg .= '||' . $error_msg
1029
-                      . sprintf(
1030
-                          esc_html__(
1031
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1032
-                              'event_espresso'
1033
-                          ),
1034
-                          $route
1035
-                      );
1036
-        throw new EE_Error($error_msg);
1037
-    }
1038
-
1039
-
1040
-    /**
1041
-     * perform nonce verification
1042
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1043
-     * using this method (and save retyping!)
1044
-     *
1045
-     * @param string $nonce     The nonce sent
1046
-     * @param string $nonce_ref The nonce reference string (name0)
1047
-     * @return void
1048
-     * @throws EE_Error
1049
-     * @throws InvalidArgumentException
1050
-     * @throws InvalidDataTypeException
1051
-     * @throws InvalidInterfaceException
1052
-     */
1053
-    protected function _verify_nonce($nonce, $nonce_ref)
1054
-    {
1055
-        // verify nonce against expected value
1056
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1057
-            // these are not the droids you are looking for !!!
1058
-            $msg = sprintf(
1059
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
1060
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1061
-                '</a>'
1062
-            );
1063
-            if (WP_DEBUG) {
1064
-                $msg .= "\n  ";
1065
-                $msg .= sprintf(
1066
-                    esc_html__(
1067
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1068
-                        'event_espresso'
1069
-                    ),
1070
-                    __CLASS__
1071
-                );
1072
-            }
1073
-            if (! $this->request->isAjax()) {
1074
-                wp_die($msg);
1075
-            }
1076
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
-            $this->_return_json();
1078
-        }
1079
-    }
1080
-
1081
-
1082
-    /**
1083
-     * _route_admin_request()
1084
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1085
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1086
-     * in the page routes and then will try to load the corresponding method.
1087
-     *
1088
-     * @return void
1089
-     * @throws EE_Error
1090
-     * @throws InvalidArgumentException
1091
-     * @throws InvalidDataTypeException
1092
-     * @throws InvalidInterfaceException
1093
-     * @throws ReflectionException
1094
-     */
1095
-    protected function _route_admin_request()
1096
-    {
1097
-        if (! $this->_is_UI_request) {
1098
-            $this->_verify_routes();
1099
-        }
1100
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1101
-        if ($this->_req_action !== 'default' && $nonce_check) {
1102
-            // set nonce from post data
1103
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
1104
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1105
-        }
1106
-        // set the nav_tabs array but ONLY if this is  UI_request
1107
-        if ($this->_is_UI_request) {
1108
-            $this->_set_nav_tabs();
1109
-        }
1110
-        // grab callback function
1111
-        $func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1112
-        // check if callback has args
1113
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1114
-        $error_msg = '';
1115
-        // action right before calling route
1116
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119
-        }
1120
-        // strip _wp_http_referer from the server REQUEST_URI
1121
-        // else it grows in length on every submission due to recursion,
1122
-        // ultimately causing a "Request-URI Too Large" error
1123
-        $request_uri = remove_query_arg(
1124
-            '_wp_http_referer',
1125
-            wp_unslash($this->request->getServerParam('REQUEST_URI'))
1126
-        );
1127
-        // set new value in both our Request object and the super global
1128
-        $this->request->setServerParam('REQUEST_URI', $request_uri, true);
1129
-        if (! empty($func)) {
1130
-            if (is_array($func)) {
1131
-                [$class, $method] = $func;
1132
-            } elseif (strpos($func, '::') !== false) {
1133
-                [$class, $method] = explode('::', $func);
1134
-            } else {
1135
-                $class  = $this;
1136
-                $method = $func;
1137
-            }
1138
-            if (! (is_object($class) && $class === $this)) {
1139
-                // send along this admin page object for access by addons.
1140
-                $args['admin_page_object'] = $this;
1141
-            }
1142
-            if (
1143
-                // is it a method on a class that doesn't work?
1144
-                (
1145
-                    (
1146
-                        method_exists($class, $method)
1147
-                        && call_user_func_array([$class, $method], $args) === false
1148
-                    )
1149
-                    && (
1150
-                        // is it a standalone function that doesn't work?
1151
-                        function_exists($method)
1152
-                        && call_user_func_array(
1153
-                            $func,
1154
-                            array_merge(['admin_page_object' => $this], $args)
1155
-                        ) === false
1156
-                    )
1157
-                )
1158
-                || (
1159
-                    // is it neither a class method NOR a standalone function?
1160
-                    ! method_exists($class, $method)
1161
-                    && ! function_exists($method)
1162
-                )
1163
-            ) {
1164
-                // user error msg
1165
-                $error_msg = esc_html__(
1166
-                    'An error occurred. The  requested page route could not be found.',
1167
-                    'event_espresso'
1168
-                );
1169
-                // developer error msg
1170
-                $error_msg .= '||';
1171
-                $error_msg .= sprintf(
1172
-                    esc_html__(
1173
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1174
-                        'event_espresso'
1175
-                    ),
1176
-                    $method
1177
-                );
1178
-            }
1179
-            if (! empty($error_msg)) {
1180
-                throw new EE_Error($error_msg);
1181
-            }
1182
-        }
1183
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1184
-        // then we need to reset the routing properties to the new route.
1185
-        // 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.
1186
-        if (
1187
-            $this->_is_UI_request === false
1188
-            && is_array($this->_route)
1189
-            && ! empty($this->_route['headers_sent_route'])
1190
-        ) {
1191
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1192
-        }
1193
-    }
1194
-
1195
-
1196
-    /**
1197
-     * This method just allows the resetting of page properties in the case where a no headers
1198
-     * route redirects to a headers route in its route config.
1199
-     *
1200
-     * @param string $new_route New (non header) route to redirect to.
1201
-     * @return   void
1202
-     * @throws ReflectionException
1203
-     * @throws InvalidArgumentException
1204
-     * @throws InvalidInterfaceException
1205
-     * @throws InvalidDataTypeException
1206
-     * @throws EE_Error
1207
-     * @since   4.3.0
1208
-     */
1209
-    protected function _reset_routing_properties($new_route)
1210
-    {
1211
-        $this->_is_UI_request = true;
1212
-        // now we set the current route to whatever the headers_sent_route is set at
1213
-        $this->request->setRequestParam('action', $new_route);
1214
-        // rerun page setup
1215
-        $this->_page_setup();
1216
-    }
1217
-
1218
-
1219
-    /**
1220
-     * _add_query_arg
1221
-     * adds nonce to array of arguments then calls WP add_query_arg function
1222
-     *(internally just uses EEH_URL's function with the same name)
1223
-     *
1224
-     * @param array  $args
1225
-     * @param string $url
1226
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1227
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1228
-     *                                        Example usage: If the current page is:
1229
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1230
-     *                                        &action=default&event_id=20&month_range=March%202015
1231
-     *                                        &_wpnonce=5467821
1232
-     *                                        and you call:
1233
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1234
-     *                                        array(
1235
-     *                                        'action' => 'resend_something',
1236
-     *                                        'page=>espresso_registrations'
1237
-     *                                        ),
1238
-     *                                        $some_url,
1239
-     *                                        true
1240
-     *                                        );
1241
-     *                                        It will produce a url in this structure:
1242
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1243
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1244
-     *                                        month_range]=March%202015
1245
-     * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1246
-     * @return string
1247
-     */
1248
-    public static function add_query_args_and_nonce(
1249
-        $args = [],
1250
-        $url = '',
1251
-        $sticky = false,
1252
-        $exclude_nonce = false
1253
-    ) {
1254
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1255
-        if ($sticky) {
1256
-            /** @var RequestInterface $request */
1257
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1258
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1259
-            $request->unSetServerParam('_wp_http_referer', true);
1260
-            foreach ($request->requestParams() as $key => $value) {
1261
-                // do not add nonces
1262
-                if (strpos($key, 'nonce') !== false) {
1263
-                    continue;
1264
-                }
1265
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1266
-            }
1267
-        }
1268
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     * This returns a generated link that will load the related help tab.
1274
-     *
1275
-     * @param string $help_tab_id the id for the connected help tab
1276
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1277
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1278
-     * @return string              generated link
1279
-     * @uses EEH_Template::get_help_tab_link()
1280
-     */
1281
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1282
-    {
1283
-        return EEH_Template::get_help_tab_link(
1284
-            $help_tab_id,
1285
-            $this->page_slug,
1286
-            $this->_req_action,
1287
-            $icon_style,
1288
-            $help_text
1289
-        );
1290
-    }
1291
-
1292
-
1293
-    /**
1294
-     * _add_help_tabs
1295
-     * Note child classes define their help tabs within the page_config array.
1296
-     *
1297
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1298
-     * @return void
1299
-     * @throws DomainException
1300
-     * @throws EE_Error
1301
-     * @throws ReflectionException
1302
-     */
1303
-    protected function _add_help_tabs()
1304
-    {
1305
-        if (isset($this->_page_config[ $this->_req_action ])) {
1306
-            $config = $this->_page_config[ $this->_req_action ];
1307
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1308
-            if (is_array($config) && isset($config['help_sidebar'])) {
1309
-                // check that the callback given is valid
1310
-                if (! method_exists($this, $config['help_sidebar'])) {
1311
-                    throw new EE_Error(
1312
-                        sprintf(
1313
-                            esc_html__(
1314
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1315
-                                'event_espresso'
1316
-                            ),
1317
-                            $config['help_sidebar'],
1318
-                            $this->class_name
1319
-                        )
1320
-                    );
1321
-                }
1322
-                $content = apply_filters(
1323
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1324
-                    $this->{$config['help_sidebar']}()
1325
-                );
1326
-                $this->_current_screen->set_help_sidebar($content);
1327
-            }
1328
-            if (! isset($config['help_tabs'])) {
1329
-                return;
1330
-            } //no help tabs for this route
1331
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1332
-                // we're here so there ARE help tabs!
1333
-                // make sure we've got what we need
1334
-                if (! isset($cfg['title'])) {
1335
-                    throw new EE_Error(
1336
-                        esc_html__(
1337
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1338
-                            'event_espresso'
1339
-                        )
1340
-                    );
1341
-                }
1342
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1343
-                    throw new EE_Error(
1344
-                        esc_html__(
1345
-                            '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',
1346
-                            'event_espresso'
1347
-                        )
1348
-                    );
1349
-                }
1350
-                // first priority goes to content.
1351
-                if (! empty($cfg['content'])) {
1352
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1353
-                    // second priority goes to filename
1354
-                } elseif (! empty($cfg['filename'])) {
1355
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1356
-                    // 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)
1357
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1358
-                                                             . basename($this->_get_dir())
1359
-                                                             . '/help_tabs/'
1360
-                                                             . $cfg['filename']
1361
-                                                             . '.help_tab.php' : $file_path;
1362
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1363
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1364
-                        EE_Error::add_error(
1365
-                            sprintf(
1366
-                                esc_html__(
1367
-                                    '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',
1368
-                                    'event_espresso'
1369
-                                ),
1370
-                                $tab_id,
1371
-                                key($config),
1372
-                                $file_path
1373
-                            ),
1374
-                            __FILE__,
1375
-                            __FUNCTION__,
1376
-                            __LINE__
1377
-                        );
1378
-                        return;
1379
-                    }
1380
-                    $template_args['admin_page_obj'] = $this;
1381
-                    $content                         = EEH_Template::display_template(
1382
-                        $file_path,
1383
-                        $template_args,
1384
-                        true
1385
-                    );
1386
-                } else {
1387
-                    $content = '';
1388
-                }
1389
-                // check if callback is valid
1390
-                if (
1391
-                    empty($content)
1392
-                    && (
1393
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1394
-                    )
1395
-                ) {
1396
-                    EE_Error::add_error(
1397
-                        sprintf(
1398
-                            esc_html__(
1399
-                                '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.',
1400
-                                'event_espresso'
1401
-                            ),
1402
-                            $cfg['title']
1403
-                        ),
1404
-                        __FILE__,
1405
-                        __FUNCTION__,
1406
-                        __LINE__
1407
-                    );
1408
-                    return;
1409
-                }
1410
-                // setup config array for help tab method
1411
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1412
-                $_ht = [
1413
-                    'id'       => $id,
1414
-                    'title'    => $cfg['title'],
1415
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1416
-                    'content'  => $content,
1417
-                ];
1418
-                $this->_current_screen->add_help_tab($_ht);
1419
-            }
1420
-        }
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * This simply sets up any qtips that have been defined in the page config
1426
-     *
1427
-     * @return void
1428
-     * @throws ReflectionException
1429
-     * @throws EE_Error
1430
-     */
1431
-    protected function _add_qtips()
1432
-    {
1433
-        if (isset($this->_route_config['qtips'])) {
1434
-            $qtips = (array) $this->_route_config['qtips'];
1435
-            // load qtip loader
1436
-            $path = [
1437
-                $this->_get_dir() . '/qtips/',
1438
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1439
-            ];
1440
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1441
-        }
1442
-    }
1443
-
1444
-
1445
-    /**
1446
-     * _set_nav_tabs
1447
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1448
-     * wish to add additional tabs or modify accordingly.
1449
-     *
1450
-     * @return void
1451
-     * @throws InvalidArgumentException
1452
-     * @throws InvalidInterfaceException
1453
-     * @throws InvalidDataTypeException
1454
-     */
1455
-    protected function _set_nav_tabs()
1456
-    {
1457
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1458
-        $i = 0;
1459
-        foreach ($this->_page_config as $slug => $config) {
1460
-            if (! is_array($config) || empty($config['nav'])) {
1461
-                continue;
1462
-            }
1463
-            // no nav tab for this config
1464
-            // check for persistent flag
1465
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1466
-                // nav tab is only to appear when route requested.
1467
-                continue;
1468
-            }
1469
-            if (! $this->check_user_access($slug, true)) {
1470
-                // no nav tab because current user does not have access.
1471
-                continue;
1472
-            }
1473
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1474
-            $this->_nav_tabs[ $slug ] = [
1475
-                'url'       => isset($config['nav']['url'])
1476
-                    ? $config['nav']['url']
1477
-                    : EE_Admin_Page::add_query_args_and_nonce(
1478
-                        ['action' => $slug],
1479
-                        $this->_admin_base_url
1480
-                    ),
1481
-                'link_text' => isset($config['nav']['label'])
1482
-                    ? $config['nav']['label']
1483
-                    : ucwords(
1484
-                        str_replace('_', ' ', $slug)
1485
-                    ),
1486
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1487
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1488
-            ];
1489
-            $i++;
1490
-        }
1491
-        // if $this->_nav_tabs is empty then lets set the default
1492
-        if (empty($this->_nav_tabs)) {
1493
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1494
-                'url'       => $this->_admin_base_url,
1495
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1496
-                'css_class' => 'nav-tab-active',
1497
-                'order'     => 10,
1498
-            ];
1499
-        }
1500
-        // now let's sort the tabs according to order
1501
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * _set_current_labels
1507
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1508
-     * property array
1509
-     *
1510
-     * @return void
1511
-     */
1512
-    private function _set_current_labels()
1513
-    {
1514
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1515
-            foreach ($this->_route_config['labels'] as $label => $text) {
1516
-                if (is_array($text)) {
1517
-                    foreach ($text as $sublabel => $subtext) {
1518
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1519
-                    }
1520
-                } else {
1521
-                    $this->_labels[ $label ] = $text;
1522
-                }
1523
-            }
1524
-        }
1525
-    }
1526
-
1527
-
1528
-    /**
1529
-     *        verifies user access for this admin page
1530
-     *
1531
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1532
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1533
-     *                               return false if verify fail.
1534
-     * @return bool
1535
-     * @throws InvalidArgumentException
1536
-     * @throws InvalidDataTypeException
1537
-     * @throws InvalidInterfaceException
1538
-     */
1539
-    public function check_user_access($route_to_check = '', $verify_only = false)
1540
-    {
1541
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1542
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1543
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1544
-                                      && is_array($this->_page_routes[ $route_to_check ])
1545
-                        && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1546
-            ? $this->_page_routes[ $route_to_check ]['capability']
1547
-            : null;
1548
-
1549
-        if (empty($capability) && empty($route_to_check)) {
1550
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1551
-                : $this->_route['capability'];
1552
-        } else {
1553
-            $capability = empty($capability) ? 'manage_options' : $capability;
1554
-        }
1555
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1556
-        if (
1557
-            ! $this->request->isAjax()
1558
-            && (
1559
-                ! function_exists('is_admin')
1560
-                || ! EE_Registry::instance()->CAP->current_user_can(
1561
-                    $capability,
1562
-                    $this->page_slug
1563
-                    . '_'
1564
-                    . $route_to_check,
1565
-                    $id
1566
-                )
1567
-            )
1568
-        ) {
1569
-            if ($verify_only) {
1570
-                return false;
1571
-            }
1572
-            if (is_user_logged_in()) {
1573
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1574
-            } else {
1575
-                return false;
1576
-            }
1577
-        }
1578
-        return true;
1579
-    }
1580
-
1581
-
1582
-    /**
1583
-     * @param string                 $box_id
1584
-     * @param string                 $title
1585
-     * @param callable|string|null   $callback
1586
-     * @param string|array|WP_Screen $screen
1587
-     * @param string                 $context
1588
-     * @param string                 $priority
1589
-     * @param array|null             $callback_args
1590
-     */
1591
-    protected function addMetaBox(
1592
-        string $box_id,
1593
-        string $title,
1594
-        $callback,
1595
-        $screen,
1596
-        string $context = 'normal',
1597
-        string $priority = 'default',
1598
-        ?array $callback_args = null
1599
-    ) {
1600
-        if (! is_callable($callback)) {
1601
-            return;
1602
-        }
1603
-
1604
-        add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1605
-        add_filter(
1606
-            "postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1607
-            function ($classes) {
1608
-                array_push($classes, 'ee-admin-container');
1609
-                return $classes;
1610
-            }
1611
-        );
1612
-    }
1613
-
1614
-
1615
-    /**
1616
-     * admin_init_global
1617
-     * This runs all the code that we want executed within the WP admin_init hook.
1618
-     * This method executes for ALL EE Admin pages.
1619
-     *
1620
-     * @return void
1621
-     */
1622
-    public function admin_init_global()
1623
-    {
1624
-    }
1625
-
1626
-
1627
-    /**
1628
-     * wp_loaded_global
1629
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1630
-     * EE_Admin page and will execute on every EE Admin Page load
1631
-     *
1632
-     * @return void
1633
-     */
1634
-    public function wp_loaded()
1635
-    {
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     * admin_notices
1641
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1642
-     * ALL EE_Admin pages.
1643
-     *
1644
-     * @return void
1645
-     */
1646
-    public function admin_notices_global()
1647
-    {
1648
-        $this->_display_no_javascript_warning();
1649
-        $this->_display_espresso_notices();
1650
-    }
1651
-
1652
-
1653
-    public function network_admin_notices_global()
1654
-    {
1655
-        $this->_display_no_javascript_warning();
1656
-        $this->_display_espresso_notices();
1657
-    }
1658
-
1659
-
1660
-    /**
1661
-     * admin_footer_scripts_global
1662
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1663
-     * will apply on ALL EE_Admin pages.
1664
-     *
1665
-     * @return void
1666
-     */
1667
-    public function admin_footer_scripts_global()
1668
-    {
1669
-        $this->_add_admin_page_ajax_loading_img();
1670
-        $this->_add_admin_page_overlay();
1671
-        // if metaboxes are present we need to add the nonce field
1672
-        if (
1673
-            isset($this->_route_config['metaboxes'])
1674
-            || isset($this->_route_config['list_table'])
1675
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1676
-        ) {
1677
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1678
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1679
-        }
1680
-    }
1681
-
1682
-
1683
-    /**
1684
-     * admin_footer_global
1685
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1686
-     * This particular method will apply on ALL EE_Admin Pages.
1687
-     *
1688
-     * @return void
1689
-     */
1690
-    public function admin_footer_global()
1691
-    {
1692
-        // dialog container for dialog helper
1693
-        echo '
142
+	/**
143
+	 * unprocessed value for the 'page' request param (default '')
144
+	 *
145
+	 * @var string
146
+	 */
147
+	protected $raw_req_page = '';
148
+
149
+	/**
150
+	 * sanitized request action (and nonce)
151
+	 *
152
+	 * @var string
153
+	 */
154
+	protected $_req_action = '';
155
+
156
+	/**
157
+	 * sanitized request action nonce
158
+	 *
159
+	 * @var string
160
+	 */
161
+	protected $_req_nonce = '';
162
+
163
+	/**
164
+	 * @var string
165
+	 */
166
+	protected $_search_btn_label = '';
167
+
168
+	/**
169
+	 * @var string
170
+	 */
171
+	protected $_search_box_callback = '';
172
+
173
+	/**
174
+	 * @var WP_Screen
175
+	 */
176
+	protected $_current_screen;
177
+
178
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
179
+	protected $_hook_obj;
180
+
181
+	// for holding incoming request data
182
+	protected $_req_data = [];
183
+
184
+	// yes / no array for admin form fields
185
+	protected $_yes_no_values = [];
186
+
187
+	// some default things shared by all child classes
188
+	protected $_default_espresso_metaboxes = [
189
+		'_espresso_news_post_box',
190
+		'_espresso_links_post_box',
191
+		'_espresso_ratings_request',
192
+		'_espresso_sponsors_post_box',
193
+	];
194
+
195
+	/**
196
+	 * @var EE_Registry
197
+	 */
198
+	protected $EE;
199
+
200
+
201
+	/**
202
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
203
+	 *
204
+	 * @var boolean
205
+	 */
206
+	protected $_is_caf = false;
207
+
208
+	/**
209
+	 * whether or not initializePage() has run
210
+	 *
211
+	 * @var boolean
212
+	 */
213
+	protected $initialized = false;
214
+
215
+	/**
216
+	 * @var FeatureFlags
217
+	 */
218
+	protected $feature;
219
+
220
+
221
+	/**
222
+	 * @var string
223
+	 */
224
+	protected $class_name;
225
+
226
+	/**
227
+	 * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
228
+	 * then this would be the parent classname: Events_Admin_Page
229
+	 *
230
+	 * @var string
231
+	 */
232
+	protected $base_class_name;
233
+
234
+
235
+	/**
236
+	 * @Constructor
237
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
238
+	 * @throws InvalidArgumentException
239
+	 * @throws InvalidDataTypeException
240
+	 * @throws InvalidInterfaceException
241
+	 * @throws ReflectionException
242
+	 */
243
+	public function __construct($routing = true)
244
+	{
245
+		$this->loader = LoaderFactory::getLoader();
246
+		$this->admin_config = $this->loader->getShared('EE_Admin_Config');
247
+		$this->feature = $this->loader->getShared(FeatureFlags::class);
248
+		$this->request = $this->loader->getShared(RequestInterface::class);
249
+		// routing enabled?
250
+		$this->_routing = $routing;
251
+
252
+		$this->class_name = get_class($this);
253
+		$this->base_class_name = strpos($this->class_name, 'Extend_') === 0
254
+			? str_replace('Extend_', '', $this->class_name)
255
+			: '';
256
+
257
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
258
+			$this->_is_caf = true;
259
+		}
260
+		$this->_yes_no_values = [
261
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
262
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
263
+		];
264
+		// set the _req_data property.
265
+		$this->_req_data = $this->request->requestParams();
266
+	}
267
+
268
+
269
+	/**
270
+	 * @return EE_Admin_Config
271
+	 */
272
+	public function adminConfig(): EE_Admin_Config
273
+	{
274
+		return $this->admin_config;
275
+	}
276
+
277
+
278
+	/**
279
+	 * @return FeatureFlags
280
+	 */
281
+	public function feature(): FeatureFlags
282
+	{
283
+		return $this->feature;
284
+	}
285
+
286
+
287
+	/**
288
+	 * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
289
+	 * for child classes that needed to set properties prior to these methods getting called,
290
+	 * but also needed the parent class to have its construction completed as well.
291
+	 * Bottom line is that constructors should ONLY be used for setting initial properties
292
+	 * and any complex initialization logic should only run after instantiation is complete.
293
+	 *
294
+	 * This method gets called immediately after construction from within
295
+	 *      EE_Admin_Page_Init::_initialize_admin_page()
296
+	 *
297
+	 * @throws EE_Error
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 * @throws ReflectionException
302
+	 * @since $VID:$
303
+	 */
304
+	public function initializePage()
305
+	{
306
+		if ($this->initialized) {
307
+			return;
308
+		}
309
+		// set initial page props (child method)
310
+		$this->_init_page_props();
311
+		// set global defaults
312
+		$this->_set_defaults();
313
+		// set early because incoming requests could be ajax related and we need to register those hooks.
314
+		$this->_global_ajax_hooks();
315
+		$this->_ajax_hooks();
316
+		// other_page_hooks have to be early too.
317
+		$this->_do_other_page_hooks();
318
+		// set up page dependencies
319
+		$this->_before_page_setup();
320
+		$this->_page_setup();
321
+		$this->initialized = true;
322
+	}
323
+
324
+
325
+	/**
326
+	 * _init_page_props
327
+	 * Child classes use to set at least the following properties:
328
+	 * $page_slug.
329
+	 * $page_label.
330
+	 *
331
+	 * @abstract
332
+	 * @return void
333
+	 */
334
+	abstract protected function _init_page_props();
335
+
336
+
337
+	/**
338
+	 * _ajax_hooks
339
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
340
+	 * Note: within the ajax callback methods.
341
+	 *
342
+	 * @abstract
343
+	 * @return void
344
+	 */
345
+	abstract protected function _ajax_hooks();
346
+
347
+
348
+	/**
349
+	 * _define_page_props
350
+	 * child classes define page properties in here.  Must include at least:
351
+	 * $_admin_base_url = base_url for all admin pages
352
+	 * $_admin_page_title = default admin_page_title for admin pages
353
+	 * $_labels = array of default labels for various automatically generated elements:
354
+	 *    array(
355
+	 *        'buttons' => array(
356
+	 *            'add' => esc_html__('label for add new button'),
357
+	 *            'edit' => esc_html__('label for edit button'),
358
+	 *            'delete' => esc_html__('label for delete button')
359
+	 *            )
360
+	 *        )
361
+	 *
362
+	 * @abstract
363
+	 * @return void
364
+	 */
365
+	abstract protected function _define_page_props();
366
+
367
+
368
+	/**
369
+	 * _set_page_routes
370
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
371
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
372
+	 * have a 'default' route. Here's the format
373
+	 * $this->_page_routes = array(
374
+	 *        'default' => array(
375
+	 *            'func' => '_default_method_handling_route',
376
+	 *            'args' => array('array','of','args'),
377
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
378
+	 *            ajax request, backend processing)
379
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
380
+	 *            headers route after.  The string you enter here should match the defined route reference for a
381
+	 *            headers sent route.
382
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
383
+	 *            this route.
384
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
385
+	 *            checks).
386
+	 *        ),
387
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
388
+	 *        handling method.
389
+	 *        )
390
+	 * )
391
+	 *
392
+	 * @abstract
393
+	 * @return void
394
+	 */
395
+	abstract protected function _set_page_routes();
396
+
397
+
398
+	/**
399
+	 * _set_page_config
400
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
401
+	 * array corresponds to the page_route for the loaded page. Format:
402
+	 * $this->_page_config = array(
403
+	 *        'default' => array(
404
+	 *            'labels' => array(
405
+	 *                'buttons' => array(
406
+	 *                    'add' => esc_html__('label for adding item'),
407
+	 *                    'edit' => esc_html__('label for editing item'),
408
+	 *                    'delete' => esc_html__('label for deleting item')
409
+	 *                ),
410
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
411
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
412
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
413
+	 *            _define_page_props() method
414
+	 *            'nav' => array(
415
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
416
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
417
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
418
+	 *                'order' => 10, //required to indicate tab position.
419
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
420
+	 *                displayed then add this parameter.
421
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
422
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
423
+	 *            metaboxes set for eventespresso admin pages.
424
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
425
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
426
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
427
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
428
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
429
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
430
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
431
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
432
+	 *            want to display.
433
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
434
+	 *                'tab_id' => array(
435
+	 *                    'title' => 'tab_title',
436
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
437
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
438
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
439
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
440
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
441
+	 *                    attempt to use the callback which should match the name of a method in the class
442
+	 *                    ),
443
+	 *                'tab2_id' => array(
444
+	 *                    'title' => 'tab2 title',
445
+	 *                    'filename' => 'file_name_2'
446
+	 *                    'callback' => 'callback_method_for_content',
447
+	 *                 ),
448
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
449
+	 *            help tab area on an admin page. @return void
450
+	 *
451
+	 * @abstract
452
+	 */
453
+	abstract protected function _set_page_config();
454
+
455
+
456
+	/**
457
+	 * _add_screen_options
458
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
459
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
460
+	 * to a particular view.
461
+	 *
462
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
463
+	 *         see also WP_Screen object documents...
464
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
465
+	 * @abstract
466
+	 * @return void
467
+	 */
468
+	abstract protected function _add_screen_options();
469
+
470
+
471
+	/**
472
+	 * _add_feature_pointers
473
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
474
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
475
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
476
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
477
+	 * extended) also see:
478
+	 *
479
+	 * @link   http://eamann.com/tech/wordpress-portland/
480
+	 * @abstract
481
+	 * @return void
482
+	 */
483
+	abstract protected function _add_feature_pointers();
484
+
485
+
486
+	/**
487
+	 * load_scripts_styles
488
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
489
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
490
+	 * scripts/styles per view by putting them in a dynamic function in this format
491
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
492
+	 *
493
+	 * @abstract
494
+	 * @return void
495
+	 */
496
+	abstract public function load_scripts_styles();
497
+
498
+
499
+	/**
500
+	 * admin_init
501
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
502
+	 * all pages/views loaded by child class.
503
+	 *
504
+	 * @abstract
505
+	 * @return void
506
+	 */
507
+	abstract public function admin_init();
508
+
509
+
510
+	/**
511
+	 * admin_notices
512
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
513
+	 * all pages/views loaded by child class.
514
+	 *
515
+	 * @abstract
516
+	 * @return void
517
+	 */
518
+	abstract public function admin_notices();
519
+
520
+
521
+	/**
522
+	 * admin_footer_scripts
523
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
524
+	 * will apply to all pages/views loaded by child class.
525
+	 *
526
+	 * @return void
527
+	 */
528
+	abstract public function admin_footer_scripts();
529
+
530
+
531
+	/**
532
+	 * admin_footer
533
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
534
+	 * apply to all pages/views loaded by child class.
535
+	 *
536
+	 * @return void
537
+	 */
538
+	public function admin_footer()
539
+	{
540
+	}
541
+
542
+
543
+	/**
544
+	 * _global_ajax_hooks
545
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
546
+	 * Note: within the ajax callback methods.
547
+	 *
548
+	 * @abstract
549
+	 * @return void
550
+	 */
551
+	protected function _global_ajax_hooks()
552
+	{
553
+		// for lazy loading of metabox content
554
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
555
+
556
+		add_action(
557
+			'wp_ajax_espresso_hide_status_change_notice',
558
+			[$this, 'hideStatusChangeNotice']
559
+		);
560
+		add_action(
561
+			'wp_ajax_nopriv_espresso_hide_status_change_notice',
562
+			[$this, 'hideStatusChangeNotice']
563
+		);
564
+	}
565
+
566
+
567
+	public function ajax_metabox_content()
568
+	{
569
+		$content_id  = $this->request->getRequestParam('contentid', '');
570
+		$content_url = $this->request->getRequestParam('contenturl', '', 'url');
571
+		EE_Admin_Page::cached_rss_display($content_id, $content_url);
572
+		wp_die();
573
+	}
574
+
575
+
576
+	public function hideStatusChangeNotice()
577
+	{
578
+		$response = [];
579
+		try {
580
+			/** @var StatusChangeNotice $status_change_notice */
581
+			$status_change_notice = $this->loader->getShared(
582
+				'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
583
+			);
584
+			$response['success'] = $status_change_notice->dismiss() > -1;
585
+		} catch (Exception $exception) {
586
+			$response['errors'] = $exception->getMessage();
587
+		}
588
+		echo wp_json_encode($response);
589
+		exit();
590
+	}
591
+
592
+
593
+	/**
594
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
595
+	 *
596
+	 * @return void
597
+	 */
598
+	protected function _before_page_setup()
599
+	{
600
+		// default is to do nothing
601
+	}
602
+
603
+
604
+	/**
605
+	 * Makes sure any things that need to be loaded early get handled.
606
+	 * We also escape early here if the page requested doesn't match the object.
607
+	 *
608
+	 * @final
609
+	 * @return void
610
+	 * @throws EE_Error
611
+	 * @throws InvalidArgumentException
612
+	 * @throws ReflectionException
613
+	 * @throws InvalidDataTypeException
614
+	 * @throws InvalidInterfaceException
615
+	 */
616
+	final protected function _page_setup()
617
+	{
618
+		// requires?
619
+		// admin_init stuff - global - we're setting this REALLY early
620
+		// so if EE_Admin pages have to hook into other WP pages they can.
621
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
622
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
623
+		// next verify if we need to load anything...
624
+		$this->_current_page = $this->request->getRequestParam('page', '', 'key');
625
+		$this->page_folder   = strtolower(
626
+			str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
627
+		);
628
+		global $ee_menu_slugs;
629
+		$ee_menu_slugs = (array) $ee_menu_slugs;
630
+		if (
631
+			! $this->request->isAjax()
632
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
633
+		) {
634
+			return;
635
+		}
636
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
637
+		// we need to copy the action from the second to the first
638
+		$action     = $this->request->getRequestParam('action', '-1', 'key');
639
+		$action2    = $this->request->getRequestParam('action2', '-1', 'key');
640
+		$action     = $action !== '-1' ? $action : $action2;
641
+		$req_action = $action !== '-1' ? $action : 'default';
642
+
643
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
644
+		// then let's use the route as the action.
645
+		// This covers cases where we're coming in from a list table that isn't on the default route.
646
+		$route = $this->request->getRequestParam('route');
647
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
648
+			? $route
649
+			: $req_action;
650
+
651
+		$this->_current_view = $this->_req_action;
652
+		$this->_req_nonce    = $this->_req_action . '_nonce';
653
+		$this->_define_page_props();
654
+		$this->_current_page_view_url = add_query_arg(
655
+			['page' => $this->_current_page, 'action' => $this->_current_view],
656
+			$this->_admin_base_url
657
+		);
658
+		// set page configs
659
+		$this->_set_page_routes();
660
+		$this->_set_page_config();
661
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
662
+		if ($this->request->requestParamIsSet('wp_referer')) {
663
+			$wp_referer = $this->request->getRequestParam('wp_referer');
664
+			if ($wp_referer) {
665
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
666
+			}
667
+		}
668
+		// for caffeinated and other extended functionality.
669
+		//  If there is a _extend_page_config method
670
+		// then let's run that to modify the all the various page configuration arrays
671
+		if (method_exists($this, '_extend_page_config')) {
672
+			$this->_extend_page_config();
673
+		}
674
+		// for CPT and other extended functionality.
675
+		// If there is an _extend_page_config_for_cpt
676
+		// then let's run that to modify all the various page configuration arrays.
677
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
678
+			$this->_extend_page_config_for_cpt();
679
+		}
680
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
681
+		$this->_page_routes = apply_filters(
682
+			'FHEE__' . $this->class_name . '__page_setup__page_routes',
683
+			$this->_page_routes,
684
+			$this
685
+		);
686
+		$this->_page_config = apply_filters(
687
+			'FHEE__' . $this->class_name . '__page_setup__page_config',
688
+			$this->_page_config,
689
+			$this
690
+		);
691
+		if ($this->base_class_name !== '') {
692
+			$this->_page_routes = apply_filters(
693
+				'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
694
+				$this->_page_routes,
695
+				$this
696
+			);
697
+			$this->_page_config = apply_filters(
698
+				'FHEE__' . $this->base_class_name . '__page_setup__page_config',
699
+				$this->_page_config,
700
+				$this
701
+			);
702
+		}
703
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
706
+			add_action(
707
+				'AHEE__EE_Admin_Page__route_admin_request',
708
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
709
+				10,
710
+				2
711
+			);
712
+		}
713
+		// next route only if routing enabled
714
+		if ($this->_routing && ! $this->request->isAjax()) {
715
+			$this->_verify_routes();
716
+			// next let's just check user_access and kill if no access
717
+			$this->check_user_access();
718
+			if ($this->_is_UI_request) {
719
+				// admin_init stuff - global, all views for this page class, specific view
720
+				add_action('admin_init', [$this, 'admin_init'], 10);
721
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
723
+				}
724
+			} else {
725
+				// hijack regular WP loading and route admin request immediately
726
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
727
+				$this->route_admin_request();
728
+			}
729
+		}
730
+	}
731
+
732
+
733
+	/**
734
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
735
+	 *
736
+	 * @return void
737
+	 * @throws EE_Error
738
+	 */
739
+	private function _do_other_page_hooks()
740
+	{
741
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
742
+		foreach ($registered_pages as $page) {
743
+			// now let's setup the file name and class that should be present
744
+			$classname = str_replace('.class.php', '', $page);
745
+			// autoloaders should take care of loading file
746
+			if (! class_exists($classname)) {
747
+				$error_msg[] = sprintf(
748
+					esc_html__(
749
+						'Something went wrong with loading the %s admin hooks page.',
750
+						'event_espresso'
751
+					),
752
+					$page
753
+				);
754
+				$error_msg[] = $error_msg[0]
755
+							   . "\r\n"
756
+							   . sprintf(
757
+								   esc_html__(
758
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
759
+									   'event_espresso'
760
+								   ),
761
+								   $page,
762
+								   '<br />',
763
+								   '<strong>' . $classname . '</strong>'
764
+							   );
765
+				throw new EE_Error(implode('||', $error_msg));
766
+			}
767
+			// notice we are passing the instance of this class to the hook object.
768
+			$this->loader->getShared($classname, [$this]);
769
+		}
770
+	}
771
+
772
+
773
+	/**
774
+	 * @throws ReflectionException
775
+	 * @throws EE_Error
776
+	 */
777
+	public function load_page_dependencies()
778
+	{
779
+		try {
780
+			$this->_load_page_dependencies();
781
+		} catch (EE_Error $e) {
782
+			$e->get_error();
783
+		}
784
+	}
785
+
786
+
787
+	/**
788
+	 * load_page_dependencies
789
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
790
+	 *
791
+	 * @return void
792
+	 * @throws DomainException
793
+	 * @throws EE_Error
794
+	 * @throws InvalidArgumentException
795
+	 * @throws InvalidDataTypeException
796
+	 * @throws InvalidInterfaceException
797
+	 */
798
+	protected function _load_page_dependencies()
799
+	{
800
+		// let's set the current_screen and screen options to override what WP set
801
+		$this->_current_screen = get_current_screen();
802
+		// load admin_notices - global, page class, and view specific
803
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804
+		add_action('admin_notices', [$this, 'admin_notices'], 10);
805
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
807
+		}
808
+		// load network admin_notices - global, page class, and view specific
809
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
812
+		}
813
+		// this will save any per_page screen options if they are present
814
+		$this->_set_per_page_screen_options();
815
+		// setup list table properties
816
+		$this->_set_list_table();
817
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
818
+		// However in some cases the metaboxes will need to be added within a route handling callback.
819
+		$this->_add_registered_meta_boxes();
820
+		$this->_add_screen_columns();
821
+		// add screen options - global, page child class, and view specific
822
+		$this->_add_global_screen_options();
823
+		$this->_add_screen_options();
824
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
825
+		if (method_exists($this, $add_screen_options)) {
826
+			$this->{$add_screen_options}();
827
+		}
828
+		// add help tab(s) - set via page_config and qtips.
829
+		$this->_add_help_tabs();
830
+		$this->_add_qtips();
831
+		// add feature_pointers - global, page child class, and view specific
832
+		$this->_add_feature_pointers();
833
+		$this->_add_global_feature_pointers();
834
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
835
+		if (method_exists($this, $add_feature_pointer)) {
836
+			$this->{$add_feature_pointer}();
837
+		}
838
+		// enqueue scripts/styles - global, page class, and view specific
839
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
840
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
841
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
842
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
843
+		}
844
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
845
+		// admin_print_footer_scripts - global, page child class, and view specific.
846
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
847
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
848
+		// is a good use case. Notice the late priority we're giving these
849
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
850
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
851
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
852
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
853
+		}
854
+		// admin footer scripts
855
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
856
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
857
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
858
+			add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
859
+		}
860
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
861
+		// targeted hook
862
+		do_action(
863
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
864
+		);
865
+	}
866
+
867
+
868
+	/**
869
+	 * _set_defaults
870
+	 * This sets some global defaults for class properties.
871
+	 */
872
+	private function _set_defaults()
873
+	{
874
+		$this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
875
+		$this->_event                = $this->_template_path = $this->_column_template_path = null;
876
+		$this->_nav_tabs             = $this->_views = $this->_page_routes = [];
877
+		$this->_page_config          = $this->_default_route_query_args = [];
878
+		$this->_default_nav_tab_name = 'overview';
879
+		// init template args
880
+		$this->_template_args = [
881
+			'admin_page_header'  => '',
882
+			'admin_page_content' => '',
883
+			'post_body_content'  => '',
884
+			'before_list_table'  => '',
885
+			'after_list_table'   => '',
886
+		];
887
+	}
888
+
889
+
890
+	/**
891
+	 * route_admin_request
892
+	 *
893
+	 * @return void
894
+	 * @throws InvalidArgumentException
895
+	 * @throws InvalidInterfaceException
896
+	 * @throws InvalidDataTypeException
897
+	 * @throws EE_Error
898
+	 * @throws ReflectionException
899
+	 * @see    _route_admin_request()
900
+	 */
901
+	public function route_admin_request()
902
+	{
903
+		try {
904
+			$this->_route_admin_request();
905
+		} catch (EE_Error $e) {
906
+			$e->get_error();
907
+		}
908
+	}
909
+
910
+
911
+	public function set_wp_page_slug($wp_page_slug)
912
+	{
913
+		$this->_wp_page_slug = $wp_page_slug;
914
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
915
+		if (is_network_admin()) {
916
+			$this->_wp_page_slug .= '-network';
917
+		}
918
+	}
919
+
920
+
921
+	/**
922
+	 * _verify_routes
923
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
924
+	 * we know if we need to drop out.
925
+	 *
926
+	 * @return bool
927
+	 * @throws EE_Error
928
+	 */
929
+	protected function _verify_routes()
930
+	{
931
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
+		if (! $this->_current_page && ! $this->request->isAjax()) {
933
+			return false;
934
+		}
935
+		$this->_route = false;
936
+		// check that the page_routes array is not empty
937
+		if (empty($this->_page_routes)) {
938
+			// user error msg
939
+			$error_msg = sprintf(
940
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
941
+				$this->_admin_page_title
942
+			);
943
+			// developer error msg
944
+			$error_msg .= '||' . $error_msg
945
+						  . esc_html__(
946
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947
+							  'event_espresso'
948
+						  );
949
+			throw new EE_Error($error_msg);
950
+		}
951
+		// and that the requested page route exists
952
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
954
+			$this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
955
+		} else {
956
+			// user error msg
957
+			$error_msg = sprintf(
958
+				esc_html__(
959
+					'The requested page route does not exist for the %s admin page.',
960
+					'event_espresso'
961
+				),
962
+				$this->_admin_page_title
963
+			);
964
+			// developer error msg
965
+			$error_msg .= '||' . $error_msg
966
+						  . sprintf(
967
+							  esc_html__(
968
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
969
+								  'event_espresso'
970
+							  ),
971
+							  $this->_req_action
972
+						  );
973
+			throw new EE_Error($error_msg);
974
+		}
975
+		// and that a default route exists
976
+		if (! array_key_exists('default', $this->_page_routes)) {
977
+			// user error msg
978
+			$error_msg = sprintf(
979
+				esc_html__(
980
+					'A default page route has not been set for the % admin page.',
981
+					'event_espresso'
982
+				),
983
+				$this->_admin_page_title
984
+			);
985
+			// developer error msg
986
+			$error_msg .= '||' . $error_msg
987
+						  . esc_html__(
988
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989
+							  'event_espresso'
990
+						  );
991
+			throw new EE_Error($error_msg);
992
+		}
993
+
994
+		// first lets' catch if the UI request has EVER been set.
995
+		if ($this->_is_UI_request === null) {
996
+			// lets set if this is a UI request or not.
997
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
998
+			// wait a minute... we might have a noheader in the route array
999
+			$this->_is_UI_request = ! (
1000
+				is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
1001
+			)
1002
+				? $this->_is_UI_request
1003
+				: false;
1004
+		}
1005
+		$this->_set_current_labels();
1006
+		return true;
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1012
+	 *
1013
+	 * @param string $route the route name we're verifying
1014
+	 * @return bool we'll throw an exception if this isn't a valid route.
1015
+	 * @throws EE_Error
1016
+	 */
1017
+	protected function _verify_route($route)
1018
+	{
1019
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
1020
+			return true;
1021
+		}
1022
+		// user error msg
1023
+		$error_msg = sprintf(
1024
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1025
+			$this->_admin_page_title
1026
+		);
1027
+		// developer error msg
1028
+		$error_msg .= '||' . $error_msg
1029
+					  . sprintf(
1030
+						  esc_html__(
1031
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1032
+							  'event_espresso'
1033
+						  ),
1034
+						  $route
1035
+					  );
1036
+		throw new EE_Error($error_msg);
1037
+	}
1038
+
1039
+
1040
+	/**
1041
+	 * perform nonce verification
1042
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1043
+	 * using this method (and save retyping!)
1044
+	 *
1045
+	 * @param string $nonce     The nonce sent
1046
+	 * @param string $nonce_ref The nonce reference string (name0)
1047
+	 * @return void
1048
+	 * @throws EE_Error
1049
+	 * @throws InvalidArgumentException
1050
+	 * @throws InvalidDataTypeException
1051
+	 * @throws InvalidInterfaceException
1052
+	 */
1053
+	protected function _verify_nonce($nonce, $nonce_ref)
1054
+	{
1055
+		// verify nonce against expected value
1056
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
1057
+			// these are not the droids you are looking for !!!
1058
+			$msg = sprintf(
1059
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
1060
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1061
+				'</a>'
1062
+			);
1063
+			if (WP_DEBUG) {
1064
+				$msg .= "\n  ";
1065
+				$msg .= sprintf(
1066
+					esc_html__(
1067
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1068
+						'event_espresso'
1069
+					),
1070
+					__CLASS__
1071
+				);
1072
+			}
1073
+			if (! $this->request->isAjax()) {
1074
+				wp_die($msg);
1075
+			}
1076
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
+			$this->_return_json();
1078
+		}
1079
+	}
1080
+
1081
+
1082
+	/**
1083
+	 * _route_admin_request()
1084
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1085
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1086
+	 * in the page routes and then will try to load the corresponding method.
1087
+	 *
1088
+	 * @return void
1089
+	 * @throws EE_Error
1090
+	 * @throws InvalidArgumentException
1091
+	 * @throws InvalidDataTypeException
1092
+	 * @throws InvalidInterfaceException
1093
+	 * @throws ReflectionException
1094
+	 */
1095
+	protected function _route_admin_request()
1096
+	{
1097
+		if (! $this->_is_UI_request) {
1098
+			$this->_verify_routes();
1099
+		}
1100
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1101
+		if ($this->_req_action !== 'default' && $nonce_check) {
1102
+			// set nonce from post data
1103
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
1104
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1105
+		}
1106
+		// set the nav_tabs array but ONLY if this is  UI_request
1107
+		if ($this->_is_UI_request) {
1108
+			$this->_set_nav_tabs();
1109
+		}
1110
+		// grab callback function
1111
+		$func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1112
+		// check if callback has args
1113
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1114
+		$error_msg = '';
1115
+		// action right before calling route
1116
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119
+		}
1120
+		// strip _wp_http_referer from the server REQUEST_URI
1121
+		// else it grows in length on every submission due to recursion,
1122
+		// ultimately causing a "Request-URI Too Large" error
1123
+		$request_uri = remove_query_arg(
1124
+			'_wp_http_referer',
1125
+			wp_unslash($this->request->getServerParam('REQUEST_URI'))
1126
+		);
1127
+		// set new value in both our Request object and the super global
1128
+		$this->request->setServerParam('REQUEST_URI', $request_uri, true);
1129
+		if (! empty($func)) {
1130
+			if (is_array($func)) {
1131
+				[$class, $method] = $func;
1132
+			} elseif (strpos($func, '::') !== false) {
1133
+				[$class, $method] = explode('::', $func);
1134
+			} else {
1135
+				$class  = $this;
1136
+				$method = $func;
1137
+			}
1138
+			if (! (is_object($class) && $class === $this)) {
1139
+				// send along this admin page object for access by addons.
1140
+				$args['admin_page_object'] = $this;
1141
+			}
1142
+			if (
1143
+				// is it a method on a class that doesn't work?
1144
+				(
1145
+					(
1146
+						method_exists($class, $method)
1147
+						&& call_user_func_array([$class, $method], $args) === false
1148
+					)
1149
+					&& (
1150
+						// is it a standalone function that doesn't work?
1151
+						function_exists($method)
1152
+						&& call_user_func_array(
1153
+							$func,
1154
+							array_merge(['admin_page_object' => $this], $args)
1155
+						) === false
1156
+					)
1157
+				)
1158
+				|| (
1159
+					// is it neither a class method NOR a standalone function?
1160
+					! method_exists($class, $method)
1161
+					&& ! function_exists($method)
1162
+				)
1163
+			) {
1164
+				// user error msg
1165
+				$error_msg = esc_html__(
1166
+					'An error occurred. The  requested page route could not be found.',
1167
+					'event_espresso'
1168
+				);
1169
+				// developer error msg
1170
+				$error_msg .= '||';
1171
+				$error_msg .= sprintf(
1172
+					esc_html__(
1173
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1174
+						'event_espresso'
1175
+					),
1176
+					$method
1177
+				);
1178
+			}
1179
+			if (! empty($error_msg)) {
1180
+				throw new EE_Error($error_msg);
1181
+			}
1182
+		}
1183
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1184
+		// then we need to reset the routing properties to the new route.
1185
+		// 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.
1186
+		if (
1187
+			$this->_is_UI_request === false
1188
+			&& is_array($this->_route)
1189
+			&& ! empty($this->_route['headers_sent_route'])
1190
+		) {
1191
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1192
+		}
1193
+	}
1194
+
1195
+
1196
+	/**
1197
+	 * This method just allows the resetting of page properties in the case where a no headers
1198
+	 * route redirects to a headers route in its route config.
1199
+	 *
1200
+	 * @param string $new_route New (non header) route to redirect to.
1201
+	 * @return   void
1202
+	 * @throws ReflectionException
1203
+	 * @throws InvalidArgumentException
1204
+	 * @throws InvalidInterfaceException
1205
+	 * @throws InvalidDataTypeException
1206
+	 * @throws EE_Error
1207
+	 * @since   4.3.0
1208
+	 */
1209
+	protected function _reset_routing_properties($new_route)
1210
+	{
1211
+		$this->_is_UI_request = true;
1212
+		// now we set the current route to whatever the headers_sent_route is set at
1213
+		$this->request->setRequestParam('action', $new_route);
1214
+		// rerun page setup
1215
+		$this->_page_setup();
1216
+	}
1217
+
1218
+
1219
+	/**
1220
+	 * _add_query_arg
1221
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1222
+	 *(internally just uses EEH_URL's function with the same name)
1223
+	 *
1224
+	 * @param array  $args
1225
+	 * @param string $url
1226
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1227
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1228
+	 *                                        Example usage: If the current page is:
1229
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1230
+	 *                                        &action=default&event_id=20&month_range=March%202015
1231
+	 *                                        &_wpnonce=5467821
1232
+	 *                                        and you call:
1233
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1234
+	 *                                        array(
1235
+	 *                                        'action' => 'resend_something',
1236
+	 *                                        'page=>espresso_registrations'
1237
+	 *                                        ),
1238
+	 *                                        $some_url,
1239
+	 *                                        true
1240
+	 *                                        );
1241
+	 *                                        It will produce a url in this structure:
1242
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1243
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1244
+	 *                                        month_range]=March%202015
1245
+	 * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1246
+	 * @return string
1247
+	 */
1248
+	public static function add_query_args_and_nonce(
1249
+		$args = [],
1250
+		$url = '',
1251
+		$sticky = false,
1252
+		$exclude_nonce = false
1253
+	) {
1254
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1255
+		if ($sticky) {
1256
+			/** @var RequestInterface $request */
1257
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1258
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1259
+			$request->unSetServerParam('_wp_http_referer', true);
1260
+			foreach ($request->requestParams() as $key => $value) {
1261
+				// do not add nonces
1262
+				if (strpos($key, 'nonce') !== false) {
1263
+					continue;
1264
+				}
1265
+				$args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1266
+			}
1267
+		}
1268
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 * This returns a generated link that will load the related help tab.
1274
+	 *
1275
+	 * @param string $help_tab_id the id for the connected help tab
1276
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1277
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1278
+	 * @return string              generated link
1279
+	 * @uses EEH_Template::get_help_tab_link()
1280
+	 */
1281
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1282
+	{
1283
+		return EEH_Template::get_help_tab_link(
1284
+			$help_tab_id,
1285
+			$this->page_slug,
1286
+			$this->_req_action,
1287
+			$icon_style,
1288
+			$help_text
1289
+		);
1290
+	}
1291
+
1292
+
1293
+	/**
1294
+	 * _add_help_tabs
1295
+	 * Note child classes define their help tabs within the page_config array.
1296
+	 *
1297
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1298
+	 * @return void
1299
+	 * @throws DomainException
1300
+	 * @throws EE_Error
1301
+	 * @throws ReflectionException
1302
+	 */
1303
+	protected function _add_help_tabs()
1304
+	{
1305
+		if (isset($this->_page_config[ $this->_req_action ])) {
1306
+			$config = $this->_page_config[ $this->_req_action ];
1307
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1308
+			if (is_array($config) && isset($config['help_sidebar'])) {
1309
+				// check that the callback given is valid
1310
+				if (! method_exists($this, $config['help_sidebar'])) {
1311
+					throw new EE_Error(
1312
+						sprintf(
1313
+							esc_html__(
1314
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1315
+								'event_espresso'
1316
+							),
1317
+							$config['help_sidebar'],
1318
+							$this->class_name
1319
+						)
1320
+					);
1321
+				}
1322
+				$content = apply_filters(
1323
+					'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1324
+					$this->{$config['help_sidebar']}()
1325
+				);
1326
+				$this->_current_screen->set_help_sidebar($content);
1327
+			}
1328
+			if (! isset($config['help_tabs'])) {
1329
+				return;
1330
+			} //no help tabs for this route
1331
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1332
+				// we're here so there ARE help tabs!
1333
+				// make sure we've got what we need
1334
+				if (! isset($cfg['title'])) {
1335
+					throw new EE_Error(
1336
+						esc_html__(
1337
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1338
+							'event_espresso'
1339
+						)
1340
+					);
1341
+				}
1342
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1343
+					throw new EE_Error(
1344
+						esc_html__(
1345
+							'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',
1346
+							'event_espresso'
1347
+						)
1348
+					);
1349
+				}
1350
+				// first priority goes to content.
1351
+				if (! empty($cfg['content'])) {
1352
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1353
+					// second priority goes to filename
1354
+				} elseif (! empty($cfg['filename'])) {
1355
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1356
+					// 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)
1357
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1358
+															 . basename($this->_get_dir())
1359
+															 . '/help_tabs/'
1360
+															 . $cfg['filename']
1361
+															 . '.help_tab.php' : $file_path;
1362
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1363
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1364
+						EE_Error::add_error(
1365
+							sprintf(
1366
+								esc_html__(
1367
+									'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',
1368
+									'event_espresso'
1369
+								),
1370
+								$tab_id,
1371
+								key($config),
1372
+								$file_path
1373
+							),
1374
+							__FILE__,
1375
+							__FUNCTION__,
1376
+							__LINE__
1377
+						);
1378
+						return;
1379
+					}
1380
+					$template_args['admin_page_obj'] = $this;
1381
+					$content                         = EEH_Template::display_template(
1382
+						$file_path,
1383
+						$template_args,
1384
+						true
1385
+					);
1386
+				} else {
1387
+					$content = '';
1388
+				}
1389
+				// check if callback is valid
1390
+				if (
1391
+					empty($content)
1392
+					&& (
1393
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1394
+					)
1395
+				) {
1396
+					EE_Error::add_error(
1397
+						sprintf(
1398
+							esc_html__(
1399
+								'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.',
1400
+								'event_espresso'
1401
+							),
1402
+							$cfg['title']
1403
+						),
1404
+						__FILE__,
1405
+						__FUNCTION__,
1406
+						__LINE__
1407
+					);
1408
+					return;
1409
+				}
1410
+				// setup config array for help tab method
1411
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1412
+				$_ht = [
1413
+					'id'       => $id,
1414
+					'title'    => $cfg['title'],
1415
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1416
+					'content'  => $content,
1417
+				];
1418
+				$this->_current_screen->add_help_tab($_ht);
1419
+			}
1420
+		}
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * This simply sets up any qtips that have been defined in the page config
1426
+	 *
1427
+	 * @return void
1428
+	 * @throws ReflectionException
1429
+	 * @throws EE_Error
1430
+	 */
1431
+	protected function _add_qtips()
1432
+	{
1433
+		if (isset($this->_route_config['qtips'])) {
1434
+			$qtips = (array) $this->_route_config['qtips'];
1435
+			// load qtip loader
1436
+			$path = [
1437
+				$this->_get_dir() . '/qtips/',
1438
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1439
+			];
1440
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1441
+		}
1442
+	}
1443
+
1444
+
1445
+	/**
1446
+	 * _set_nav_tabs
1447
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1448
+	 * wish to add additional tabs or modify accordingly.
1449
+	 *
1450
+	 * @return void
1451
+	 * @throws InvalidArgumentException
1452
+	 * @throws InvalidInterfaceException
1453
+	 * @throws InvalidDataTypeException
1454
+	 */
1455
+	protected function _set_nav_tabs()
1456
+	{
1457
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1458
+		$i = 0;
1459
+		foreach ($this->_page_config as $slug => $config) {
1460
+			if (! is_array($config) || empty($config['nav'])) {
1461
+				continue;
1462
+			}
1463
+			// no nav tab for this config
1464
+			// check for persistent flag
1465
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1466
+				// nav tab is only to appear when route requested.
1467
+				continue;
1468
+			}
1469
+			if (! $this->check_user_access($slug, true)) {
1470
+				// no nav tab because current user does not have access.
1471
+				continue;
1472
+			}
1473
+			$css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1474
+			$this->_nav_tabs[ $slug ] = [
1475
+				'url'       => isset($config['nav']['url'])
1476
+					? $config['nav']['url']
1477
+					: EE_Admin_Page::add_query_args_and_nonce(
1478
+						['action' => $slug],
1479
+						$this->_admin_base_url
1480
+					),
1481
+				'link_text' => isset($config['nav']['label'])
1482
+					? $config['nav']['label']
1483
+					: ucwords(
1484
+						str_replace('_', ' ', $slug)
1485
+					),
1486
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1487
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1488
+			];
1489
+			$i++;
1490
+		}
1491
+		// if $this->_nav_tabs is empty then lets set the default
1492
+		if (empty($this->_nav_tabs)) {
1493
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1494
+				'url'       => $this->_admin_base_url,
1495
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1496
+				'css_class' => 'nav-tab-active',
1497
+				'order'     => 10,
1498
+			];
1499
+		}
1500
+		// now let's sort the tabs according to order
1501
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * _set_current_labels
1507
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1508
+	 * property array
1509
+	 *
1510
+	 * @return void
1511
+	 */
1512
+	private function _set_current_labels()
1513
+	{
1514
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1515
+			foreach ($this->_route_config['labels'] as $label => $text) {
1516
+				if (is_array($text)) {
1517
+					foreach ($text as $sublabel => $subtext) {
1518
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1519
+					}
1520
+				} else {
1521
+					$this->_labels[ $label ] = $text;
1522
+				}
1523
+			}
1524
+		}
1525
+	}
1526
+
1527
+
1528
+	/**
1529
+	 *        verifies user access for this admin page
1530
+	 *
1531
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1532
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1533
+	 *                               return false if verify fail.
1534
+	 * @return bool
1535
+	 * @throws InvalidArgumentException
1536
+	 * @throws InvalidDataTypeException
1537
+	 * @throws InvalidInterfaceException
1538
+	 */
1539
+	public function check_user_access($route_to_check = '', $verify_only = false)
1540
+	{
1541
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1542
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1543
+		$capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1544
+									  && is_array($this->_page_routes[ $route_to_check ])
1545
+						&& ! empty($this->_page_routes[ $route_to_check ]['capability'])
1546
+			? $this->_page_routes[ $route_to_check ]['capability']
1547
+			: null;
1548
+
1549
+		if (empty($capability) && empty($route_to_check)) {
1550
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1551
+				: $this->_route['capability'];
1552
+		} else {
1553
+			$capability = empty($capability) ? 'manage_options' : $capability;
1554
+		}
1555
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1556
+		if (
1557
+			! $this->request->isAjax()
1558
+			&& (
1559
+				! function_exists('is_admin')
1560
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1561
+					$capability,
1562
+					$this->page_slug
1563
+					. '_'
1564
+					. $route_to_check,
1565
+					$id
1566
+				)
1567
+			)
1568
+		) {
1569
+			if ($verify_only) {
1570
+				return false;
1571
+			}
1572
+			if (is_user_logged_in()) {
1573
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1574
+			} else {
1575
+				return false;
1576
+			}
1577
+		}
1578
+		return true;
1579
+	}
1580
+
1581
+
1582
+	/**
1583
+	 * @param string                 $box_id
1584
+	 * @param string                 $title
1585
+	 * @param callable|string|null   $callback
1586
+	 * @param string|array|WP_Screen $screen
1587
+	 * @param string                 $context
1588
+	 * @param string                 $priority
1589
+	 * @param array|null             $callback_args
1590
+	 */
1591
+	protected function addMetaBox(
1592
+		string $box_id,
1593
+		string $title,
1594
+		$callback,
1595
+		$screen,
1596
+		string $context = 'normal',
1597
+		string $priority = 'default',
1598
+		?array $callback_args = null
1599
+	) {
1600
+		if (! is_callable($callback)) {
1601
+			return;
1602
+		}
1603
+
1604
+		add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1605
+		add_filter(
1606
+			"postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1607
+			function ($classes) {
1608
+				array_push($classes, 'ee-admin-container');
1609
+				return $classes;
1610
+			}
1611
+		);
1612
+	}
1613
+
1614
+
1615
+	/**
1616
+	 * admin_init_global
1617
+	 * This runs all the code that we want executed within the WP admin_init hook.
1618
+	 * This method executes for ALL EE Admin pages.
1619
+	 *
1620
+	 * @return void
1621
+	 */
1622
+	public function admin_init_global()
1623
+	{
1624
+	}
1625
+
1626
+
1627
+	/**
1628
+	 * wp_loaded_global
1629
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1630
+	 * EE_Admin page and will execute on every EE Admin Page load
1631
+	 *
1632
+	 * @return void
1633
+	 */
1634
+	public function wp_loaded()
1635
+	{
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 * admin_notices
1641
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1642
+	 * ALL EE_Admin pages.
1643
+	 *
1644
+	 * @return void
1645
+	 */
1646
+	public function admin_notices_global()
1647
+	{
1648
+		$this->_display_no_javascript_warning();
1649
+		$this->_display_espresso_notices();
1650
+	}
1651
+
1652
+
1653
+	public function network_admin_notices_global()
1654
+	{
1655
+		$this->_display_no_javascript_warning();
1656
+		$this->_display_espresso_notices();
1657
+	}
1658
+
1659
+
1660
+	/**
1661
+	 * admin_footer_scripts_global
1662
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1663
+	 * will apply on ALL EE_Admin pages.
1664
+	 *
1665
+	 * @return void
1666
+	 */
1667
+	public function admin_footer_scripts_global()
1668
+	{
1669
+		$this->_add_admin_page_ajax_loading_img();
1670
+		$this->_add_admin_page_overlay();
1671
+		// if metaboxes are present we need to add the nonce field
1672
+		if (
1673
+			isset($this->_route_config['metaboxes'])
1674
+			|| isset($this->_route_config['list_table'])
1675
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1676
+		) {
1677
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1678
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1679
+		}
1680
+	}
1681
+
1682
+
1683
+	/**
1684
+	 * admin_footer_global
1685
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1686
+	 * This particular method will apply on ALL EE_Admin Pages.
1687
+	 *
1688
+	 * @return void
1689
+	 */
1690
+	public function admin_footer_global()
1691
+	{
1692
+		// dialog container for dialog helper
1693
+		echo '
1694 1694
         <div class="ee-admin-dialog-container auto-hide hidden">
1695 1695
             <div class="ee-notices"></div>
1696 1696
             <div class="ee-admin-dialog-container-inner-content"></div>
1697 1697
         </div>
1698 1698
         ';
1699 1699
 
1700
-        // current set timezone for timezone js
1701
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1702
-    }
1703
-
1704
-
1705
-    /**
1706
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1707
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1708
-     * help popups then in your templates or your content you set "triggers" for the content using the
1709
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1710
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1711
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1712
-     * for the
1713
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1714
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1715
-     *    'help_trigger_id' => array(
1716
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1717
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1718
-     *    )
1719
-     * );
1720
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1721
-     *
1722
-     * @param array $help_array
1723
-     * @param bool  $display
1724
-     * @return string content
1725
-     * @throws DomainException
1726
-     * @throws EE_Error
1727
-     */
1728
-    protected function _set_help_popup_content($help_array = [], $display = false)
1729
-    {
1730
-        $content    = '';
1731
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1732
-        // loop through the array and setup content
1733
-        foreach ($help_array as $trigger => $help) {
1734
-            // make sure the array is setup properly
1735
-            if (! isset($help['title'], $help['content'])) {
1736
-                throw new EE_Error(
1737
-                    esc_html__(
1738
-                        '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',
1739
-                        'event_espresso'
1740
-                    )
1741
-                );
1742
-            }
1743
-            // we're good so let's setup the template vars and then assign parsed template content to our content.
1744
-            $template_args = [
1745
-                'help_popup_id'      => $trigger,
1746
-                'help_popup_title'   => $help['title'],
1747
-                'help_popup_content' => $help['content'],
1748
-            ];
1749
-            $content       .= EEH_Template::display_template(
1750
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1751
-                $template_args,
1752
-                true
1753
-            );
1754
-        }
1755
-        if ($display) {
1756
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1757
-            return '';
1758
-        }
1759
-        return $content;
1760
-    }
1761
-
1762
-
1763
-    /**
1764
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1765
-     *
1766
-     * @return array properly formatted array for help popup content
1767
-     * @throws EE_Error
1768
-     */
1769
-    private function _get_help_content()
1770
-    {
1771
-        // what is the method we're looking for?
1772
-        $method_name = '_help_popup_content_' . $this->_req_action;
1773
-        // if method doesn't exist let's get out.
1774
-        if (! method_exists($this, $method_name)) {
1775
-            return [];
1776
-        }
1777
-        // k we're good to go let's retrieve the help array
1778
-        $help_array = $this->{$method_name}();
1779
-        // make sure we've got an array!
1780
-        if (! is_array($help_array)) {
1781
-            throw new EE_Error(
1782
-                esc_html__(
1783
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1784
-                    'event_espresso'
1785
-                )
1786
-            );
1787
-        }
1788
-        return $help_array;
1789
-    }
1790
-
1791
-
1792
-    /**
1793
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1794
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1795
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1796
-     *
1797
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1798
-     * @param boolean $display    if false then we return the trigger string
1799
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1800
-     * @return string
1801
-     * @throws DomainException
1802
-     * @throws EE_Error
1803
-     */
1804
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1805
-    {
1806
-        if ($this->request->isAjax()) {
1807
-            return '';
1808
-        }
1809
-        // 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
1810
-        $help_array   = $this->_get_help_content();
1811
-        $help_content = '';
1812
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1813
-            $help_array[ $trigger_id ] = [
1814
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1815
-                'content' => esc_html__(
1816
-                    '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.)',
1817
-                    'event_espresso'
1818
-                ),
1819
-            ];
1820
-            $help_content = $this->_set_help_popup_content($help_array);
1821
-        }
1822
-        // let's setup the trigger
1823
-        $content = '<a class="ee-dialog" href="?height='
1824
-                   . esc_attr($dimensions[0])
1825
-                   . '&width='
1826
-                   . esc_attr($dimensions[1])
1827
-                   . '&inlineId='
1828
-                   . esc_attr($trigger_id)
1829
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1830
-        $content .= $help_content;
1831
-        if ($display) {
1832
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1833
-            return '';
1834
-        }
1835
-        return $content;
1836
-    }
1837
-
1838
-
1839
-    /**
1840
-     * _add_global_screen_options
1841
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1842
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1843
-     *
1844
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1845
-     *         see also WP_Screen object documents...
1846
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1847
-     * @abstract
1848
-     * @return void
1849
-     */
1850
-    private function _add_global_screen_options()
1851
-    {
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * _add_global_feature_pointers
1857
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1858
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1859
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1860
-     *
1861
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1862
-     *         extended) also see:
1863
-     * @link   http://eamann.com/tech/wordpress-portland/
1864
-     * @abstract
1865
-     * @return void
1866
-     */
1867
-    private function _add_global_feature_pointers()
1868
-    {
1869
-    }
1870
-
1871
-
1872
-    /**
1873
-     * load_global_scripts_styles
1874
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1875
-     *
1876
-     * @return void
1877
-     */
1878
-    public function load_global_scripts_styles()
1879
-    {
1880
-        // add debugging styles
1881
-        if (WP_DEBUG) {
1882
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1883
-        }
1884
-        // taking care of metaboxes
1885
-        if (
1886
-            empty($this->_cpt_route)
1887
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1888
-        ) {
1889
-            wp_enqueue_script('dashboard');
1890
-        }
1891
-
1892
-        wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1893
-        wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1894
-        // LOCALIZED DATA
1895
-        // localize script for ajax lazy loading
1896
-        wp_localize_script(
1897
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1898
-            'eeLazyLoadingContainers',
1899
-            apply_filters(
1900
-                'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1901
-                ['espresso_news_post_box_content']
1902
-            )
1903
-        );
1904
-        StatusChangeNotice::loadAssets();
1905
-
1906
-        add_filter(
1907
-            'admin_body_class',
1908
-            function ($classes) {
1909
-                if (strpos($classes, 'espresso-admin') === false) {
1910
-                    $classes .= ' espresso-admin';
1911
-                }
1912
-                return $classes;
1913
-            }
1914
-        );
1915
-    }
1916
-
1917
-
1918
-    /**
1919
-     *        admin_footer_scripts_eei18n_js_strings
1920
-     *
1921
-     * @return        void
1922
-     */
1923
-    public function admin_footer_scripts_eei18n_js_strings()
1924
-    {
1925
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1926
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1927
-            __(
1928
-                '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!!!',
1929
-                'event_espresso'
1930
-            )
1931
-        );
1932
-        EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1933
-        EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1934
-        EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1935
-        EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1936
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1937
-        EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1938
-        EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1939
-        EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1940
-        EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1941
-        EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1942
-        EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1943
-        EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1944
-        EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1945
-        EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1946
-        EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1947
-        EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1948
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1949
-        EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1950
-        EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1951
-        EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1952
-        EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1953
-        EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1954
-        EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1955
-        EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1956
-        EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1957
-        EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1958
-        EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1959
-        EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1960
-        EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1961
-        EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1962
-        EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1963
-        EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1964
-        EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1965
-        EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1966
-        EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1967
-        EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1968
-        EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1969
-        EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1970
-    }
1971
-
1972
-
1973
-    /**
1974
-     *        load enhanced xdebug styles for ppl with failing eyesight
1975
-     *
1976
-     * @return        void
1977
-     */
1978
-    public function add_xdebug_style()
1979
-    {
1980
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1981
-    }
1982
-
1983
-
1984
-    /************************/
1985
-    /** LIST TABLE METHODS **/
1986
-    /************************/
1987
-    /**
1988
-     * this sets up the list table if the current view requires it.
1989
-     *
1990
-     * @return void
1991
-     * @throws EE_Error
1992
-     * @throws InvalidArgumentException
1993
-     * @throws InvalidDataTypeException
1994
-     * @throws InvalidInterfaceException
1995
-     */
1996
-    protected function _set_list_table()
1997
-    {
1998
-        // first is this a list_table view?
1999
-        if (! isset($this->_route_config['list_table'])) {
2000
-            return;
2001
-        } //not a list_table view so get out.
2002
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2003
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2004
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2005
-            // user error msg
2006
-            $error_msg = esc_html__(
2007
-                'An error occurred. The requested list table views could not be found.',
2008
-                'event_espresso'
2009
-            );
2010
-            // developer error msg
2011
-            $error_msg .= '||'
2012
-                          . sprintf(
2013
-                              esc_html__(
2014
-                                  '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.',
2015
-                                  'event_espresso'
2016
-                              ),
2017
-                              $this->_req_action,
2018
-                              $list_table_view
2019
-                          );
2020
-            throw new EE_Error($error_msg);
2021
-        }
2022
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2023
-        $this->_views = apply_filters(
2024
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2025
-            $this->_views
2026
-        );
2027
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2028
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2029
-        $this->_set_list_table_view();
2030
-        $this->_set_list_table_object();
2031
-    }
2032
-
2033
-
2034
-    /**
2035
-     * set current view for List Table
2036
-     *
2037
-     * @return void
2038
-     */
2039
-    protected function _set_list_table_view()
2040
-    {
2041
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2042
-        $status = $this->request->getRequestParam('status', null, 'key');
2043
-        $this->_view = $status && array_key_exists($status, $this->_views)
2044
-            ? $status
2045
-            : $this->_view;
2046
-    }
2047
-
2048
-
2049
-    /**
2050
-     * _set_list_table_object
2051
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2052
-     *
2053
-     * @throws InvalidInterfaceException
2054
-     * @throws InvalidArgumentException
2055
-     * @throws InvalidDataTypeException
2056
-     * @throws EE_Error
2057
-     * @throws InvalidInterfaceException
2058
-     */
2059
-    protected function _set_list_table_object()
2060
-    {
2061
-        if (isset($this->_route_config['list_table'])) {
2062
-            if (! class_exists($this->_route_config['list_table'])) {
2063
-                throw new EE_Error(
2064
-                    sprintf(
2065
-                        esc_html__(
2066
-                            '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.',
2067
-                            'event_espresso'
2068
-                        ),
2069
-                        $this->_route_config['list_table'],
2070
-                        $this->class_name
2071
-                    )
2072
-                );
2073
-            }
2074
-            $this->_list_table_object = $this->loader->getShared(
2075
-                $this->_route_config['list_table'],
2076
-                [$this]
2077
-            );
2078
-        }
2079
-    }
2080
-
2081
-
2082
-    /**
2083
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2084
-     *
2085
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2086
-     *                                                    urls.  The array should be indexed by the view it is being
2087
-     *                                                    added to.
2088
-     * @return array
2089
-     */
2090
-    public function get_list_table_view_RLs($extra_query_args = [])
2091
-    {
2092
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2093
-        if (empty($this->_views)) {
2094
-            $this->_views = [];
2095
-        }
2096
-        // cycle thru views
2097
-        foreach ($this->_views as $key => $view) {
2098
-            $query_args = [];
2099
-            // check for current view
2100
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2101
-            $query_args['action']                        = $this->_req_action;
2102
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2103
-            $query_args['status']                        = $view['slug'];
2104
-            // merge any other arguments sent in.
2105
-            if (isset($extra_query_args[ $view['slug'] ])) {
2106
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2107
-                    $query_args[] = $extra_query_arg;
2108
-                }
2109
-            }
2110
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2111
-        }
2112
-        return $this->_views;
2113
-    }
2114
-
2115
-
2116
-    /**
2117
-     * _entries_per_page_dropdown
2118
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2119
-     *
2120
-     * @param int $max_entries total number of rows in the table
2121
-     * @return string
2122
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2123
-     *         WP does it.
2124
-     */
2125
-    protected function _entries_per_page_dropdown($max_entries = 0)
2126
-    {
2127
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2128
-        $values   = [10, 25, 50, 100];
2129
-        $per_page = $this->request->getRequestParam('per_page', 10, 'int');
2130
-        if ($max_entries) {
2131
-            $values[] = $max_entries;
2132
-            sort($values);
2133
-        }
2134
-        $entries_per_page_dropdown = '
1700
+		// current set timezone for timezone js
1701
+		echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1702
+	}
1703
+
1704
+
1705
+	/**
1706
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1707
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1708
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1709
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1710
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1711
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1712
+	 * for the
1713
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1714
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1715
+	 *    'help_trigger_id' => array(
1716
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1717
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1718
+	 *    )
1719
+	 * );
1720
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1721
+	 *
1722
+	 * @param array $help_array
1723
+	 * @param bool  $display
1724
+	 * @return string content
1725
+	 * @throws DomainException
1726
+	 * @throws EE_Error
1727
+	 */
1728
+	protected function _set_help_popup_content($help_array = [], $display = false)
1729
+	{
1730
+		$content    = '';
1731
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1732
+		// loop through the array and setup content
1733
+		foreach ($help_array as $trigger => $help) {
1734
+			// make sure the array is setup properly
1735
+			if (! isset($help['title'], $help['content'])) {
1736
+				throw new EE_Error(
1737
+					esc_html__(
1738
+						'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',
1739
+						'event_espresso'
1740
+					)
1741
+				);
1742
+			}
1743
+			// we're good so let's setup the template vars and then assign parsed template content to our content.
1744
+			$template_args = [
1745
+				'help_popup_id'      => $trigger,
1746
+				'help_popup_title'   => $help['title'],
1747
+				'help_popup_content' => $help['content'],
1748
+			];
1749
+			$content       .= EEH_Template::display_template(
1750
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1751
+				$template_args,
1752
+				true
1753
+			);
1754
+		}
1755
+		if ($display) {
1756
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1757
+			return '';
1758
+		}
1759
+		return $content;
1760
+	}
1761
+
1762
+
1763
+	/**
1764
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1765
+	 *
1766
+	 * @return array properly formatted array for help popup content
1767
+	 * @throws EE_Error
1768
+	 */
1769
+	private function _get_help_content()
1770
+	{
1771
+		// what is the method we're looking for?
1772
+		$method_name = '_help_popup_content_' . $this->_req_action;
1773
+		// if method doesn't exist let's get out.
1774
+		if (! method_exists($this, $method_name)) {
1775
+			return [];
1776
+		}
1777
+		// k we're good to go let's retrieve the help array
1778
+		$help_array = $this->{$method_name}();
1779
+		// make sure we've got an array!
1780
+		if (! is_array($help_array)) {
1781
+			throw new EE_Error(
1782
+				esc_html__(
1783
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1784
+					'event_espresso'
1785
+				)
1786
+			);
1787
+		}
1788
+		return $help_array;
1789
+	}
1790
+
1791
+
1792
+	/**
1793
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1794
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1795
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1796
+	 *
1797
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1798
+	 * @param boolean $display    if false then we return the trigger string
1799
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1800
+	 * @return string
1801
+	 * @throws DomainException
1802
+	 * @throws EE_Error
1803
+	 */
1804
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1805
+	{
1806
+		if ($this->request->isAjax()) {
1807
+			return '';
1808
+		}
1809
+		// 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
1810
+		$help_array   = $this->_get_help_content();
1811
+		$help_content = '';
1812
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1813
+			$help_array[ $trigger_id ] = [
1814
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1815
+				'content' => esc_html__(
1816
+					'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.)',
1817
+					'event_espresso'
1818
+				),
1819
+			];
1820
+			$help_content = $this->_set_help_popup_content($help_array);
1821
+		}
1822
+		// let's setup the trigger
1823
+		$content = '<a class="ee-dialog" href="?height='
1824
+				   . esc_attr($dimensions[0])
1825
+				   . '&width='
1826
+				   . esc_attr($dimensions[1])
1827
+				   . '&inlineId='
1828
+				   . esc_attr($trigger_id)
1829
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1830
+		$content .= $help_content;
1831
+		if ($display) {
1832
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1833
+			return '';
1834
+		}
1835
+		return $content;
1836
+	}
1837
+
1838
+
1839
+	/**
1840
+	 * _add_global_screen_options
1841
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1842
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1843
+	 *
1844
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1845
+	 *         see also WP_Screen object documents...
1846
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1847
+	 * @abstract
1848
+	 * @return void
1849
+	 */
1850
+	private function _add_global_screen_options()
1851
+	{
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * _add_global_feature_pointers
1857
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1858
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1859
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1860
+	 *
1861
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1862
+	 *         extended) also see:
1863
+	 * @link   http://eamann.com/tech/wordpress-portland/
1864
+	 * @abstract
1865
+	 * @return void
1866
+	 */
1867
+	private function _add_global_feature_pointers()
1868
+	{
1869
+	}
1870
+
1871
+
1872
+	/**
1873
+	 * load_global_scripts_styles
1874
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1875
+	 *
1876
+	 * @return void
1877
+	 */
1878
+	public function load_global_scripts_styles()
1879
+	{
1880
+		// add debugging styles
1881
+		if (WP_DEBUG) {
1882
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1883
+		}
1884
+		// taking care of metaboxes
1885
+		if (
1886
+			empty($this->_cpt_route)
1887
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1888
+		) {
1889
+			wp_enqueue_script('dashboard');
1890
+		}
1891
+
1892
+		wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1893
+		wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1894
+		// LOCALIZED DATA
1895
+		// localize script for ajax lazy loading
1896
+		wp_localize_script(
1897
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1898
+			'eeLazyLoadingContainers',
1899
+			apply_filters(
1900
+				'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1901
+				['espresso_news_post_box_content']
1902
+			)
1903
+		);
1904
+		StatusChangeNotice::loadAssets();
1905
+
1906
+		add_filter(
1907
+			'admin_body_class',
1908
+			function ($classes) {
1909
+				if (strpos($classes, 'espresso-admin') === false) {
1910
+					$classes .= ' espresso-admin';
1911
+				}
1912
+				return $classes;
1913
+			}
1914
+		);
1915
+	}
1916
+
1917
+
1918
+	/**
1919
+	 *        admin_footer_scripts_eei18n_js_strings
1920
+	 *
1921
+	 * @return        void
1922
+	 */
1923
+	public function admin_footer_scripts_eei18n_js_strings()
1924
+	{
1925
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1926
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1927
+			__(
1928
+				'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!!!',
1929
+				'event_espresso'
1930
+			)
1931
+		);
1932
+		EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1933
+		EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1934
+		EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1935
+		EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1936
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1937
+		EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1938
+		EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1939
+		EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1940
+		EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1941
+		EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1942
+		EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1943
+		EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1944
+		EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1945
+		EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1946
+		EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1947
+		EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1948
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1949
+		EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1950
+		EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1951
+		EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1952
+		EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1953
+		EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1954
+		EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1955
+		EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1956
+		EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1957
+		EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1958
+		EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1959
+		EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1960
+		EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1961
+		EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1962
+		EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1963
+		EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1964
+		EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1965
+		EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1966
+		EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1967
+		EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1968
+		EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1969
+		EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1970
+	}
1971
+
1972
+
1973
+	/**
1974
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1975
+	 *
1976
+	 * @return        void
1977
+	 */
1978
+	public function add_xdebug_style()
1979
+	{
1980
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1981
+	}
1982
+
1983
+
1984
+	/************************/
1985
+	/** LIST TABLE METHODS **/
1986
+	/************************/
1987
+	/**
1988
+	 * this sets up the list table if the current view requires it.
1989
+	 *
1990
+	 * @return void
1991
+	 * @throws EE_Error
1992
+	 * @throws InvalidArgumentException
1993
+	 * @throws InvalidDataTypeException
1994
+	 * @throws InvalidInterfaceException
1995
+	 */
1996
+	protected function _set_list_table()
1997
+	{
1998
+		// first is this a list_table view?
1999
+		if (! isset($this->_route_config['list_table'])) {
2000
+			return;
2001
+		} //not a list_table view so get out.
2002
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2003
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2004
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2005
+			// user error msg
2006
+			$error_msg = esc_html__(
2007
+				'An error occurred. The requested list table views could not be found.',
2008
+				'event_espresso'
2009
+			);
2010
+			// developer error msg
2011
+			$error_msg .= '||'
2012
+						  . sprintf(
2013
+							  esc_html__(
2014
+								  '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.',
2015
+								  'event_espresso'
2016
+							  ),
2017
+							  $this->_req_action,
2018
+							  $list_table_view
2019
+						  );
2020
+			throw new EE_Error($error_msg);
2021
+		}
2022
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2023
+		$this->_views = apply_filters(
2024
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2025
+			$this->_views
2026
+		);
2027
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2028
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2029
+		$this->_set_list_table_view();
2030
+		$this->_set_list_table_object();
2031
+	}
2032
+
2033
+
2034
+	/**
2035
+	 * set current view for List Table
2036
+	 *
2037
+	 * @return void
2038
+	 */
2039
+	protected function _set_list_table_view()
2040
+	{
2041
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2042
+		$status = $this->request->getRequestParam('status', null, 'key');
2043
+		$this->_view = $status && array_key_exists($status, $this->_views)
2044
+			? $status
2045
+			: $this->_view;
2046
+	}
2047
+
2048
+
2049
+	/**
2050
+	 * _set_list_table_object
2051
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2052
+	 *
2053
+	 * @throws InvalidInterfaceException
2054
+	 * @throws InvalidArgumentException
2055
+	 * @throws InvalidDataTypeException
2056
+	 * @throws EE_Error
2057
+	 * @throws InvalidInterfaceException
2058
+	 */
2059
+	protected function _set_list_table_object()
2060
+	{
2061
+		if (isset($this->_route_config['list_table'])) {
2062
+			if (! class_exists($this->_route_config['list_table'])) {
2063
+				throw new EE_Error(
2064
+					sprintf(
2065
+						esc_html__(
2066
+							'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.',
2067
+							'event_espresso'
2068
+						),
2069
+						$this->_route_config['list_table'],
2070
+						$this->class_name
2071
+					)
2072
+				);
2073
+			}
2074
+			$this->_list_table_object = $this->loader->getShared(
2075
+				$this->_route_config['list_table'],
2076
+				[$this]
2077
+			);
2078
+		}
2079
+	}
2080
+
2081
+
2082
+	/**
2083
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2084
+	 *
2085
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2086
+	 *                                                    urls.  The array should be indexed by the view it is being
2087
+	 *                                                    added to.
2088
+	 * @return array
2089
+	 */
2090
+	public function get_list_table_view_RLs($extra_query_args = [])
2091
+	{
2092
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2093
+		if (empty($this->_views)) {
2094
+			$this->_views = [];
2095
+		}
2096
+		// cycle thru views
2097
+		foreach ($this->_views as $key => $view) {
2098
+			$query_args = [];
2099
+			// check for current view
2100
+			$this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2101
+			$query_args['action']                        = $this->_req_action;
2102
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2103
+			$query_args['status']                        = $view['slug'];
2104
+			// merge any other arguments sent in.
2105
+			if (isset($extra_query_args[ $view['slug'] ])) {
2106
+				foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2107
+					$query_args[] = $extra_query_arg;
2108
+				}
2109
+			}
2110
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2111
+		}
2112
+		return $this->_views;
2113
+	}
2114
+
2115
+
2116
+	/**
2117
+	 * _entries_per_page_dropdown
2118
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2119
+	 *
2120
+	 * @param int $max_entries total number of rows in the table
2121
+	 * @return string
2122
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2123
+	 *         WP does it.
2124
+	 */
2125
+	protected function _entries_per_page_dropdown($max_entries = 0)
2126
+	{
2127
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2128
+		$values   = [10, 25, 50, 100];
2129
+		$per_page = $this->request->getRequestParam('per_page', 10, 'int');
2130
+		if ($max_entries) {
2131
+			$values[] = $max_entries;
2132
+			sort($values);
2133
+		}
2134
+		$entries_per_page_dropdown = '
2135 2135
 			<div id="entries-per-page-dv" class="alignleft actions">
2136 2136
 				<label class="hide-if-no-js">
2137 2137
 					Show
2138 2138
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2139
-        foreach ($values as $value) {
2140
-            if ($value < $max_entries) {
2141
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2142
-                $entries_per_page_dropdown .= '
2139
+		foreach ($values as $value) {
2140
+			if ($value < $max_entries) {
2141
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2142
+				$entries_per_page_dropdown .= '
2143 2143
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2144
-            }
2145
-        }
2146
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2147
-        $entries_per_page_dropdown .= '
2144
+			}
2145
+		}
2146
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2147
+		$entries_per_page_dropdown .= '
2148 2148
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2149
-        $entries_per_page_dropdown .= '
2149
+		$entries_per_page_dropdown .= '
2150 2150
 					</select>
2151 2151
 					entries
2152 2152
 				</label>
2153 2153
 				<input id="entries-per-page-btn" class="button button--secondary" type="submit" value="Go" >
2154 2154
 			</div>
2155 2155
 		';
2156
-        return $entries_per_page_dropdown;
2157
-    }
2158
-
2159
-
2160
-    /**
2161
-     *        _set_search_attributes
2162
-     *
2163
-     * @return        void
2164
-     */
2165
-    public function _set_search_attributes()
2166
-    {
2167
-        $this->_template_args['search']['btn_label'] = sprintf(
2168
-            esc_html__('Search %s', 'event_espresso'),
2169
-            empty($this->_search_btn_label) ? $this->page_label
2170
-                : $this->_search_btn_label
2171
-        );
2172
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2173
-    }
2174
-
2175
-
2176
-
2177
-    /*** END LIST TABLE METHODS **/
2178
-
2179
-
2180
-    /**
2181
-     * _add_registered_metaboxes
2182
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2183
-     *
2184
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2185
-     * @return void
2186
-     * @throws EE_Error
2187
-     */
2188
-    private function _add_registered_meta_boxes()
2189
-    {
2190
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2191
-        // we only add meta boxes if the page_route calls for it
2192
-        if (
2193
-            is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2194
-            && is_array(
2195
-                $this->_route_config['metaboxes']
2196
-            )
2197
-        ) {
2198
-            // this simply loops through the callbacks provided
2199
-            // and checks if there is a corresponding callback registered by the child
2200
-            // if there is then we go ahead and process the metabox loader.
2201
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2202
-                // first check for Closures
2203
-                if ($metabox_callback instanceof Closure) {
2204
-                    $result = $metabox_callback();
2205
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2206
-                    $result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2207
-                } else {
2208
-                    $result = $this->{$metabox_callback}();
2209
-                }
2210
-                if ($result === false) {
2211
-                    // user error msg
2212
-                    $error_msg = esc_html__(
2213
-                        'An error occurred. The  requested metabox could not be found.',
2214
-                        'event_espresso'
2215
-                    );
2216
-                    // developer error msg
2217
-                    $error_msg .= '||'
2218
-                                  . sprintf(
2219
-                                      esc_html__(
2220
-                                          '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.',
2221
-                                          'event_espresso'
2222
-                                      ),
2223
-                                      $metabox_callback
2224
-                                  );
2225
-                    throw new EE_Error($error_msg);
2226
-                }
2227
-            }
2228
-        }
2229
-    }
2230
-
2231
-
2232
-    /**
2233
-     * _add_screen_columns
2234
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2235
-     * the dynamic column template and we'll setup the column options for the page.
2236
-     *
2237
-     * @return void
2238
-     */
2239
-    private function _add_screen_columns()
2240
-    {
2241
-        if (
2242
-            is_array($this->_route_config)
2243
-            && isset($this->_route_config['columns'])
2244
-            && is_array($this->_route_config['columns'])
2245
-            && count($this->_route_config['columns']) === 2
2246
-        ) {
2247
-            add_screen_option(
2248
-                'layout_columns',
2249
-                [
2250
-                    'max'     => (int) $this->_route_config['columns'][0],
2251
-                    'default' => (int) $this->_route_config['columns'][1],
2252
-                ]
2253
-            );
2254
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2255
-            $screen_id                                           = $this->_current_screen->id;
2256
-            $screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2257
-            $total_columns                                       = ! empty($screen_columns)
2258
-                ? $screen_columns
2259
-                : $this->_route_config['columns'][1];
2260
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2261
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2262
-            $this->_template_args['screen']                      = $this->_current_screen;
2263
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2264
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2265
-            // finally if we don't have has_metaboxes set in the route config
2266
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2267
-            $this->_route_config['has_metaboxes'] = true;
2268
-        }
2269
-    }
2270
-
2271
-
2272
-
2273
-    /** GLOBALLY AVAILABLE METABOXES **/
2274
-
2275
-
2276
-    /**
2277
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2278
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2279
-     * these get loaded on.
2280
-     */
2281
-    private function _espresso_news_post_box()
2282
-    {
2283
-        $news_box_title = apply_filters(
2284
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2285
-            esc_html__('New @ Event Espresso', 'event_espresso')
2286
-        );
2287
-        $this->addMetaBox(
2288
-            'espresso_news_post_box',
2289
-            $news_box_title,
2290
-            [
2291
-                $this,
2292
-                'espresso_news_post_box',
2293
-            ],
2294
-            $this->_wp_page_slug,
2295
-            'side',
2296
-            'low'
2297
-        );
2298
-    }
2299
-
2300
-
2301
-    /**
2302
-     * Code for setting up espresso ratings request metabox.
2303
-     */
2304
-    protected function _espresso_ratings_request()
2305
-    {
2306
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2307
-            return;
2308
-        }
2309
-        $ratings_box_title = apply_filters(
2310
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2311
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2312
-        );
2313
-        $this->addMetaBox(
2314
-            'espresso_ratings_request',
2315
-            $ratings_box_title,
2316
-            [
2317
-                $this,
2318
-                'espresso_ratings_request',
2319
-            ],
2320
-            $this->_wp_page_slug,
2321
-            'side'
2322
-        );
2323
-    }
2324
-
2325
-
2326
-    /**
2327
-     * Code for setting up espresso ratings request metabox content.
2328
-     *
2329
-     * @throws DomainException
2330
-     */
2331
-    public function espresso_ratings_request()
2332
-    {
2333
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2334
-    }
2335
-
2336
-
2337
-    public static function cached_rss_display($rss_id, $url)
2338
-    {
2339
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2340
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2341
-                     . '</p><p class="hide-if-js">'
2342
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2343
-                     . '</p>';
2344
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2345
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2346
-        $post      = '</div>' . "\n";
2347
-        $cache_key = 'ee_rss_' . md5($rss_id);
2348
-        $output    = get_transient($cache_key);
2349
-        if ($output !== false) {
2350
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2351
-            return true;
2352
-        }
2353
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2355
-            return false;
2356
-        }
2357
-        ob_start();
2358
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2359
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2360
-        return true;
2361
-    }
2362
-
2363
-
2364
-    public function espresso_news_post_box()
2365
-    {
2366
-        ?>
2156
+		return $entries_per_page_dropdown;
2157
+	}
2158
+
2159
+
2160
+	/**
2161
+	 *        _set_search_attributes
2162
+	 *
2163
+	 * @return        void
2164
+	 */
2165
+	public function _set_search_attributes()
2166
+	{
2167
+		$this->_template_args['search']['btn_label'] = sprintf(
2168
+			esc_html__('Search %s', 'event_espresso'),
2169
+			empty($this->_search_btn_label) ? $this->page_label
2170
+				: $this->_search_btn_label
2171
+		);
2172
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2173
+	}
2174
+
2175
+
2176
+
2177
+	/*** END LIST TABLE METHODS **/
2178
+
2179
+
2180
+	/**
2181
+	 * _add_registered_metaboxes
2182
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2183
+	 *
2184
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2185
+	 * @return void
2186
+	 * @throws EE_Error
2187
+	 */
2188
+	private function _add_registered_meta_boxes()
2189
+	{
2190
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2191
+		// we only add meta boxes if the page_route calls for it
2192
+		if (
2193
+			is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2194
+			&& is_array(
2195
+				$this->_route_config['metaboxes']
2196
+			)
2197
+		) {
2198
+			// this simply loops through the callbacks provided
2199
+			// and checks if there is a corresponding callback registered by the child
2200
+			// if there is then we go ahead and process the metabox loader.
2201
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2202
+				// first check for Closures
2203
+				if ($metabox_callback instanceof Closure) {
2204
+					$result = $metabox_callback();
2205
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2206
+					$result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2207
+				} else {
2208
+					$result = $this->{$metabox_callback}();
2209
+				}
2210
+				if ($result === false) {
2211
+					// user error msg
2212
+					$error_msg = esc_html__(
2213
+						'An error occurred. The  requested metabox could not be found.',
2214
+						'event_espresso'
2215
+					);
2216
+					// developer error msg
2217
+					$error_msg .= '||'
2218
+								  . sprintf(
2219
+									  esc_html__(
2220
+										  '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.',
2221
+										  'event_espresso'
2222
+									  ),
2223
+									  $metabox_callback
2224
+								  );
2225
+					throw new EE_Error($error_msg);
2226
+				}
2227
+			}
2228
+		}
2229
+	}
2230
+
2231
+
2232
+	/**
2233
+	 * _add_screen_columns
2234
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2235
+	 * the dynamic column template and we'll setup the column options for the page.
2236
+	 *
2237
+	 * @return void
2238
+	 */
2239
+	private function _add_screen_columns()
2240
+	{
2241
+		if (
2242
+			is_array($this->_route_config)
2243
+			&& isset($this->_route_config['columns'])
2244
+			&& is_array($this->_route_config['columns'])
2245
+			&& count($this->_route_config['columns']) === 2
2246
+		) {
2247
+			add_screen_option(
2248
+				'layout_columns',
2249
+				[
2250
+					'max'     => (int) $this->_route_config['columns'][0],
2251
+					'default' => (int) $this->_route_config['columns'][1],
2252
+				]
2253
+			);
2254
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2255
+			$screen_id                                           = $this->_current_screen->id;
2256
+			$screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2257
+			$total_columns                                       = ! empty($screen_columns)
2258
+				? $screen_columns
2259
+				: $this->_route_config['columns'][1];
2260
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2261
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2262
+			$this->_template_args['screen']                      = $this->_current_screen;
2263
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2264
+																   . 'admin_details_metabox_column_wrapper.template.php';
2265
+			// finally if we don't have has_metaboxes set in the route config
2266
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2267
+			$this->_route_config['has_metaboxes'] = true;
2268
+		}
2269
+	}
2270
+
2271
+
2272
+
2273
+	/** GLOBALLY AVAILABLE METABOXES **/
2274
+
2275
+
2276
+	/**
2277
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2278
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2279
+	 * these get loaded on.
2280
+	 */
2281
+	private function _espresso_news_post_box()
2282
+	{
2283
+		$news_box_title = apply_filters(
2284
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2285
+			esc_html__('New @ Event Espresso', 'event_espresso')
2286
+		);
2287
+		$this->addMetaBox(
2288
+			'espresso_news_post_box',
2289
+			$news_box_title,
2290
+			[
2291
+				$this,
2292
+				'espresso_news_post_box',
2293
+			],
2294
+			$this->_wp_page_slug,
2295
+			'side',
2296
+			'low'
2297
+		);
2298
+	}
2299
+
2300
+
2301
+	/**
2302
+	 * Code for setting up espresso ratings request metabox.
2303
+	 */
2304
+	protected function _espresso_ratings_request()
2305
+	{
2306
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2307
+			return;
2308
+		}
2309
+		$ratings_box_title = apply_filters(
2310
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2311
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2312
+		);
2313
+		$this->addMetaBox(
2314
+			'espresso_ratings_request',
2315
+			$ratings_box_title,
2316
+			[
2317
+				$this,
2318
+				'espresso_ratings_request',
2319
+			],
2320
+			$this->_wp_page_slug,
2321
+			'side'
2322
+		);
2323
+	}
2324
+
2325
+
2326
+	/**
2327
+	 * Code for setting up espresso ratings request metabox content.
2328
+	 *
2329
+	 * @throws DomainException
2330
+	 */
2331
+	public function espresso_ratings_request()
2332
+	{
2333
+		EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2334
+	}
2335
+
2336
+
2337
+	public static function cached_rss_display($rss_id, $url)
2338
+	{
2339
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2340
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2341
+					 . '</p><p class="hide-if-js">'
2342
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2343
+					 . '</p>';
2344
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2345
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2346
+		$post      = '</div>' . "\n";
2347
+		$cache_key = 'ee_rss_' . md5($rss_id);
2348
+		$output    = get_transient($cache_key);
2349
+		if ($output !== false) {
2350
+			echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2351
+			return true;
2352
+		}
2353
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
+			echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2355
+			return false;
2356
+		}
2357
+		ob_start();
2358
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2359
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2360
+		return true;
2361
+	}
2362
+
2363
+
2364
+	public function espresso_news_post_box()
2365
+	{
2366
+		?>
2367 2367
         <div class="padding">
2368 2368
             <div id="espresso_news_post_box_content" class="infolinks">
2369 2369
                 <?php
2370
-                // Get RSS Feed(s)
2371
-                EE_Admin_Page::cached_rss_display(
2372
-                    'espresso_news_post_box_content',
2373
-                    esc_url_raw(
2374
-                        apply_filters(
2375
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2376
-                            'https://eventespresso.com/feed/'
2377
-                        )
2378
-                    )
2379
-                );
2380
-                ?>
2370
+				// Get RSS Feed(s)
2371
+				EE_Admin_Page::cached_rss_display(
2372
+					'espresso_news_post_box_content',
2373
+					esc_url_raw(
2374
+						apply_filters(
2375
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2376
+							'https://eventespresso.com/feed/'
2377
+						)
2378
+					)
2379
+				);
2380
+				?>
2381 2381
             </div>
2382 2382
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2383 2383
         </div>
2384 2384
         <?php
2385
-    }
2386
-
2387
-
2388
-    private function _espresso_links_post_box()
2389
-    {
2390
-        // Hiding until we actually have content to put in here...
2391
-        // $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2392
-    }
2393
-
2394
-
2395
-    public function espresso_links_post_box()
2396
-    {
2397
-        // Hiding until we actually have content to put in here...
2398
-        // EEH_Template::display_template(
2399
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2400
-        // );
2401
-    }
2402
-
2403
-
2404
-    protected function _espresso_sponsors_post_box()
2405
-    {
2406
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2407
-            $this->addMetaBox(
2408
-                'espresso_sponsors_post_box',
2409
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2410
-                [$this, 'espresso_sponsors_post_box'],
2411
-                $this->_wp_page_slug,
2412
-                'side'
2413
-            );
2414
-        }
2415
-    }
2416
-
2417
-
2418
-    public function espresso_sponsors_post_box()
2419
-    {
2420
-        EEH_Template::display_template(
2421
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2422
-        );
2423
-    }
2424
-
2425
-
2426
-    private function _publish_post_box()
2427
-    {
2428
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2429
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2430
-        // then we'll use that for the metabox label.
2431
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2432
-        if (! empty($this->_labels['publishbox'])) {
2433
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2434
-                : $this->_labels['publishbox'];
2435
-        } else {
2436
-            $box_label = esc_html__('Publish', 'event_espresso');
2437
-        }
2438
-        $box_label = apply_filters(
2439
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2440
-            $box_label,
2441
-            $this->_req_action,
2442
-            $this
2443
-        );
2444
-        $this->addMetaBox(
2445
-            $meta_box_ref,
2446
-            $box_label,
2447
-            [$this, 'editor_overview'],
2448
-            $this->_current_screen->id,
2449
-            'side',
2450
-            'high'
2451
-        );
2452
-    }
2453
-
2454
-
2455
-    public function editor_overview()
2456
-    {
2457
-        // if we have extra content set let's add it in if not make sure its empty
2458
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2459
-            ? $this->_template_args['publish_box_extra_content']
2460
-            : '';
2461
-        echo EEH_Template::display_template(
2462
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2463
-            $this->_template_args,
2464
-            true
2465
-        );
2466
-    }
2467
-
2468
-
2469
-    /** end of globally available metaboxes section **/
2470
-
2471
-
2472
-    /**
2473
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2474
-     * protected method.
2475
-     *
2476
-     * @param string $name
2477
-     * @param int    $id
2478
-     * @param bool   $delete
2479
-     * @param string $save_close_redirect_URL
2480
-     * @param bool   $both_btns
2481
-     * @throws EE_Error
2482
-     * @throws InvalidArgumentException
2483
-     * @throws InvalidDataTypeException
2484
-     * @throws InvalidInterfaceException
2485
-     * @see   $this->_set_publish_post_box_vars for param details
2486
-     * @since 4.6.0
2487
-     */
2488
-    public function set_publish_post_box_vars(
2489
-        $name = '',
2490
-        $id = 0,
2491
-        $delete = false,
2492
-        $save_close_redirect_URL = '',
2493
-        $both_btns = true
2494
-    ) {
2495
-        $this->_set_publish_post_box_vars(
2496
-            $name,
2497
-            $id,
2498
-            $delete,
2499
-            $save_close_redirect_URL,
2500
-            $both_btns
2501
-        );
2502
-    }
2503
-
2504
-
2505
-    /**
2506
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2507
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2508
-     * save, and save and close buttons to work properly, then you will want to include a
2509
-     * values for the name and id arguments.
2510
-     *
2511
-     * @param string  $name                       key used for the action ID (i.e. event_id)
2512
-     * @param int     $id                         id attached to the item published
2513
-     * @param string  $delete                     page route callback for the delete action
2514
-     * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2515
-     * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2516
-     *                                            the Save button
2517
-     * @throws EE_Error
2518
-     * @throws InvalidArgumentException
2519
-     * @throws InvalidDataTypeException
2520
-     * @throws InvalidInterfaceException
2521
-     * @todo  Add in validation for name/id arguments.
2522
-     */
2523
-    protected function _set_publish_post_box_vars(
2524
-        $name = '',
2525
-        $id = 0,
2526
-        $delete = '',
2527
-        $save_close_redirect_URL = '',
2528
-        $both_btns = true
2529
-    ) {
2530
-        // if Save & Close, use a custom redirect URL or default to the main page?
2531
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2532
-            ? $save_close_redirect_URL
2533
-            : $this->_admin_base_url;
2534
-        // create the Save & Close and Save buttons
2535
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2536
-        // if we have extra content set let's add it in if not make sure its empty
2537
-        $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2538
-        $delete_link = '';
2539
-        if ($delete && ! empty($id)) {
2540
-            // make sure we have a default if just true is sent.
2541
-            $delete           = ! empty($delete) ? $delete : 'delete';
2542
-            $delete_link      = $this->get_action_link_or_button(
2543
-                $delete,
2544
-                $delete,
2545
-                [$name => $id],
2546
-                'submitdelete deletion button button--outline button--caution'
2547
-            );
2548
-        }
2549
-        $this->_template_args['publish_delete_link'] = $delete_link;
2550
-        if (! empty($name) && ! empty($id)) {
2551
-            $hidden_field_arr[ $name ] = [
2552
-                'type'  => 'hidden',
2553
-                'value' => $id,
2554
-            ];
2555
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2556
-        } else {
2557
-            $hf = '';
2558
-        }
2559
-        // add hidden field
2560
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2561
-            ? $hf[ $name ]['field']
2562
-            : $hf;
2563
-    }
2564
-
2565
-
2566
-    /**
2567
-     * displays an error message to ppl who have javascript disabled
2568
-     *
2569
-     * @return void
2570
-     */
2571
-    private function _display_no_javascript_warning()
2572
-    {
2573
-        ?>
2385
+	}
2386
+
2387
+
2388
+	private function _espresso_links_post_box()
2389
+	{
2390
+		// Hiding until we actually have content to put in here...
2391
+		// $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2392
+	}
2393
+
2394
+
2395
+	public function espresso_links_post_box()
2396
+	{
2397
+		// Hiding until we actually have content to put in here...
2398
+		// EEH_Template::display_template(
2399
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2400
+		// );
2401
+	}
2402
+
2403
+
2404
+	protected function _espresso_sponsors_post_box()
2405
+	{
2406
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2407
+			$this->addMetaBox(
2408
+				'espresso_sponsors_post_box',
2409
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2410
+				[$this, 'espresso_sponsors_post_box'],
2411
+				$this->_wp_page_slug,
2412
+				'side'
2413
+			);
2414
+		}
2415
+	}
2416
+
2417
+
2418
+	public function espresso_sponsors_post_box()
2419
+	{
2420
+		EEH_Template::display_template(
2421
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2422
+		);
2423
+	}
2424
+
2425
+
2426
+	private function _publish_post_box()
2427
+	{
2428
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2429
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2430
+		// then we'll use that for the metabox label.
2431
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2432
+		if (! empty($this->_labels['publishbox'])) {
2433
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2434
+				: $this->_labels['publishbox'];
2435
+		} else {
2436
+			$box_label = esc_html__('Publish', 'event_espresso');
2437
+		}
2438
+		$box_label = apply_filters(
2439
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2440
+			$box_label,
2441
+			$this->_req_action,
2442
+			$this
2443
+		);
2444
+		$this->addMetaBox(
2445
+			$meta_box_ref,
2446
+			$box_label,
2447
+			[$this, 'editor_overview'],
2448
+			$this->_current_screen->id,
2449
+			'side',
2450
+			'high'
2451
+		);
2452
+	}
2453
+
2454
+
2455
+	public function editor_overview()
2456
+	{
2457
+		// if we have extra content set let's add it in if not make sure its empty
2458
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2459
+			? $this->_template_args['publish_box_extra_content']
2460
+			: '';
2461
+		echo EEH_Template::display_template(
2462
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2463
+			$this->_template_args,
2464
+			true
2465
+		);
2466
+	}
2467
+
2468
+
2469
+	/** end of globally available metaboxes section **/
2470
+
2471
+
2472
+	/**
2473
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2474
+	 * protected method.
2475
+	 *
2476
+	 * @param string $name
2477
+	 * @param int    $id
2478
+	 * @param bool   $delete
2479
+	 * @param string $save_close_redirect_URL
2480
+	 * @param bool   $both_btns
2481
+	 * @throws EE_Error
2482
+	 * @throws InvalidArgumentException
2483
+	 * @throws InvalidDataTypeException
2484
+	 * @throws InvalidInterfaceException
2485
+	 * @see   $this->_set_publish_post_box_vars for param details
2486
+	 * @since 4.6.0
2487
+	 */
2488
+	public function set_publish_post_box_vars(
2489
+		$name = '',
2490
+		$id = 0,
2491
+		$delete = false,
2492
+		$save_close_redirect_URL = '',
2493
+		$both_btns = true
2494
+	) {
2495
+		$this->_set_publish_post_box_vars(
2496
+			$name,
2497
+			$id,
2498
+			$delete,
2499
+			$save_close_redirect_URL,
2500
+			$both_btns
2501
+		);
2502
+	}
2503
+
2504
+
2505
+	/**
2506
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2507
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2508
+	 * save, and save and close buttons to work properly, then you will want to include a
2509
+	 * values for the name and id arguments.
2510
+	 *
2511
+	 * @param string  $name                       key used for the action ID (i.e. event_id)
2512
+	 * @param int     $id                         id attached to the item published
2513
+	 * @param string  $delete                     page route callback for the delete action
2514
+	 * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2515
+	 * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2516
+	 *                                            the Save button
2517
+	 * @throws EE_Error
2518
+	 * @throws InvalidArgumentException
2519
+	 * @throws InvalidDataTypeException
2520
+	 * @throws InvalidInterfaceException
2521
+	 * @todo  Add in validation for name/id arguments.
2522
+	 */
2523
+	protected function _set_publish_post_box_vars(
2524
+		$name = '',
2525
+		$id = 0,
2526
+		$delete = '',
2527
+		$save_close_redirect_URL = '',
2528
+		$both_btns = true
2529
+	) {
2530
+		// if Save & Close, use a custom redirect URL or default to the main page?
2531
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2532
+			? $save_close_redirect_URL
2533
+			: $this->_admin_base_url;
2534
+		// create the Save & Close and Save buttons
2535
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2536
+		// if we have extra content set let's add it in if not make sure its empty
2537
+		$this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2538
+		$delete_link = '';
2539
+		if ($delete && ! empty($id)) {
2540
+			// make sure we have a default if just true is sent.
2541
+			$delete           = ! empty($delete) ? $delete : 'delete';
2542
+			$delete_link      = $this->get_action_link_or_button(
2543
+				$delete,
2544
+				$delete,
2545
+				[$name => $id],
2546
+				'submitdelete deletion button button--outline button--caution'
2547
+			);
2548
+		}
2549
+		$this->_template_args['publish_delete_link'] = $delete_link;
2550
+		if (! empty($name) && ! empty($id)) {
2551
+			$hidden_field_arr[ $name ] = [
2552
+				'type'  => 'hidden',
2553
+				'value' => $id,
2554
+			];
2555
+			$hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2556
+		} else {
2557
+			$hf = '';
2558
+		}
2559
+		// add hidden field
2560
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2561
+			? $hf[ $name ]['field']
2562
+			: $hf;
2563
+	}
2564
+
2565
+
2566
+	/**
2567
+	 * displays an error message to ppl who have javascript disabled
2568
+	 *
2569
+	 * @return void
2570
+	 */
2571
+	private function _display_no_javascript_warning()
2572
+	{
2573
+		?>
2574 2574
         <noscript>
2575 2575
             <div id="no-js-message" class="error">
2576 2576
                 <p style="font-size:1.3em;">
2577 2577
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2578 2578
                     <?php esc_html_e(
2579
-                        '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.',
2580
-                        'event_espresso'
2581
-                    ); ?>
2579
+						'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.',
2580
+						'event_espresso'
2581
+					); ?>
2582 2582
                 </p>
2583 2583
             </div>
2584 2584
         </noscript>
2585 2585
         <?php
2586
-    }
2587
-
2588
-
2589
-    /**
2590
-     * displays espresso success and/or error notices
2591
-     *
2592
-     * @return void
2593
-     */
2594
-    protected function _display_espresso_notices()
2595
-    {
2596
-        $notices = $this->_get_transient(true);
2597
-        echo stripslashes($notices);
2598
-    }
2599
-
2600
-
2601
-    /**
2602
-     * spinny things pacify the masses
2603
-     *
2604
-     * @return void
2605
-     */
2606
-    protected function _add_admin_page_ajax_loading_img()
2607
-    {
2608
-        ?>
2586
+	}
2587
+
2588
+
2589
+	/**
2590
+	 * displays espresso success and/or error notices
2591
+	 *
2592
+	 * @return void
2593
+	 */
2594
+	protected function _display_espresso_notices()
2595
+	{
2596
+		$notices = $this->_get_transient(true);
2597
+		echo stripslashes($notices);
2598
+	}
2599
+
2600
+
2601
+	/**
2602
+	 * spinny things pacify the masses
2603
+	 *
2604
+	 * @return void
2605
+	 */
2606
+	protected function _add_admin_page_ajax_loading_img()
2607
+	{
2608
+		?>
2609 2609
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2610 2610
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2611
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2611
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2612 2612
         </div>
2613 2613
         <?php
2614
-    }
2614
+	}
2615 2615
 
2616 2616
 
2617
-    /**
2618
-     * add admin page overlay for modal boxes
2619
-     *
2620
-     * @return void
2621
-     */
2622
-    protected function _add_admin_page_overlay()
2623
-    {
2624
-        ?>
2617
+	/**
2618
+	 * add admin page overlay for modal boxes
2619
+	 *
2620
+	 * @return void
2621
+	 */
2622
+	protected function _add_admin_page_overlay()
2623
+	{
2624
+		?>
2625 2625
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2626 2626
         <?php
2627
-    }
2628
-
2629
-
2630
-    /**
2631
-     * facade for $this->addMetaBox()
2632
-     *
2633
-     * @param string  $action        where the metabox gets displayed
2634
-     * @param string  $title         Title of Metabox (output in metabox header)
2635
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2636
-     *                               instead of the one created in here.
2637
-     * @param array   $callback_args an array of args supplied for the metabox
2638
-     * @param string  $column        what metabox column
2639
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2640
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2641
-     *                               created but just set our own callback for wp's add_meta_box.
2642
-     * @throws DomainException
2643
-     */
2644
-    public function _add_admin_page_meta_box(
2645
-        $action,
2646
-        $title,
2647
-        $callback,
2648
-        $callback_args,
2649
-        $column = 'normal',
2650
-        $priority = 'high',
2651
-        $create_func = true
2652
-    ) {
2653
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2654
-        // 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.
2655
-        if (empty($callback_args) && $create_func) {
2656
-            $callback_args = [
2657
-                'template_path' => $this->_template_path,
2658
-                'template_args' => $this->_template_args,
2659
-            ];
2660
-        }
2661
-        // 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)
2662
-        $call_back_func = $create_func
2663
-            ? static function ($post, $metabox) {
2664
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2665
-                echo EEH_Template::display_template(
2666
-                    $metabox['args']['template_path'],
2667
-                    $metabox['args']['template_args'],
2668
-                    true
2669
-                );
2670
-            }
2671
-            : $callback;
2672
-        $this->addMetaBox(
2673
-            str_replace('_', '-', $action) . '-mbox',
2674
-            $title,
2675
-            $call_back_func,
2676
-            $this->_wp_page_slug,
2677
-            $column,
2678
-            $priority,
2679
-            $callback_args
2680
-        );
2681
-    }
2682
-
2683
-
2684
-    /**
2685
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2686
-     *
2687
-     * @throws DomainException
2688
-     * @throws EE_Error
2689
-     * @throws InvalidArgumentException
2690
-     * @throws InvalidDataTypeException
2691
-     * @throws InvalidInterfaceException
2692
-     */
2693
-    public function display_admin_page_with_metabox_columns()
2694
-    {
2695
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2696
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2697
-            $this->_column_template_path,
2698
-            $this->_template_args,
2699
-            true
2700
-        );
2701
-        // the final wrapper
2702
-        $this->admin_page_wrapper();
2703
-    }
2704
-
2705
-
2706
-    /**
2707
-     * generates  HTML wrapper for an admin details page
2708
-     *
2709
-     * @return void
2710
-     * @throws DomainException
2711
-     * @throws EE_Error
2712
-     * @throws InvalidArgumentException
2713
-     * @throws InvalidDataTypeException
2714
-     * @throws InvalidInterfaceException
2715
-     */
2716
-    public function display_admin_page_with_sidebar()
2717
-    {
2718
-        $this->_display_admin_page(true);
2719
-    }
2720
-
2721
-
2722
-    /**
2723
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2724
-     *
2725
-     * @return void
2726
-     * @throws DomainException
2727
-     * @throws EE_Error
2728
-     * @throws InvalidArgumentException
2729
-     * @throws InvalidDataTypeException
2730
-     * @throws InvalidInterfaceException
2731
-     */
2732
-    public function display_admin_page_with_no_sidebar()
2733
-    {
2734
-        $this->_display_admin_page();
2735
-    }
2736
-
2737
-
2738
-    /**
2739
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2740
-     *
2741
-     * @return void
2742
-     * @throws DomainException
2743
-     * @throws EE_Error
2744
-     * @throws InvalidArgumentException
2745
-     * @throws InvalidDataTypeException
2746
-     * @throws InvalidInterfaceException
2747
-     */
2748
-    public function display_about_admin_page()
2749
-    {
2750
-        $this->_display_admin_page(false, true);
2751
-    }
2752
-
2753
-
2754
-    /**
2755
-     * display_admin_page
2756
-     * contains the code for actually displaying an admin page
2757
-     *
2758
-     * @param boolean $sidebar true with sidebar, false without
2759
-     * @param boolean $about   use the about admin wrapper instead of the default.
2760
-     * @return void
2761
-     * @throws DomainException
2762
-     * @throws EE_Error
2763
-     * @throws InvalidArgumentException
2764
-     * @throws InvalidDataTypeException
2765
-     * @throws InvalidInterfaceException
2766
-     */
2767
-    private function _display_admin_page($sidebar = false, $about = false)
2768
-    {
2769
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2770
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2771
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2772
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2773
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2774
-
2775
-        $post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2776
-
2777
-        $this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2778
-                                                 && $this->_req_action !== 'data_reset'
2779
-                                                 && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2780
-                                                 && strpos($post_body_content, 'wp-list-table') === false;
2781
-
2782
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2783
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2784
-            ? 'poststuff'
2785
-            : 'espresso-default-admin';
2786
-        $this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2787
-            'event-espresso_page_espresso_',
2788
-            '',
2789
-            $this->_wp_page_slug
2790
-        ) . ' ' . $this->_req_action . '-route';
2791
-
2792
-        $template_path = $sidebar
2793
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2794
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2795
-        if ($this->request->isAjax()) {
2796
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2797
-        }
2798
-        $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2799
-
2800
-        $this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2801
-        $this->_template_args['before_admin_page_content'] = $post_body_content;
2802
-        $this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2803
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2804
-            $template_path,
2805
-            $this->_template_args,
2806
-            true
2807
-        );
2808
-        // the final template wrapper
2809
-        $this->admin_page_wrapper($about);
2810
-    }
2811
-
2812
-
2813
-    /**
2814
-     * This is used to display caf preview pages.
2815
-     *
2816
-     * @param string $utm_campaign_source what is the key used for google analytics link
2817
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2818
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2819
-     * @return void
2820
-     * @throws DomainException
2821
-     * @throws EE_Error
2822
-     * @throws InvalidArgumentException
2823
-     * @throws InvalidDataTypeException
2824
-     * @throws InvalidInterfaceException
2825
-     * @since 4.3.2
2826
-     */
2827
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2828
-    {
2829
-        // let's generate a default preview action button if there isn't one already present.
2830
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2831
-            'Upgrade to Event Espresso 4 Right Now',
2832
-            'event_espresso'
2833
-        );
2834
-        $buy_now_url                                   = add_query_arg(
2835
-            [
2836
-                'ee_ver'       => 'ee4',
2837
-                'utm_source'   => 'ee4_plugin_admin',
2838
-                'utm_medium'   => 'link',
2839
-                'utm_campaign' => $utm_campaign_source,
2840
-                'utm_content'  => 'buy_now_button',
2841
-            ],
2842
-            'https://eventespresso.com/pricing/'
2843
-        );
2844
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2845
-            ? $this->get_action_link_or_button(
2846
-                '',
2847
-                'buy_now',
2848
-                [],
2849
-                'button button--primary button--big',
2850
-                esc_url_raw($buy_now_url),
2851
-                true
2852
-            )
2853
-            : $this->_template_args['preview_action_button'];
2854
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2855
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2856
-            $this->_template_args,
2857
-            true
2858
-        );
2859
-        $this->_display_admin_page($display_sidebar);
2860
-    }
2861
-
2862
-
2863
-    /**
2864
-     * display_admin_list_table_page_with_sidebar
2865
-     * generates HTML wrapper for an admin_page with list_table
2866
-     *
2867
-     * @return void
2868
-     * @throws DomainException
2869
-     * @throws EE_Error
2870
-     * @throws InvalidArgumentException
2871
-     * @throws InvalidDataTypeException
2872
-     * @throws InvalidInterfaceException
2873
-     */
2874
-    public function display_admin_list_table_page_with_sidebar()
2875
-    {
2876
-        $this->_display_admin_list_table_page(true);
2877
-    }
2878
-
2879
-
2880
-    /**
2881
-     * display_admin_list_table_page_with_no_sidebar
2882
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2883
-     *
2884
-     * @return void
2885
-     * @throws DomainException
2886
-     * @throws EE_Error
2887
-     * @throws InvalidArgumentException
2888
-     * @throws InvalidDataTypeException
2889
-     * @throws InvalidInterfaceException
2890
-     */
2891
-    public function display_admin_list_table_page_with_no_sidebar()
2892
-    {
2893
-        $this->_display_admin_list_table_page();
2894
-    }
2895
-
2896
-
2897
-    /**
2898
-     * generates html wrapper for an admin_list_table page
2899
-     *
2900
-     * @param boolean $sidebar whether to display with sidebar or not.
2901
-     * @return void
2902
-     * @throws DomainException
2903
-     * @throws EE_Error
2904
-     * @throws InvalidArgumentException
2905
-     * @throws InvalidDataTypeException
2906
-     * @throws InvalidInterfaceException
2907
-     */
2908
-    private function _display_admin_list_table_page($sidebar = false)
2909
-    {
2910
-        // setup search attributes
2911
-        $this->_set_search_attributes();
2912
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
2913
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2914
-        $this->_template_args['table_url']        = $this->request->isAjax()
2915
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2916
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2917
-        $this->_template_args['list_table']       = $this->_list_table_object;
2918
-        $this->_template_args['current_route']    = $this->_req_action;
2919
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2920
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2921
-        if (! empty($ajax_sorting_callback)) {
2922
-            $sortable_list_table_form_fields = wp_nonce_field(
2923
-                $ajax_sorting_callback . '_nonce',
2924
-                $ajax_sorting_callback . '_nonce',
2925
-                false,
2926
-                false
2927
-            );
2928
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2929
-                                                . $this->page_slug
2930
-                                                . '" />';
2931
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2932
-                                                . $ajax_sorting_callback
2933
-                                                . '" />';
2934
-        } else {
2935
-            $sortable_list_table_form_fields = '';
2936
-        }
2937
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2938
-
2939
-        $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2940
-
2941
-        $nonce_ref          = $this->_req_action . '_nonce';
2942
-        $hidden_form_fields .= '
2627
+	}
2628
+
2629
+
2630
+	/**
2631
+	 * facade for $this->addMetaBox()
2632
+	 *
2633
+	 * @param string  $action        where the metabox gets displayed
2634
+	 * @param string  $title         Title of Metabox (output in metabox header)
2635
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2636
+	 *                               instead of the one created in here.
2637
+	 * @param array   $callback_args an array of args supplied for the metabox
2638
+	 * @param string  $column        what metabox column
2639
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2640
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2641
+	 *                               created but just set our own callback for wp's add_meta_box.
2642
+	 * @throws DomainException
2643
+	 */
2644
+	public function _add_admin_page_meta_box(
2645
+		$action,
2646
+		$title,
2647
+		$callback,
2648
+		$callback_args,
2649
+		$column = 'normal',
2650
+		$priority = 'high',
2651
+		$create_func = true
2652
+	) {
2653
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2654
+		// 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.
2655
+		if (empty($callback_args) && $create_func) {
2656
+			$callback_args = [
2657
+				'template_path' => $this->_template_path,
2658
+				'template_args' => $this->_template_args,
2659
+			];
2660
+		}
2661
+		// 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)
2662
+		$call_back_func = $create_func
2663
+			? static function ($post, $metabox) {
2664
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2665
+				echo EEH_Template::display_template(
2666
+					$metabox['args']['template_path'],
2667
+					$metabox['args']['template_args'],
2668
+					true
2669
+				);
2670
+			}
2671
+			: $callback;
2672
+		$this->addMetaBox(
2673
+			str_replace('_', '-', $action) . '-mbox',
2674
+			$title,
2675
+			$call_back_func,
2676
+			$this->_wp_page_slug,
2677
+			$column,
2678
+			$priority,
2679
+			$callback_args
2680
+		);
2681
+	}
2682
+
2683
+
2684
+	/**
2685
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2686
+	 *
2687
+	 * @throws DomainException
2688
+	 * @throws EE_Error
2689
+	 * @throws InvalidArgumentException
2690
+	 * @throws InvalidDataTypeException
2691
+	 * @throws InvalidInterfaceException
2692
+	 */
2693
+	public function display_admin_page_with_metabox_columns()
2694
+	{
2695
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2696
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2697
+			$this->_column_template_path,
2698
+			$this->_template_args,
2699
+			true
2700
+		);
2701
+		// the final wrapper
2702
+		$this->admin_page_wrapper();
2703
+	}
2704
+
2705
+
2706
+	/**
2707
+	 * generates  HTML wrapper for an admin details page
2708
+	 *
2709
+	 * @return void
2710
+	 * @throws DomainException
2711
+	 * @throws EE_Error
2712
+	 * @throws InvalidArgumentException
2713
+	 * @throws InvalidDataTypeException
2714
+	 * @throws InvalidInterfaceException
2715
+	 */
2716
+	public function display_admin_page_with_sidebar()
2717
+	{
2718
+		$this->_display_admin_page(true);
2719
+	}
2720
+
2721
+
2722
+	/**
2723
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2724
+	 *
2725
+	 * @return void
2726
+	 * @throws DomainException
2727
+	 * @throws EE_Error
2728
+	 * @throws InvalidArgumentException
2729
+	 * @throws InvalidDataTypeException
2730
+	 * @throws InvalidInterfaceException
2731
+	 */
2732
+	public function display_admin_page_with_no_sidebar()
2733
+	{
2734
+		$this->_display_admin_page();
2735
+	}
2736
+
2737
+
2738
+	/**
2739
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2740
+	 *
2741
+	 * @return void
2742
+	 * @throws DomainException
2743
+	 * @throws EE_Error
2744
+	 * @throws InvalidArgumentException
2745
+	 * @throws InvalidDataTypeException
2746
+	 * @throws InvalidInterfaceException
2747
+	 */
2748
+	public function display_about_admin_page()
2749
+	{
2750
+		$this->_display_admin_page(false, true);
2751
+	}
2752
+
2753
+
2754
+	/**
2755
+	 * display_admin_page
2756
+	 * contains the code for actually displaying an admin page
2757
+	 *
2758
+	 * @param boolean $sidebar true with sidebar, false without
2759
+	 * @param boolean $about   use the about admin wrapper instead of the default.
2760
+	 * @return void
2761
+	 * @throws DomainException
2762
+	 * @throws EE_Error
2763
+	 * @throws InvalidArgumentException
2764
+	 * @throws InvalidDataTypeException
2765
+	 * @throws InvalidInterfaceException
2766
+	 */
2767
+	private function _display_admin_page($sidebar = false, $about = false)
2768
+	{
2769
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2770
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2771
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2772
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2773
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2774
+
2775
+		$post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2776
+
2777
+		$this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2778
+												 && $this->_req_action !== 'data_reset'
2779
+												 && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2780
+												 && strpos($post_body_content, 'wp-list-table') === false;
2781
+
2782
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2783
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2784
+			? 'poststuff'
2785
+			: 'espresso-default-admin';
2786
+		$this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2787
+			'event-espresso_page_espresso_',
2788
+			'',
2789
+			$this->_wp_page_slug
2790
+		) . ' ' . $this->_req_action . '-route';
2791
+
2792
+		$template_path = $sidebar
2793
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2794
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2795
+		if ($this->request->isAjax()) {
2796
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2797
+		}
2798
+		$template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2799
+
2800
+		$this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2801
+		$this->_template_args['before_admin_page_content'] = $post_body_content;
2802
+		$this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2803
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2804
+			$template_path,
2805
+			$this->_template_args,
2806
+			true
2807
+		);
2808
+		// the final template wrapper
2809
+		$this->admin_page_wrapper($about);
2810
+	}
2811
+
2812
+
2813
+	/**
2814
+	 * This is used to display caf preview pages.
2815
+	 *
2816
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2817
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2818
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2819
+	 * @return void
2820
+	 * @throws DomainException
2821
+	 * @throws EE_Error
2822
+	 * @throws InvalidArgumentException
2823
+	 * @throws InvalidDataTypeException
2824
+	 * @throws InvalidInterfaceException
2825
+	 * @since 4.3.2
2826
+	 */
2827
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2828
+	{
2829
+		// let's generate a default preview action button if there isn't one already present.
2830
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2831
+			'Upgrade to Event Espresso 4 Right Now',
2832
+			'event_espresso'
2833
+		);
2834
+		$buy_now_url                                   = add_query_arg(
2835
+			[
2836
+				'ee_ver'       => 'ee4',
2837
+				'utm_source'   => 'ee4_plugin_admin',
2838
+				'utm_medium'   => 'link',
2839
+				'utm_campaign' => $utm_campaign_source,
2840
+				'utm_content'  => 'buy_now_button',
2841
+			],
2842
+			'https://eventespresso.com/pricing/'
2843
+		);
2844
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2845
+			? $this->get_action_link_or_button(
2846
+				'',
2847
+				'buy_now',
2848
+				[],
2849
+				'button button--primary button--big',
2850
+				esc_url_raw($buy_now_url),
2851
+				true
2852
+			)
2853
+			: $this->_template_args['preview_action_button'];
2854
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2855
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2856
+			$this->_template_args,
2857
+			true
2858
+		);
2859
+		$this->_display_admin_page($display_sidebar);
2860
+	}
2861
+
2862
+
2863
+	/**
2864
+	 * display_admin_list_table_page_with_sidebar
2865
+	 * generates HTML wrapper for an admin_page with list_table
2866
+	 *
2867
+	 * @return void
2868
+	 * @throws DomainException
2869
+	 * @throws EE_Error
2870
+	 * @throws InvalidArgumentException
2871
+	 * @throws InvalidDataTypeException
2872
+	 * @throws InvalidInterfaceException
2873
+	 */
2874
+	public function display_admin_list_table_page_with_sidebar()
2875
+	{
2876
+		$this->_display_admin_list_table_page(true);
2877
+	}
2878
+
2879
+
2880
+	/**
2881
+	 * display_admin_list_table_page_with_no_sidebar
2882
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2883
+	 *
2884
+	 * @return void
2885
+	 * @throws DomainException
2886
+	 * @throws EE_Error
2887
+	 * @throws InvalidArgumentException
2888
+	 * @throws InvalidDataTypeException
2889
+	 * @throws InvalidInterfaceException
2890
+	 */
2891
+	public function display_admin_list_table_page_with_no_sidebar()
2892
+	{
2893
+		$this->_display_admin_list_table_page();
2894
+	}
2895
+
2896
+
2897
+	/**
2898
+	 * generates html wrapper for an admin_list_table page
2899
+	 *
2900
+	 * @param boolean $sidebar whether to display with sidebar or not.
2901
+	 * @return void
2902
+	 * @throws DomainException
2903
+	 * @throws EE_Error
2904
+	 * @throws InvalidArgumentException
2905
+	 * @throws InvalidDataTypeException
2906
+	 * @throws InvalidInterfaceException
2907
+	 */
2908
+	private function _display_admin_list_table_page($sidebar = false)
2909
+	{
2910
+		// setup search attributes
2911
+		$this->_set_search_attributes();
2912
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
2913
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2914
+		$this->_template_args['table_url']        = $this->request->isAjax()
2915
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2916
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2917
+		$this->_template_args['list_table']       = $this->_list_table_object;
2918
+		$this->_template_args['current_route']    = $this->_req_action;
2919
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2920
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2921
+		if (! empty($ajax_sorting_callback)) {
2922
+			$sortable_list_table_form_fields = wp_nonce_field(
2923
+				$ajax_sorting_callback . '_nonce',
2924
+				$ajax_sorting_callback . '_nonce',
2925
+				false,
2926
+				false
2927
+			);
2928
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2929
+												. $this->page_slug
2930
+												. '" />';
2931
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2932
+												. $ajax_sorting_callback
2933
+												. '" />';
2934
+		} else {
2935
+			$sortable_list_table_form_fields = '';
2936
+		}
2937
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2938
+
2939
+		$hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2940
+
2941
+		$nonce_ref          = $this->_req_action . '_nonce';
2942
+		$hidden_form_fields .= '
2943 2943
             <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2944 2944
 
2945
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2946
-        // display message about search results?
2947
-        $search = $this->request->getRequestParam('s');
2948
-        $this->_template_args['before_list_table'] .= ! empty($search)
2949
-            ? '<p class="ee-search-results">' . sprintf(
2950
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2951
-                trim($search, '%')
2952
-            ) . '</p>'
2953
-            : '';
2954
-        // filter before_list_table template arg
2955
-        $this->_template_args['before_list_table'] = apply_filters(
2956
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2957
-            $this->_template_args['before_list_table'],
2958
-            $this->page_slug,
2959
-            $this->request->requestParams(),
2960
-            $this->_req_action
2961
-        );
2962
-        // convert to array and filter again
2963
-        // arrays are easier to inject new items in a specific location,
2964
-        // but would not be backwards compatible, so we have to add a new filter
2965
-        $this->_template_args['before_list_table'] = implode(
2966
-            " \n",
2967
-            (array) apply_filters(
2968
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2969
-                (array) $this->_template_args['before_list_table'],
2970
-                $this->page_slug,
2971
-                $this->request->requestParams(),
2972
-                $this->_req_action
2973
-            )
2974
-        );
2975
-        // filter after_list_table template arg
2976
-        $this->_template_args['after_list_table'] = apply_filters(
2977
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2978
-            $this->_template_args['after_list_table'],
2979
-            $this->page_slug,
2980
-            $this->request->requestParams(),
2981
-            $this->_req_action
2982
-        );
2983
-        // convert to array and filter again
2984
-        // arrays are easier to inject new items in a specific location,
2985
-        // but would not be backwards compatible, so we have to add a new filter
2986
-        $this->_template_args['after_list_table']   = implode(
2987
-            " \n",
2988
-            (array) apply_filters(
2989
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2990
-                (array) $this->_template_args['after_list_table'],
2991
-                $this->page_slug,
2992
-                $this->request->requestParams(),
2993
-                $this->_req_action
2994
-            )
2995
-        );
2996
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2997
-            $template_path,
2998
-            $this->_template_args,
2999
-            true
3000
-        );
3001
-        // the final template wrapper
3002
-        if ($sidebar) {
3003
-            $this->display_admin_page_with_sidebar();
3004
-        } else {
3005
-            $this->display_admin_page_with_no_sidebar();
3006
-        }
3007
-    }
3008
-
3009
-
3010
-    /**
3011
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3012
-     * html string for the legend.
3013
-     * $items are expected in an array in the following format:
3014
-     * $legend_items = array(
3015
-     *        'item_id' => array(
3016
-     *            'icon' => 'http://url_to_icon_being_described.png',
3017
-     *            'desc' => esc_html__('localized description of item');
3018
-     *        )
3019
-     * );
3020
-     *
3021
-     * @param array $items see above for format of array
3022
-     * @return string html string of legend
3023
-     * @throws DomainException
3024
-     */
3025
-    protected function _display_legend($items)
3026
-    {
3027
-        $this->_template_args['items'] = apply_filters(
3028
-            'FHEE__EE_Admin_Page___display_legend__items',
3029
-            (array) $items,
3030
-            $this
3031
-        );
3032
-        /** @var StatusChangeNotice $status_change_notice */
3033
-        $status_change_notice = $this->loader->getShared(
3034
-            'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3035
-        );
3036
-        $this->_template_args['status_change_notice'] = $status_change_notice->display(
3037
-            '__admin-legend',
3038
-            $this->page_slug
3039
-        );
3040
-        return EEH_Template::display_template(
3041
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3042
-            $this->_template_args,
3043
-            true
3044
-        );
3045
-    }
3046
-
3047
-
3048
-    /**
3049
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3050
-     * The returned json object is created from an array in the following format:
3051
-     * array(
3052
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3053
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3054
-     *  'notices' => '', // - contains any EE_Error formatted notices
3055
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3056
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3057
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3058
-     *  that might be included in here)
3059
-     * )
3060
-     * The json object is populated by whatever is set in the $_template_args property.
3061
-     *
3062
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3063
-     *                                 instead of displayed.
3064
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3065
-     * @return void
3066
-     * @throws EE_Error
3067
-     * @throws InvalidArgumentException
3068
-     * @throws InvalidDataTypeException
3069
-     * @throws InvalidInterfaceException
3070
-     */
3071
-    protected function _return_json($sticky_notices = false, $notices_arguments = [])
3072
-    {
3073
-        // make sure any EE_Error notices have been handled.
3074
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3075
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3076
-        unset($this->_template_args['data']);
3077
-        $json = [
3078
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3079
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3080
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3081
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3082
-            'notices'   => EE_Error::get_notices(),
3083
-            'content'   => isset($this->_template_args['admin_page_content'])
3084
-                ? $this->_template_args['admin_page_content'] : '',
3085
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3086
-            'isEEajax'  => true
3087
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3088
-        ];
3089
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3090
-        if (null === error_get_last() || ! headers_sent()) {
3091
-            header('Content-Type: application/json; charset=UTF-8');
3092
-        }
3093
-        echo wp_json_encode($json);
3094
-        exit();
3095
-    }
3096
-
3097
-
3098
-    /**
3099
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3100
-     *
3101
-     * @return void
3102
-     * @throws EE_Error
3103
-     * @throws InvalidArgumentException
3104
-     * @throws InvalidDataTypeException
3105
-     * @throws InvalidInterfaceException
3106
-     */
3107
-    public function return_json()
3108
-    {
3109
-        if ($this->request->isAjax()) {
3110
-            $this->_return_json();
3111
-        } else {
3112
-            throw new EE_Error(
3113
-                sprintf(
3114
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3115
-                    __FUNCTION__
3116
-                )
3117
-            );
3118
-        }
3119
-    }
3120
-
3121
-
3122
-    /**
3123
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3124
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3125
-     *
3126
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3127
-     */
3128
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3129
-    {
3130
-        $this->_hook_obj = $hook_obj;
3131
-    }
3132
-
3133
-
3134
-    /**
3135
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3136
-     *
3137
-     * @param boolean $about whether to use the special about page wrapper or default.
3138
-     * @return void
3139
-     * @throws DomainException
3140
-     * @throws EE_Error
3141
-     * @throws InvalidArgumentException
3142
-     * @throws InvalidDataTypeException
3143
-     * @throws InvalidInterfaceException
3144
-     */
3145
-    public function admin_page_wrapper($about = false)
3146
-    {
3147
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3148
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3149
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3150
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3151
-
3152
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3153
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3154
-            $this->_template_args['before_admin_page_content'] ?? ''
3155
-        );
3156
-
3157
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3158
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3159
-            $this->_template_args['after_admin_page_content'] ?? ''
3160
-        );
3161
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3162
-
3163
-        if ($this->request->isAjax()) {
3164
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3165
-                // $template_path,
3166
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3167
-                $this->_template_args,
3168
-                true
3169
-            );
3170
-            $this->_return_json();
3171
-        }
3172
-        // load settings page wrapper template
3173
-        $template_path = $about
3174
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3175
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3176
-
3177
-        EEH_Template::display_template($template_path, $this->_template_args);
3178
-    }
3179
-
3180
-
3181
-    /**
3182
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3183
-     *
3184
-     * @return string html
3185
-     * @throws EE_Error
3186
-     */
3187
-    protected function _get_main_nav_tabs()
3188
-    {
3189
-        // let's generate the html using the EEH_Tabbed_Content helper.
3190
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3191
-        // (rather than setting in the page_routes array)
3192
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3193
-    }
3194
-
3195
-
3196
-    /**
3197
-     *        sort nav tabs
3198
-     *
3199
-     * @param $a
3200
-     * @param $b
3201
-     * @return int
3202
-     */
3203
-    private function _sort_nav_tabs($a, $b)
3204
-    {
3205
-        if ($a['order'] === $b['order']) {
3206
-            return 0;
3207
-        }
3208
-        return ($a['order'] < $b['order']) ? -1 : 1;
3209
-    }
3210
-
3211
-
3212
-    /**
3213
-     * generates HTML for the forms used on admin pages
3214
-     *
3215
-     * @param array  $input_vars - array of input field details
3216
-     * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3217
-     * @param bool   $id
3218
-     * @return array|string
3219
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3220
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3221
-     */
3222
-    protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3223
-    {
3224
-        return $generator === 'string'
3225
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3226
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3227
-    }
3228
-
3229
-
3230
-    /**
3231
-     * generates the "Save" and "Save & Close" buttons for edit forms
3232
-     *
3233
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3234
-     *                                   Close" button.
3235
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3236
-     *                                   'Save', [1] => 'save & close')
3237
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3238
-     *                                   via the "name" value in the button).  We can also use this to just dump
3239
-     *                                   default actions by submitting some other value.
3240
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3241
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3242
-     *                                   close (normal form handling).
3243
-     */
3244
-    protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3245
-    {
3246
-        // make sure $text and $actions are in an array
3247
-        $text          = (array) $text;
3248
-        $actions       = (array) $actions;
3249
-        $referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3250
-        $button_text   = ! empty($text)
3251
-            ? $text
3252
-            : [
3253
-                esc_html__('Save', 'event_espresso'),
3254
-                esc_html__('Save and Close', 'event_espresso'),
3255
-            ];
3256
-        $default_names = ['save', 'save_and_close'];
3257
-        $buttons = '';
3258
-        foreach ($button_text as $key => $button) {
3259
-            $ref     = $default_names[ $key ];
3260
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3261
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3262
-                        . 'value="' . $button . '" name="' . $name . '" '
3263
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3264
-            if (! $both) {
3265
-                break;
3266
-            }
3267
-        }
3268
-        // add in a hidden index for the current page (so save and close redirects properly)
3269
-        $buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3270
-                   . $referrer_url
3271
-                   . '" />';
3272
-        $this->_template_args['save_buttons'] = $buttons;
3273
-    }
3274
-
3275
-
3276
-    /**
3277
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3278
-     *
3279
-     * @param string $route
3280
-     * @param array  $additional_hidden_fields
3281
-     * @see   $this->_set_add_edit_form_tags() for details on params
3282
-     * @since 4.6.0
3283
-     */
3284
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3285
-    {
3286
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3287
-    }
3288
-
3289
-
3290
-    /**
3291
-     * set form open and close tags on add/edit pages.
3292
-     *
3293
-     * @param string $route                    the route you want the form to direct to
3294
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3295
-     * @return void
3296
-     */
3297
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3298
-    {
3299
-        if (empty($route)) {
3300
-            $user_msg = esc_html__(
3301
-                'An error occurred. No action was set for this page\'s form.',
3302
-                'event_espresso'
3303
-            );
3304
-            $dev_msg  = $user_msg . "\n"
3305
-                        . sprintf(
3306
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3307
-                            __FUNCTION__,
3308
-                            __CLASS__
3309
-                        );
3310
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3311
-        }
3312
-        // open form
3313
-        $action = $this->_admin_base_url;
3314
-        $this->_template_args['before_admin_page_content'] = "
2945
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2946
+		// display message about search results?
2947
+		$search = $this->request->getRequestParam('s');
2948
+		$this->_template_args['before_list_table'] .= ! empty($search)
2949
+			? '<p class="ee-search-results">' . sprintf(
2950
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2951
+				trim($search, '%')
2952
+			) . '</p>'
2953
+			: '';
2954
+		// filter before_list_table template arg
2955
+		$this->_template_args['before_list_table'] = apply_filters(
2956
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2957
+			$this->_template_args['before_list_table'],
2958
+			$this->page_slug,
2959
+			$this->request->requestParams(),
2960
+			$this->_req_action
2961
+		);
2962
+		// convert to array and filter again
2963
+		// arrays are easier to inject new items in a specific location,
2964
+		// but would not be backwards compatible, so we have to add a new filter
2965
+		$this->_template_args['before_list_table'] = implode(
2966
+			" \n",
2967
+			(array) apply_filters(
2968
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2969
+				(array) $this->_template_args['before_list_table'],
2970
+				$this->page_slug,
2971
+				$this->request->requestParams(),
2972
+				$this->_req_action
2973
+			)
2974
+		);
2975
+		// filter after_list_table template arg
2976
+		$this->_template_args['after_list_table'] = apply_filters(
2977
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2978
+			$this->_template_args['after_list_table'],
2979
+			$this->page_slug,
2980
+			$this->request->requestParams(),
2981
+			$this->_req_action
2982
+		);
2983
+		// convert to array and filter again
2984
+		// arrays are easier to inject new items in a specific location,
2985
+		// but would not be backwards compatible, so we have to add a new filter
2986
+		$this->_template_args['after_list_table']   = implode(
2987
+			" \n",
2988
+			(array) apply_filters(
2989
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2990
+				(array) $this->_template_args['after_list_table'],
2991
+				$this->page_slug,
2992
+				$this->request->requestParams(),
2993
+				$this->_req_action
2994
+			)
2995
+		);
2996
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2997
+			$template_path,
2998
+			$this->_template_args,
2999
+			true
3000
+		);
3001
+		// the final template wrapper
3002
+		if ($sidebar) {
3003
+			$this->display_admin_page_with_sidebar();
3004
+		} else {
3005
+			$this->display_admin_page_with_no_sidebar();
3006
+		}
3007
+	}
3008
+
3009
+
3010
+	/**
3011
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3012
+	 * html string for the legend.
3013
+	 * $items are expected in an array in the following format:
3014
+	 * $legend_items = array(
3015
+	 *        'item_id' => array(
3016
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3017
+	 *            'desc' => esc_html__('localized description of item');
3018
+	 *        )
3019
+	 * );
3020
+	 *
3021
+	 * @param array $items see above for format of array
3022
+	 * @return string html string of legend
3023
+	 * @throws DomainException
3024
+	 */
3025
+	protected function _display_legend($items)
3026
+	{
3027
+		$this->_template_args['items'] = apply_filters(
3028
+			'FHEE__EE_Admin_Page___display_legend__items',
3029
+			(array) $items,
3030
+			$this
3031
+		);
3032
+		/** @var StatusChangeNotice $status_change_notice */
3033
+		$status_change_notice = $this->loader->getShared(
3034
+			'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3035
+		);
3036
+		$this->_template_args['status_change_notice'] = $status_change_notice->display(
3037
+			'__admin-legend',
3038
+			$this->page_slug
3039
+		);
3040
+		return EEH_Template::display_template(
3041
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3042
+			$this->_template_args,
3043
+			true
3044
+		);
3045
+	}
3046
+
3047
+
3048
+	/**
3049
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3050
+	 * The returned json object is created from an array in the following format:
3051
+	 * array(
3052
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3053
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3054
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3055
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3056
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3057
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3058
+	 *  that might be included in here)
3059
+	 * )
3060
+	 * The json object is populated by whatever is set in the $_template_args property.
3061
+	 *
3062
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3063
+	 *                                 instead of displayed.
3064
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3065
+	 * @return void
3066
+	 * @throws EE_Error
3067
+	 * @throws InvalidArgumentException
3068
+	 * @throws InvalidDataTypeException
3069
+	 * @throws InvalidInterfaceException
3070
+	 */
3071
+	protected function _return_json($sticky_notices = false, $notices_arguments = [])
3072
+	{
3073
+		// make sure any EE_Error notices have been handled.
3074
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3075
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3076
+		unset($this->_template_args['data']);
3077
+		$json = [
3078
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3079
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3080
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3081
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3082
+			'notices'   => EE_Error::get_notices(),
3083
+			'content'   => isset($this->_template_args['admin_page_content'])
3084
+				? $this->_template_args['admin_page_content'] : '',
3085
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3086
+			'isEEajax'  => true
3087
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3088
+		];
3089
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3090
+		if (null === error_get_last() || ! headers_sent()) {
3091
+			header('Content-Type: application/json; charset=UTF-8');
3092
+		}
3093
+		echo wp_json_encode($json);
3094
+		exit();
3095
+	}
3096
+
3097
+
3098
+	/**
3099
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3100
+	 *
3101
+	 * @return void
3102
+	 * @throws EE_Error
3103
+	 * @throws InvalidArgumentException
3104
+	 * @throws InvalidDataTypeException
3105
+	 * @throws InvalidInterfaceException
3106
+	 */
3107
+	public function return_json()
3108
+	{
3109
+		if ($this->request->isAjax()) {
3110
+			$this->_return_json();
3111
+		} else {
3112
+			throw new EE_Error(
3113
+				sprintf(
3114
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3115
+					__FUNCTION__
3116
+				)
3117
+			);
3118
+		}
3119
+	}
3120
+
3121
+
3122
+	/**
3123
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3124
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3125
+	 *
3126
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3127
+	 */
3128
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3129
+	{
3130
+		$this->_hook_obj = $hook_obj;
3131
+	}
3132
+
3133
+
3134
+	/**
3135
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3136
+	 *
3137
+	 * @param boolean $about whether to use the special about page wrapper or default.
3138
+	 * @return void
3139
+	 * @throws DomainException
3140
+	 * @throws EE_Error
3141
+	 * @throws InvalidArgumentException
3142
+	 * @throws InvalidDataTypeException
3143
+	 * @throws InvalidInterfaceException
3144
+	 */
3145
+	public function admin_page_wrapper($about = false)
3146
+	{
3147
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3148
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3149
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3150
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3151
+
3152
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3153
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3154
+			$this->_template_args['before_admin_page_content'] ?? ''
3155
+		);
3156
+
3157
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3158
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3159
+			$this->_template_args['after_admin_page_content'] ?? ''
3160
+		);
3161
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3162
+
3163
+		if ($this->request->isAjax()) {
3164
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3165
+				// $template_path,
3166
+				EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3167
+				$this->_template_args,
3168
+				true
3169
+			);
3170
+			$this->_return_json();
3171
+		}
3172
+		// load settings page wrapper template
3173
+		$template_path = $about
3174
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3175
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3176
+
3177
+		EEH_Template::display_template($template_path, $this->_template_args);
3178
+	}
3179
+
3180
+
3181
+	/**
3182
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3183
+	 *
3184
+	 * @return string html
3185
+	 * @throws EE_Error
3186
+	 */
3187
+	protected function _get_main_nav_tabs()
3188
+	{
3189
+		// let's generate the html using the EEH_Tabbed_Content helper.
3190
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3191
+		// (rather than setting in the page_routes array)
3192
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3193
+	}
3194
+
3195
+
3196
+	/**
3197
+	 *        sort nav tabs
3198
+	 *
3199
+	 * @param $a
3200
+	 * @param $b
3201
+	 * @return int
3202
+	 */
3203
+	private function _sort_nav_tabs($a, $b)
3204
+	{
3205
+		if ($a['order'] === $b['order']) {
3206
+			return 0;
3207
+		}
3208
+		return ($a['order'] < $b['order']) ? -1 : 1;
3209
+	}
3210
+
3211
+
3212
+	/**
3213
+	 * generates HTML for the forms used on admin pages
3214
+	 *
3215
+	 * @param array  $input_vars - array of input field details
3216
+	 * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3217
+	 * @param bool   $id
3218
+	 * @return array|string
3219
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3220
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3221
+	 */
3222
+	protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3223
+	{
3224
+		return $generator === 'string'
3225
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3226
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3227
+	}
3228
+
3229
+
3230
+	/**
3231
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3232
+	 *
3233
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3234
+	 *                                   Close" button.
3235
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3236
+	 *                                   'Save', [1] => 'save & close')
3237
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3238
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3239
+	 *                                   default actions by submitting some other value.
3240
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3241
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3242
+	 *                                   close (normal form handling).
3243
+	 */
3244
+	protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3245
+	{
3246
+		// make sure $text and $actions are in an array
3247
+		$text          = (array) $text;
3248
+		$actions       = (array) $actions;
3249
+		$referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3250
+		$button_text   = ! empty($text)
3251
+			? $text
3252
+			: [
3253
+				esc_html__('Save', 'event_espresso'),
3254
+				esc_html__('Save and Close', 'event_espresso'),
3255
+			];
3256
+		$default_names = ['save', 'save_and_close'];
3257
+		$buttons = '';
3258
+		foreach ($button_text as $key => $button) {
3259
+			$ref     = $default_names[ $key ];
3260
+			$name    = ! empty($actions) ? $actions[ $key ] : $ref;
3261
+			$buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3262
+						. 'value="' . $button . '" name="' . $name . '" '
3263
+						. 'id="' . $this->_current_view . '_' . $ref . '" />';
3264
+			if (! $both) {
3265
+				break;
3266
+			}
3267
+		}
3268
+		// add in a hidden index for the current page (so save and close redirects properly)
3269
+		$buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3270
+				   . $referrer_url
3271
+				   . '" />';
3272
+		$this->_template_args['save_buttons'] = $buttons;
3273
+	}
3274
+
3275
+
3276
+	/**
3277
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3278
+	 *
3279
+	 * @param string $route
3280
+	 * @param array  $additional_hidden_fields
3281
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3282
+	 * @since 4.6.0
3283
+	 */
3284
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3285
+	{
3286
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3287
+	}
3288
+
3289
+
3290
+	/**
3291
+	 * set form open and close tags on add/edit pages.
3292
+	 *
3293
+	 * @param string $route                    the route you want the form to direct to
3294
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3295
+	 * @return void
3296
+	 */
3297
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3298
+	{
3299
+		if (empty($route)) {
3300
+			$user_msg = esc_html__(
3301
+				'An error occurred. No action was set for this page\'s form.',
3302
+				'event_espresso'
3303
+			);
3304
+			$dev_msg  = $user_msg . "\n"
3305
+						. sprintf(
3306
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3307
+							__FUNCTION__,
3308
+							__CLASS__
3309
+						);
3310
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3311
+		}
3312
+		// open form
3313
+		$action = $this->_admin_base_url;
3314
+		$this->_template_args['before_admin_page_content'] = "
3315 3315
             <form name='form' method='post' action='{$action}' id='{$route}_event_form' class='ee-admin-page-form' >
3316 3316
             ";
3317
-        // add nonce
3318
-        $nonce                                             =
3319
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3320
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3321
-        // add REQUIRED form action
3322
-        $hidden_fields = [
3323
-            'action' => ['type' => 'hidden', 'value' => $route],
3324
-        ];
3325
-        // merge arrays
3326
-        $hidden_fields = is_array($additional_hidden_fields)
3327
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3328
-            : $hidden_fields;
3329
-        // generate form fields
3330
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3331
-        // add fields to form
3332
-        foreach ((array) $form_fields as $form_field) {
3333
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3334
-        }
3335
-        // close form
3336
-        $this->_template_args['after_admin_page_content'] = '</form>';
3337
-    }
3338
-
3339
-
3340
-    /**
3341
-     * Public Wrapper for _redirect_after_action() method since its
3342
-     * discovered it would be useful for external code to have access.
3343
-     *
3344
-     * @param bool   $success
3345
-     * @param string $what
3346
-     * @param string $action_desc
3347
-     * @param array  $query_args
3348
-     * @param bool   $override_overwrite
3349
-     * @throws EE_Error
3350
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3351
-     * @since 4.5.0
3352
-     */
3353
-    public function redirect_after_action(
3354
-        $success = false,
3355
-        $what = 'item',
3356
-        $action_desc = 'processed',
3357
-        $query_args = [],
3358
-        $override_overwrite = false
3359
-    ) {
3360
-        $this->_redirect_after_action(
3361
-            $success,
3362
-            $what,
3363
-            $action_desc,
3364
-            $query_args,
3365
-            $override_overwrite
3366
-        );
3367
-    }
3368
-
3369
-
3370
-    /**
3371
-     * Helper method for merging existing request data with the returned redirect url.
3372
-     *
3373
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3374
-     * filters are still applied.
3375
-     *
3376
-     * @param array $new_route_data
3377
-     * @return array
3378
-     */
3379
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3380
-    {
3381
-        foreach ($this->request->requestParams() as $ref => $value) {
3382
-            // unset nonces
3383
-            if (strpos($ref, 'nonce') !== false) {
3384
-                $this->request->unSetRequestParam($ref);
3385
-                continue;
3386
-            }
3387
-            // urlencode values.
3388
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3389
-            $this->request->setRequestParam($ref, $value);
3390
-        }
3391
-        return array_merge($this->request->requestParams(), $new_route_data);
3392
-    }
3393
-
3394
-
3395
-    /**
3396
-     * @param int|float|string $success      - whether success was for two or more records, or just one, or none
3397
-     * @param string           $what         - what the action was performed on
3398
-     * @param string           $action_desc  - what was done ie: updated, deleted, etc
3399
-     * @param array $query_args              - an array of query_args to be added to the URL to redirect to
3400
-     * @param BOOL $override_overwrite       - by default all EE_Error::success messages are overwritten,
3401
-     *                                         this allows you to override this so that they show.
3402
-     * @return void
3403
-     * @throws EE_Error
3404
-     * @throws InvalidArgumentException
3405
-     * @throws InvalidDataTypeException
3406
-     * @throws InvalidInterfaceException
3407
-     */
3408
-    protected function _redirect_after_action(
3409
-        $success = 0,
3410
-        string $what = 'item',
3411
-        string $action_desc = 'processed',
3412
-        array $query_args = [],
3413
-        bool $override_overwrite = false
3414
-    ) {
3415
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3416
-        $notices      = EE_Error::get_notices(false);
3417
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3418
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3419
-            EE_Error::overwrite_success();
3420
-        }
3421
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3422
-            // how many records affected ? more than one record ? or just one ?
3423
-            EE_Error::add_success(
3424
-                sprintf(
3425
-                    esc_html(
3426
-                        _n(
3427
-                            'The "%1$s" has been successfully %2$s.',
3428
-                            'The "%1$s" have been successfully %2$s.',
3429
-                            $success,
3430
-                            'event_espresso'
3431
-                        )
3432
-                    ),
3433
-                    $what,
3434
-                    $action_desc
3435
-                ),
3436
-                __FILE__,
3437
-                __FUNCTION__,
3438
-                __LINE__
3439
-            );
3440
-        }
3441
-        // check that $query_args isn't something crazy
3442
-        if (! is_array($query_args)) {
3443
-            $query_args = [];
3444
-        }
3445
-        /**
3446
-         * Allow injecting actions before the query_args are modified for possible different
3447
-         * redirections on save and close actions
3448
-         *
3449
-         * @param array $query_args       The original query_args array coming into the
3450
-         *                                method.
3451
-         * @since 4.2.0
3452
-         */
3453
-        do_action(
3454
-            "AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3455
-            $query_args
3456
-        );
3457
-        // set redirect url.
3458
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3459
-        // otherwise we go with whatever is set as the _admin_base_url
3460
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3461
-        // calculate where we're going (if we have a "save and close" button pushed)
3462
-        if (
3463
-            $this->request->requestParamIsSet('save_and_close')
3464
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3465
-        ) {
3466
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3467
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3468
-            // regenerate query args array from referrer URL
3469
-            parse_str($parsed_url['query'], $query_args);
3470
-            // correct page and action will be in the query args now
3471
-            $redirect_url = admin_url('admin.php');
3472
-        }
3473
-        // merge any default query_args set in _default_route_query_args property
3474
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3475
-            $args_to_merge = [];
3476
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3477
-                // is there a wp_referer array in our _default_route_query_args property?
3478
-                if ($query_param === 'wp_referer') {
3479
-                    $query_value = (array) $query_value;
3480
-                    foreach ($query_value as $reference => $value) {
3481
-                        if (strpos($reference, 'nonce') !== false) {
3482
-                            continue;
3483
-                        }
3484
-                        // finally we will override any arguments in the referer with
3485
-                        // what might be set on the _default_route_query_args array.
3486
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3487
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3488
-                        } else {
3489
-                            $args_to_merge[ $reference ] = urlencode($value);
3490
-                        }
3491
-                    }
3492
-                    continue;
3493
-                }
3494
-                $args_to_merge[ $query_param ] = $query_value;
3495
-            }
3496
-            // now let's merge these arguments but override with what was specifically sent in to the
3497
-            // redirect.
3498
-            $query_args = array_merge($args_to_merge, $query_args);
3499
-        }
3500
-        $this->_process_notices($query_args);
3501
-        // generate redirect url
3502
-        // if redirecting to anything other than the main page, add a nonce
3503
-        if (isset($query_args['action'])) {
3504
-            // manually generate wp_nonce and merge that with the query vars
3505
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3506
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3507
-        }
3508
-        // we're adding some hooks and filters in here for processing any things just before redirects
3509
-        // (example: an admin page has done an insert or update and we want to run something after that).
3510
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3511
-        $redirect_url = apply_filters(
3512
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3513
-            EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3514
-            $query_args
3515
-        );
3516
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3517
-        if ($this->request->isAjax()) {
3518
-            $default_data                    = [
3519
-                'close'        => true,
3520
-                'redirect_url' => $redirect_url,
3521
-                'where'        => 'main',
3522
-                'what'         => 'append',
3523
-            ];
3524
-            $this->_template_args['success'] = $success;
3525
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3526
-                $default_data,
3527
-                $this->_template_args['data']
3528
-            ) : $default_data;
3529
-            $this->_return_json();
3530
-        }
3531
-        wp_safe_redirect($redirect_url);
3532
-        exit();
3533
-    }
3534
-
3535
-
3536
-    /**
3537
-     * process any notices before redirecting (or returning ajax request)
3538
-     * This method sets the $this->_template_args['notices'] attribute;
3539
-     *
3540
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3541
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3542
-     *                                  page_routes haven't been defined yet.
3543
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3544
-     *                                  still save a transient for the notice.
3545
-     * @return void
3546
-     * @throws EE_Error
3547
-     * @throws InvalidArgumentException
3548
-     * @throws InvalidDataTypeException
3549
-     * @throws InvalidInterfaceException
3550
-     */
3551
-    protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3552
-    {
3553
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3554
-        if ($this->request->isAjax()) {
3555
-            $notices = EE_Error::get_notices(false);
3556
-            if (empty($this->_template_args['success'])) {
3557
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3558
-            }
3559
-            if (empty($this->_template_args['errors'])) {
3560
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3561
-            }
3562
-            if (empty($this->_template_args['attention'])) {
3563
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3564
-            }
3565
-        }
3566
-        $this->_template_args['notices'] = EE_Error::get_notices();
3567
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3568
-        if (! $this->request->isAjax() || $sticky_notices) {
3569
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3570
-            $this->_add_transient(
3571
-                $route,
3572
-                $this->_template_args['notices'],
3573
-                true,
3574
-                $skip_route_verify
3575
-            );
3576
-        }
3577
-    }
3578
-
3579
-
3580
-    /**
3581
-     * get_action_link_or_button
3582
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3583
-     *
3584
-     * @param string $action        use this to indicate which action the url is generated with.
3585
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3586
-     *                              property.
3587
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3588
-     * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3589
-     * @param string $base_url      If this is not provided
3590
-     *                              the _admin_base_url will be used as the default for the button base_url.
3591
-     *                              Otherwise this value will be used.
3592
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3593
-     * @return string
3594
-     * @throws InvalidArgumentException
3595
-     * @throws InvalidInterfaceException
3596
-     * @throws InvalidDataTypeException
3597
-     * @throws EE_Error
3598
-     */
3599
-    public function get_action_link_or_button(
3600
-        $action,
3601
-        $type = 'add',
3602
-        $extra_request = [],
3603
-        $class = 'button--primary',
3604
-        $base_url = '',
3605
-        $exclude_nonce = false
3606
-    ) {
3607
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3608
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3609
-            throw new EE_Error(
3610
-                sprintf(
3611
-                    esc_html__(
3612
-                        'There is no page route for given action for the button.  This action was given: %s',
3613
-                        'event_espresso'
3614
-                    ),
3615
-                    $action
3616
-                )
3617
-            );
3618
-        }
3619
-        if (! isset($this->_labels['buttons'][ $type ])) {
3620
-            throw new EE_Error(
3621
-                sprintf(
3622
-                    esc_html__(
3623
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3624
-                        'event_espresso'
3625
-                    ),
3626
-                    $type
3627
-                )
3628
-            );
3629
-        }
3630
-        // finally check user access for this button.
3631
-        $has_access = $this->check_user_access($action, true);
3632
-        if (! $has_access) {
3633
-            return '';
3634
-        }
3635
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3636
-        $query_args = [
3637
-            'action' => $action,
3638
-        ];
3639
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3640
-        if (! empty($extra_request)) {
3641
-            $query_args = array_merge($extra_request, $query_args);
3642
-        }
3643
-        $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3644
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3645
-    }
3646
-
3647
-
3648
-    /**
3649
-     * _per_page_screen_option
3650
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3651
-     *
3652
-     * @return void
3653
-     * @throws InvalidArgumentException
3654
-     * @throws InvalidInterfaceException
3655
-     * @throws InvalidDataTypeException
3656
-     */
3657
-    protected function _per_page_screen_option()
3658
-    {
3659
-        $option = 'per_page';
3660
-        $args   = [
3661
-            'label'   => apply_filters(
3662
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3663
-                $this->_admin_page_title,
3664
-                $this
3665
-            ),
3666
-            'default' => (int) apply_filters(
3667
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3668
-                20
3669
-            ),
3670
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3671
-        ];
3672
-        // ONLY add the screen option if the user has access to it.
3673
-        if ($this->check_user_access($this->_current_view, true)) {
3674
-            add_screen_option($option, $args);
3675
-        }
3676
-    }
3677
-
3678
-
3679
-    /**
3680
-     * set_per_page_screen_option
3681
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3682
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3683
-     * admin_menu.
3684
-     *
3685
-     * @return void
3686
-     */
3687
-    private function _set_per_page_screen_options()
3688
-    {
3689
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3690
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3691
-            if (! $user = wp_get_current_user()) {
3692
-                return;
3693
-            }
3694
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3695
-            if (! $option) {
3696
-                return;
3697
-            }
3698
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3699
-            $map_option = $option;
3700
-            $option     = str_replace('-', '_', $option);
3701
-            switch ($map_option) {
3702
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3703
-                    $max_value = apply_filters(
3704
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3705
-                        999,
3706
-                        $this->_current_page,
3707
-                        $this->_current_view
3708
-                    );
3709
-                    if ($value < 1) {
3710
-                        return;
3711
-                    }
3712
-                    $value = min($value, $max_value);
3713
-                    break;
3714
-                default:
3715
-                    $value = apply_filters(
3716
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3717
-                        false,
3718
-                        $option,
3719
-                        $value
3720
-                    );
3721
-                    if (false === $value) {
3722
-                        return;
3723
-                    }
3724
-                    break;
3725
-            }
3726
-            update_user_meta($user->ID, $option, $value);
3727
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3728
-            exit;
3729
-        }
3730
-    }
3731
-
3732
-
3733
-    /**
3734
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3735
-     *
3736
-     * @param array $data array that will be assigned to template args.
3737
-     */
3738
-    public function set_template_args($data)
3739
-    {
3740
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3741
-    }
3742
-
3743
-
3744
-    /**
3745
-     * This makes available the WP transient system for temporarily moving data between routes
3746
-     *
3747
-     * @param string $route             the route that should receive the transient
3748
-     * @param array  $data              the data that gets sent
3749
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3750
-     *                                  normal route transient.
3751
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3752
-     *                                  when we are adding a transient before page_routes have been defined.
3753
-     * @return void
3754
-     * @throws EE_Error
3755
-     */
3756
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3757
-    {
3758
-        $user_id = get_current_user_id();
3759
-        if (! $skip_route_verify) {
3760
-            $this->_verify_route($route);
3761
-        }
3762
-        // now let's set the string for what kind of transient we're setting
3763
-        $transient = $notices
3764
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3765
-            : 'rte_tx_' . $route . '_' . $user_id;
3766
-        $data      = $notices ? ['notices' => $data] : $data;
3767
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3768
-        $existing = is_multisite() && is_network_admin()
3769
-            ? get_site_transient($transient)
3770
-            : get_transient($transient);
3771
-        if ($existing) {
3772
-            $data = array_merge((array) $data, (array) $existing);
3773
-        }
3774
-        if (is_multisite() && is_network_admin()) {
3775
-            set_site_transient($transient, $data, 8);
3776
-        } else {
3777
-            set_transient($transient, $data, 8);
3778
-        }
3779
-    }
3780
-
3781
-
3782
-    /**
3783
-     * this retrieves the temporary transient that has been set for moving data between routes.
3784
-     *
3785
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3786
-     * @param string $route
3787
-     * @return mixed data
3788
-     */
3789
-    protected function _get_transient($notices = false, $route = '')
3790
-    {
3791
-        $user_id   = get_current_user_id();
3792
-        $route     = ! $route ? $this->_req_action : $route;
3793
-        $transient = $notices
3794
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3795
-            : 'rte_tx_' . $route . '_' . $user_id;
3796
-        $data      = is_multisite() && is_network_admin()
3797
-            ? get_site_transient($transient)
3798
-            : get_transient($transient);
3799
-        // delete transient after retrieval (just in case it hasn't expired);
3800
-        if (is_multisite() && is_network_admin()) {
3801
-            delete_site_transient($transient);
3802
-        } else {
3803
-            delete_transient($transient);
3804
-        }
3805
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3806
-    }
3807
-
3808
-
3809
-    /**
3810
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3811
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3812
-     * default route callback on the EE_Admin page you want it run.)
3813
-     *
3814
-     * @return void
3815
-     */
3816
-    protected function _transient_garbage_collection()
3817
-    {
3818
-        global $wpdb;
3819
-        // retrieve all existing transients
3820
-        $query =
3821
-            "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3822
-        if ($results = $wpdb->get_results($query)) {
3823
-            foreach ($results as $result) {
3824
-                $transient = str_replace('_transient_', '', $result->option_name);
3825
-                get_transient($transient);
3826
-                if (is_multisite() && is_network_admin()) {
3827
-                    get_site_transient($transient);
3828
-                }
3829
-            }
3830
-        }
3831
-    }
3832
-
3833
-
3834
-    /**
3835
-     * get_view
3836
-     *
3837
-     * @return string content of _view property
3838
-     */
3839
-    public function get_view()
3840
-    {
3841
-        return $this->_view;
3842
-    }
3843
-
3844
-
3845
-    /**
3846
-     * getter for the protected $_views property
3847
-     *
3848
-     * @return array
3849
-     */
3850
-    public function get_views()
3851
-    {
3852
-        return $this->_views;
3853
-    }
3854
-
3855
-
3856
-    /**
3857
-     * get_current_page
3858
-     *
3859
-     * @return string _current_page property value
3860
-     */
3861
-    public function get_current_page()
3862
-    {
3863
-        return $this->_current_page;
3864
-    }
3865
-
3866
-
3867
-    /**
3868
-     * get_current_view
3869
-     *
3870
-     * @return string _current_view property value
3871
-     */
3872
-    public function get_current_view()
3873
-    {
3874
-        return $this->_current_view;
3875
-    }
3876
-
3877
-
3878
-    /**
3879
-     * get_current_screen
3880
-     *
3881
-     * @return object The current WP_Screen object
3882
-     */
3883
-    public function get_current_screen()
3884
-    {
3885
-        return $this->_current_screen;
3886
-    }
3887
-
3888
-
3889
-    /**
3890
-     * get_current_page_view_url
3891
-     *
3892
-     * @return string This returns the url for the current_page_view.
3893
-     */
3894
-    public function get_current_page_view_url()
3895
-    {
3896
-        return $this->_current_page_view_url;
3897
-    }
3898
-
3899
-
3900
-    /**
3901
-     * just returns the Request
3902
-     *
3903
-     * @return RequestInterface
3904
-     */
3905
-    public function get_request()
3906
-    {
3907
-        return $this->request;
3908
-    }
3909
-
3910
-
3911
-    /**
3912
-     * just returns the _req_data property
3913
-     *
3914
-     * @return array
3915
-     */
3916
-    public function get_request_data()
3917
-    {
3918
-        return $this->request->requestParams();
3919
-    }
3920
-
3921
-
3922
-    /**
3923
-     * returns the _req_data protected property
3924
-     *
3925
-     * @return string
3926
-     */
3927
-    public function get_req_action()
3928
-    {
3929
-        return $this->_req_action;
3930
-    }
3931
-
3932
-
3933
-    /**
3934
-     * @return bool  value of $_is_caf property
3935
-     */
3936
-    public function is_caf()
3937
-    {
3938
-        return $this->_is_caf;
3939
-    }
3940
-
3941
-
3942
-    /**
3943
-     * @return mixed
3944
-     */
3945
-    public function default_espresso_metaboxes()
3946
-    {
3947
-        return $this->_default_espresso_metaboxes;
3948
-    }
3949
-
3950
-
3951
-    /**
3952
-     * @return mixed
3953
-     */
3954
-    public function admin_base_url()
3955
-    {
3956
-        return $this->_admin_base_url;
3957
-    }
3958
-
3959
-
3960
-    /**
3961
-     * @return mixed
3962
-     */
3963
-    public function wp_page_slug()
3964
-    {
3965
-        return $this->_wp_page_slug;
3966
-    }
3967
-
3968
-
3969
-    /**
3970
-     * updates  espresso configuration settings
3971
-     *
3972
-     * @param string                   $tab
3973
-     * @param EE_Config_Base|EE_Config $config
3974
-     * @param string                   $file file where error occurred
3975
-     * @param string                   $func function  where error occurred
3976
-     * @param string                   $line line no where error occurred
3977
-     * @return boolean
3978
-     */
3979
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3980
-    {
3981
-        // remove any options that are NOT going to be saved with the config settings.
3982
-        if (isset($config->core->ee_ueip_optin)) {
3983
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
3984
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3985
-            update_option('ee_ueip_has_notified', true);
3986
-        }
3987
-        // and save it (note we're also doing the network save here)
3988
-        $net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3989
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
3990
-        if ($config_saved && $net_saved) {
3991
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3992
-            return true;
3993
-        }
3994
-        EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3995
-        return false;
3996
-    }
3997
-
3998
-
3999
-    /**
4000
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4001
-     *
4002
-     * @return array
4003
-     */
4004
-    public function get_yes_no_values()
4005
-    {
4006
-        return $this->_yes_no_values;
4007
-    }
4008
-
4009
-
4010
-    /**
4011
-     * @return string
4012
-     * @throws ReflectionException
4013
-     * @since $VID:$
4014
-     */
4015
-    protected function _get_dir()
4016
-    {
4017
-        $reflector = new ReflectionClass($this->class_name);
4018
-        return dirname($reflector->getFileName());
4019
-    }
4020
-
4021
-
4022
-    /**
4023
-     * A helper for getting a "next link".
4024
-     *
4025
-     * @param string $url   The url to link to
4026
-     * @param string $class The class to use.
4027
-     * @return string
4028
-     */
4029
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4030
-    {
4031
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4032
-    }
4033
-
4034
-
4035
-    /**
4036
-     * A helper for getting a "previous link".
4037
-     *
4038
-     * @param string $url   The url to link to
4039
-     * @param string $class The class to use.
4040
-     * @return string
4041
-     */
4042
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4043
-    {
4044
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4045
-    }
4046
-
4047
-
4048
-
4049
-
4050
-
4051
-
4052
-
4053
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4054
-
4055
-
4056
-    /**
4057
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4058
-     * 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
4059
-     * _req_data array.
4060
-     *
4061
-     * @return bool success/fail
4062
-     * @throws EE_Error
4063
-     * @throws InvalidArgumentException
4064
-     * @throws ReflectionException
4065
-     * @throws InvalidDataTypeException
4066
-     * @throws InvalidInterfaceException
4067
-     */
4068
-    protected function _process_resend_registration()
4069
-    {
4070
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4071
-        do_action(
4072
-            'AHEE__EE_Admin_Page___process_resend_registration',
4073
-            $this->_template_args['success'],
4074
-            $this->request->requestParams()
4075
-        );
4076
-        return $this->_template_args['success'];
4077
-    }
4078
-
4079
-
4080
-    /**
4081
-     * This automatically processes any payment message notifications when manual payment has been applied.
4082
-     *
4083
-     * @param EE_Payment $payment
4084
-     * @return bool success/fail
4085
-     */
4086
-    protected function _process_payment_notification(EE_Payment $payment)
4087
-    {
4088
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4089
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4090
-        $this->_template_args['success'] = apply_filters(
4091
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4092
-            false,
4093
-            $payment
4094
-        );
4095
-        return $this->_template_args['success'];
4096
-    }
4097
-
4098
-
4099
-    /**
4100
-     * @param EEM_Base      $entity_model
4101
-     * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4102
-     * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4103
-     * @param string        $delete_column  name of the field that denotes whether entity is trashed
4104
-     * @param callable|null $callback       called after entity is trashed, restored, or deleted
4105
-     * @return int|float
4106
-     * @throws EE_Error
4107
-     */
4108
-    protected function trashRestoreDeleteEntities(
4109
-        EEM_Base $entity_model,
4110
-        string $entity_PK_name,
4111
-        string $action = EE_Admin_List_Table::ACTION_DELETE,
4112
-        string $delete_column = '',
4113
-        callable $callback = null
4114
-    ) {
4115
-        $entity_PK      = $entity_model->get_primary_key_field();
4116
-        $entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4117
-        $entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4118
-        // grab ID if deleting a single entity
4119
-        if ($this->request->requestParamIsSet($entity_PK_name)) {
4120
-            $ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4121
-            return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4122
-        }
4123
-        // or grab checkbox array if bulk deleting
4124
-        $checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4125
-        if (empty($checkboxes)) {
4126
-            return 0;
4127
-        }
4128
-        $success = 0;
4129
-        $IDs     = array_keys($checkboxes);
4130
-        // cycle thru bulk action checkboxes
4131
-        foreach ($IDs as $ID) {
4132
-            // increment $success
4133
-            if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4134
-                $success++;
4135
-            }
4136
-        }
4137
-        $count = (int) count($checkboxes);
4138
-        // if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4139
-        // otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4140
-        return $success === $count ? $count : $success / $count;
4141
-    }
4142
-
4143
-
4144
-    /**
4145
-     * @param EE_Primary_Key_Field_Base $entity_PK
4146
-     * @return string
4147
-     * @throws EE_Error
4148
-     * @since   4.10.30.p
4149
-     */
4150
-    private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4151
-    {
4152
-        $entity_PK_type = $entity_PK->getSchemaType();
4153
-        switch ($entity_PK_type) {
4154
-            case 'boolean':
4155
-                return 'bool';
4156
-            case 'integer':
4157
-                return 'int';
4158
-            case 'number':
4159
-                return 'float';
4160
-            case 'string':
4161
-                return 'string';
4162
-        }
4163
-        throw new RuntimeException(
4164
-            sprintf(
4165
-                esc_html__(
4166
-                    '"%1$s" is an invalid schema type for the %2$s primary key.',
4167
-                    'event_espresso'
4168
-                ),
4169
-                $entity_PK_type,
4170
-                $entity_PK->get_name()
4171
-            )
4172
-        );
4173
-    }
4174
-
4175
-
4176
-    /**
4177
-     * @param EEM_Base      $entity_model
4178
-     * @param int|string    $entity_ID
4179
-     * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4180
-     * @param string        $delete_column name of the field that denotes whether entity is trashed
4181
-     * @param callable|null $callback      called after entity is trashed, restored, or deleted
4182
-     * @return bool
4183
-     */
4184
-    protected function trashRestoreDeleteEntity(
4185
-        EEM_Base $entity_model,
4186
-        $entity_ID,
4187
-        string $action,
4188
-        string $delete_column,
4189
-        ?callable $callback = null
4190
-    ): bool {
4191
-        $entity_ID = absint($entity_ID);
4192
-        if (! $entity_ID) {
4193
-            $this->trashRestoreDeleteError($action, $entity_model);
4194
-        }
4195
-        $result = 0;
4196
-        try {
4197
-            switch ($action) {
4198
-                case EE_Admin_List_Table::ACTION_DELETE:
4199
-                    $result = (bool) $entity_model->delete_permanently_by_ID($entity_ID);
4200
-                    break;
4201
-                case EE_Admin_List_Table::ACTION_RESTORE:
4202
-                    $this->validateDeleteColumn($entity_model, $delete_column);
4203
-                    $result = $entity_model->update_by_ID([$delete_column => 0], $entity_ID);
4204
-                    break;
4205
-                case EE_Admin_List_Table::ACTION_TRASH:
4206
-                    $this->validateDeleteColumn($entity_model, $delete_column);
4207
-                    $result = $entity_model->update_by_ID([$delete_column => 1], $entity_ID);
4208
-                    break;
4209
-            }
4210
-        } catch (Exception $exception) {
4211
-            $this->trashRestoreDeleteError($action, $entity_model, $exception);
4212
-        }
4213
-        if (is_callable($callback)) {
4214
-            call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4215
-        }
4216
-        return $result;
4217
-    }
4218
-
4219
-
4220
-    /**
4221
-     * @param EEM_Base $entity_model
4222
-     * @param string   $delete_column
4223
-     * @since 4.10.30.p
4224
-     */
4225
-    private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4226
-    {
4227
-        if (empty($delete_column)) {
4228
-            throw new DomainException(
4229
-                sprintf(
4230
-                    esc_html__(
4231
-                        'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4232
-                        'event_espresso'
4233
-                    ),
4234
-                    $entity_model->get_this_model_name()
4235
-                )
4236
-            );
4237
-        }
4238
-        if (! $entity_model->has_field($delete_column)) {
4239
-            throw new DomainException(
4240
-                sprintf(
4241
-                    esc_html__(
4242
-                        'The %1$s field does not exist on the %2$s model.',
4243
-                        'event_espresso'
4244
-                    ),
4245
-                    $delete_column,
4246
-                    $entity_model->get_this_model_name()
4247
-                )
4248
-            );
4249
-        }
4250
-    }
4251
-
4252
-
4253
-    /**
4254
-     * @param EEM_Base       $entity_model
4255
-     * @param Exception|null $exception
4256
-     * @param string         $action
4257
-     * @since 4.10.30.p
4258
-     */
4259
-    private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, ?Exception $exception = null)
4260
-    {
4261
-        if ($exception instanceof Exception) {
4262
-            throw new RuntimeException(
4263
-                sprintf(
4264
-                    esc_html__(
4265
-                        'Could not %1$s the %2$s because the following error occurred: %3$s',
4266
-                        'event_espresso'
4267
-                    ),
4268
-                    $action,
4269
-                    $entity_model->get_this_model_name(),
4270
-                    $exception->getMessage()
4271
-                )
4272
-            );
4273
-        }
4274
-        throw new RuntimeException(
4275
-            sprintf(
4276
-                esc_html__(
4277
-                    'Could not %1$s the %2$s because an invalid ID was received.',
4278
-                    'event_espresso'
4279
-                ),
4280
-                $action,
4281
-                $entity_model->get_this_model_name()
4282
-            )
4283
-        );
4284
-    }
3317
+		// add nonce
3318
+		$nonce                                             =
3319
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3320
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3321
+		// add REQUIRED form action
3322
+		$hidden_fields = [
3323
+			'action' => ['type' => 'hidden', 'value' => $route],
3324
+		];
3325
+		// merge arrays
3326
+		$hidden_fields = is_array($additional_hidden_fields)
3327
+			? array_merge($hidden_fields, $additional_hidden_fields)
3328
+			: $hidden_fields;
3329
+		// generate form fields
3330
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3331
+		// add fields to form
3332
+		foreach ((array) $form_fields as $form_field) {
3333
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3334
+		}
3335
+		// close form
3336
+		$this->_template_args['after_admin_page_content'] = '</form>';
3337
+	}
3338
+
3339
+
3340
+	/**
3341
+	 * Public Wrapper for _redirect_after_action() method since its
3342
+	 * discovered it would be useful for external code to have access.
3343
+	 *
3344
+	 * @param bool   $success
3345
+	 * @param string $what
3346
+	 * @param string $action_desc
3347
+	 * @param array  $query_args
3348
+	 * @param bool   $override_overwrite
3349
+	 * @throws EE_Error
3350
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3351
+	 * @since 4.5.0
3352
+	 */
3353
+	public function redirect_after_action(
3354
+		$success = false,
3355
+		$what = 'item',
3356
+		$action_desc = 'processed',
3357
+		$query_args = [],
3358
+		$override_overwrite = false
3359
+	) {
3360
+		$this->_redirect_after_action(
3361
+			$success,
3362
+			$what,
3363
+			$action_desc,
3364
+			$query_args,
3365
+			$override_overwrite
3366
+		);
3367
+	}
3368
+
3369
+
3370
+	/**
3371
+	 * Helper method for merging existing request data with the returned redirect url.
3372
+	 *
3373
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3374
+	 * filters are still applied.
3375
+	 *
3376
+	 * @param array $new_route_data
3377
+	 * @return array
3378
+	 */
3379
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3380
+	{
3381
+		foreach ($this->request->requestParams() as $ref => $value) {
3382
+			// unset nonces
3383
+			if (strpos($ref, 'nonce') !== false) {
3384
+				$this->request->unSetRequestParam($ref);
3385
+				continue;
3386
+			}
3387
+			// urlencode values.
3388
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3389
+			$this->request->setRequestParam($ref, $value);
3390
+		}
3391
+		return array_merge($this->request->requestParams(), $new_route_data);
3392
+	}
3393
+
3394
+
3395
+	/**
3396
+	 * @param int|float|string $success      - whether success was for two or more records, or just one, or none
3397
+	 * @param string           $what         - what the action was performed on
3398
+	 * @param string           $action_desc  - what was done ie: updated, deleted, etc
3399
+	 * @param array $query_args              - an array of query_args to be added to the URL to redirect to
3400
+	 * @param BOOL $override_overwrite       - by default all EE_Error::success messages are overwritten,
3401
+	 *                                         this allows you to override this so that they show.
3402
+	 * @return void
3403
+	 * @throws EE_Error
3404
+	 * @throws InvalidArgumentException
3405
+	 * @throws InvalidDataTypeException
3406
+	 * @throws InvalidInterfaceException
3407
+	 */
3408
+	protected function _redirect_after_action(
3409
+		$success = 0,
3410
+		string $what = 'item',
3411
+		string $action_desc = 'processed',
3412
+		array $query_args = [],
3413
+		bool $override_overwrite = false
3414
+	) {
3415
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3416
+		$notices      = EE_Error::get_notices(false);
3417
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3418
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3419
+			EE_Error::overwrite_success();
3420
+		}
3421
+		if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3422
+			// how many records affected ? more than one record ? or just one ?
3423
+			EE_Error::add_success(
3424
+				sprintf(
3425
+					esc_html(
3426
+						_n(
3427
+							'The "%1$s" has been successfully %2$s.',
3428
+							'The "%1$s" have been successfully %2$s.',
3429
+							$success,
3430
+							'event_espresso'
3431
+						)
3432
+					),
3433
+					$what,
3434
+					$action_desc
3435
+				),
3436
+				__FILE__,
3437
+				__FUNCTION__,
3438
+				__LINE__
3439
+			);
3440
+		}
3441
+		// check that $query_args isn't something crazy
3442
+		if (! is_array($query_args)) {
3443
+			$query_args = [];
3444
+		}
3445
+		/**
3446
+		 * Allow injecting actions before the query_args are modified for possible different
3447
+		 * redirections on save and close actions
3448
+		 *
3449
+		 * @param array $query_args       The original query_args array coming into the
3450
+		 *                                method.
3451
+		 * @since 4.2.0
3452
+		 */
3453
+		do_action(
3454
+			"AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3455
+			$query_args
3456
+		);
3457
+		// set redirect url.
3458
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3459
+		// otherwise we go with whatever is set as the _admin_base_url
3460
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3461
+		// calculate where we're going (if we have a "save and close" button pushed)
3462
+		if (
3463
+			$this->request->requestParamIsSet('save_and_close')
3464
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3465
+		) {
3466
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3467
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3468
+			// regenerate query args array from referrer URL
3469
+			parse_str($parsed_url['query'], $query_args);
3470
+			// correct page and action will be in the query args now
3471
+			$redirect_url = admin_url('admin.php');
3472
+		}
3473
+		// merge any default query_args set in _default_route_query_args property
3474
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3475
+			$args_to_merge = [];
3476
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3477
+				// is there a wp_referer array in our _default_route_query_args property?
3478
+				if ($query_param === 'wp_referer') {
3479
+					$query_value = (array) $query_value;
3480
+					foreach ($query_value as $reference => $value) {
3481
+						if (strpos($reference, 'nonce') !== false) {
3482
+							continue;
3483
+						}
3484
+						// finally we will override any arguments in the referer with
3485
+						// what might be set on the _default_route_query_args array.
3486
+						if (isset($this->_default_route_query_args[ $reference ])) {
3487
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3488
+						} else {
3489
+							$args_to_merge[ $reference ] = urlencode($value);
3490
+						}
3491
+					}
3492
+					continue;
3493
+				}
3494
+				$args_to_merge[ $query_param ] = $query_value;
3495
+			}
3496
+			// now let's merge these arguments but override with what was specifically sent in to the
3497
+			// redirect.
3498
+			$query_args = array_merge($args_to_merge, $query_args);
3499
+		}
3500
+		$this->_process_notices($query_args);
3501
+		// generate redirect url
3502
+		// if redirecting to anything other than the main page, add a nonce
3503
+		if (isset($query_args['action'])) {
3504
+			// manually generate wp_nonce and merge that with the query vars
3505
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3506
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3507
+		}
3508
+		// we're adding some hooks and filters in here for processing any things just before redirects
3509
+		// (example: an admin page has done an insert or update and we want to run something after that).
3510
+		do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3511
+		$redirect_url = apply_filters(
3512
+			'FHEE_redirect_' . $this->class_name . $this->_req_action,
3513
+			EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3514
+			$query_args
3515
+		);
3516
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3517
+		if ($this->request->isAjax()) {
3518
+			$default_data                    = [
3519
+				'close'        => true,
3520
+				'redirect_url' => $redirect_url,
3521
+				'where'        => 'main',
3522
+				'what'         => 'append',
3523
+			];
3524
+			$this->_template_args['success'] = $success;
3525
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3526
+				$default_data,
3527
+				$this->_template_args['data']
3528
+			) : $default_data;
3529
+			$this->_return_json();
3530
+		}
3531
+		wp_safe_redirect($redirect_url);
3532
+		exit();
3533
+	}
3534
+
3535
+
3536
+	/**
3537
+	 * process any notices before redirecting (or returning ajax request)
3538
+	 * This method sets the $this->_template_args['notices'] attribute;
3539
+	 *
3540
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3541
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3542
+	 *                                  page_routes haven't been defined yet.
3543
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3544
+	 *                                  still save a transient for the notice.
3545
+	 * @return void
3546
+	 * @throws EE_Error
3547
+	 * @throws InvalidArgumentException
3548
+	 * @throws InvalidDataTypeException
3549
+	 * @throws InvalidInterfaceException
3550
+	 */
3551
+	protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3552
+	{
3553
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3554
+		if ($this->request->isAjax()) {
3555
+			$notices = EE_Error::get_notices(false);
3556
+			if (empty($this->_template_args['success'])) {
3557
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3558
+			}
3559
+			if (empty($this->_template_args['errors'])) {
3560
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3561
+			}
3562
+			if (empty($this->_template_args['attention'])) {
3563
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3564
+			}
3565
+		}
3566
+		$this->_template_args['notices'] = EE_Error::get_notices();
3567
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3568
+		if (! $this->request->isAjax() || $sticky_notices) {
3569
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3570
+			$this->_add_transient(
3571
+				$route,
3572
+				$this->_template_args['notices'],
3573
+				true,
3574
+				$skip_route_verify
3575
+			);
3576
+		}
3577
+	}
3578
+
3579
+
3580
+	/**
3581
+	 * get_action_link_or_button
3582
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3583
+	 *
3584
+	 * @param string $action        use this to indicate which action the url is generated with.
3585
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3586
+	 *                              property.
3587
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3588
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3589
+	 * @param string $base_url      If this is not provided
3590
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3591
+	 *                              Otherwise this value will be used.
3592
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3593
+	 * @return string
3594
+	 * @throws InvalidArgumentException
3595
+	 * @throws InvalidInterfaceException
3596
+	 * @throws InvalidDataTypeException
3597
+	 * @throws EE_Error
3598
+	 */
3599
+	public function get_action_link_or_button(
3600
+		$action,
3601
+		$type = 'add',
3602
+		$extra_request = [],
3603
+		$class = 'button--primary',
3604
+		$base_url = '',
3605
+		$exclude_nonce = false
3606
+	) {
3607
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3608
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3609
+			throw new EE_Error(
3610
+				sprintf(
3611
+					esc_html__(
3612
+						'There is no page route for given action for the button.  This action was given: %s',
3613
+						'event_espresso'
3614
+					),
3615
+					$action
3616
+				)
3617
+			);
3618
+		}
3619
+		if (! isset($this->_labels['buttons'][ $type ])) {
3620
+			throw new EE_Error(
3621
+				sprintf(
3622
+					esc_html__(
3623
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3624
+						'event_espresso'
3625
+					),
3626
+					$type
3627
+				)
3628
+			);
3629
+		}
3630
+		// finally check user access for this button.
3631
+		$has_access = $this->check_user_access($action, true);
3632
+		if (! $has_access) {
3633
+			return '';
3634
+		}
3635
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3636
+		$query_args = [
3637
+			'action' => $action,
3638
+		];
3639
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3640
+		if (! empty($extra_request)) {
3641
+			$query_args = array_merge($extra_request, $query_args);
3642
+		}
3643
+		$url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3644
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3645
+	}
3646
+
3647
+
3648
+	/**
3649
+	 * _per_page_screen_option
3650
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3651
+	 *
3652
+	 * @return void
3653
+	 * @throws InvalidArgumentException
3654
+	 * @throws InvalidInterfaceException
3655
+	 * @throws InvalidDataTypeException
3656
+	 */
3657
+	protected function _per_page_screen_option()
3658
+	{
3659
+		$option = 'per_page';
3660
+		$args   = [
3661
+			'label'   => apply_filters(
3662
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3663
+				$this->_admin_page_title,
3664
+				$this
3665
+			),
3666
+			'default' => (int) apply_filters(
3667
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3668
+				20
3669
+			),
3670
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3671
+		];
3672
+		// ONLY add the screen option if the user has access to it.
3673
+		if ($this->check_user_access($this->_current_view, true)) {
3674
+			add_screen_option($option, $args);
3675
+		}
3676
+	}
3677
+
3678
+
3679
+	/**
3680
+	 * set_per_page_screen_option
3681
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3682
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3683
+	 * admin_menu.
3684
+	 *
3685
+	 * @return void
3686
+	 */
3687
+	private function _set_per_page_screen_options()
3688
+	{
3689
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3690
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3691
+			if (! $user = wp_get_current_user()) {
3692
+				return;
3693
+			}
3694
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3695
+			if (! $option) {
3696
+				return;
3697
+			}
3698
+			$value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3699
+			$map_option = $option;
3700
+			$option     = str_replace('-', '_', $option);
3701
+			switch ($map_option) {
3702
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3703
+					$max_value = apply_filters(
3704
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3705
+						999,
3706
+						$this->_current_page,
3707
+						$this->_current_view
3708
+					);
3709
+					if ($value < 1) {
3710
+						return;
3711
+					}
3712
+					$value = min($value, $max_value);
3713
+					break;
3714
+				default:
3715
+					$value = apply_filters(
3716
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3717
+						false,
3718
+						$option,
3719
+						$value
3720
+					);
3721
+					if (false === $value) {
3722
+						return;
3723
+					}
3724
+					break;
3725
+			}
3726
+			update_user_meta($user->ID, $option, $value);
3727
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3728
+			exit;
3729
+		}
3730
+	}
3731
+
3732
+
3733
+	/**
3734
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3735
+	 *
3736
+	 * @param array $data array that will be assigned to template args.
3737
+	 */
3738
+	public function set_template_args($data)
3739
+	{
3740
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3741
+	}
3742
+
3743
+
3744
+	/**
3745
+	 * This makes available the WP transient system for temporarily moving data between routes
3746
+	 *
3747
+	 * @param string $route             the route that should receive the transient
3748
+	 * @param array  $data              the data that gets sent
3749
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3750
+	 *                                  normal route transient.
3751
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3752
+	 *                                  when we are adding a transient before page_routes have been defined.
3753
+	 * @return void
3754
+	 * @throws EE_Error
3755
+	 */
3756
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3757
+	{
3758
+		$user_id = get_current_user_id();
3759
+		if (! $skip_route_verify) {
3760
+			$this->_verify_route($route);
3761
+		}
3762
+		// now let's set the string for what kind of transient we're setting
3763
+		$transient = $notices
3764
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3765
+			: 'rte_tx_' . $route . '_' . $user_id;
3766
+		$data      = $notices ? ['notices' => $data] : $data;
3767
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3768
+		$existing = is_multisite() && is_network_admin()
3769
+			? get_site_transient($transient)
3770
+			: get_transient($transient);
3771
+		if ($existing) {
3772
+			$data = array_merge((array) $data, (array) $existing);
3773
+		}
3774
+		if (is_multisite() && is_network_admin()) {
3775
+			set_site_transient($transient, $data, 8);
3776
+		} else {
3777
+			set_transient($transient, $data, 8);
3778
+		}
3779
+	}
3780
+
3781
+
3782
+	/**
3783
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3784
+	 *
3785
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3786
+	 * @param string $route
3787
+	 * @return mixed data
3788
+	 */
3789
+	protected function _get_transient($notices = false, $route = '')
3790
+	{
3791
+		$user_id   = get_current_user_id();
3792
+		$route     = ! $route ? $this->_req_action : $route;
3793
+		$transient = $notices
3794
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3795
+			: 'rte_tx_' . $route . '_' . $user_id;
3796
+		$data      = is_multisite() && is_network_admin()
3797
+			? get_site_transient($transient)
3798
+			: get_transient($transient);
3799
+		// delete transient after retrieval (just in case it hasn't expired);
3800
+		if (is_multisite() && is_network_admin()) {
3801
+			delete_site_transient($transient);
3802
+		} else {
3803
+			delete_transient($transient);
3804
+		}
3805
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3806
+	}
3807
+
3808
+
3809
+	/**
3810
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3811
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3812
+	 * default route callback on the EE_Admin page you want it run.)
3813
+	 *
3814
+	 * @return void
3815
+	 */
3816
+	protected function _transient_garbage_collection()
3817
+	{
3818
+		global $wpdb;
3819
+		// retrieve all existing transients
3820
+		$query =
3821
+			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3822
+		if ($results = $wpdb->get_results($query)) {
3823
+			foreach ($results as $result) {
3824
+				$transient = str_replace('_transient_', '', $result->option_name);
3825
+				get_transient($transient);
3826
+				if (is_multisite() && is_network_admin()) {
3827
+					get_site_transient($transient);
3828
+				}
3829
+			}
3830
+		}
3831
+	}
3832
+
3833
+
3834
+	/**
3835
+	 * get_view
3836
+	 *
3837
+	 * @return string content of _view property
3838
+	 */
3839
+	public function get_view()
3840
+	{
3841
+		return $this->_view;
3842
+	}
3843
+
3844
+
3845
+	/**
3846
+	 * getter for the protected $_views property
3847
+	 *
3848
+	 * @return array
3849
+	 */
3850
+	public function get_views()
3851
+	{
3852
+		return $this->_views;
3853
+	}
3854
+
3855
+
3856
+	/**
3857
+	 * get_current_page
3858
+	 *
3859
+	 * @return string _current_page property value
3860
+	 */
3861
+	public function get_current_page()
3862
+	{
3863
+		return $this->_current_page;
3864
+	}
3865
+
3866
+
3867
+	/**
3868
+	 * get_current_view
3869
+	 *
3870
+	 * @return string _current_view property value
3871
+	 */
3872
+	public function get_current_view()
3873
+	{
3874
+		return $this->_current_view;
3875
+	}
3876
+
3877
+
3878
+	/**
3879
+	 * get_current_screen
3880
+	 *
3881
+	 * @return object The current WP_Screen object
3882
+	 */
3883
+	public function get_current_screen()
3884
+	{
3885
+		return $this->_current_screen;
3886
+	}
3887
+
3888
+
3889
+	/**
3890
+	 * get_current_page_view_url
3891
+	 *
3892
+	 * @return string This returns the url for the current_page_view.
3893
+	 */
3894
+	public function get_current_page_view_url()
3895
+	{
3896
+		return $this->_current_page_view_url;
3897
+	}
3898
+
3899
+
3900
+	/**
3901
+	 * just returns the Request
3902
+	 *
3903
+	 * @return RequestInterface
3904
+	 */
3905
+	public function get_request()
3906
+	{
3907
+		return $this->request;
3908
+	}
3909
+
3910
+
3911
+	/**
3912
+	 * just returns the _req_data property
3913
+	 *
3914
+	 * @return array
3915
+	 */
3916
+	public function get_request_data()
3917
+	{
3918
+		return $this->request->requestParams();
3919
+	}
3920
+
3921
+
3922
+	/**
3923
+	 * returns the _req_data protected property
3924
+	 *
3925
+	 * @return string
3926
+	 */
3927
+	public function get_req_action()
3928
+	{
3929
+		return $this->_req_action;
3930
+	}
3931
+
3932
+
3933
+	/**
3934
+	 * @return bool  value of $_is_caf property
3935
+	 */
3936
+	public function is_caf()
3937
+	{
3938
+		return $this->_is_caf;
3939
+	}
3940
+
3941
+
3942
+	/**
3943
+	 * @return mixed
3944
+	 */
3945
+	public function default_espresso_metaboxes()
3946
+	{
3947
+		return $this->_default_espresso_metaboxes;
3948
+	}
3949
+
3950
+
3951
+	/**
3952
+	 * @return mixed
3953
+	 */
3954
+	public function admin_base_url()
3955
+	{
3956
+		return $this->_admin_base_url;
3957
+	}
3958
+
3959
+
3960
+	/**
3961
+	 * @return mixed
3962
+	 */
3963
+	public function wp_page_slug()
3964
+	{
3965
+		return $this->_wp_page_slug;
3966
+	}
3967
+
3968
+
3969
+	/**
3970
+	 * updates  espresso configuration settings
3971
+	 *
3972
+	 * @param string                   $tab
3973
+	 * @param EE_Config_Base|EE_Config $config
3974
+	 * @param string                   $file file where error occurred
3975
+	 * @param string                   $func function  where error occurred
3976
+	 * @param string                   $line line no where error occurred
3977
+	 * @return boolean
3978
+	 */
3979
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3980
+	{
3981
+		// remove any options that are NOT going to be saved with the config settings.
3982
+		if (isset($config->core->ee_ueip_optin)) {
3983
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
3984
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3985
+			update_option('ee_ueip_has_notified', true);
3986
+		}
3987
+		// and save it (note we're also doing the network save here)
3988
+		$net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3989
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
3990
+		if ($config_saved && $net_saved) {
3991
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3992
+			return true;
3993
+		}
3994
+		EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3995
+		return false;
3996
+	}
3997
+
3998
+
3999
+	/**
4000
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4001
+	 *
4002
+	 * @return array
4003
+	 */
4004
+	public function get_yes_no_values()
4005
+	{
4006
+		return $this->_yes_no_values;
4007
+	}
4008
+
4009
+
4010
+	/**
4011
+	 * @return string
4012
+	 * @throws ReflectionException
4013
+	 * @since $VID:$
4014
+	 */
4015
+	protected function _get_dir()
4016
+	{
4017
+		$reflector = new ReflectionClass($this->class_name);
4018
+		return dirname($reflector->getFileName());
4019
+	}
4020
+
4021
+
4022
+	/**
4023
+	 * A helper for getting a "next link".
4024
+	 *
4025
+	 * @param string $url   The url to link to
4026
+	 * @param string $class The class to use.
4027
+	 * @return string
4028
+	 */
4029
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4030
+	{
4031
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4032
+	}
4033
+
4034
+
4035
+	/**
4036
+	 * A helper for getting a "previous link".
4037
+	 *
4038
+	 * @param string $url   The url to link to
4039
+	 * @param string $class The class to use.
4040
+	 * @return string
4041
+	 */
4042
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4043
+	{
4044
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4045
+	}
4046
+
4047
+
4048
+
4049
+
4050
+
4051
+
4052
+
4053
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4054
+
4055
+
4056
+	/**
4057
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4058
+	 * 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
4059
+	 * _req_data array.
4060
+	 *
4061
+	 * @return bool success/fail
4062
+	 * @throws EE_Error
4063
+	 * @throws InvalidArgumentException
4064
+	 * @throws ReflectionException
4065
+	 * @throws InvalidDataTypeException
4066
+	 * @throws InvalidInterfaceException
4067
+	 */
4068
+	protected function _process_resend_registration()
4069
+	{
4070
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4071
+		do_action(
4072
+			'AHEE__EE_Admin_Page___process_resend_registration',
4073
+			$this->_template_args['success'],
4074
+			$this->request->requestParams()
4075
+		);
4076
+		return $this->_template_args['success'];
4077
+	}
4078
+
4079
+
4080
+	/**
4081
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4082
+	 *
4083
+	 * @param EE_Payment $payment
4084
+	 * @return bool success/fail
4085
+	 */
4086
+	protected function _process_payment_notification(EE_Payment $payment)
4087
+	{
4088
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4089
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4090
+		$this->_template_args['success'] = apply_filters(
4091
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4092
+			false,
4093
+			$payment
4094
+		);
4095
+		return $this->_template_args['success'];
4096
+	}
4097
+
4098
+
4099
+	/**
4100
+	 * @param EEM_Base      $entity_model
4101
+	 * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4102
+	 * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4103
+	 * @param string        $delete_column  name of the field that denotes whether entity is trashed
4104
+	 * @param callable|null $callback       called after entity is trashed, restored, or deleted
4105
+	 * @return int|float
4106
+	 * @throws EE_Error
4107
+	 */
4108
+	protected function trashRestoreDeleteEntities(
4109
+		EEM_Base $entity_model,
4110
+		string $entity_PK_name,
4111
+		string $action = EE_Admin_List_Table::ACTION_DELETE,
4112
+		string $delete_column = '',
4113
+		callable $callback = null
4114
+	) {
4115
+		$entity_PK      = $entity_model->get_primary_key_field();
4116
+		$entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4117
+		$entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4118
+		// grab ID if deleting a single entity
4119
+		if ($this->request->requestParamIsSet($entity_PK_name)) {
4120
+			$ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4121
+			return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4122
+		}
4123
+		// or grab checkbox array if bulk deleting
4124
+		$checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4125
+		if (empty($checkboxes)) {
4126
+			return 0;
4127
+		}
4128
+		$success = 0;
4129
+		$IDs     = array_keys($checkboxes);
4130
+		// cycle thru bulk action checkboxes
4131
+		foreach ($IDs as $ID) {
4132
+			// increment $success
4133
+			if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4134
+				$success++;
4135
+			}
4136
+		}
4137
+		$count = (int) count($checkboxes);
4138
+		// if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4139
+		// otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4140
+		return $success === $count ? $count : $success / $count;
4141
+	}
4142
+
4143
+
4144
+	/**
4145
+	 * @param EE_Primary_Key_Field_Base $entity_PK
4146
+	 * @return string
4147
+	 * @throws EE_Error
4148
+	 * @since   4.10.30.p
4149
+	 */
4150
+	private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4151
+	{
4152
+		$entity_PK_type = $entity_PK->getSchemaType();
4153
+		switch ($entity_PK_type) {
4154
+			case 'boolean':
4155
+				return 'bool';
4156
+			case 'integer':
4157
+				return 'int';
4158
+			case 'number':
4159
+				return 'float';
4160
+			case 'string':
4161
+				return 'string';
4162
+		}
4163
+		throw new RuntimeException(
4164
+			sprintf(
4165
+				esc_html__(
4166
+					'"%1$s" is an invalid schema type for the %2$s primary key.',
4167
+					'event_espresso'
4168
+				),
4169
+				$entity_PK_type,
4170
+				$entity_PK->get_name()
4171
+			)
4172
+		);
4173
+	}
4174
+
4175
+
4176
+	/**
4177
+	 * @param EEM_Base      $entity_model
4178
+	 * @param int|string    $entity_ID
4179
+	 * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4180
+	 * @param string        $delete_column name of the field that denotes whether entity is trashed
4181
+	 * @param callable|null $callback      called after entity is trashed, restored, or deleted
4182
+	 * @return bool
4183
+	 */
4184
+	protected function trashRestoreDeleteEntity(
4185
+		EEM_Base $entity_model,
4186
+		$entity_ID,
4187
+		string $action,
4188
+		string $delete_column,
4189
+		?callable $callback = null
4190
+	): bool {
4191
+		$entity_ID = absint($entity_ID);
4192
+		if (! $entity_ID) {
4193
+			$this->trashRestoreDeleteError($action, $entity_model);
4194
+		}
4195
+		$result = 0;
4196
+		try {
4197
+			switch ($action) {
4198
+				case EE_Admin_List_Table::ACTION_DELETE:
4199
+					$result = (bool) $entity_model->delete_permanently_by_ID($entity_ID);
4200
+					break;
4201
+				case EE_Admin_List_Table::ACTION_RESTORE:
4202
+					$this->validateDeleteColumn($entity_model, $delete_column);
4203
+					$result = $entity_model->update_by_ID([$delete_column => 0], $entity_ID);
4204
+					break;
4205
+				case EE_Admin_List_Table::ACTION_TRASH:
4206
+					$this->validateDeleteColumn($entity_model, $delete_column);
4207
+					$result = $entity_model->update_by_ID([$delete_column => 1], $entity_ID);
4208
+					break;
4209
+			}
4210
+		} catch (Exception $exception) {
4211
+			$this->trashRestoreDeleteError($action, $entity_model, $exception);
4212
+		}
4213
+		if (is_callable($callback)) {
4214
+			call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4215
+		}
4216
+		return $result;
4217
+	}
4218
+
4219
+
4220
+	/**
4221
+	 * @param EEM_Base $entity_model
4222
+	 * @param string   $delete_column
4223
+	 * @since 4.10.30.p
4224
+	 */
4225
+	private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4226
+	{
4227
+		if (empty($delete_column)) {
4228
+			throw new DomainException(
4229
+				sprintf(
4230
+					esc_html__(
4231
+						'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4232
+						'event_espresso'
4233
+					),
4234
+					$entity_model->get_this_model_name()
4235
+				)
4236
+			);
4237
+		}
4238
+		if (! $entity_model->has_field($delete_column)) {
4239
+			throw new DomainException(
4240
+				sprintf(
4241
+					esc_html__(
4242
+						'The %1$s field does not exist on the %2$s model.',
4243
+						'event_espresso'
4244
+					),
4245
+					$delete_column,
4246
+					$entity_model->get_this_model_name()
4247
+				)
4248
+			);
4249
+		}
4250
+	}
4251
+
4252
+
4253
+	/**
4254
+	 * @param EEM_Base       $entity_model
4255
+	 * @param Exception|null $exception
4256
+	 * @param string         $action
4257
+	 * @since 4.10.30.p
4258
+	 */
4259
+	private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, ?Exception $exception = null)
4260
+	{
4261
+		if ($exception instanceof Exception) {
4262
+			throw new RuntimeException(
4263
+				sprintf(
4264
+					esc_html__(
4265
+						'Could not %1$s the %2$s because the following error occurred: %3$s',
4266
+						'event_espresso'
4267
+					),
4268
+					$action,
4269
+					$entity_model->get_this_model_name(),
4270
+					$exception->getMessage()
4271
+				)
4272
+			);
4273
+		}
4274
+		throw new RuntimeException(
4275
+			sprintf(
4276
+				esc_html__(
4277
+					'Could not %1$s the %2$s because an invalid ID was received.',
4278
+					'event_espresso'
4279
+				),
4280
+				$action,
4281
+				$entity_model->get_this_model_name()
4282
+			)
4283
+		);
4284
+	}
4285 4285
 }
Please login to merge, or discard this patch.
Spacing   +176 added lines, -176 removed lines patch added patch discarded remove patch
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
         $ee_menu_slugs = (array) $ee_menu_slugs;
630 630
         if (
631 631
             ! $this->request->isAjax()
632
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
632
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
633 633
         ) {
634 634
             return;
635 635
         }
@@ -649,7 +649,7 @@  discard block
 block discarded – undo
649 649
             : $req_action;
650 650
 
651 651
         $this->_current_view = $this->_req_action;
652
-        $this->_req_nonce    = $this->_req_action . '_nonce';
652
+        $this->_req_nonce    = $this->_req_action.'_nonce';
653 653
         $this->_define_page_props();
654 654
         $this->_current_page_view_url = add_query_arg(
655 655
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -679,33 +679,33 @@  discard block
 block discarded – undo
679 679
         }
680 680
         // filter routes and page_config so addons can add their stuff. Filtering done per class
681 681
         $this->_page_routes = apply_filters(
682
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
682
+            'FHEE__'.$this->class_name.'__page_setup__page_routes',
683 683
             $this->_page_routes,
684 684
             $this
685 685
         );
686 686
         $this->_page_config = apply_filters(
687
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
687
+            'FHEE__'.$this->class_name.'__page_setup__page_config',
688 688
             $this->_page_config,
689 689
             $this
690 690
         );
691 691
         if ($this->base_class_name !== '') {
692 692
             $this->_page_routes = apply_filters(
693
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
693
+                'FHEE__'.$this->base_class_name.'__page_setup__page_routes',
694 694
                 $this->_page_routes,
695 695
                 $this
696 696
             );
697 697
             $this->_page_config = apply_filters(
698
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
698
+                'FHEE__'.$this->base_class_name.'__page_setup__page_config',
699 699
                 $this->_page_config,
700 700
                 $this
701 701
             );
702 702
         }
703 703
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704 704
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
705
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
706 706
             add_action(
707 707
                 'AHEE__EE_Admin_Page__route_admin_request',
708
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
708
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
709 709
                 10,
710 710
                 2
711 711
             );
@@ -718,8 +718,8 @@  discard block
 block discarded – undo
718 718
             if ($this->_is_UI_request) {
719 719
                 // admin_init stuff - global, all views for this page class, specific view
720 720
                 add_action('admin_init', [$this, 'admin_init'], 10);
721
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
721
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
722
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
723 723
                 }
724 724
             } else {
725 725
                 // hijack regular WP loading and route admin request immediately
@@ -738,12 +738,12 @@  discard block
 block discarded – undo
738 738
      */
739 739
     private function _do_other_page_hooks()
740 740
     {
741
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
741
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
742 742
         foreach ($registered_pages as $page) {
743 743
             // now let's setup the file name and class that should be present
744 744
             $classname = str_replace('.class.php', '', $page);
745 745
             // autoloaders should take care of loading file
746
-            if (! class_exists($classname)) {
746
+            if ( ! class_exists($classname)) {
747 747
                 $error_msg[] = sprintf(
748 748
                     esc_html__(
749 749
                         'Something went wrong with loading the %s admin hooks page.',
@@ -760,7 +760,7 @@  discard block
 block discarded – undo
760 760
                                    ),
761 761
                                    $page,
762 762
                                    '<br />',
763
-                                   '<strong>' . $classname . '</strong>'
763
+                                   '<strong>'.$classname.'</strong>'
764 764
                                );
765 765
                 throw new EE_Error(implode('||', $error_msg));
766 766
             }
@@ -802,13 +802,13 @@  discard block
 block discarded – undo
802 802
         // load admin_notices - global, page class, and view specific
803 803
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804 804
         add_action('admin_notices', [$this, 'admin_notices'], 10);
805
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
805
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
806
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
807 807
         }
808 808
         // load network admin_notices - global, page class, and view specific
809 809
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
810
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
811
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
812 812
         }
813 813
         // this will save any per_page screen options if they are present
814 814
         $this->_set_per_page_screen_options();
@@ -929,7 +929,7 @@  discard block
 block discarded – undo
929 929
     protected function _verify_routes()
930 930
     {
931 931
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
-        if (! $this->_current_page && ! $this->request->isAjax()) {
932
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
933 933
             return false;
934 934
         }
935 935
         $this->_route = false;
@@ -941,7 +941,7 @@  discard block
 block discarded – undo
941 941
                 $this->_admin_page_title
942 942
             );
943 943
             // developer error msg
944
-            $error_msg .= '||' . $error_msg
944
+            $error_msg .= '||'.$error_msg
945 945
                           . esc_html__(
946 946
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947 947
                               'event_espresso'
@@ -950,8 +950,8 @@  discard block
 block discarded – undo
950 950
         }
951 951
         // and that the requested page route exists
952 952
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
954
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
953
+            $this->_route        = $this->_page_routes[$this->_req_action];
954
+            $this->_route_config = $this->_page_config[$this->_req_action] ?? [];
955 955
         } else {
956 956
             // user error msg
957 957
             $error_msg = sprintf(
@@ -962,7 +962,7 @@  discard block
 block discarded – undo
962 962
                 $this->_admin_page_title
963 963
             );
964 964
             // developer error msg
965
-            $error_msg .= '||' . $error_msg
965
+            $error_msg .= '||'.$error_msg
966 966
                           . sprintf(
967 967
                               esc_html__(
968 968
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
             throw new EE_Error($error_msg);
974 974
         }
975 975
         // and that a default route exists
976
-        if (! array_key_exists('default', $this->_page_routes)) {
976
+        if ( ! array_key_exists('default', $this->_page_routes)) {
977 977
             // user error msg
978 978
             $error_msg = sprintf(
979 979
                 esc_html__(
@@ -983,7 +983,7 @@  discard block
 block discarded – undo
983 983
                 $this->_admin_page_title
984 984
             );
985 985
             // developer error msg
986
-            $error_msg .= '||' . $error_msg
986
+            $error_msg .= '||'.$error_msg
987 987
                           . esc_html__(
988 988
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989 989
                               'event_espresso'
@@ -1025,7 +1025,7 @@  discard block
 block discarded – undo
1025 1025
             $this->_admin_page_title
1026 1026
         );
1027 1027
         // developer error msg
1028
-        $error_msg .= '||' . $error_msg
1028
+        $error_msg .= '||'.$error_msg
1029 1029
                       . sprintf(
1030 1030
                           esc_html__(
1031 1031
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -1053,7 +1053,7 @@  discard block
 block discarded – undo
1053 1053
     protected function _verify_nonce($nonce, $nonce_ref)
1054 1054
     {
1055 1055
         // verify nonce against expected value
1056
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1056
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
1057 1057
             // these are not the droids you are looking for !!!
1058 1058
             $msg = sprintf(
1059 1059
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -1070,7 +1070,7 @@  discard block
 block discarded – undo
1070 1070
                     __CLASS__
1071 1071
                 );
1072 1072
             }
1073
-            if (! $this->request->isAjax()) {
1073
+            if ( ! $this->request->isAjax()) {
1074 1074
                 wp_die($msg);
1075 1075
             }
1076 1076
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -1094,7 +1094,7 @@  discard block
 block discarded – undo
1094 1094
      */
1095 1095
     protected function _route_admin_request()
1096 1096
     {
1097
-        if (! $this->_is_UI_request) {
1097
+        if ( ! $this->_is_UI_request) {
1098 1098
             $this->_verify_routes();
1099 1099
         }
1100 1100
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -1114,7 +1114,7 @@  discard block
 block discarded – undo
1114 1114
         $error_msg = '';
1115 1115
         // action right before calling route
1116 1116
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1117
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118 1118
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119 1119
         }
1120 1120
         // strip _wp_http_referer from the server REQUEST_URI
@@ -1126,7 +1126,7 @@  discard block
 block discarded – undo
1126 1126
         );
1127 1127
         // set new value in both our Request object and the super global
1128 1128
         $this->request->setServerParam('REQUEST_URI', $request_uri, true);
1129
-        if (! empty($func)) {
1129
+        if ( ! empty($func)) {
1130 1130
             if (is_array($func)) {
1131 1131
                 [$class, $method] = $func;
1132 1132
             } elseif (strpos($func, '::') !== false) {
@@ -1135,7 +1135,7 @@  discard block
 block discarded – undo
1135 1135
                 $class  = $this;
1136 1136
                 $method = $func;
1137 1137
             }
1138
-            if (! (is_object($class) && $class === $this)) {
1138
+            if ( ! (is_object($class) && $class === $this)) {
1139 1139
                 // send along this admin page object for access by addons.
1140 1140
                 $args['admin_page_object'] = $this;
1141 1141
             }
@@ -1176,7 +1176,7 @@  discard block
 block discarded – undo
1176 1176
                     $method
1177 1177
                 );
1178 1178
             }
1179
-            if (! empty($error_msg)) {
1179
+            if ( ! empty($error_msg)) {
1180 1180
                 throw new EE_Error($error_msg);
1181 1181
             }
1182 1182
         }
@@ -1262,7 +1262,7 @@  discard block
 block discarded – undo
1262 1262
                 if (strpos($key, 'nonce') !== false) {
1263 1263
                     continue;
1264 1264
                 }
1265
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1265
+                $args['wp_referer['.$key.']'] = is_string($value) ? htmlspecialchars($value) : $value;
1266 1266
             }
1267 1267
         }
1268 1268
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
@@ -1302,12 +1302,12 @@  discard block
 block discarded – undo
1302 1302
      */
1303 1303
     protected function _add_help_tabs()
1304 1304
     {
1305
-        if (isset($this->_page_config[ $this->_req_action ])) {
1306
-            $config = $this->_page_config[ $this->_req_action ];
1305
+        if (isset($this->_page_config[$this->_req_action])) {
1306
+            $config = $this->_page_config[$this->_req_action];
1307 1307
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1308 1308
             if (is_array($config) && isset($config['help_sidebar'])) {
1309 1309
                 // check that the callback given is valid
1310
-                if (! method_exists($this, $config['help_sidebar'])) {
1310
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1311 1311
                     throw new EE_Error(
1312 1312
                         sprintf(
1313 1313
                             esc_html__(
@@ -1320,18 +1320,18 @@  discard block
 block discarded – undo
1320 1320
                     );
1321 1321
                 }
1322 1322
                 $content = apply_filters(
1323
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1323
+                    'FHEE__'.$this->class_name.'__add_help_tabs__help_sidebar',
1324 1324
                     $this->{$config['help_sidebar']}()
1325 1325
                 );
1326 1326
                 $this->_current_screen->set_help_sidebar($content);
1327 1327
             }
1328
-            if (! isset($config['help_tabs'])) {
1328
+            if ( ! isset($config['help_tabs'])) {
1329 1329
                 return;
1330 1330
             } //no help tabs for this route
1331 1331
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1332 1332
                 // we're here so there ARE help tabs!
1333 1333
                 // make sure we've got what we need
1334
-                if (! isset($cfg['title'])) {
1334
+                if ( ! isset($cfg['title'])) {
1335 1335
                     throw new EE_Error(
1336 1336
                         esc_html__(
1337 1337
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1339,7 +1339,7 @@  discard block
 block discarded – undo
1339 1339
                         )
1340 1340
                     );
1341 1341
                 }
1342
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1342
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1343 1343
                     throw new EE_Error(
1344 1344
                         esc_html__(
1345 1345
                             'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
@@ -1348,11 +1348,11 @@  discard block
 block discarded – undo
1348 1348
                     );
1349 1349
                 }
1350 1350
                 // first priority goes to content.
1351
-                if (! empty($cfg['content'])) {
1351
+                if ( ! empty($cfg['content'])) {
1352 1352
                     $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1353 1353
                     // second priority goes to filename
1354
-                } elseif (! empty($cfg['filename'])) {
1355
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1354
+                } elseif ( ! empty($cfg['filename'])) {
1355
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1356 1356
                     // 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)
1357 1357
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1358 1358
                                                              . basename($this->_get_dir())
@@ -1360,7 +1360,7 @@  discard block
 block discarded – undo
1360 1360
                                                              . $cfg['filename']
1361 1361
                                                              . '.help_tab.php' : $file_path;
1362 1362
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1363
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1363
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1364 1364
                         EE_Error::add_error(
1365 1365
                             sprintf(
1366 1366
                                 esc_html__(
@@ -1408,7 +1408,7 @@  discard block
 block discarded – undo
1408 1408
                     return;
1409 1409
                 }
1410 1410
                 // setup config array for help tab method
1411
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1411
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1412 1412
                 $_ht = [
1413 1413
                     'id'       => $id,
1414 1414
                     'title'    => $cfg['title'],
@@ -1434,8 +1434,8 @@  discard block
 block discarded – undo
1434 1434
             $qtips = (array) $this->_route_config['qtips'];
1435 1435
             // load qtip loader
1436 1436
             $path = [
1437
-                $this->_get_dir() . '/qtips/',
1438
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1437
+                $this->_get_dir().'/qtips/',
1438
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1439 1439
             ];
1440 1440
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1441 1441
         }
@@ -1457,7 +1457,7 @@  discard block
 block discarded – undo
1457 1457
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1458 1458
         $i = 0;
1459 1459
         foreach ($this->_page_config as $slug => $config) {
1460
-            if (! is_array($config) || empty($config['nav'])) {
1460
+            if ( ! is_array($config) || empty($config['nav'])) {
1461 1461
                 continue;
1462 1462
             }
1463 1463
             // no nav tab for this config
@@ -1466,12 +1466,12 @@  discard block
 block discarded – undo
1466 1466
                 // nav tab is only to appear when route requested.
1467 1467
                 continue;
1468 1468
             }
1469
-            if (! $this->check_user_access($slug, true)) {
1469
+            if ( ! $this->check_user_access($slug, true)) {
1470 1470
                 // no nav tab because current user does not have access.
1471 1471
                 continue;
1472 1472
             }
1473
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1474
-            $this->_nav_tabs[ $slug ] = [
1473
+            $css_class                = isset($config['css_class']) ? $config['css_class'].' ' : '';
1474
+            $this->_nav_tabs[$slug] = [
1475 1475
                 'url'       => isset($config['nav']['url'])
1476 1476
                     ? $config['nav']['url']
1477 1477
                     : EE_Admin_Page::add_query_args_and_nonce(
@@ -1483,14 +1483,14 @@  discard block
 block discarded – undo
1483 1483
                     : ucwords(
1484 1484
                         str_replace('_', ' ', $slug)
1485 1485
                     ),
1486
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1486
+                'css_class' => $this->_req_action === $slug ? $css_class.'nav-tab-active' : $css_class,
1487 1487
                 'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1488 1488
             ];
1489 1489
             $i++;
1490 1490
         }
1491 1491
         // if $this->_nav_tabs is empty then lets set the default
1492 1492
         if (empty($this->_nav_tabs)) {
1493
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1493
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1494 1494
                 'url'       => $this->_admin_base_url,
1495 1495
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1496 1496
                 'css_class' => 'nav-tab-active',
@@ -1515,10 +1515,10 @@  discard block
 block discarded – undo
1515 1515
             foreach ($this->_route_config['labels'] as $label => $text) {
1516 1516
                 if (is_array($text)) {
1517 1517
                     foreach ($text as $sublabel => $subtext) {
1518
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1518
+                        $this->_labels[$label][$sublabel] = $subtext;
1519 1519
                     }
1520 1520
                 } else {
1521
-                    $this->_labels[ $label ] = $text;
1521
+                    $this->_labels[$label] = $text;
1522 1522
                 }
1523 1523
             }
1524 1524
         }
@@ -1540,10 +1540,10 @@  discard block
 block discarded – undo
1540 1540
     {
1541 1541
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1542 1542
         $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1543
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1544
-                                      && is_array($this->_page_routes[ $route_to_check ])
1545
-                        && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1546
-            ? $this->_page_routes[ $route_to_check ]['capability']
1543
+        $capability = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1544
+                                      && is_array($this->_page_routes[$route_to_check])
1545
+                        && ! empty($this->_page_routes[$route_to_check]['capability'])
1546
+            ? $this->_page_routes[$route_to_check]['capability']
1547 1547
             : null;
1548 1548
 
1549 1549
         if (empty($capability) && empty($route_to_check)) {
@@ -1597,14 +1597,14 @@  discard block
 block discarded – undo
1597 1597
         string $priority = 'default',
1598 1598
         ?array $callback_args = null
1599 1599
     ) {
1600
-        if (! is_callable($callback)) {
1600
+        if ( ! is_callable($callback)) {
1601 1601
             return;
1602 1602
         }
1603 1603
 
1604 1604
         add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1605 1605
         add_filter(
1606 1606
             "postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1607
-            function ($classes) {
1607
+            function($classes) {
1608 1608
                 array_push($classes, 'ee-admin-container');
1609 1609
                 return $classes;
1610 1610
             }
@@ -1698,7 +1698,7 @@  discard block
 block discarded – undo
1698 1698
         ';
1699 1699
 
1700 1700
         // current set timezone for timezone js
1701
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1701
+        echo '<span id="current_timezone" class="hidden">'.esc_html(EEH_DTT_Helper::get_timezone()).'</span>';
1702 1702
     }
1703 1703
 
1704 1704
 
@@ -1732,7 +1732,7 @@  discard block
 block discarded – undo
1732 1732
         // loop through the array and setup content
1733 1733
         foreach ($help_array as $trigger => $help) {
1734 1734
             // make sure the array is setup properly
1735
-            if (! isset($help['title'], $help['content'])) {
1735
+            if ( ! isset($help['title'], $help['content'])) {
1736 1736
                 throw new EE_Error(
1737 1737
                     esc_html__(
1738 1738
                         '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',
@@ -1746,8 +1746,8 @@  discard block
 block discarded – undo
1746 1746
                 'help_popup_title'   => $help['title'],
1747 1747
                 'help_popup_content' => $help['content'],
1748 1748
             ];
1749
-            $content       .= EEH_Template::display_template(
1750
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1749
+            $content .= EEH_Template::display_template(
1750
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1751 1751
                 $template_args,
1752 1752
                 true
1753 1753
             );
@@ -1769,15 +1769,15 @@  discard block
 block discarded – undo
1769 1769
     private function _get_help_content()
1770 1770
     {
1771 1771
         // what is the method we're looking for?
1772
-        $method_name = '_help_popup_content_' . $this->_req_action;
1772
+        $method_name = '_help_popup_content_'.$this->_req_action;
1773 1773
         // if method doesn't exist let's get out.
1774
-        if (! method_exists($this, $method_name)) {
1774
+        if ( ! method_exists($this, $method_name)) {
1775 1775
             return [];
1776 1776
         }
1777 1777
         // k we're good to go let's retrieve the help array
1778 1778
         $help_array = $this->{$method_name}();
1779 1779
         // make sure we've got an array!
1780
-        if (! is_array($help_array)) {
1780
+        if ( ! is_array($help_array)) {
1781 1781
             throw new EE_Error(
1782 1782
                 esc_html__(
1783 1783
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1809,8 +1809,8 @@  discard block
 block discarded – undo
1809 1809
         // 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
1810 1810
         $help_array   = $this->_get_help_content();
1811 1811
         $help_content = '';
1812
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1813
-            $help_array[ $trigger_id ] = [
1812
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1813
+            $help_array[$trigger_id] = [
1814 1814
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1815 1815
                 'content' => esc_html__(
1816 1816
                     '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.)',
@@ -1905,7 +1905,7 @@  discard block
 block discarded – undo
1905 1905
 
1906 1906
         add_filter(
1907 1907
             'admin_body_class',
1908
-            function ($classes) {
1908
+            function($classes) {
1909 1909
                 if (strpos($classes, 'espresso-admin') === false) {
1910 1910
                     $classes .= ' espresso-admin';
1911 1911
                 }
@@ -1996,12 +1996,12 @@  discard block
 block discarded – undo
1996 1996
     protected function _set_list_table()
1997 1997
     {
1998 1998
         // first is this a list_table view?
1999
-        if (! isset($this->_route_config['list_table'])) {
1999
+        if ( ! isset($this->_route_config['list_table'])) {
2000 2000
             return;
2001 2001
         } //not a list_table view so get out.
2002 2002
         // list table functions are per view specific (because some admin pages might have more than one list table!)
2003
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2004
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2003
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
2004
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2005 2005
             // user error msg
2006 2006
             $error_msg = esc_html__(
2007 2007
                 'An error occurred. The requested list table views could not be found.',
@@ -2021,10 +2021,10 @@  discard block
 block discarded – undo
2021 2021
         }
2022 2022
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2023 2023
         $this->_views = apply_filters(
2024
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2024
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2025 2025
             $this->_views
2026 2026
         );
2027
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2027
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2028 2028
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2029 2029
         $this->_set_list_table_view();
2030 2030
         $this->_set_list_table_object();
@@ -2059,7 +2059,7 @@  discard block
 block discarded – undo
2059 2059
     protected function _set_list_table_object()
2060 2060
     {
2061 2061
         if (isset($this->_route_config['list_table'])) {
2062
-            if (! class_exists($this->_route_config['list_table'])) {
2062
+            if ( ! class_exists($this->_route_config['list_table'])) {
2063 2063
                 throw new EE_Error(
2064 2064
                     sprintf(
2065 2065
                         esc_html__(
@@ -2097,17 +2097,17 @@  discard block
 block discarded – undo
2097 2097
         foreach ($this->_views as $key => $view) {
2098 2098
             $query_args = [];
2099 2099
             // check for current view
2100
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2100
+            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2101 2101
             $query_args['action']                        = $this->_req_action;
2102
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2102
+            $query_args[$this->_req_action.'_nonce'] = wp_create_nonce($query_args['action'].'_nonce');
2103 2103
             $query_args['status']                        = $view['slug'];
2104 2104
             // merge any other arguments sent in.
2105
-            if (isset($extra_query_args[ $view['slug'] ])) {
2106
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2105
+            if (isset($extra_query_args[$view['slug']])) {
2106
+                foreach ($extra_query_args[$view['slug']] as $extra_query_arg) {
2107 2107
                     $query_args[] = $extra_query_arg;
2108 2108
                 }
2109 2109
             }
2110
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2110
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2111 2111
         }
2112 2112
         return $this->_views;
2113 2113
     }
@@ -2138,14 +2138,14 @@  discard block
 block discarded – undo
2138 2138
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2139 2139
         foreach ($values as $value) {
2140 2140
             if ($value < $max_entries) {
2141
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2141
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2142 2142
                 $entries_per_page_dropdown .= '
2143
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2143
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2144 2144
             }
2145 2145
         }
2146
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2146
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2147 2147
         $entries_per_page_dropdown .= '
2148
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2148
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2149 2149
         $entries_per_page_dropdown .= '
2150 2150
 					</select>
2151 2151
 					entries
@@ -2169,7 +2169,7 @@  discard block
 block discarded – undo
2169 2169
             empty($this->_search_btn_label) ? $this->page_label
2170 2170
                 : $this->_search_btn_label
2171 2171
         );
2172
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2172
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2173 2173
     }
2174 2174
 
2175 2175
 
@@ -2257,7 +2257,7 @@  discard block
 block discarded – undo
2257 2257
             $total_columns                                       = ! empty($screen_columns)
2258 2258
                 ? $screen_columns
2259 2259
                 : $this->_route_config['columns'][1];
2260
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2260
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2261 2261
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2262 2262
             $this->_template_args['screen']                      = $this->_current_screen;
2263 2263
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2303,7 +2303,7 @@  discard block
 block discarded – undo
2303 2303
      */
2304 2304
     protected function _espresso_ratings_request()
2305 2305
     {
2306
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2306
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2307 2307
             return;
2308 2308
         }
2309 2309
         $ratings_box_title = apply_filters(
@@ -2330,28 +2330,28 @@  discard block
 block discarded – undo
2330 2330
      */
2331 2331
     public function espresso_ratings_request()
2332 2332
     {
2333
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2333
+        EEH_Template::display_template(EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php');
2334 2334
     }
2335 2335
 
2336 2336
 
2337 2337
     public static function cached_rss_display($rss_id, $url)
2338 2338
     {
2339
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2339
+        $loading = '<p class="widget-loading hide-if-no-js">'
2340 2340
                      . esc_html__('Loading&#8230;', 'event_espresso')
2341 2341
                      . '</p><p class="hide-if-js">'
2342 2342
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2343 2343
                      . '</p>';
2344
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2345
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2346
-        $post      = '</div>' . "\n";
2347
-        $cache_key = 'ee_rss_' . md5($rss_id);
2344
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2345
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2346
+        $post      = '</div>'."\n";
2347
+        $cache_key = 'ee_rss_'.md5($rss_id);
2348 2348
         $output    = get_transient($cache_key);
2349 2349
         if ($output !== false) {
2350
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2350
+            echo wp_kses($pre.$output.$post, AllowedTags::getWithFormTags());
2351 2351
             return true;
2352 2352
         }
2353
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2353
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
+            echo wp_kses($pre.$loading.$post, AllowedTags::getWithFormTags());
2355 2355
             return false;
2356 2356
         }
2357 2357
         ob_start();
@@ -2418,19 +2418,19 @@  discard block
 block discarded – undo
2418 2418
     public function espresso_sponsors_post_box()
2419 2419
     {
2420 2420
         EEH_Template::display_template(
2421
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2421
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2422 2422
         );
2423 2423
     }
2424 2424
 
2425 2425
 
2426 2426
     private function _publish_post_box()
2427 2427
     {
2428
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2428
+        $meta_box_ref = 'espresso_'.$this->page_slug.'_editor_overview';
2429 2429
         // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2430 2430
         // then we'll use that for the metabox label.
2431 2431
         // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2432
-        if (! empty($this->_labels['publishbox'])) {
2433
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2432
+        if ( ! empty($this->_labels['publishbox'])) {
2433
+            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2434 2434
                 : $this->_labels['publishbox'];
2435 2435
         } else {
2436 2436
             $box_label = esc_html__('Publish', 'event_espresso');
@@ -2459,7 +2459,7 @@  discard block
 block discarded – undo
2459 2459
             ? $this->_template_args['publish_box_extra_content']
2460 2460
             : '';
2461 2461
         echo EEH_Template::display_template(
2462
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2462
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2463 2463
             $this->_template_args,
2464 2464
             true
2465 2465
         );
@@ -2547,18 +2547,18 @@  discard block
 block discarded – undo
2547 2547
             );
2548 2548
         }
2549 2549
         $this->_template_args['publish_delete_link'] = $delete_link;
2550
-        if (! empty($name) && ! empty($id)) {
2551
-            $hidden_field_arr[ $name ] = [
2550
+        if ( ! empty($name) && ! empty($id)) {
2551
+            $hidden_field_arr[$name] = [
2552 2552
                 'type'  => 'hidden',
2553 2553
                 'value' => $id,
2554 2554
             ];
2555
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2555
+            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2556 2556
         } else {
2557 2557
             $hf = '';
2558 2558
         }
2559 2559
         // add hidden field
2560 2560
         $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2561
-            ? $hf[ $name ]['field']
2561
+            ? $hf[$name]['field']
2562 2562
             : $hf;
2563 2563
     }
2564 2564
 
@@ -2660,7 +2660,7 @@  discard block
 block discarded – undo
2660 2660
         }
2661 2661
         // 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)
2662 2662
         $call_back_func = $create_func
2663
-            ? static function ($post, $metabox) {
2663
+            ? static function($post, $metabox) {
2664 2664
                 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2665 2665
                 echo EEH_Template::display_template(
2666 2666
                     $metabox['args']['template_path'],
@@ -2670,7 +2670,7 @@  discard block
 block discarded – undo
2670 2670
             }
2671 2671
             : $callback;
2672 2672
         $this->addMetaBox(
2673
-            str_replace('_', '-', $action) . '-mbox',
2673
+            str_replace('_', '-', $action).'-mbox',
2674 2674
             $title,
2675 2675
             $call_back_func,
2676 2676
             $this->_wp_page_slug,
@@ -2787,13 +2787,13 @@  discard block
 block discarded – undo
2787 2787
             'event-espresso_page_espresso_',
2788 2788
             '',
2789 2789
             $this->_wp_page_slug
2790
-        ) . ' ' . $this->_req_action . '-route';
2790
+        ).' '.$this->_req_action.'-route';
2791 2791
 
2792 2792
         $template_path = $sidebar
2793 2793
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2794
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2794
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2795 2795
         if ($this->request->isAjax()) {
2796
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2796
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2797 2797
         }
2798 2798
         $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2799 2799
 
@@ -2827,11 +2827,11 @@  discard block
 block discarded – undo
2827 2827
     public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2828 2828
     {
2829 2829
         // let's generate a default preview action button if there isn't one already present.
2830
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2830
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2831 2831
             'Upgrade to Event Espresso 4 Right Now',
2832 2832
             'event_espresso'
2833 2833
         );
2834
-        $buy_now_url                                   = add_query_arg(
2834
+        $buy_now_url = add_query_arg(
2835 2835
             [
2836 2836
                 'ee_ver'       => 'ee4',
2837 2837
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2851,8 +2851,8 @@  discard block
 block discarded – undo
2851 2851
                 true
2852 2852
             )
2853 2853
             : $this->_template_args['preview_action_button'];
2854
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2855
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2854
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2855
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2856 2856
             $this->_template_args,
2857 2857
             true
2858 2858
         );
@@ -2910,7 +2910,7 @@  discard block
 block discarded – undo
2910 2910
         // setup search attributes
2911 2911
         $this->_set_search_attributes();
2912 2912
         $this->_template_args['current_page']     = $this->_wp_page_slug;
2913
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2913
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
2914 2914
         $this->_template_args['table_url']        = $this->request->isAjax()
2915 2915
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2916 2916
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -2918,10 +2918,10 @@  discard block
 block discarded – undo
2918 2918
         $this->_template_args['current_route']    = $this->_req_action;
2919 2919
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2920 2920
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2921
-        if (! empty($ajax_sorting_callback)) {
2921
+        if ( ! empty($ajax_sorting_callback)) {
2922 2922
             $sortable_list_table_form_fields = wp_nonce_field(
2923
-                $ajax_sorting_callback . '_nonce',
2924
-                $ajax_sorting_callback . '_nonce',
2923
+                $ajax_sorting_callback.'_nonce',
2924
+                $ajax_sorting_callback.'_nonce',
2925 2925
                 false,
2926 2926
                 false
2927 2927
             );
@@ -2938,18 +2938,18 @@  discard block
 block discarded – undo
2938 2938
 
2939 2939
         $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2940 2940
 
2941
-        $nonce_ref          = $this->_req_action . '_nonce';
2941
+        $nonce_ref          = $this->_req_action.'_nonce';
2942 2942
         $hidden_form_fields .= '
2943
-            <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2943
+            <input type="hidden" name="' . $nonce_ref.'" value="'.wp_create_nonce($nonce_ref).'">';
2944 2944
 
2945
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2945
+        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2946 2946
         // display message about search results?
2947 2947
         $search = $this->request->getRequestParam('s');
2948 2948
         $this->_template_args['before_list_table'] .= ! empty($search)
2949
-            ? '<p class="ee-search-results">' . sprintf(
2949
+            ? '<p class="ee-search-results">'.sprintf(
2950 2950
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2951 2951
                 trim($search, '%')
2952
-            ) . '</p>'
2952
+            ).'</p>'
2953 2953
             : '';
2954 2954
         // filter before_list_table template arg
2955 2955
         $this->_template_args['before_list_table'] = apply_filters(
@@ -2983,7 +2983,7 @@  discard block
 block discarded – undo
2983 2983
         // convert to array and filter again
2984 2984
         // arrays are easier to inject new items in a specific location,
2985 2985
         // but would not be backwards compatible, so we have to add a new filter
2986
-        $this->_template_args['after_list_table']   = implode(
2986
+        $this->_template_args['after_list_table'] = implode(
2987 2987
             " \n",
2988 2988
             (array) apply_filters(
2989 2989
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -3038,7 +3038,7 @@  discard block
 block discarded – undo
3038 3038
             $this->page_slug
3039 3039
         );
3040 3040
         return EEH_Template::display_template(
3041
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3041
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3042 3042
             $this->_template_args,
3043 3043
             true
3044 3044
         );
@@ -3154,16 +3154,16 @@  discard block
 block discarded – undo
3154 3154
             $this->_template_args['before_admin_page_content'] ?? ''
3155 3155
         );
3156 3156
 
3157
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3157
+        $this->_template_args['after_admin_page_content'] = apply_filters(
3158 3158
             "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3159 3159
             $this->_template_args['after_admin_page_content'] ?? ''
3160 3160
         );
3161
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3161
+        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3162 3162
 
3163 3163
         if ($this->request->isAjax()) {
3164 3164
             $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3165 3165
                 // $template_path,
3166
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3166
+                EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php',
3167 3167
                 $this->_template_args,
3168 3168
                 true
3169 3169
             );
@@ -3172,7 +3172,7 @@  discard block
 block discarded – undo
3172 3172
         // load settings page wrapper template
3173 3173
         $template_path = $about
3174 3174
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3175
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3175
+            : EE_ADMIN_TEMPLATE.'admin_wrapper.template.php';
3176 3176
 
3177 3177
         EEH_Template::display_template($template_path, $this->_template_args);
3178 3178
     }
@@ -3256,12 +3256,12 @@  discard block
 block discarded – undo
3256 3256
         $default_names = ['save', 'save_and_close'];
3257 3257
         $buttons = '';
3258 3258
         foreach ($button_text as $key => $button) {
3259
-            $ref     = $default_names[ $key ];
3260
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3261
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3262
-                        . 'value="' . $button . '" name="' . $name . '" '
3263
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3264
-            if (! $both) {
3259
+            $ref     = $default_names[$key];
3260
+            $name    = ! empty($actions) ? $actions[$key] : $ref;
3261
+            $buttons .= '<input type="submit" class="button button--primary '.$ref.'" '
3262
+                        . 'value="'.$button.'" name="'.$name.'" '
3263
+                        . 'id="'.$this->_current_view.'_'.$ref.'" />';
3264
+            if ( ! $both) {
3265 3265
                 break;
3266 3266
             }
3267 3267
         }
@@ -3301,13 +3301,13 @@  discard block
 block discarded – undo
3301 3301
                 'An error occurred. No action was set for this page\'s form.',
3302 3302
                 'event_espresso'
3303 3303
             );
3304
-            $dev_msg  = $user_msg . "\n"
3304
+            $dev_msg = $user_msg."\n"
3305 3305
                         . sprintf(
3306 3306
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3307 3307
                             __FUNCTION__,
3308 3308
                             __CLASS__
3309 3309
                         );
3310
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3310
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3311 3311
         }
3312 3312
         // open form
3313 3313
         $action = $this->_admin_base_url;
@@ -3315,9 +3315,9 @@  discard block
 block discarded – undo
3315 3315
             <form name='form' method='post' action='{$action}' id='{$route}_event_form' class='ee-admin-page-form' >
3316 3316
             ";
3317 3317
         // add nonce
3318
-        $nonce                                             =
3319
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3320
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3318
+        $nonce =
3319
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3320
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3321 3321
         // add REQUIRED form action
3322 3322
         $hidden_fields = [
3323 3323
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3330,7 +3330,7 @@  discard block
 block discarded – undo
3330 3330
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3331 3331
         // add fields to form
3332 3332
         foreach ((array) $form_fields as $form_field) {
3333
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3333
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3334 3334
         }
3335 3335
         // close form
3336 3336
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3413,12 +3413,12 @@  discard block
 block discarded – undo
3413 3413
         bool $override_overwrite = false
3414 3414
     ) {
3415 3415
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3416
-        $notices      = EE_Error::get_notices(false);
3416
+        $notices = EE_Error::get_notices(false);
3417 3417
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3418
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3418
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3419 3419
             EE_Error::overwrite_success();
3420 3420
         }
3421
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3421
+        if ( ! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3422 3422
             // how many records affected ? more than one record ? or just one ?
3423 3423
             EE_Error::add_success(
3424 3424
                 sprintf(
@@ -3439,7 +3439,7 @@  discard block
 block discarded – undo
3439 3439
             );
3440 3440
         }
3441 3441
         // check that $query_args isn't something crazy
3442
-        if (! is_array($query_args)) {
3442
+        if ( ! is_array($query_args)) {
3443 3443
             $query_args = [];
3444 3444
         }
3445 3445
         /**
@@ -3471,7 +3471,7 @@  discard block
 block discarded – undo
3471 3471
             $redirect_url = admin_url('admin.php');
3472 3472
         }
3473 3473
         // merge any default query_args set in _default_route_query_args property
3474
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3474
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3475 3475
             $args_to_merge = [];
3476 3476
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3477 3477
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3483,15 +3483,15 @@  discard block
 block discarded – undo
3483 3483
                         }
3484 3484
                         // finally we will override any arguments in the referer with
3485 3485
                         // what might be set on the _default_route_query_args array.
3486
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3487
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3486
+                        if (isset($this->_default_route_query_args[$reference])) {
3487
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3488 3488
                         } else {
3489
-                            $args_to_merge[ $reference ] = urlencode($value);
3489
+                            $args_to_merge[$reference] = urlencode($value);
3490 3490
                         }
3491 3491
                     }
3492 3492
                     continue;
3493 3493
                 }
3494
-                $args_to_merge[ $query_param ] = $query_value;
3494
+                $args_to_merge[$query_param] = $query_value;
3495 3495
             }
3496 3496
             // now let's merge these arguments but override with what was specifically sent in to the
3497 3497
             // redirect.
@@ -3503,19 +3503,19 @@  discard block
 block discarded – undo
3503 3503
         if (isset($query_args['action'])) {
3504 3504
             // manually generate wp_nonce and merge that with the query vars
3505 3505
             // becuz the wp_nonce_url function wrecks havoc on some vars
3506
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3506
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3507 3507
         }
3508 3508
         // we're adding some hooks and filters in here for processing any things just before redirects
3509 3509
         // (example: an admin page has done an insert or update and we want to run something after that).
3510
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3510
+        do_action('AHEE_redirect_'.$this->class_name.$this->_req_action, $query_args);
3511 3511
         $redirect_url = apply_filters(
3512
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3512
+            'FHEE_redirect_'.$this->class_name.$this->_req_action,
3513 3513
             EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3514 3514
             $query_args
3515 3515
         );
3516 3516
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3517 3517
         if ($this->request->isAjax()) {
3518
-            $default_data                    = [
3518
+            $default_data = [
3519 3519
                 'close'        => true,
3520 3520
                 'redirect_url' => $redirect_url,
3521 3521
                 'where'        => 'main',
@@ -3565,7 +3565,7 @@  discard block
 block discarded – undo
3565 3565
         }
3566 3566
         $this->_template_args['notices'] = EE_Error::get_notices();
3567 3567
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3568
-        if (! $this->request->isAjax() || $sticky_notices) {
3568
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3569 3569
             $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3570 3570
             $this->_add_transient(
3571 3571
                 $route,
@@ -3605,7 +3605,7 @@  discard block
 block discarded – undo
3605 3605
         $exclude_nonce = false
3606 3606
     ) {
3607 3607
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3608
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3608
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3609 3609
             throw new EE_Error(
3610 3610
                 sprintf(
3611 3611
                     esc_html__(
@@ -3616,7 +3616,7 @@  discard block
 block discarded – undo
3616 3616
                 )
3617 3617
             );
3618 3618
         }
3619
-        if (! isset($this->_labels['buttons'][ $type ])) {
3619
+        if ( ! isset($this->_labels['buttons'][$type])) {
3620 3620
             throw new EE_Error(
3621 3621
                 sprintf(
3622 3622
                     esc_html__(
@@ -3629,7 +3629,7 @@  discard block
 block discarded – undo
3629 3629
         }
3630 3630
         // finally check user access for this button.
3631 3631
         $has_access = $this->check_user_access($action, true);
3632
-        if (! $has_access) {
3632
+        if ( ! $has_access) {
3633 3633
             return '';
3634 3634
         }
3635 3635
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3637,11 +3637,11 @@  discard block
 block discarded – undo
3637 3637
             'action' => $action,
3638 3638
         ];
3639 3639
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3640
-        if (! empty($extra_request)) {
3640
+        if ( ! empty($extra_request)) {
3641 3641
             $query_args = array_merge($extra_request, $query_args);
3642 3642
         }
3643 3643
         $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3644
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3644
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3645 3645
     }
3646 3646
 
3647 3647
 
@@ -3667,7 +3667,7 @@  discard block
 block discarded – undo
3667 3667
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3668 3668
                 20
3669 3669
             ),
3670
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3670
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3671 3671
         ];
3672 3672
         // ONLY add the screen option if the user has access to it.
3673 3673
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3688,18 +3688,18 @@  discard block
 block discarded – undo
3688 3688
     {
3689 3689
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3690 3690
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3691
-            if (! $user = wp_get_current_user()) {
3691
+            if ( ! $user = wp_get_current_user()) {
3692 3692
                 return;
3693 3693
             }
3694 3694
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3695
-            if (! $option) {
3695
+            if ( ! $option) {
3696 3696
                 return;
3697 3697
             }
3698
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3698
+            $value = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3699 3699
             $map_option = $option;
3700 3700
             $option     = str_replace('-', '_', $option);
3701 3701
             switch ($map_option) {
3702
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3702
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3703 3703
                     $max_value = apply_filters(
3704 3704
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3705 3705
                         999,
@@ -3756,13 +3756,13 @@  discard block
 block discarded – undo
3756 3756
     protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3757 3757
     {
3758 3758
         $user_id = get_current_user_id();
3759
-        if (! $skip_route_verify) {
3759
+        if ( ! $skip_route_verify) {
3760 3760
             $this->_verify_route($route);
3761 3761
         }
3762 3762
         // now let's set the string for what kind of transient we're setting
3763 3763
         $transient = $notices
3764
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3765
-            : 'rte_tx_' . $route . '_' . $user_id;
3764
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3765
+            : 'rte_tx_'.$route.'_'.$user_id;
3766 3766
         $data      = $notices ? ['notices' => $data] : $data;
3767 3767
         // is there already a transient for this route?  If there is then let's ADD to that transient
3768 3768
         $existing = is_multisite() && is_network_admin()
@@ -3791,8 +3791,8 @@  discard block
 block discarded – undo
3791 3791
         $user_id   = get_current_user_id();
3792 3792
         $route     = ! $route ? $this->_req_action : $route;
3793 3793
         $transient = $notices
3794
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3795
-            : 'rte_tx_' . $route . '_' . $user_id;
3794
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3795
+            : 'rte_tx_'.$route.'_'.$user_id;
3796 3796
         $data      = is_multisite() && is_network_admin()
3797 3797
             ? get_site_transient($transient)
3798 3798
             : get_transient($transient);
@@ -4028,7 +4028,7 @@  discard block
 block discarded – undo
4028 4028
      */
4029 4029
     protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4030 4030
     {
4031
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4031
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4032 4032
     }
4033 4033
 
4034 4034
 
@@ -4041,7 +4041,7 @@  discard block
 block discarded – undo
4041 4041
      */
4042 4042
     protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4043 4043
     {
4044
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4044
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4045 4045
     }
4046 4046
 
4047 4047
 
@@ -4189,7 +4189,7 @@  discard block
 block discarded – undo
4189 4189
         ?callable $callback = null
4190 4190
     ): bool {
4191 4191
         $entity_ID = absint($entity_ID);
4192
-        if (! $entity_ID) {
4192
+        if ( ! $entity_ID) {
4193 4193
             $this->trashRestoreDeleteError($action, $entity_model);
4194 4194
         }
4195 4195
         $result = 0;
@@ -4235,7 +4235,7 @@  discard block
 block discarded – undo
4235 4235
                 )
4236 4236
             );
4237 4237
         }
4238
-        if (! $entity_model->has_field($delete_column)) {
4238
+        if ( ! $entity_model->has_field($delete_column)) {
4239 4239
             throw new DomainException(
4240 4240
                 sprintf(
4241 4241
                     esc_html__(
Please login to merge, or discard this patch.
core/EE_Dependency_Map.core.php 1 patch
Indentation   +1126 added lines, -1126 removed lines patch added patch discarded remove patch
@@ -20,1130 +20,1130 @@
 block discarded – undo
20 20
  */
21 21
 class EE_Dependency_Map
22 22
 {
23
-    /**
24
-     * This means that the requested class dependency is not present in the dependency map
25
-     */
26
-    const not_registered = 0;
27
-
28
-    /**
29
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
-     */
31
-    const load_new_object = 1;
32
-
33
-    /**
34
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
-     */
37
-    const load_from_cache = 2;
38
-
39
-    /**
40
-     * When registering a dependency,
41
-     * this indicates to keep any existing dependencies that already exist,
42
-     * and simply discard any new dependencies declared in the incoming data
43
-     */
44
-    const KEEP_EXISTING_DEPENDENCIES = 0;
45
-
46
-    /**
47
-     * When registering a dependency,
48
-     * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
-     */
50
-    const OVERWRITE_DEPENDENCIES = 1;
51
-
52
-    /**
53
-     * @type EE_Dependency_Map $_instance
54
-     */
55
-    protected static $_instance;
56
-
57
-    /**
58
-     * @var ClassInterfaceCache $class_cache
59
-     */
60
-    private $class_cache;
61
-
62
-    /**
63
-     * @type RequestInterface $request
64
-     */
65
-    protected $request;
66
-
67
-    /**
68
-     * @type LegacyRequestInterface $legacy_request
69
-     */
70
-    protected $legacy_request;
71
-
72
-    /**
73
-     * @type ResponseInterface $response
74
-     */
75
-    protected $response;
76
-
77
-    /**
78
-     * @type LoaderInterface $loader
79
-     */
80
-    protected $loader;
81
-
82
-    /**
83
-     * @type array $_dependency_map
84
-     */
85
-    protected $_dependency_map = [];
86
-
87
-    /**
88
-     * @type array $_class_loaders
89
-     */
90
-    protected $_class_loaders = [];
91
-
92
-
93
-    /**
94
-     * EE_Dependency_Map constructor.
95
-     *
96
-     * @param ClassInterfaceCache $class_cache
97
-     */
98
-    protected function __construct(ClassInterfaceCache $class_cache)
99
-    {
100
-        $this->class_cache = $class_cache;
101
-        do_action('EE_Dependency_Map____construct', $this);
102
-    }
103
-
104
-
105
-    /**
106
-     * @return void
107
-     * @throws InvalidAliasException
108
-     */
109
-    public function initialize()
110
-    {
111
-        $this->_register_core_dependencies();
112
-        $this->_register_core_class_loaders();
113
-        $this->_register_core_aliases();
114
-    }
115
-
116
-
117
-    /**
118
-     * @singleton method used to instantiate class object
119
-     * @param ClassInterfaceCache|null $class_cache
120
-     * @return EE_Dependency_Map
121
-     */
122
-    public static function instance(ClassInterfaceCache $class_cache = null): EE_Dependency_Map
123
-    {
124
-        // check if class object is instantiated, and instantiated properly
125
-        if (
126
-            ! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
127
-            && $class_cache instanceof ClassInterfaceCache
128
-        ) {
129
-            EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
130
-        }
131
-        return EE_Dependency_Map::$_instance;
132
-    }
133
-
134
-
135
-    /**
136
-     * @param RequestInterface $request
137
-     */
138
-    public function setRequest(RequestInterface $request)
139
-    {
140
-        $this->request = $request;
141
-    }
142
-
143
-
144
-    /**
145
-     * @param LegacyRequestInterface $legacy_request
146
-     */
147
-    public function setLegacyRequest(LegacyRequestInterface $legacy_request)
148
-    {
149
-        $this->legacy_request = $legacy_request;
150
-    }
151
-
152
-
153
-    /**
154
-     * @param ResponseInterface $response
155
-     */
156
-    public function setResponse(ResponseInterface $response)
157
-    {
158
-        $this->response = $response;
159
-    }
160
-
161
-
162
-    /**
163
-     * @param LoaderInterface $loader
164
-     */
165
-    public function setLoader(LoaderInterface $loader)
166
-    {
167
-        $this->loader = $loader;
168
-    }
169
-
170
-
171
-    /**
172
-     * @param string $class
173
-     * @param array  $dependencies
174
-     * @param int    $overwrite
175
-     * @return bool
176
-     */
177
-    public static function register_dependencies(
178
-        string $class,
179
-        array $dependencies,
180
-        int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
181
-    ): bool {
182
-        return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
183
-    }
184
-
185
-
186
-    /**
187
-     * Assigns an array of class names and corresponding load sources (new or cached)
188
-     * to the class specified by the first parameter.
189
-     * IMPORTANT !!!
190
-     * The order of elements in the incoming $dependencies array MUST match
191
-     * the order of the constructor parameters for the class in question.
192
-     * This is especially important when overriding any existing dependencies that are registered.
193
-     * the third parameter controls whether any duplicate dependencies are overwritten or not.
194
-     *
195
-     * @param string $class
196
-     * @param array  $dependencies
197
-     * @param int    $overwrite
198
-     * @return bool
199
-     */
200
-    public function registerDependencies(
201
-        string $class,
202
-        array $dependencies,
203
-        int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
204
-    ): bool {
205
-        $class      = trim($class, '\\');
206
-        $registered = false;
207
-        if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
208
-            EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
209
-        }
210
-        // we need to make sure that any aliases used when registering a dependency
211
-        // get resolved to the correct class name
212
-        foreach ($dependencies as $dependency => $load_source) {
213
-            $alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
214
-            if (
215
-                $overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
216
-                || ! isset(EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ])
217
-            ) {
218
-                unset($dependencies[ $dependency ]);
219
-                $dependencies[ $alias ] = $load_source;
220
-                $registered             = true;
221
-            }
222
-        }
223
-        // now add our two lists of dependencies together.
224
-        // using Union (+=) favours the arrays in precedence from left to right,
225
-        // so $dependencies is NOT overwritten because it is listed first
226
-        // ie: with A = B + C, entries in B take precedence over duplicate entries in C
227
-        // Union is way faster than array_merge() but should be used with caution...
228
-        // especially with numerically indexed arrays
229
-        $dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
230
-        // now we need to ensure that the resulting dependencies
231
-        // array only has the entries that are required for the class
232
-        // so first count how many dependencies were originally registered for the class
233
-        $dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
234
-        // if that count is non-zero (meaning dependencies were already registered)
235
-        EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
236
-            // then truncate the  final array to match that count
237
-            ? array_slice($dependencies, 0, $dependency_count)
238
-            // otherwise just take the incoming array because nothing previously existed
239
-            : $dependencies;
240
-        return $registered;
241
-    }
242
-
243
-
244
-    /**
245
-     * @param string          $class_name
246
-     * @param callable|string $loader
247
-     * @param bool            $overwrite
248
-     * @return bool
249
-     * @throws DomainException
250
-     */
251
-    public static function register_class_loader(
252
-        string $class_name,
253
-        $loader = 'load_core',
254
-        bool $overwrite = false
255
-    ): bool {
256
-        return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader, $overwrite);
257
-    }
258
-
259
-
260
-    /**
261
-     * @param string         $class_name
262
-     * @param Closure|string $loader
263
-     * @param bool           $overwrite
264
-     * @return bool
265
-     * @throws DomainException
266
-     */
267
-    public function registerClassLoader(string $class_name, $loader = 'load_core', bool $overwrite = false): bool
268
-    {
269
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
270
-            throw new DomainException(
271
-                esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
272
-            );
273
-        }
274
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
275
-        if (
276
-            ! is_callable($loader)
277
-            && (
278
-                strpos($loader, 'load_') !== 0
279
-                || ! method_exists('EE_Registry', $loader)
280
-            )
281
-        ) {
282
-            throw new DomainException(
283
-                sprintf(
284
-                    esc_html__(
285
-                        '"%1$s" is not a valid loader method on EE_Registry.',
286
-                        'event_espresso'
287
-                    ),
288
-                    $loader
289
-                )
290
-            );
291
-        }
292
-        $class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
293
-        if ($overwrite || ! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
294
-            EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
295
-            return true;
296
-        }
297
-        return false;
298
-    }
299
-
300
-
301
-    /**
302
-     * @return array
303
-     */
304
-    public function dependency_map(): array
305
-    {
306
-        return $this->_dependency_map;
307
-    }
308
-
309
-
310
-    /**
311
-     * returns TRUE if dependency map contains a listing for the provided class name
312
-     *
313
-     * @param string $class_name
314
-     * @return boolean
315
-     */
316
-    public function has(string $class_name = ''): bool
317
-    {
318
-        // all legacy models have the same dependencies
319
-        if (strpos($class_name, 'EEM_') === 0) {
320
-            $class_name = 'LEGACY_MODELS';
321
-        }
322
-        return isset($this->_dependency_map[ $class_name ]);
323
-    }
324
-
325
-
326
-    /**
327
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
328
-     *
329
-     * @param string $class_name
330
-     * @param string $dependency
331
-     * @return bool
332
-     */
333
-    public function has_dependency_for_class(string $class_name = '', string $dependency = ''): bool
334
-    {
335
-        // all legacy models have the same dependencies
336
-        if (strpos($class_name, 'EEM_') === 0) {
337
-            $class_name = 'LEGACY_MODELS';
338
-        }
339
-        $dependency = $this->getFqnForAlias($dependency, $class_name);
340
-        return isset($this->_dependency_map[ $class_name ][ $dependency ]);
341
-    }
342
-
343
-
344
-    /**
345
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
346
-     *
347
-     * @param string $class_name
348
-     * @param string $dependency
349
-     * @return int
350
-     */
351
-    public function loading_strategy_for_class_dependency(string $class_name = '', string $dependency = ''): int
352
-    {
353
-        // all legacy models have the same dependencies
354
-        if (strpos($class_name, 'EEM_') === 0) {
355
-            $class_name = 'LEGACY_MODELS';
356
-        }
357
-        $dependency = $this->getFqnForAlias($dependency);
358
-        return $this->has_dependency_for_class($class_name, $dependency)
359
-            ? $this->_dependency_map[ $class_name ][ $dependency ]
360
-            : EE_Dependency_Map::not_registered;
361
-    }
362
-
363
-
364
-    /**
365
-     * @param string $class_name
366
-     * @return string | Closure
367
-     */
368
-    public function class_loader(string $class_name)
369
-    {
370
-        // all legacy models use load_model()
371
-        if (strpos($class_name, 'EEM_') === 0) {
372
-            return 'load_model';
373
-        }
374
-        // EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
375
-        // perform strpos() first to avoid loading regex every time we load a class
376
-        if (
377
-            strpos($class_name, 'EE_CPT_') === 0
378
-            && preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
379
-        ) {
380
-            return 'load_core';
381
-        }
382
-        $class_name = $this->getFqnForAlias($class_name);
383
-        return $this->_class_loaders[ $class_name ] ?? '';
384
-    }
385
-
386
-
387
-    /**
388
-     * @return array
389
-     */
390
-    public function class_loaders(): array
391
-    {
392
-        return $this->_class_loaders;
393
-    }
394
-
395
-
396
-    /**
397
-     * adds an alias for a classname
398
-     *
399
-     * @param string $fqcn      the class name that should be used (concrete class to replace interface)
400
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
401
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
402
-     * @throws InvalidAliasException
403
-     */
404
-    public function add_alias(string $fqcn, string $alias, string $for_class = '')
405
-    {
406
-        $this->class_cache->addAlias($fqcn, $alias, $for_class);
407
-    }
408
-
409
-
410
-    /**
411
-     * Returns TRUE if the provided fully qualified name IS an alias
412
-     * WHY?
413
-     * Because if a class is type hinting for a concretion,
414
-     * then why would we need to find another class to supply it?
415
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
416
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
417
-     * Don't go looking for some substitute.
418
-     * Whereas if a class is type hinting for an interface...
419
-     * then we need to find an actual class to use.
420
-     * So the interface IS the alias for some other FQN,
421
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
422
-     * represents some other class.
423
-     *
424
-     * @param string $fqn
425
-     * @param string $for_class
426
-     * @return bool
427
-     */
428
-    public function isAlias(string $fqn = '', string $for_class = ''): bool
429
-    {
430
-        return $this->class_cache->isAlias($fqn, $for_class);
431
-    }
432
-
433
-
434
-    /**
435
-     * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
436
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
437
-     *  for example:
438
-     *      if the following two entries were added to the _aliases array:
439
-     *          array(
440
-     *              'interface_alias'           => 'some\namespace\interface'
441
-     *              'some\namespace\interface'  => 'some\namespace\classname'
442
-     *          )
443
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
444
-     *      to load an instance of 'some\namespace\classname'
445
-     *
446
-     * @param string $alias
447
-     * @param string $for_class
448
-     * @return string
449
-     */
450
-    public function getFqnForAlias(string $alias = '', string $for_class = ''): string
451
-    {
452
-        return $this->class_cache->getFqnForAlias($alias, $for_class);
453
-    }
454
-
455
-
456
-    /**
457
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
458
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
459
-     * This is done by using the following class constants:
460
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
461
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
462
-     */
463
-    protected function _register_core_dependencies()
464
-    {
465
-        $this->_dependency_map = [
466
-            'EE_Admin'                                                                                                    => [
467
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
468
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
469
-            ],
470
-            'EE_Request_Handler'                                                                                          => [
471
-                'EventEspresso\core\services\request\Request'  => EE_Dependency_Map::load_from_cache,
472
-                'EventEspresso\core\services\request\Response' => EE_Dependency_Map::load_from_cache,
473
-            ],
474
-            'EE_System'                                                                                                   => [
475
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
476
-                'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
477
-                'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
478
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
479
-                'EventEspresso\core\services\routing\Router'  => EE_Dependency_Map::load_from_cache,
480
-            ],
481
-            'EE_Session'                                                                                                  => [
482
-                'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
483
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
484
-                'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
485
-                'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
486
-                'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
487
-            ],
488
-            'EE_Cart'                                                                                                     => [
489
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
490
-            ],
491
-            'EE_Messenger_Collection_Loader'                                                                              => [
492
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
493
-            ],
494
-            'EE_Message_Type_Collection_Loader'                                                                           => [
495
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
496
-            ],
497
-            'EE_Message_Resource_Manager'                                                                                 => [
498
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
499
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
500
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
501
-            ],
502
-            'EE_Message_Factory'                                                                                          => [
503
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
504
-            ],
505
-            'EE_messages'                                                                                                 => [
506
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
507
-            ],
508
-            'EE_Messages_Generator'                                                                                       => [
509
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
510
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
511
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
512
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
513
-            ],
514
-            'EE_Messages_Processor'                                                                                       => [
515
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
516
-            ],
517
-            'EE_Messages_Queue'                                                                                           => [
518
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
519
-            ],
520
-            'EE_Messages_Template_Defaults'                                                                               => [
521
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
522
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
523
-            ],
524
-            'EE_Message_To_Generate_From_Request'                                                                         => [
525
-                'EE_Message_Resource_Manager'                 => EE_Dependency_Map::load_from_cache,
526
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
527
-            ],
528
-            'EventEspresso\core\services\commands\CommandBus'                                                             => [
529
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
530
-            ],
531
-            'EventEspresso\services\commands\CommandHandler'                                                              => [
532
-                'EE_Registry'         => EE_Dependency_Map::load_from_cache,
533
-                'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
534
-            ],
535
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => [
536
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
537
-            ],
538
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => [
539
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
540
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
541
-            ],
542
-            'EventEspresso\core\services\commands\CommandFactory'                                                         => [
543
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
544
-            ],
545
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => [
546
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
547
-            ],
548
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => [
549
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
550
-            ],
551
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => [
552
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
553
-            ],
554
-            'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => [
555
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
556
-            ],
557
-            'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
558
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
559
-            ],
560
-            'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
561
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
562
-            ],
563
-            'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
564
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
565
-            ],
566
-            'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
567
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
568
-            ],
569
-            'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
570
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
571
-            ],
572
-            'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
573
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
574
-            ],
575
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => [
576
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
577
-            ],
578
-            'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
579
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
580
-            ],
581
-            'EventEspresso\core\services\database\TableManager'                                                           => [
582
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
583
-            ],
584
-            'EE_Data_Migration_Class_Base'                                                                                => [
585
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
586
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
587
-            ],
588
-            'EE_DMS_Core_4_1_0'                                                                                           => [
589
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
590
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
591
-            ],
592
-            'EE_DMS_Core_4_2_0'                                                                                           => [
593
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
594
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
595
-            ],
596
-            'EE_DMS_Core_4_3_0'                                                                                           => [
597
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
598
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
599
-            ],
600
-            'EE_DMS_Core_4_4_0'                                                                                           => [
601
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
602
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
603
-            ],
604
-            'EE_DMS_Core_4_5_0'                                                                                           => [
605
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
606
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
607
-            ],
608
-            'EE_DMS_Core_4_6_0'                                                                                           => [
609
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
610
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
611
-            ],
612
-            'EE_DMS_Core_4_7_0'                                                                                           => [
613
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
614
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
615
-            ],
616
-            'EE_DMS_Core_4_8_0'                                                                                           => [
617
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
618
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
619
-            ],
620
-            'EE_DMS_Core_4_9_0'                                                                                           => [
621
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
622
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
623
-            ],
624
-            'EE_DMS_Core_4_10_0'                                                                                          => [
625
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
626
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
627
-                'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
628
-            ],
629
-            'EE_DMS_Core_4_11_0'                                                                                          => [
630
-                'EE_DMS_Core_4_10_0'                                 => EE_Dependency_Map::load_from_cache,
631
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
632
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
633
-            ],
634
-            'EE_DMS_Core_4_12_0'                                                                                          => [
635
-                'EE_DMS_Core_4_11_0'                                 => EE_Dependency_Map::load_from_cache,
636
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
637
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
638
-            ],
639
-            'EventEspresso\core\services\assets\I18nRegistry'                                                             => [
640
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
641
-            ],
642
-            'EventEspresso\core\services\assets\Registry'                                                                 => [
643
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
644
-                'EventEspresso\core\services\assets\AssetManifest'   => EE_Dependency_Map::load_from_cache,
645
-            ],
646
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => [
647
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
648
-            ],
649
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => [
650
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
651
-            ],
652
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => [
653
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
654
-            ],
655
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => [
656
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
657
-            ],
658
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => [
659
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
660
-            ],
661
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => [
662
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
663
-            ],
664
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => [
665
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
666
-            ],
667
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                         => [
668
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
669
-            ],
670
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => [
671
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
672
-            ],
673
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => [
674
-                'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
675
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
676
-            ],
677
-            'EventEspresso\core\domain\values\EmailAddress'                                                               => [
678
-                null,
679
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
680
-            ],
681
-            'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => [
682
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
683
-            ],
684
-            'LEGACY_MODELS'                                                                                               => [
685
-                null,
686
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
687
-            ],
688
-            'EE_Module_Request_Router'                                                                                    => [
689
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
690
-            ],
691
-            'EE_Registration_Processor'                                                                                   => [
692
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
693
-            ],
694
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => [
695
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
696
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
697
-            ],
698
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => [
699
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
700
-                'EE_Session'             => EE_Dependency_Map::load_from_cache,
701
-            ],
702
-            'EventEspresso\modules\ticket_selector\DisplayTicketSelector'                                                 => [
703
-                'EventEspresso\core\domain\entities\users\CurrentUser' => EE_Dependency_Map::load_from_cache,
704
-                'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
705
-                'EE_Ticket_Selector_Config'                            => EE_Dependency_Map::load_from_cache,
706
-            ],
707
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => [
708
-                'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
709
-                'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
710
-                'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
711
-                'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
712
-                'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
713
-            ],
714
-            'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => [
715
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
716
-            ],
717
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => [
718
-                'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
719
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
720
-            ],
721
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => [
722
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
723
-            ],
724
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => [
725
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
726
-            ],
727
-            'EE_CPT_Strategy'                                                                                             => [
728
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
729
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
730
-            ],
731
-            'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => [
732
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
733
-            ],
734
-            'EventEspresso\core\CPTs\CptQueryModifier'                                                                    => [
735
-                null,
736
-                null,
737
-                null,
738
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
739
-                'EventEspresso\core\services\request\Request'     => EE_Dependency_Map::load_from_cache,
740
-                'EventEspresso\core\services\loaders\Loader'      => EE_Dependency_Map::load_from_cache,
741
-            ],
742
-            'EventEspresso\core\services\dependencies\DependencyResolver'                                                 => [
743
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
744
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
745
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
746
-            ],
747
-            'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                               => [
748
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
749
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
750
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
751
-            ],
752
-            'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                          => [
753
-                'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
754
-                'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
755
-            ],
756
-            'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                          => [
757
-                'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
758
-                'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
759
-            ],
760
-            'EE_URL_Validation_Strategy'                                                                                  => [
761
-                null,
762
-                null,
763
-                'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache,
764
-            ],
765
-            'EventEspresso\core\services\request\files\FilesDataHandler'                                                  => [
766
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
767
-            ],
768
-            'EventEspressoBatchRequest\BatchRequestProcessor'                                                             => [
769
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
770
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
771
-            ],
772
-            'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                => [
773
-                'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
774
-                'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
775
-                'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
776
-                null,
777
-            ],
778
-            'EventEspresso\core\services\routing\RouteHandler'                                                            => [
779
-                'EventEspresso\core\services\json\JsonDataNodeHandler' => EE_Dependency_Map::load_from_cache,
780
-                'EventEspresso\core\services\loaders\Loader'           => EE_Dependency_Map::load_from_cache,
781
-                'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
782
-                'EventEspresso\core\services\routing\RouteCollection'  => EE_Dependency_Map::load_from_cache,
783
-            ],
784
-            'EventEspresso\core\services\json\JsonDataNodeHandler'                                                        => [
785
-                'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
786
-            ],
787
-            'EventEspresso\core\services\routing\Router'                                                                  => [
788
-                'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
789
-                'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
790
-                'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
791
-            ],
792
-            'EventEspresso\core\services\assets\AssetManifest'                                                            => [
793
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
794
-            ],
795
-            'EventEspresso\core\services\assets\AssetManifestFactory'                                                     => [
796
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
797
-            ],
798
-            'EventEspresso\core\services\assets\BaristaFactory'                                                           => [
799
-                'EventEspresso\core\services\assets\AssetManifestFactory' => EE_Dependency_Map::load_from_cache,
800
-                'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
801
-            ],
802
-            'EventEspresso\core\domain\services\capabilities\FeatureFlags'                                                => [
803
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
804
-                'EventEspresso\core\domain\Domain'                                    => EE_Dependency_Map::load_from_cache,
805
-            ],
806
-            'EventEspresso\core\services\addon\AddonManager'                                                              => [
807
-                'EventEspresso\core\services\addon\AddonCollection'              => EE_Dependency_Map::load_from_cache,
808
-                'EventEspresso\core\Psr4Autoloader'                              => EE_Dependency_Map::load_from_cache,
809
-                'EventEspresso\core\services\addon\api\v1\RegisterAddon'         => EE_Dependency_Map::load_from_cache,
810
-                'EventEspresso\core\services\addon\api\IncompatibleAddonHandler' => EE_Dependency_Map::load_from_cache,
811
-                'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'  => EE_Dependency_Map::load_from_cache,
812
-            ],
813
-            'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'                                               => [
814
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
815
-            ],
816
-            'EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion'                                                  => [
817
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
818
-            ],
819
-            'EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'                                                  => [
820
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
821
-            ],
822
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'                                        => [
823
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
824
-                'EEM_Event'                                                   => EE_Dependency_Map::load_from_cache,
825
-                'EEM_Datetime'                                                => EE_Dependency_Map::load_from_cache,
826
-                'EEM_Registration'                                            => EE_Dependency_Map::load_from_cache,
827
-            ],
828
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'                                        => [
829
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
830
-            ],
831
-            'EventEspresso\core\services\request\CurrentPage'                                                             => [
832
-                'EE_CPT_Strategy'                             => EE_Dependency_Map::load_from_cache,
833
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
834
-            ],
835
-            'EventEspresso\core\services\shortcodes\LegacyShortcodesManager'                                              => [
836
-                'EE_Registry'                                     => EE_Dependency_Map::load_from_cache,
837
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
838
-            ],
839
-            'EventEspresso\core\services\shortcodes\ShortcodesManager'                                                    => [
840
-                'EventEspresso\core\services\shortcodes\LegacyShortcodesManager' => EE_Dependency_Map::load_from_cache,
841
-                'EventEspresso\core\services\request\CurrentPage'                => EE_Dependency_Map::load_from_cache,
842
-            ],
843
-            'EventEspresso\core\domain\entities\users\CurrentUser'                                                        => [
844
-                'EventEspresso\core\domain\entities\users\EventManagers' => EE_Dependency_Map::load_from_cache,
845
-            ],
846
-            'EventEspresso\core\services\form\meta\InputTypes'                                                            => [
847
-                'EventEspresso\core\services\form\meta\inputs\Block'    => EE_Dependency_Map::load_from_cache,
848
-                'EventEspresso\core\services\form\meta\inputs\Button'   => EE_Dependency_Map::load_from_cache,
849
-                'EventEspresso\core\services\form\meta\inputs\DateTime' => EE_Dependency_Map::load_from_cache,
850
-                'EventEspresso\core\services\form\meta\inputs\Input'    => EE_Dependency_Map::load_from_cache,
851
-                'EventEspresso\core\services\form\meta\inputs\Number'   => EE_Dependency_Map::load_from_cache,
852
-                'EventEspresso\core\services\form\meta\inputs\Phone'    => EE_Dependency_Map::load_from_cache,
853
-                'EventEspresso\core\services\form\meta\inputs\Select'   => EE_Dependency_Map::load_from_cache,
854
-                'EventEspresso\core\services\form\meta\inputs\Text'     => EE_Dependency_Map::load_from_cache,
855
-            ],
856
-            'EventEspresso\core\domain\services\registration\form\v1\RegFormDependencyHandler'                            => [
857
-                'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
858
-            ],
859
-            'EventEspresso\core\services\calculators\LineItemCalculator'                                                  => [
860
-                'EventEspresso\core\services\helpers\DecimalValues' => EE_Dependency_Map::load_from_cache,
861
-            ],
862
-            'EventEspresso\core\services\helpers\DecimalValues'                                                           => [
863
-                'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
864
-            ],
865
-        ];
866
-    }
867
-
868
-
869
-    /**
870
-     * Registers how core classes are loaded.
871
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
872
-     *        'EE_Request_Handler' => 'load_core'
873
-     *        'EE_Messages_Queue'  => 'load_lib'
874
-     *        'EEH_Debug_Tools'    => 'load_helper'
875
-     * or, if greater control is required, by providing a custom closure. For example:
876
-     *        'Some_Class' => function () {
877
-     *            return new Some_Class();
878
-     *        },
879
-     * This is required for instantiating dependencies
880
-     * where an interface has been type hinted in a class constructor. For example:
881
-     *        'Required_Interface' => function () {
882
-     *            return new A_Class_That_Implements_Required_Interface();
883
-     *        },
884
-     */
885
-    protected function _register_core_class_loaders()
886
-    {
887
-        $this->_class_loaders = [
888
-            // load_core
889
-            'EE_Dependency_Map'                            => function () {
890
-                return $this;
891
-            },
892
-            'EE_Capabilities'                              => 'load_core',
893
-            'EE_Encryption'                                => 'load_core',
894
-            'EE_Front_Controller'                          => 'load_core',
895
-            'EE_Module_Request_Router'                     => 'load_core',
896
-            'EE_Registry'                                  => 'load_core',
897
-            'EE_Request'                                   => function () {
898
-                return $this->legacy_request;
899
-            },
900
-            'EventEspresso\core\services\request\Request'  => function () {
901
-                return $this->request;
902
-            },
903
-            'EventEspresso\core\services\request\Response' => function () {
904
-                return $this->response;
905
-            },
906
-            'EE_Base'                                      => 'load_core',
907
-            'EE_Request_Handler'                           => 'load_core',
908
-            'EE_Session'                                   => 'load_core',
909
-            'EE_Cron_Tasks'                                => 'load_core',
910
-            'EE_System'                                    => 'load_core',
911
-            'EE_Maintenance_Mode'                          => 'load_core',
912
-            'EE_Register_CPTs'                             => 'load_core',
913
-            'EE_Admin'                                     => 'load_core',
914
-            'EE_CPT_Strategy'                              => 'load_core',
915
-            // load_class
916
-            'EE_Registration_Processor'                    => 'load_class',
917
-            // load_lib
918
-            'EE_Message_Resource_Manager'                  => 'load_lib',
919
-            'EE_Message_Type_Collection'                   => 'load_lib',
920
-            'EE_Message_Type_Collection_Loader'            => 'load_lib',
921
-            'EE_Messenger_Collection'                      => 'load_lib',
922
-            'EE_Messenger_Collection_Loader'               => 'load_lib',
923
-            'EE_Messages_Processor'                        => 'load_lib',
924
-            'EE_Message_Repository'                        => 'load_lib',
925
-            'EE_Messages_Queue'                            => 'load_lib',
926
-            'EE_Messages_Data_Handler_Collection'          => 'load_lib',
927
-            'EE_Message_Template_Group_Collection'         => 'load_lib',
928
-            'EE_Payment_Method_Manager'                    => 'load_lib',
929
-            'EE_DMS_Core_4_1_0'                            => 'load_dms',
930
-            'EE_DMS_Core_4_2_0'                            => 'load_dms',
931
-            'EE_DMS_Core_4_3_0'                            => 'load_dms',
932
-            'EE_DMS_Core_4_5_0'                            => 'load_dms',
933
-            'EE_DMS_Core_4_6_0'                            => 'load_dms',
934
-            'EE_DMS_Core_4_7_0'                            => 'load_dms',
935
-            'EE_DMS_Core_4_8_0'                            => 'load_dms',
936
-            'EE_DMS_Core_4_9_0'                            => 'load_dms',
937
-            'EE_DMS_Core_4_10_0'                           => 'load_dms',
938
-            'EE_DMS_Core_4_11_0'                           => 'load_dms',
939
-            'EE_DMS_Core_4_12_0'                           => 'load_dms',
940
-            'EE_Messages_Generator'                        => static function () {
941
-                return EE_Registry::instance()->load_lib(
942
-                    'Messages_Generator',
943
-                    [],
944
-                    false,
945
-                    false
946
-                );
947
-            },
948
-            'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
949
-                return EE_Registry::instance()->load_lib(
950
-                    'Messages_Template_Defaults',
951
-                    $arguments,
952
-                    false,
953
-                    false
954
-                );
955
-            },
956
-            // load_helper
957
-            'EEH_Parse_Shortcodes'                         => static function () {
958
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
959
-                    return new EEH_Parse_Shortcodes();
960
-                }
961
-                return null;
962
-            },
963
-            'EE_Template_Config'                           => static function () {
964
-                return EE_Config::instance()->template_settings;
965
-            },
966
-            'EE_Currency_Config'                           => static function () {
967
-                return EE_Currency_Config::getCurrencyConfig();
968
-            },
969
-            'EE_Registration_Config'                       => static function () {
970
-                return EE_Config::instance()->registration;
971
-            },
972
-            'EE_Core_Config'                               => static function () {
973
-                return EE_Config::instance()->core;
974
-            },
975
-            'EventEspresso\core\services\loaders\Loader'   => static function () {
976
-                return LoaderFactory::getLoader();
977
-            },
978
-            'EE_Network_Config'                            => static function () {
979
-                return EE_Network_Config::instance();
980
-            },
981
-            'EE_Config'                                    => static function () {
982
-                return EE_Config::instance();
983
-            },
984
-            'EventEspresso\core\domain\Domain'             => static function () {
985
-                return DomainFactory::getEventEspressoCoreDomain();
986
-            },
987
-            'EE_Admin_Config'                              => static function () {
988
-                return EE_Config::instance()->admin;
989
-            },
990
-            'EE_Organization_Config'                       => static function () {
991
-                return EE_Config::instance()->organization;
992
-            },
993
-            'EE_Network_Core_Config'                       => static function () {
994
-                return EE_Network_Config::instance()->core;
995
-            },
996
-            'EE_Environment_Config'                        => static function () {
997
-                return EE_Config::instance()->environment;
998
-            },
999
-            'EED_Core_Rest_Api'                            => static function () {
1000
-                return EED_Core_Rest_Api::instance();
1001
-            },
1002
-            'WP_REST_Server'                               => static function () {
1003
-                return rest_get_server();
1004
-            },
1005
-            'EventEspresso\core\Psr4Autoloader'            => static function () {
1006
-                return EE_Psr4AutoloaderInit::psr4_loader();
1007
-            },
1008
-            'EE_Ticket_Selector_Config'                    => function () {
1009
-                return EE_Config::instance()->template_settings->EED_Ticket_Selector;
1010
-            },
1011
-        ];
1012
-    }
1013
-
1014
-
1015
-    /**
1016
-     * can be used for supplying alternate names for classes,
1017
-     * or for connecting interface names to instantiable classes
1018
-     *
1019
-     * @throws InvalidAliasException
1020
-     */
1021
-    protected function _register_core_aliases()
1022
-    {
1023
-        $aliases = [
1024
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1025
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1026
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1027
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1028
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1029
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1030
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1031
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1032
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1033
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1034
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1035
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1036
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1037
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1038
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1039
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1040
-            'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1041
-            'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1042
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1043
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1044
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1045
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1046
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1047
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1048
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1049
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1050
-            'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1051
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1052
-            'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1053
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1054
-            'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1055
-            'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1056
-            'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1057
-            'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1058
-            'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1059
-            'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1060
-            'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1061
-            'Registration_Processor'                                                       => 'EE_Registration_Processor',
1062
-            'EventEspresso\core\services\assets\AssetManifestInterface'                    => 'EventEspresso\core\services\assets\AssetManifest',
1063
-        ];
1064
-        foreach ($aliases as $alias => $fqn) {
1065
-            if (is_array($fqn)) {
1066
-                foreach ($fqn as $class => $for_class) {
1067
-                    $this->class_cache->addAlias($class, $alias, $for_class);
1068
-                }
1069
-                continue;
1070
-            }
1071
-            $this->class_cache->addAlias($fqn, $alias);
1072
-        }
1073
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1074
-            $this->class_cache->addAlias(
1075
-                'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1076
-                'EventEspresso\core\services\notices\NoticeConverterInterface'
1077
-            );
1078
-        }
1079
-    }
1080
-
1081
-
1082
-    public function debug($for_class = '')
1083
-    {
1084
-        if (method_exists($this->class_cache, 'debug')) {
1085
-            $this->class_cache->debug($for_class);
1086
-        }
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1092
-     * request Primarily used by unit tests.
1093
-     */
1094
-    public function reset()
1095
-    {
1096
-        $this->_register_core_class_loaders();
1097
-        $this->_register_core_dependencies();
1098
-    }
1099
-
1100
-
1101
-    /**
1102
-     * PLZ NOTE: a better name for this method would be is_alias()
1103
-     * because it returns TRUE if the provided fully qualified name IS an alias
1104
-     * WHY?
1105
-     * Because if a class is type hinting for a concretion,
1106
-     * then why would we need to find another class to supply it?
1107
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1108
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1109
-     * Don't go looking for some substitute.
1110
-     * Whereas if a class is type hinting for an interface...
1111
-     * then we need to find an actual class to use.
1112
-     * So the interface IS the alias for some other FQN,
1113
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1114
-     * represents some other class.
1115
-     *
1116
-     * @param string $fqn
1117
-     * @param string $for_class
1118
-     * @return bool
1119
-     * @deprecated 4.9.62.p
1120
-     */
1121
-    public function has_alias(string $fqn = '', string $for_class = ''): bool
1122
-    {
1123
-        return $this->isAlias($fqn, $for_class);
1124
-    }
1125
-
1126
-
1127
-    /**
1128
-     * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1129
-     * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1130
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
1131
-     *  for example:
1132
-     *      if the following two entries were added to the _aliases array:
1133
-     *          array(
1134
-     *              'interface_alias'           => 'some\namespace\interface'
1135
-     *              'some\namespace\interface'  => 'some\namespace\classname'
1136
-     *          )
1137
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1138
-     *      to load an instance of 'some\namespace\classname'
1139
-     *
1140
-     * @param string $alias
1141
-     * @param string $for_class
1142
-     * @return string
1143
-     * @deprecated 4.9.62.p
1144
-     */
1145
-    public function get_alias(string $alias = '', string $for_class = ''): string
1146
-    {
1147
-        return $this->getFqnForAlias($alias, $for_class);
1148
-    }
23
+	/**
24
+	 * This means that the requested class dependency is not present in the dependency map
25
+	 */
26
+	const not_registered = 0;
27
+
28
+	/**
29
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
+	 */
31
+	const load_new_object = 1;
32
+
33
+	/**
34
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
+	 */
37
+	const load_from_cache = 2;
38
+
39
+	/**
40
+	 * When registering a dependency,
41
+	 * this indicates to keep any existing dependencies that already exist,
42
+	 * and simply discard any new dependencies declared in the incoming data
43
+	 */
44
+	const KEEP_EXISTING_DEPENDENCIES = 0;
45
+
46
+	/**
47
+	 * When registering a dependency,
48
+	 * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
+	 */
50
+	const OVERWRITE_DEPENDENCIES = 1;
51
+
52
+	/**
53
+	 * @type EE_Dependency_Map $_instance
54
+	 */
55
+	protected static $_instance;
56
+
57
+	/**
58
+	 * @var ClassInterfaceCache $class_cache
59
+	 */
60
+	private $class_cache;
61
+
62
+	/**
63
+	 * @type RequestInterface $request
64
+	 */
65
+	protected $request;
66
+
67
+	/**
68
+	 * @type LegacyRequestInterface $legacy_request
69
+	 */
70
+	protected $legacy_request;
71
+
72
+	/**
73
+	 * @type ResponseInterface $response
74
+	 */
75
+	protected $response;
76
+
77
+	/**
78
+	 * @type LoaderInterface $loader
79
+	 */
80
+	protected $loader;
81
+
82
+	/**
83
+	 * @type array $_dependency_map
84
+	 */
85
+	protected $_dependency_map = [];
86
+
87
+	/**
88
+	 * @type array $_class_loaders
89
+	 */
90
+	protected $_class_loaders = [];
91
+
92
+
93
+	/**
94
+	 * EE_Dependency_Map constructor.
95
+	 *
96
+	 * @param ClassInterfaceCache $class_cache
97
+	 */
98
+	protected function __construct(ClassInterfaceCache $class_cache)
99
+	{
100
+		$this->class_cache = $class_cache;
101
+		do_action('EE_Dependency_Map____construct', $this);
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return void
107
+	 * @throws InvalidAliasException
108
+	 */
109
+	public function initialize()
110
+	{
111
+		$this->_register_core_dependencies();
112
+		$this->_register_core_class_loaders();
113
+		$this->_register_core_aliases();
114
+	}
115
+
116
+
117
+	/**
118
+	 * @singleton method used to instantiate class object
119
+	 * @param ClassInterfaceCache|null $class_cache
120
+	 * @return EE_Dependency_Map
121
+	 */
122
+	public static function instance(ClassInterfaceCache $class_cache = null): EE_Dependency_Map
123
+	{
124
+		// check if class object is instantiated, and instantiated properly
125
+		if (
126
+			! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
127
+			&& $class_cache instanceof ClassInterfaceCache
128
+		) {
129
+			EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
130
+		}
131
+		return EE_Dependency_Map::$_instance;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param RequestInterface $request
137
+	 */
138
+	public function setRequest(RequestInterface $request)
139
+	{
140
+		$this->request = $request;
141
+	}
142
+
143
+
144
+	/**
145
+	 * @param LegacyRequestInterface $legacy_request
146
+	 */
147
+	public function setLegacyRequest(LegacyRequestInterface $legacy_request)
148
+	{
149
+		$this->legacy_request = $legacy_request;
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param ResponseInterface $response
155
+	 */
156
+	public function setResponse(ResponseInterface $response)
157
+	{
158
+		$this->response = $response;
159
+	}
160
+
161
+
162
+	/**
163
+	 * @param LoaderInterface $loader
164
+	 */
165
+	public function setLoader(LoaderInterface $loader)
166
+	{
167
+		$this->loader = $loader;
168
+	}
169
+
170
+
171
+	/**
172
+	 * @param string $class
173
+	 * @param array  $dependencies
174
+	 * @param int    $overwrite
175
+	 * @return bool
176
+	 */
177
+	public static function register_dependencies(
178
+		string $class,
179
+		array $dependencies,
180
+		int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
181
+	): bool {
182
+		return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
183
+	}
184
+
185
+
186
+	/**
187
+	 * Assigns an array of class names and corresponding load sources (new or cached)
188
+	 * to the class specified by the first parameter.
189
+	 * IMPORTANT !!!
190
+	 * The order of elements in the incoming $dependencies array MUST match
191
+	 * the order of the constructor parameters for the class in question.
192
+	 * This is especially important when overriding any existing dependencies that are registered.
193
+	 * the third parameter controls whether any duplicate dependencies are overwritten or not.
194
+	 *
195
+	 * @param string $class
196
+	 * @param array  $dependencies
197
+	 * @param int    $overwrite
198
+	 * @return bool
199
+	 */
200
+	public function registerDependencies(
201
+		string $class,
202
+		array $dependencies,
203
+		int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
204
+	): bool {
205
+		$class      = trim($class, '\\');
206
+		$registered = false;
207
+		if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
208
+			EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
209
+		}
210
+		// we need to make sure that any aliases used when registering a dependency
211
+		// get resolved to the correct class name
212
+		foreach ($dependencies as $dependency => $load_source) {
213
+			$alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
214
+			if (
215
+				$overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
216
+				|| ! isset(EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ])
217
+			) {
218
+				unset($dependencies[ $dependency ]);
219
+				$dependencies[ $alias ] = $load_source;
220
+				$registered             = true;
221
+			}
222
+		}
223
+		// now add our two lists of dependencies together.
224
+		// using Union (+=) favours the arrays in precedence from left to right,
225
+		// so $dependencies is NOT overwritten because it is listed first
226
+		// ie: with A = B + C, entries in B take precedence over duplicate entries in C
227
+		// Union is way faster than array_merge() but should be used with caution...
228
+		// especially with numerically indexed arrays
229
+		$dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
230
+		// now we need to ensure that the resulting dependencies
231
+		// array only has the entries that are required for the class
232
+		// so first count how many dependencies were originally registered for the class
233
+		$dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
234
+		// if that count is non-zero (meaning dependencies were already registered)
235
+		EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
236
+			// then truncate the  final array to match that count
237
+			? array_slice($dependencies, 0, $dependency_count)
238
+			// otherwise just take the incoming array because nothing previously existed
239
+			: $dependencies;
240
+		return $registered;
241
+	}
242
+
243
+
244
+	/**
245
+	 * @param string          $class_name
246
+	 * @param callable|string $loader
247
+	 * @param bool            $overwrite
248
+	 * @return bool
249
+	 * @throws DomainException
250
+	 */
251
+	public static function register_class_loader(
252
+		string $class_name,
253
+		$loader = 'load_core',
254
+		bool $overwrite = false
255
+	): bool {
256
+		return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader, $overwrite);
257
+	}
258
+
259
+
260
+	/**
261
+	 * @param string         $class_name
262
+	 * @param Closure|string $loader
263
+	 * @param bool           $overwrite
264
+	 * @return bool
265
+	 * @throws DomainException
266
+	 */
267
+	public function registerClassLoader(string $class_name, $loader = 'load_core', bool $overwrite = false): bool
268
+	{
269
+		if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
270
+			throw new DomainException(
271
+				esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
272
+			);
273
+		}
274
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
275
+		if (
276
+			! is_callable($loader)
277
+			&& (
278
+				strpos($loader, 'load_') !== 0
279
+				|| ! method_exists('EE_Registry', $loader)
280
+			)
281
+		) {
282
+			throw new DomainException(
283
+				sprintf(
284
+					esc_html__(
285
+						'"%1$s" is not a valid loader method on EE_Registry.',
286
+						'event_espresso'
287
+					),
288
+					$loader
289
+				)
290
+			);
291
+		}
292
+		$class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
293
+		if ($overwrite || ! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
294
+			EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
295
+			return true;
296
+		}
297
+		return false;
298
+	}
299
+
300
+
301
+	/**
302
+	 * @return array
303
+	 */
304
+	public function dependency_map(): array
305
+	{
306
+		return $this->_dependency_map;
307
+	}
308
+
309
+
310
+	/**
311
+	 * returns TRUE if dependency map contains a listing for the provided class name
312
+	 *
313
+	 * @param string $class_name
314
+	 * @return boolean
315
+	 */
316
+	public function has(string $class_name = ''): bool
317
+	{
318
+		// all legacy models have the same dependencies
319
+		if (strpos($class_name, 'EEM_') === 0) {
320
+			$class_name = 'LEGACY_MODELS';
321
+		}
322
+		return isset($this->_dependency_map[ $class_name ]);
323
+	}
324
+
325
+
326
+	/**
327
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
328
+	 *
329
+	 * @param string $class_name
330
+	 * @param string $dependency
331
+	 * @return bool
332
+	 */
333
+	public function has_dependency_for_class(string $class_name = '', string $dependency = ''): bool
334
+	{
335
+		// all legacy models have the same dependencies
336
+		if (strpos($class_name, 'EEM_') === 0) {
337
+			$class_name = 'LEGACY_MODELS';
338
+		}
339
+		$dependency = $this->getFqnForAlias($dependency, $class_name);
340
+		return isset($this->_dependency_map[ $class_name ][ $dependency ]);
341
+	}
342
+
343
+
344
+	/**
345
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
346
+	 *
347
+	 * @param string $class_name
348
+	 * @param string $dependency
349
+	 * @return int
350
+	 */
351
+	public function loading_strategy_for_class_dependency(string $class_name = '', string $dependency = ''): int
352
+	{
353
+		// all legacy models have the same dependencies
354
+		if (strpos($class_name, 'EEM_') === 0) {
355
+			$class_name = 'LEGACY_MODELS';
356
+		}
357
+		$dependency = $this->getFqnForAlias($dependency);
358
+		return $this->has_dependency_for_class($class_name, $dependency)
359
+			? $this->_dependency_map[ $class_name ][ $dependency ]
360
+			: EE_Dependency_Map::not_registered;
361
+	}
362
+
363
+
364
+	/**
365
+	 * @param string $class_name
366
+	 * @return string | Closure
367
+	 */
368
+	public function class_loader(string $class_name)
369
+	{
370
+		// all legacy models use load_model()
371
+		if (strpos($class_name, 'EEM_') === 0) {
372
+			return 'load_model';
373
+		}
374
+		// EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
375
+		// perform strpos() first to avoid loading regex every time we load a class
376
+		if (
377
+			strpos($class_name, 'EE_CPT_') === 0
378
+			&& preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
379
+		) {
380
+			return 'load_core';
381
+		}
382
+		$class_name = $this->getFqnForAlias($class_name);
383
+		return $this->_class_loaders[ $class_name ] ?? '';
384
+	}
385
+
386
+
387
+	/**
388
+	 * @return array
389
+	 */
390
+	public function class_loaders(): array
391
+	{
392
+		return $this->_class_loaders;
393
+	}
394
+
395
+
396
+	/**
397
+	 * adds an alias for a classname
398
+	 *
399
+	 * @param string $fqcn      the class name that should be used (concrete class to replace interface)
400
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
401
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
402
+	 * @throws InvalidAliasException
403
+	 */
404
+	public function add_alias(string $fqcn, string $alias, string $for_class = '')
405
+	{
406
+		$this->class_cache->addAlias($fqcn, $alias, $for_class);
407
+	}
408
+
409
+
410
+	/**
411
+	 * Returns TRUE if the provided fully qualified name IS an alias
412
+	 * WHY?
413
+	 * Because if a class is type hinting for a concretion,
414
+	 * then why would we need to find another class to supply it?
415
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
416
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
417
+	 * Don't go looking for some substitute.
418
+	 * Whereas if a class is type hinting for an interface...
419
+	 * then we need to find an actual class to use.
420
+	 * So the interface IS the alias for some other FQN,
421
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
422
+	 * represents some other class.
423
+	 *
424
+	 * @param string $fqn
425
+	 * @param string $for_class
426
+	 * @return bool
427
+	 */
428
+	public function isAlias(string $fqn = '', string $for_class = ''): bool
429
+	{
430
+		return $this->class_cache->isAlias($fqn, $for_class);
431
+	}
432
+
433
+
434
+	/**
435
+	 * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
436
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
437
+	 *  for example:
438
+	 *      if the following two entries were added to the _aliases array:
439
+	 *          array(
440
+	 *              'interface_alias'           => 'some\namespace\interface'
441
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
442
+	 *          )
443
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
444
+	 *      to load an instance of 'some\namespace\classname'
445
+	 *
446
+	 * @param string $alias
447
+	 * @param string $for_class
448
+	 * @return string
449
+	 */
450
+	public function getFqnForAlias(string $alias = '', string $for_class = ''): string
451
+	{
452
+		return $this->class_cache->getFqnForAlias($alias, $for_class);
453
+	}
454
+
455
+
456
+	/**
457
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
458
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
459
+	 * This is done by using the following class constants:
460
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
461
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
462
+	 */
463
+	protected function _register_core_dependencies()
464
+	{
465
+		$this->_dependency_map = [
466
+			'EE_Admin'                                                                                                    => [
467
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
468
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
469
+			],
470
+			'EE_Request_Handler'                                                                                          => [
471
+				'EventEspresso\core\services\request\Request'  => EE_Dependency_Map::load_from_cache,
472
+				'EventEspresso\core\services\request\Response' => EE_Dependency_Map::load_from_cache,
473
+			],
474
+			'EE_System'                                                                                                   => [
475
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
476
+				'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
477
+				'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
478
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
479
+				'EventEspresso\core\services\routing\Router'  => EE_Dependency_Map::load_from_cache,
480
+			],
481
+			'EE_Session'                                                                                                  => [
482
+				'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
483
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
484
+				'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
485
+				'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
486
+				'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
487
+			],
488
+			'EE_Cart'                                                                                                     => [
489
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
490
+			],
491
+			'EE_Messenger_Collection_Loader'                                                                              => [
492
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
493
+			],
494
+			'EE_Message_Type_Collection_Loader'                                                                           => [
495
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
496
+			],
497
+			'EE_Message_Resource_Manager'                                                                                 => [
498
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
499
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
500
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
501
+			],
502
+			'EE_Message_Factory'                                                                                          => [
503
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
504
+			],
505
+			'EE_messages'                                                                                                 => [
506
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
507
+			],
508
+			'EE_Messages_Generator'                                                                                       => [
509
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
510
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
511
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
512
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
513
+			],
514
+			'EE_Messages_Processor'                                                                                       => [
515
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
516
+			],
517
+			'EE_Messages_Queue'                                                                                           => [
518
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
519
+			],
520
+			'EE_Messages_Template_Defaults'                                                                               => [
521
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
522
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
523
+			],
524
+			'EE_Message_To_Generate_From_Request'                                                                         => [
525
+				'EE_Message_Resource_Manager'                 => EE_Dependency_Map::load_from_cache,
526
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
527
+			],
528
+			'EventEspresso\core\services\commands\CommandBus'                                                             => [
529
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
530
+			],
531
+			'EventEspresso\services\commands\CommandHandler'                                                              => [
532
+				'EE_Registry'         => EE_Dependency_Map::load_from_cache,
533
+				'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
534
+			],
535
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => [
536
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
537
+			],
538
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => [
539
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
540
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
541
+			],
542
+			'EventEspresso\core\services\commands\CommandFactory'                                                         => [
543
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
544
+			],
545
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => [
546
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
547
+			],
548
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => [
549
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
550
+			],
551
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => [
552
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
553
+			],
554
+			'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => [
555
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
556
+			],
557
+			'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
558
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
559
+			],
560
+			'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
561
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
562
+			],
563
+			'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
564
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
565
+			],
566
+			'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
567
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
568
+			],
569
+			'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
570
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
571
+			],
572
+			'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
573
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
574
+			],
575
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => [
576
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
577
+			],
578
+			'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
579
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
580
+			],
581
+			'EventEspresso\core\services\database\TableManager'                                                           => [
582
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
583
+			],
584
+			'EE_Data_Migration_Class_Base'                                                                                => [
585
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
586
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
587
+			],
588
+			'EE_DMS_Core_4_1_0'                                                                                           => [
589
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
590
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
591
+			],
592
+			'EE_DMS_Core_4_2_0'                                                                                           => [
593
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
594
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
595
+			],
596
+			'EE_DMS_Core_4_3_0'                                                                                           => [
597
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
598
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
599
+			],
600
+			'EE_DMS_Core_4_4_0'                                                                                           => [
601
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
602
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
603
+			],
604
+			'EE_DMS_Core_4_5_0'                                                                                           => [
605
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
606
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
607
+			],
608
+			'EE_DMS_Core_4_6_0'                                                                                           => [
609
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
610
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
611
+			],
612
+			'EE_DMS_Core_4_7_0'                                                                                           => [
613
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
614
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
615
+			],
616
+			'EE_DMS_Core_4_8_0'                                                                                           => [
617
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
618
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
619
+			],
620
+			'EE_DMS_Core_4_9_0'                                                                                           => [
621
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
622
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
623
+			],
624
+			'EE_DMS_Core_4_10_0'                                                                                          => [
625
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
626
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
627
+				'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
628
+			],
629
+			'EE_DMS_Core_4_11_0'                                                                                          => [
630
+				'EE_DMS_Core_4_10_0'                                 => EE_Dependency_Map::load_from_cache,
631
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
632
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
633
+			],
634
+			'EE_DMS_Core_4_12_0'                                                                                          => [
635
+				'EE_DMS_Core_4_11_0'                                 => EE_Dependency_Map::load_from_cache,
636
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
637
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
638
+			],
639
+			'EventEspresso\core\services\assets\I18nRegistry'                                                             => [
640
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
641
+			],
642
+			'EventEspresso\core\services\assets\Registry'                                                                 => [
643
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
644
+				'EventEspresso\core\services\assets\AssetManifest'   => EE_Dependency_Map::load_from_cache,
645
+			],
646
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => [
647
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
648
+			],
649
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => [
650
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
651
+			],
652
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => [
653
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
654
+			],
655
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => [
656
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
657
+			],
658
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => [
659
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
660
+			],
661
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => [
662
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
663
+			],
664
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => [
665
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
666
+			],
667
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                         => [
668
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
669
+			],
670
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => [
671
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
672
+			],
673
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => [
674
+				'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
675
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
676
+			],
677
+			'EventEspresso\core\domain\values\EmailAddress'                                                               => [
678
+				null,
679
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
680
+			],
681
+			'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => [
682
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
683
+			],
684
+			'LEGACY_MODELS'                                                                                               => [
685
+				null,
686
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
687
+			],
688
+			'EE_Module_Request_Router'                                                                                    => [
689
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
690
+			],
691
+			'EE_Registration_Processor'                                                                                   => [
692
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
693
+			],
694
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => [
695
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
696
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
697
+			],
698
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => [
699
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
700
+				'EE_Session'             => EE_Dependency_Map::load_from_cache,
701
+			],
702
+			'EventEspresso\modules\ticket_selector\DisplayTicketSelector'                                                 => [
703
+				'EventEspresso\core\domain\entities\users\CurrentUser' => EE_Dependency_Map::load_from_cache,
704
+				'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
705
+				'EE_Ticket_Selector_Config'                            => EE_Dependency_Map::load_from_cache,
706
+			],
707
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => [
708
+				'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
709
+				'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
710
+				'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
711
+				'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
712
+				'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
713
+			],
714
+			'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => [
715
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
716
+			],
717
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => [
718
+				'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
719
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
720
+			],
721
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => [
722
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
723
+			],
724
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => [
725
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
726
+			],
727
+			'EE_CPT_Strategy'                                                                                             => [
728
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
729
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
730
+			],
731
+			'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => [
732
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
733
+			],
734
+			'EventEspresso\core\CPTs\CptQueryModifier'                                                                    => [
735
+				null,
736
+				null,
737
+				null,
738
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
739
+				'EventEspresso\core\services\request\Request'     => EE_Dependency_Map::load_from_cache,
740
+				'EventEspresso\core\services\loaders\Loader'      => EE_Dependency_Map::load_from_cache,
741
+			],
742
+			'EventEspresso\core\services\dependencies\DependencyResolver'                                                 => [
743
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
744
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
745
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
746
+			],
747
+			'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                               => [
748
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
749
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
750
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
751
+			],
752
+			'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                          => [
753
+				'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
754
+				'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
755
+			],
756
+			'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                          => [
757
+				'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
758
+				'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
759
+			],
760
+			'EE_URL_Validation_Strategy'                                                                                  => [
761
+				null,
762
+				null,
763
+				'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache,
764
+			],
765
+			'EventEspresso\core\services\request\files\FilesDataHandler'                                                  => [
766
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
767
+			],
768
+			'EventEspressoBatchRequest\BatchRequestProcessor'                                                             => [
769
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
770
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
771
+			],
772
+			'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                => [
773
+				'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
774
+				'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
775
+				'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
776
+				null,
777
+			],
778
+			'EventEspresso\core\services\routing\RouteHandler'                                                            => [
779
+				'EventEspresso\core\services\json\JsonDataNodeHandler' => EE_Dependency_Map::load_from_cache,
780
+				'EventEspresso\core\services\loaders\Loader'           => EE_Dependency_Map::load_from_cache,
781
+				'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
782
+				'EventEspresso\core\services\routing\RouteCollection'  => EE_Dependency_Map::load_from_cache,
783
+			],
784
+			'EventEspresso\core\services\json\JsonDataNodeHandler'                                                        => [
785
+				'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
786
+			],
787
+			'EventEspresso\core\services\routing\Router'                                                                  => [
788
+				'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
789
+				'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
790
+				'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
791
+			],
792
+			'EventEspresso\core\services\assets\AssetManifest'                                                            => [
793
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
794
+			],
795
+			'EventEspresso\core\services\assets\AssetManifestFactory'                                                     => [
796
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
797
+			],
798
+			'EventEspresso\core\services\assets\BaristaFactory'                                                           => [
799
+				'EventEspresso\core\services\assets\AssetManifestFactory' => EE_Dependency_Map::load_from_cache,
800
+				'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
801
+			],
802
+			'EventEspresso\core\domain\services\capabilities\FeatureFlags'                                                => [
803
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
804
+				'EventEspresso\core\domain\Domain'                                    => EE_Dependency_Map::load_from_cache,
805
+			],
806
+			'EventEspresso\core\services\addon\AddonManager'                                                              => [
807
+				'EventEspresso\core\services\addon\AddonCollection'              => EE_Dependency_Map::load_from_cache,
808
+				'EventEspresso\core\Psr4Autoloader'                              => EE_Dependency_Map::load_from_cache,
809
+				'EventEspresso\core\services\addon\api\v1\RegisterAddon'         => EE_Dependency_Map::load_from_cache,
810
+				'EventEspresso\core\services\addon\api\IncompatibleAddonHandler' => EE_Dependency_Map::load_from_cache,
811
+				'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'  => EE_Dependency_Map::load_from_cache,
812
+			],
813
+			'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'                                               => [
814
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
815
+			],
816
+			'EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion'                                                  => [
817
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
818
+			],
819
+			'EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'                                                  => [
820
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
821
+			],
822
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'                                        => [
823
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
824
+				'EEM_Event'                                                   => EE_Dependency_Map::load_from_cache,
825
+				'EEM_Datetime'                                                => EE_Dependency_Map::load_from_cache,
826
+				'EEM_Registration'                                            => EE_Dependency_Map::load_from_cache,
827
+			],
828
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'                                        => [
829
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
830
+			],
831
+			'EventEspresso\core\services\request\CurrentPage'                                                             => [
832
+				'EE_CPT_Strategy'                             => EE_Dependency_Map::load_from_cache,
833
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
834
+			],
835
+			'EventEspresso\core\services\shortcodes\LegacyShortcodesManager'                                              => [
836
+				'EE_Registry'                                     => EE_Dependency_Map::load_from_cache,
837
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
838
+			],
839
+			'EventEspresso\core\services\shortcodes\ShortcodesManager'                                                    => [
840
+				'EventEspresso\core\services\shortcodes\LegacyShortcodesManager' => EE_Dependency_Map::load_from_cache,
841
+				'EventEspresso\core\services\request\CurrentPage'                => EE_Dependency_Map::load_from_cache,
842
+			],
843
+			'EventEspresso\core\domain\entities\users\CurrentUser'                                                        => [
844
+				'EventEspresso\core\domain\entities\users\EventManagers' => EE_Dependency_Map::load_from_cache,
845
+			],
846
+			'EventEspresso\core\services\form\meta\InputTypes'                                                            => [
847
+				'EventEspresso\core\services\form\meta\inputs\Block'    => EE_Dependency_Map::load_from_cache,
848
+				'EventEspresso\core\services\form\meta\inputs\Button'   => EE_Dependency_Map::load_from_cache,
849
+				'EventEspresso\core\services\form\meta\inputs\DateTime' => EE_Dependency_Map::load_from_cache,
850
+				'EventEspresso\core\services\form\meta\inputs\Input'    => EE_Dependency_Map::load_from_cache,
851
+				'EventEspresso\core\services\form\meta\inputs\Number'   => EE_Dependency_Map::load_from_cache,
852
+				'EventEspresso\core\services\form\meta\inputs\Phone'    => EE_Dependency_Map::load_from_cache,
853
+				'EventEspresso\core\services\form\meta\inputs\Select'   => EE_Dependency_Map::load_from_cache,
854
+				'EventEspresso\core\services\form\meta\inputs\Text'     => EE_Dependency_Map::load_from_cache,
855
+			],
856
+			'EventEspresso\core\domain\services\registration\form\v1\RegFormDependencyHandler'                            => [
857
+				'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
858
+			],
859
+			'EventEspresso\core\services\calculators\LineItemCalculator'                                                  => [
860
+				'EventEspresso\core\services\helpers\DecimalValues' => EE_Dependency_Map::load_from_cache,
861
+			],
862
+			'EventEspresso\core\services\helpers\DecimalValues'                                                           => [
863
+				'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
864
+			],
865
+		];
866
+	}
867
+
868
+
869
+	/**
870
+	 * Registers how core classes are loaded.
871
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
872
+	 *        'EE_Request_Handler' => 'load_core'
873
+	 *        'EE_Messages_Queue'  => 'load_lib'
874
+	 *        'EEH_Debug_Tools'    => 'load_helper'
875
+	 * or, if greater control is required, by providing a custom closure. For example:
876
+	 *        'Some_Class' => function () {
877
+	 *            return new Some_Class();
878
+	 *        },
879
+	 * This is required for instantiating dependencies
880
+	 * where an interface has been type hinted in a class constructor. For example:
881
+	 *        'Required_Interface' => function () {
882
+	 *            return new A_Class_That_Implements_Required_Interface();
883
+	 *        },
884
+	 */
885
+	protected function _register_core_class_loaders()
886
+	{
887
+		$this->_class_loaders = [
888
+			// load_core
889
+			'EE_Dependency_Map'                            => function () {
890
+				return $this;
891
+			},
892
+			'EE_Capabilities'                              => 'load_core',
893
+			'EE_Encryption'                                => 'load_core',
894
+			'EE_Front_Controller'                          => 'load_core',
895
+			'EE_Module_Request_Router'                     => 'load_core',
896
+			'EE_Registry'                                  => 'load_core',
897
+			'EE_Request'                                   => function () {
898
+				return $this->legacy_request;
899
+			},
900
+			'EventEspresso\core\services\request\Request'  => function () {
901
+				return $this->request;
902
+			},
903
+			'EventEspresso\core\services\request\Response' => function () {
904
+				return $this->response;
905
+			},
906
+			'EE_Base'                                      => 'load_core',
907
+			'EE_Request_Handler'                           => 'load_core',
908
+			'EE_Session'                                   => 'load_core',
909
+			'EE_Cron_Tasks'                                => 'load_core',
910
+			'EE_System'                                    => 'load_core',
911
+			'EE_Maintenance_Mode'                          => 'load_core',
912
+			'EE_Register_CPTs'                             => 'load_core',
913
+			'EE_Admin'                                     => 'load_core',
914
+			'EE_CPT_Strategy'                              => 'load_core',
915
+			// load_class
916
+			'EE_Registration_Processor'                    => 'load_class',
917
+			// load_lib
918
+			'EE_Message_Resource_Manager'                  => 'load_lib',
919
+			'EE_Message_Type_Collection'                   => 'load_lib',
920
+			'EE_Message_Type_Collection_Loader'            => 'load_lib',
921
+			'EE_Messenger_Collection'                      => 'load_lib',
922
+			'EE_Messenger_Collection_Loader'               => 'load_lib',
923
+			'EE_Messages_Processor'                        => 'load_lib',
924
+			'EE_Message_Repository'                        => 'load_lib',
925
+			'EE_Messages_Queue'                            => 'load_lib',
926
+			'EE_Messages_Data_Handler_Collection'          => 'load_lib',
927
+			'EE_Message_Template_Group_Collection'         => 'load_lib',
928
+			'EE_Payment_Method_Manager'                    => 'load_lib',
929
+			'EE_DMS_Core_4_1_0'                            => 'load_dms',
930
+			'EE_DMS_Core_4_2_0'                            => 'load_dms',
931
+			'EE_DMS_Core_4_3_0'                            => 'load_dms',
932
+			'EE_DMS_Core_4_5_0'                            => 'load_dms',
933
+			'EE_DMS_Core_4_6_0'                            => 'load_dms',
934
+			'EE_DMS_Core_4_7_0'                            => 'load_dms',
935
+			'EE_DMS_Core_4_8_0'                            => 'load_dms',
936
+			'EE_DMS_Core_4_9_0'                            => 'load_dms',
937
+			'EE_DMS_Core_4_10_0'                           => 'load_dms',
938
+			'EE_DMS_Core_4_11_0'                           => 'load_dms',
939
+			'EE_DMS_Core_4_12_0'                           => 'load_dms',
940
+			'EE_Messages_Generator'                        => static function () {
941
+				return EE_Registry::instance()->load_lib(
942
+					'Messages_Generator',
943
+					[],
944
+					false,
945
+					false
946
+				);
947
+			},
948
+			'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
949
+				return EE_Registry::instance()->load_lib(
950
+					'Messages_Template_Defaults',
951
+					$arguments,
952
+					false,
953
+					false
954
+				);
955
+			},
956
+			// load_helper
957
+			'EEH_Parse_Shortcodes'                         => static function () {
958
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
959
+					return new EEH_Parse_Shortcodes();
960
+				}
961
+				return null;
962
+			},
963
+			'EE_Template_Config'                           => static function () {
964
+				return EE_Config::instance()->template_settings;
965
+			},
966
+			'EE_Currency_Config'                           => static function () {
967
+				return EE_Currency_Config::getCurrencyConfig();
968
+			},
969
+			'EE_Registration_Config'                       => static function () {
970
+				return EE_Config::instance()->registration;
971
+			},
972
+			'EE_Core_Config'                               => static function () {
973
+				return EE_Config::instance()->core;
974
+			},
975
+			'EventEspresso\core\services\loaders\Loader'   => static function () {
976
+				return LoaderFactory::getLoader();
977
+			},
978
+			'EE_Network_Config'                            => static function () {
979
+				return EE_Network_Config::instance();
980
+			},
981
+			'EE_Config'                                    => static function () {
982
+				return EE_Config::instance();
983
+			},
984
+			'EventEspresso\core\domain\Domain'             => static function () {
985
+				return DomainFactory::getEventEspressoCoreDomain();
986
+			},
987
+			'EE_Admin_Config'                              => static function () {
988
+				return EE_Config::instance()->admin;
989
+			},
990
+			'EE_Organization_Config'                       => static function () {
991
+				return EE_Config::instance()->organization;
992
+			},
993
+			'EE_Network_Core_Config'                       => static function () {
994
+				return EE_Network_Config::instance()->core;
995
+			},
996
+			'EE_Environment_Config'                        => static function () {
997
+				return EE_Config::instance()->environment;
998
+			},
999
+			'EED_Core_Rest_Api'                            => static function () {
1000
+				return EED_Core_Rest_Api::instance();
1001
+			},
1002
+			'WP_REST_Server'                               => static function () {
1003
+				return rest_get_server();
1004
+			},
1005
+			'EventEspresso\core\Psr4Autoloader'            => static function () {
1006
+				return EE_Psr4AutoloaderInit::psr4_loader();
1007
+			},
1008
+			'EE_Ticket_Selector_Config'                    => function () {
1009
+				return EE_Config::instance()->template_settings->EED_Ticket_Selector;
1010
+			},
1011
+		];
1012
+	}
1013
+
1014
+
1015
+	/**
1016
+	 * can be used for supplying alternate names for classes,
1017
+	 * or for connecting interface names to instantiable classes
1018
+	 *
1019
+	 * @throws InvalidAliasException
1020
+	 */
1021
+	protected function _register_core_aliases()
1022
+	{
1023
+		$aliases = [
1024
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1025
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1026
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1027
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1028
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1029
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1030
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1031
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1032
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1033
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1034
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1035
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1036
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1037
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1038
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1039
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1040
+			'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1041
+			'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1042
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1043
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1044
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1045
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1046
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1047
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1048
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1049
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1050
+			'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1051
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1052
+			'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1053
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1054
+			'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1055
+			'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1056
+			'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1057
+			'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1058
+			'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1059
+			'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1060
+			'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1061
+			'Registration_Processor'                                                       => 'EE_Registration_Processor',
1062
+			'EventEspresso\core\services\assets\AssetManifestInterface'                    => 'EventEspresso\core\services\assets\AssetManifest',
1063
+		];
1064
+		foreach ($aliases as $alias => $fqn) {
1065
+			if (is_array($fqn)) {
1066
+				foreach ($fqn as $class => $for_class) {
1067
+					$this->class_cache->addAlias($class, $alias, $for_class);
1068
+				}
1069
+				continue;
1070
+			}
1071
+			$this->class_cache->addAlias($fqn, $alias);
1072
+		}
1073
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1074
+			$this->class_cache->addAlias(
1075
+				'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1076
+				'EventEspresso\core\services\notices\NoticeConverterInterface'
1077
+			);
1078
+		}
1079
+	}
1080
+
1081
+
1082
+	public function debug($for_class = '')
1083
+	{
1084
+		if (method_exists($this->class_cache, 'debug')) {
1085
+			$this->class_cache->debug($for_class);
1086
+		}
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1092
+	 * request Primarily used by unit tests.
1093
+	 */
1094
+	public function reset()
1095
+	{
1096
+		$this->_register_core_class_loaders();
1097
+		$this->_register_core_dependencies();
1098
+	}
1099
+
1100
+
1101
+	/**
1102
+	 * PLZ NOTE: a better name for this method would be is_alias()
1103
+	 * because it returns TRUE if the provided fully qualified name IS an alias
1104
+	 * WHY?
1105
+	 * Because if a class is type hinting for a concretion,
1106
+	 * then why would we need to find another class to supply it?
1107
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1108
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1109
+	 * Don't go looking for some substitute.
1110
+	 * Whereas if a class is type hinting for an interface...
1111
+	 * then we need to find an actual class to use.
1112
+	 * So the interface IS the alias for some other FQN,
1113
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1114
+	 * represents some other class.
1115
+	 *
1116
+	 * @param string $fqn
1117
+	 * @param string $for_class
1118
+	 * @return bool
1119
+	 * @deprecated 4.9.62.p
1120
+	 */
1121
+	public function has_alias(string $fqn = '', string $for_class = ''): bool
1122
+	{
1123
+		return $this->isAlias($fqn, $for_class);
1124
+	}
1125
+
1126
+
1127
+	/**
1128
+	 * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1129
+	 * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1130
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
1131
+	 *  for example:
1132
+	 *      if the following two entries were added to the _aliases array:
1133
+	 *          array(
1134
+	 *              'interface_alias'           => 'some\namespace\interface'
1135
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
1136
+	 *          )
1137
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1138
+	 *      to load an instance of 'some\namespace\classname'
1139
+	 *
1140
+	 * @param string $alias
1141
+	 * @param string $for_class
1142
+	 * @return string
1143
+	 * @deprecated 4.9.62.p
1144
+	 */
1145
+	public function get_alias(string $alias = '', string $for_class = ''): string
1146
+	{
1147
+		return $this->getFqnForAlias($alias, $for_class);
1148
+	}
1149 1149
 }
Please login to merge, or discard this patch.