Completed
Branch add-cap-checks-to-routes (73eed8)
by
unknown
08:17 queued 10s
created
admin_pages/registrations/Registrations_Admin_Page_Init.core.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -11,48 +11,48 @@
 block discarded – undo
11 11
  */
12 12
 class Registrations_Admin_Page_Init extends EE_Admin_Page_CPT_Init
13 13
 {
14
-    /**
15
-     *        constructor
16
-     *
17
-     * @Constructor
18
-     * @access public
19
-     * @return void
20
-     */
21
-    public function __construct()
22
-    {
23
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
24
-        if (! defined('REG_PG_SLUG')) {
25
-            define('REG_PG_SLUG', 'espresso_registrations');
26
-            define('REG_PG_NAME', ucwords(str_replace('_', '', REG_PG_SLUG)));
27
-            define('REG_ADMIN', EE_ADMIN_PAGES . 'registrations/');
28
-            define('REG_ADMIN_URL', admin_url('admin.php?page=' . REG_PG_SLUG));
29
-            define('REG_ASSETS_PATH', REG_ADMIN . 'assets/');
30
-            define('REG_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registrations/assets/');
31
-            define('REG_TEMPLATE_PATH', REG_ADMIN . 'templates/');
32
-            define('REG_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registrations/templates/');
33
-        }
14
+	/**
15
+	 *        constructor
16
+	 *
17
+	 * @Constructor
18
+	 * @access public
19
+	 * @return void
20
+	 */
21
+	public function __construct()
22
+	{
23
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
24
+		if (! defined('REG_PG_SLUG')) {
25
+			define('REG_PG_SLUG', 'espresso_registrations');
26
+			define('REG_PG_NAME', ucwords(str_replace('_', '', REG_PG_SLUG)));
27
+			define('REG_ADMIN', EE_ADMIN_PAGES . 'registrations/');
28
+			define('REG_ADMIN_URL', admin_url('admin.php?page=' . REG_PG_SLUG));
29
+			define('REG_ASSETS_PATH', REG_ADMIN . 'assets/');
30
+			define('REG_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registrations/assets/');
31
+			define('REG_TEMPLATE_PATH', REG_ADMIN . 'templates/');
32
+			define('REG_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registrations/templates/');
33
+		}
34 34
 
35
-        parent::__construct();
36
-    }
35
+		parent::__construct();
36
+	}
37 37
 
38 38
 
39
-    protected function _set_init_properties()
40
-    {
41
-        $this->label = esc_html__('Registrations Overview', 'event_espresso');
42
-    }
39
+	protected function _set_init_properties()
40
+	{
41
+		$this->label = esc_html__('Registrations Overview', 'event_espresso');
42
+	}
43 43
 
44 44
 
45
-    public function getMenuProperties(): array
46
-    {
47
-        return [
48
-            'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
49
-            'menu_group'      => 'main',
50
-            'menu_order'      => 40,
51
-            'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
52
-            'parent_slug'     => 'espresso_events',
53
-            'menu_slug'       => REG_PG_SLUG,
54
-            'menu_label'      => esc_html__('Registrations', 'event_espresso'),
55
-            'capability'      => 'ee_read_registrations',
56
-        ];
57
-    }
45
+	public function getMenuProperties(): array
46
+	{
47
+		return [
48
+			'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
49
+			'menu_group'      => 'main',
50
+			'menu_order'      => 40,
51
+			'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
52
+			'parent_slug'     => 'espresso_events',
53
+			'menu_slug'       => REG_PG_SLUG,
54
+			'menu_label'      => esc_html__('Registrations', 'event_espresso'),
55
+			'capability'      => 'ee_read_registrations',
56
+		];
57
+	}
58 58
 }
Please login to merge, or discard this patch.
admin_pages/payments/Payments_Admin_Page_Init.core.php 2 patches
Indentation   +141 added lines, -141 removed lines patch added patch discarded remove patch
@@ -15,147 +15,147 @@
 block discarded – undo
15 15
  */
16 16
 class Payments_Admin_Page_Init extends EE_Admin_Page_Init
17 17
 {
18
-    /**
19
-     * @var TableAnalysis $table_analysis
20
-     */
21
-    protected $_table_analysis;
22
-
23
-
24
-    /**
25
-     * @throws EE_Error
26
-     * @throws ReflectionException
27
-     */
28
-    public function __construct()
29
-    {
30
-        // define some page related constants
31
-        if (! defined('EE_PAYMENTS_PG_SLUG')) {
32
-            define('EE_PAYMENTS_PG_SLUG', 'espresso_payment_settings');
33
-            define('EE_PAYMENTS_ADMIN_URL', admin_url('admin.php?page=' . EE_PAYMENTS_PG_SLUG));
34
-            define('EE_PAYMENTS_ADMIN', EE_ADMIN_PAGES . 'payments/');
35
-            define('EE_PAYMENTS_TEMPLATE_PATH', EE_PAYMENTS_ADMIN . 'templates/');
36
-            define('EE_PAYMENTS_ASSETS_URL', EE_ADMIN_PAGES_URL . 'payments/assets/');
37
-        }
38
-        $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
39
-        // check that there are active gateways on all admin page loads. but don't do it just yet
40
-        add_action('admin_notices', [$this, 'check_payment_gateway_setup']);
41
-
42
-        // Show/hide PP Standard alongside PP Express.
43
-        add_filter(
44
-            'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
45
-            [$this, 'unset_pp_standard']
46
-        );
47
-
48
-        parent::__construct();
49
-    }
50
-
51
-
52
-    protected function _set_init_properties()
53
-    {
54
-        $this->label = esc_html__('Payment Methods', 'event_espresso');
55
-    }
56
-
57
-
58
-    public function getMenuProperties(): array
59
-    {
60
-        return [
61
-            'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
62
-            'menu_group'      => 'settings',
63
-            'menu_order'      => 30,
64
-            'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
65
-            'parent_slug'     => 'espresso_events',
66
-            'menu_slug'       => EE_PAYMENTS_PG_SLUG,
67
-            'menu_label'      => esc_html__('Payment Methods', 'event_espresso'),
68
-            'capability'      => 'ee_manage_gateways',
69
-        ];
70
-    }
71
-
72
-
73
-    /**
74
-     * Checks that there is at least one active gateway. If not, add a notice
75
-     *
76
-     * @throws EE_Error
77
-     */
78
-    public function check_payment_gateway_setup()
79
-    {
80
-        // ONLY do this check if models can query
81
-        // and avoid a bug where when we nuke EE4's data that this causes a fatal error
82
-        // because the tables are deleted just before this request runs.
83
-        // see https://events.codebasehq.com/projects/event-espresso/tickets/7539
84
-        if (
85
-            ! EE_Maintenance_Mode::instance()->models_can_query()
86
-            || ! $this->_get_table_analysis()->tableExists(EEM_Payment_Method::instance()->table())
87
-        ) {
88
-            return;
89
-        }
90
-
91
-        $actives = EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart);
92
-        if ($actives < 1) {
93
-            $url = EE_Admin_Page::add_query_args_and_nonce([], EE_PAYMENTS_ADMIN_URL);
94
-            echo '<div class="error">
18
+	/**
19
+	 * @var TableAnalysis $table_analysis
20
+	 */
21
+	protected $_table_analysis;
22
+
23
+
24
+	/**
25
+	 * @throws EE_Error
26
+	 * @throws ReflectionException
27
+	 */
28
+	public function __construct()
29
+	{
30
+		// define some page related constants
31
+		if (! defined('EE_PAYMENTS_PG_SLUG')) {
32
+			define('EE_PAYMENTS_PG_SLUG', 'espresso_payment_settings');
33
+			define('EE_PAYMENTS_ADMIN_URL', admin_url('admin.php?page=' . EE_PAYMENTS_PG_SLUG));
34
+			define('EE_PAYMENTS_ADMIN', EE_ADMIN_PAGES . 'payments/');
35
+			define('EE_PAYMENTS_TEMPLATE_PATH', EE_PAYMENTS_ADMIN . 'templates/');
36
+			define('EE_PAYMENTS_ASSETS_URL', EE_ADMIN_PAGES_URL . 'payments/assets/');
37
+		}
38
+		$this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
39
+		// check that there are active gateways on all admin page loads. but don't do it just yet
40
+		add_action('admin_notices', [$this, 'check_payment_gateway_setup']);
41
+
42
+		// Show/hide PP Standard alongside PP Express.
43
+		add_filter(
44
+			'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
45
+			[$this, 'unset_pp_standard']
46
+		);
47
+
48
+		parent::__construct();
49
+	}
50
+
51
+
52
+	protected function _set_init_properties()
53
+	{
54
+		$this->label = esc_html__('Payment Methods', 'event_espresso');
55
+	}
56
+
57
+
58
+	public function getMenuProperties(): array
59
+	{
60
+		return [
61
+			'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
62
+			'menu_group'      => 'settings',
63
+			'menu_order'      => 30,
64
+			'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
65
+			'parent_slug'     => 'espresso_events',
66
+			'menu_slug'       => EE_PAYMENTS_PG_SLUG,
67
+			'menu_label'      => esc_html__('Payment Methods', 'event_espresso'),
68
+			'capability'      => 'ee_manage_gateways',
69
+		];
70
+	}
71
+
72
+
73
+	/**
74
+	 * Checks that there is at least one active gateway. If not, add a notice
75
+	 *
76
+	 * @throws EE_Error
77
+	 */
78
+	public function check_payment_gateway_setup()
79
+	{
80
+		// ONLY do this check if models can query
81
+		// and avoid a bug where when we nuke EE4's data that this causes a fatal error
82
+		// because the tables are deleted just before this request runs.
83
+		// see https://events.codebasehq.com/projects/event-espresso/tickets/7539
84
+		if (
85
+			! EE_Maintenance_Mode::instance()->models_can_query()
86
+			|| ! $this->_get_table_analysis()->tableExists(EEM_Payment_Method::instance()->table())
87
+		) {
88
+			return;
89
+		}
90
+
91
+		$actives = EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart);
92
+		if ($actives < 1) {
93
+			$url = EE_Admin_Page::add_query_args_and_nonce([], EE_PAYMENTS_ADMIN_URL);
94
+			echo '<div class="error">
95 95
 				 <p>'
96
-                 . sprintf(
97
-                     esc_html__(
98
-                         "There are no Active Payment Methods setup for Event Espresso. Please %s activate at least one.%s",
99
-                         "event_espresso"
100
-                     ),
101
-                     "<a href='$url'>",
102
-                     "</a>"
103
-                 )
104
-                 . '</p>
96
+				 . sprintf(
97
+					 esc_html__(
98
+						 "There are no Active Payment Methods setup for Event Espresso. Please %s activate at least one.%s",
99
+						 "event_espresso"
100
+					 ),
101
+					 "<a href='$url'>",
102
+					 "</a>"
103
+				 )
104
+				 . '</p>
105 105
 			 </div>';
106
-        }
107
-    }
108
-
109
-
110
-    /**
111
-     * Gets the injected table analyzer, or throws an exception
112
-     *
113
-     * @return TableAnalysis
114
-     * @throws EE_Error
115
-     */
116
-    protected function _get_table_analysis()
117
-    {
118
-        if ($this->_table_analysis instanceof TableAnalysis) {
119
-            return $this->_table_analysis;
120
-        } else {
121
-            throw new EE_Error(
122
-                sprintf(
123
-                    esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
124
-                    get_class($this)
125
-                )
126
-            );
127
-        }
128
-    }
129
-
130
-
131
-    /**
132
-     * Hide PayPal Standard for "new" users.
133
-     *
134
-     * @throws EE_Error
135
-     * @throws ReflectionException
136
-     */
137
-    public static function unset_pp_standard($payment_method_types)
138
-    {
139
-        $pps                           = EEM_Payment_Method::instance()->get_one_of_type('Paypal_Standard');
140
-        $paypal_standard_active        = ! empty($pps) && $pps->active();
141
-        $paypal_standard_active_before = false;
142
-        if ($pps) {
143
-            // PP Standard used before ?
144
-            $paypal_id = $pps->get_extra_meta('paypal_id', true);
145
-            if ($paypal_id && ! empty($paypal_id)) {
146
-                $paypal_standard_active_before = true;
147
-            }
148
-        }
149
-
150
-        // Not using PP Standard? Then display only PayPal Express, do not show PayPal Standard.
151
-        if (
152
-            apply_filters(
153
-                'FHEE__EE_PMT_Paypal_Express__register_payment_methods__hide_paypal_standard',
154
-                ! $paypal_standard_active && ! $paypal_standard_active_before
155
-            )
156
-        ) {
157
-            unset($payment_method_types['paypal_standard']);
158
-        }
159
-        return $payment_method_types;
160
-    }
106
+		}
107
+	}
108
+
109
+
110
+	/**
111
+	 * Gets the injected table analyzer, or throws an exception
112
+	 *
113
+	 * @return TableAnalysis
114
+	 * @throws EE_Error
115
+	 */
116
+	protected function _get_table_analysis()
117
+	{
118
+		if ($this->_table_analysis instanceof TableAnalysis) {
119
+			return $this->_table_analysis;
120
+		} else {
121
+			throw new EE_Error(
122
+				sprintf(
123
+					esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
124
+					get_class($this)
125
+				)
126
+			);
127
+		}
128
+	}
129
+
130
+
131
+	/**
132
+	 * Hide PayPal Standard for "new" users.
133
+	 *
134
+	 * @throws EE_Error
135
+	 * @throws ReflectionException
136
+	 */
137
+	public static function unset_pp_standard($payment_method_types)
138
+	{
139
+		$pps                           = EEM_Payment_Method::instance()->get_one_of_type('Paypal_Standard');
140
+		$paypal_standard_active        = ! empty($pps) && $pps->active();
141
+		$paypal_standard_active_before = false;
142
+		if ($pps) {
143
+			// PP Standard used before ?
144
+			$paypal_id = $pps->get_extra_meta('paypal_id', true);
145
+			if ($paypal_id && ! empty($paypal_id)) {
146
+				$paypal_standard_active_before = true;
147
+			}
148
+		}
149
+
150
+		// Not using PP Standard? Then display only PayPal Express, do not show PayPal Standard.
151
+		if (
152
+			apply_filters(
153
+				'FHEE__EE_PMT_Paypal_Express__register_payment_methods__hide_paypal_standard',
154
+				! $paypal_standard_active && ! $paypal_standard_active_before
155
+			)
156
+		) {
157
+			unset($payment_method_types['paypal_standard']);
158
+		}
159
+		return $payment_method_types;
160
+	}
161 161
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -28,12 +28,12 @@
 block discarded – undo
28 28
     public function __construct()
29 29
     {
30 30
         // define some page related constants
31
-        if (! defined('EE_PAYMENTS_PG_SLUG')) {
31
+        if ( ! defined('EE_PAYMENTS_PG_SLUG')) {
32 32
             define('EE_PAYMENTS_PG_SLUG', 'espresso_payment_settings');
33
-            define('EE_PAYMENTS_ADMIN_URL', admin_url('admin.php?page=' . EE_PAYMENTS_PG_SLUG));
34
-            define('EE_PAYMENTS_ADMIN', EE_ADMIN_PAGES . 'payments/');
35
-            define('EE_PAYMENTS_TEMPLATE_PATH', EE_PAYMENTS_ADMIN . 'templates/');
36
-            define('EE_PAYMENTS_ASSETS_URL', EE_ADMIN_PAGES_URL . 'payments/assets/');
33
+            define('EE_PAYMENTS_ADMIN_URL', admin_url('admin.php?page='.EE_PAYMENTS_PG_SLUG));
34
+            define('EE_PAYMENTS_ADMIN', EE_ADMIN_PAGES.'payments/');
35
+            define('EE_PAYMENTS_TEMPLATE_PATH', EE_PAYMENTS_ADMIN.'templates/');
36
+            define('EE_PAYMENTS_ASSETS_URL', EE_ADMIN_PAGES_URL.'payments/assets/');
37 37
         }
38 38
         $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', [], true);
39 39
         // check that there are active gateways on all admin page loads. but don't do it just yet
Please login to merge, or discard this patch.
admin_pages/registration_form/Registration_Form_Admin_Page_Init.core.php 2 patches
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -17,42 +17,42 @@
 block discarded – undo
17 17
  */
18 18
 class Registration_Form_Admin_Page_Init extends EE_Admin_Page_Init
19 19
 {
20
-    public function __construct()
21
-    {
22
-        // define some constants
23
-        if (! defined('REGISTRATION_FORM_PG_SLUG')) {
24
-            define('REGISTRATION_FORM_PG_SLUG', 'espresso_registration_form');
25
-            define('REGISTRATION_FORM_LABEL', esc_html__('Registration Form', 'event_espresso'));
26
-            define('REGISTRATION_FORM_PG_NAME', REGISTRATION_FORM_LABEL);
27
-            define('REGISTRATION_FORM_ADMIN', EE_ADMIN_PAGES . 'registration_form/');
28
-            define('REGISTRATION_FORM_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
29
-            define('EE_FORMS_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
30
-            define('REGISTRATION_FORM_ASSETS_PATH', REGISTRATION_FORM_ADMIN . 'assets/');
31
-            define('REGISTRATION_FORM_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registration_form/assets/');
32
-            define('REGISTRATION_FORM_TEMPLATE_PATH', REGISTRATION_FORM_ADMIN . 'templates/');
33
-            define('REGISTRATION_FORM_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registration_form/templates/');
34
-        }
35
-        parent::__construct();
36
-    }
20
+	public function __construct()
21
+	{
22
+		// define some constants
23
+		if (! defined('REGISTRATION_FORM_PG_SLUG')) {
24
+			define('REGISTRATION_FORM_PG_SLUG', 'espresso_registration_form');
25
+			define('REGISTRATION_FORM_LABEL', esc_html__('Registration Form', 'event_espresso'));
26
+			define('REGISTRATION_FORM_PG_NAME', REGISTRATION_FORM_LABEL);
27
+			define('REGISTRATION_FORM_ADMIN', EE_ADMIN_PAGES . 'registration_form/');
28
+			define('REGISTRATION_FORM_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
29
+			define('EE_FORMS_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
30
+			define('REGISTRATION_FORM_ASSETS_PATH', REGISTRATION_FORM_ADMIN . 'assets/');
31
+			define('REGISTRATION_FORM_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registration_form/assets/');
32
+			define('REGISTRATION_FORM_TEMPLATE_PATH', REGISTRATION_FORM_ADMIN . 'templates/');
33
+			define('REGISTRATION_FORM_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registration_form/templates/');
34
+		}
35
+		parent::__construct();
36
+	}
37 37
 
38 38
 
39
-    protected function _set_init_properties()
40
-    {
41
-        $this->label = esc_html__('Registration Form Overview', 'event_espresso');
42
-    }
39
+	protected function _set_init_properties()
40
+	{
41
+		$this->label = esc_html__('Registration Form Overview', 'event_espresso');
42
+	}
43 43
 
44 44
 
45
-    public function getMenuProperties(): array
46
-    {
47
-        return [
48
-            'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
49
-            'menu_group'      => 'management',
50
-            'menu_order'      => 30,
51
-            'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
52
-            'parent_slug'     => 'espresso_events',
53
-            'menu_slug'       => REGISTRATION_FORM_PG_SLUG,
54
-            'menu_label'      => esc_html__('Registration Form', 'event_espresso'),
55
-            'capability'      => 'ee_read_questions',
56
-        ];
57
-    }
45
+	public function getMenuProperties(): array
46
+	{
47
+		return [
48
+			'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
49
+			'menu_group'      => 'management',
50
+			'menu_order'      => 30,
51
+			'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
52
+			'parent_slug'     => 'espresso_events',
53
+			'menu_slug'       => REGISTRATION_FORM_PG_SLUG,
54
+			'menu_label'      => esc_html__('Registration Form', 'event_espresso'),
55
+			'capability'      => 'ee_read_questions',
56
+		];
57
+	}
58 58
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -20,17 +20,17 @@
 block discarded – undo
20 20
     public function __construct()
21 21
     {
22 22
         // define some constants
23
-        if (! defined('REGISTRATION_FORM_PG_SLUG')) {
23
+        if ( ! defined('REGISTRATION_FORM_PG_SLUG')) {
24 24
             define('REGISTRATION_FORM_PG_SLUG', 'espresso_registration_form');
25 25
             define('REGISTRATION_FORM_LABEL', esc_html__('Registration Form', 'event_espresso'));
26 26
             define('REGISTRATION_FORM_PG_NAME', REGISTRATION_FORM_LABEL);
27
-            define('REGISTRATION_FORM_ADMIN', EE_ADMIN_PAGES . 'registration_form/');
28
-            define('REGISTRATION_FORM_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
29
-            define('EE_FORMS_ADMIN_URL', admin_url('admin.php?page=' . REGISTRATION_FORM_PG_SLUG));
30
-            define('REGISTRATION_FORM_ASSETS_PATH', REGISTRATION_FORM_ADMIN . 'assets/');
31
-            define('REGISTRATION_FORM_ASSETS_URL', EE_ADMIN_PAGES_URL . 'registration_form/assets/');
32
-            define('REGISTRATION_FORM_TEMPLATE_PATH', REGISTRATION_FORM_ADMIN . 'templates/');
33
-            define('REGISTRATION_FORM_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'registration_form/templates/');
27
+            define('REGISTRATION_FORM_ADMIN', EE_ADMIN_PAGES.'registration_form/');
28
+            define('REGISTRATION_FORM_ADMIN_URL', admin_url('admin.php?page='.REGISTRATION_FORM_PG_SLUG));
29
+            define('EE_FORMS_ADMIN_URL', admin_url('admin.php?page='.REGISTRATION_FORM_PG_SLUG));
30
+            define('REGISTRATION_FORM_ASSETS_PATH', REGISTRATION_FORM_ADMIN.'assets/');
31
+            define('REGISTRATION_FORM_ASSETS_URL', EE_ADMIN_PAGES_URL.'registration_form/assets/');
32
+            define('REGISTRATION_FORM_TEMPLATE_PATH', REGISTRATION_FORM_ADMIN.'templates/');
33
+            define('REGISTRATION_FORM_TEMPLATE_URL', EE_ADMIN_PAGES_URL.'registration_form/templates/');
34 34
         }
35 35
         parent::__construct();
36 36
     }
Please login to merge, or discard this patch.
admin_pages/other_services/Other_Services_Admin_Page_Init.core.php 2 patches
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -14,38 +14,38 @@
 block discarded – undo
14 14
  */
15 15
 class Other_Services_Admin_Page_Init extends EE_Admin_Page_Init
16 16
 {
17
-    public function __construct()
18
-    {
19
-        // define some help/support page related constants
20
-        if (! defined('EE_OTHER_SERVICES_PG_SLUG')) {
21
-            define('EE_OTHER_SERVICES_PG_SLUG', 'espresso_packages');
22
-            define('EE_OTHER_SERVICES_ADMIN_URL', admin_url('admin.php?page=' . EE_OTHER_SERVICES_PG_SLUG));
23
-            define('EE_OTHER_SERVICES_ADMIN_TEMPLATE_PATH', EE_ADMIN_PAGES . 'other_services/templates/');
24
-            define('EE_OTHER_SERVICES_ADMIN', EE_ADMIN_PAGES . 'other_services/');
25
-            define('EE_OTHER_SERVICES_ASSETS_URL', EE_ADMIN_PAGES_URL . 'other_services/assets/');
26
-        }
27
-        parent::__construct();
28
-    }
17
+	public function __construct()
18
+	{
19
+		// define some help/support page related constants
20
+		if (! defined('EE_OTHER_SERVICES_PG_SLUG')) {
21
+			define('EE_OTHER_SERVICES_PG_SLUG', 'espresso_packages');
22
+			define('EE_OTHER_SERVICES_ADMIN_URL', admin_url('admin.php?page=' . EE_OTHER_SERVICES_PG_SLUG));
23
+			define('EE_OTHER_SERVICES_ADMIN_TEMPLATE_PATH', EE_ADMIN_PAGES . 'other_services/templates/');
24
+			define('EE_OTHER_SERVICES_ADMIN', EE_ADMIN_PAGES . 'other_services/');
25
+			define('EE_OTHER_SERVICES_ASSETS_URL', EE_ADMIN_PAGES_URL . 'other_services/assets/');
26
+		}
27
+		parent::__construct();
28
+	}
29 29
 
30 30
 
31
-    protected function _set_init_properties()
32
-    {
33
-        $this->label = esc_html__('Extensions & Services', 'event_espresso');
34
-    }
31
+	protected function _set_init_properties()
32
+	{
33
+		$this->label = esc_html__('Extensions & Services', 'event_espresso');
34
+	}
35 35
 
36 36
 
37
-    public function getMenuProperties(): array
38
-    {
39
-        return [
40
-            'menu_type'               => AdminMenuItem::TYPE_MENU_SUB_ITEM,
41
-            'menu_group'              => 'extras',
42
-            'menu_order'              => 30,
43
-            'show_on_menu'            => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK,
44
-            'parent_slug'             => 'espresso_events',
45
-            'menu_slug'               => EE_OTHER_SERVICES_PG_SLUG,
46
-            'menu_label'              => esc_html__('Extensions & Services', 'event_espresso'),
47
-            'capability'              => 'ee_read_ee',
48
-            'maintenance_mode_parent' => 'espresso_maintenance_settings',
49
-        ];
50
-    }
37
+	public function getMenuProperties(): array
38
+	{
39
+		return [
40
+			'menu_type'               => AdminMenuItem::TYPE_MENU_SUB_ITEM,
41
+			'menu_group'              => 'extras',
42
+			'menu_order'              => 30,
43
+			'show_on_menu'            => AdminMenuItem::DISPLAY_BLOG_AND_NETWORK,
44
+			'parent_slug'             => 'espresso_events',
45
+			'menu_slug'               => EE_OTHER_SERVICES_PG_SLUG,
46
+			'menu_label'              => esc_html__('Extensions & Services', 'event_espresso'),
47
+			'capability'              => 'ee_read_ee',
48
+			'maintenance_mode_parent' => 'espresso_maintenance_settings',
49
+		];
50
+	}
51 51
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -17,12 +17,12 @@
 block discarded – undo
17 17
     public function __construct()
18 18
     {
19 19
         // define some help/support page related constants
20
-        if (! defined('EE_OTHER_SERVICES_PG_SLUG')) {
20
+        if ( ! defined('EE_OTHER_SERVICES_PG_SLUG')) {
21 21
             define('EE_OTHER_SERVICES_PG_SLUG', 'espresso_packages');
22
-            define('EE_OTHER_SERVICES_ADMIN_URL', admin_url('admin.php?page=' . EE_OTHER_SERVICES_PG_SLUG));
23
-            define('EE_OTHER_SERVICES_ADMIN_TEMPLATE_PATH', EE_ADMIN_PAGES . 'other_services/templates/');
24
-            define('EE_OTHER_SERVICES_ADMIN', EE_ADMIN_PAGES . 'other_services/');
25
-            define('EE_OTHER_SERVICES_ASSETS_URL', EE_ADMIN_PAGES_URL . 'other_services/assets/');
22
+            define('EE_OTHER_SERVICES_ADMIN_URL', admin_url('admin.php?page='.EE_OTHER_SERVICES_PG_SLUG));
23
+            define('EE_OTHER_SERVICES_ADMIN_TEMPLATE_PATH', EE_ADMIN_PAGES.'other_services/templates/');
24
+            define('EE_OTHER_SERVICES_ADMIN', EE_ADMIN_PAGES.'other_services/');
25
+            define('EE_OTHER_SERVICES_ASSETS_URL', EE_ADMIN_PAGES_URL.'other_services/assets/');
26 26
         }
27 27
         parent::__construct();
28 28
     }
Please login to merge, or discard this patch.
admin_pages/messages/Messages_Admin_Page_Init.core.php 2 patches
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -13,49 +13,49 @@
 block discarded – undo
13 13
  */
14 14
 class Messages_Admin_Page_Init extends EE_Admin_Page_Init
15 15
 {
16
-    /**
17
-     *constructor
18
-     *
19
-     * @Constructor
20
-     * @access public
21
-     * @return void
22
-     */
23
-    public function __construct()
24
-    {
25
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
26
-
27
-        if (! defined('EE_MSG_PG_SLUG')) {
28
-            define('EE_MSG_PG_SLUG', 'espresso_messages');
29
-            define('EE_MSG_PG_NAME', ucwords(str_replace('_', '', EE_MSG_PG_SLUG)));
30
-            define('EE_MSG_ADMIN', EE_ADMIN_PAGES . 'messages/');
31
-            define('EE_MSG_ADMIN_URL', admin_url('admin.php?page=' . EE_MSG_PG_SLUG));
32
-            define('EE_MSG_ASSETS_PATH', EE_MSG_ADMIN . 'assets/');
33
-            define('EE_MSG_ASSETS_URL', EE_ADMIN_PAGES_URL . 'messages/assets/');
34
-            define('EE_MSG_TEMPLATE_PATH', EE_MSG_ADMIN . 'templates/');
35
-            define('EE_MSG_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'messages/templates/');
36
-        }
37
-
38
-        parent::__construct();
39
-    }
40
-
41
-
42
-    protected function _set_init_properties()
43
-    {
44
-        $this->label = esc_html__('Messages System', 'event_espresso');
45
-    }
46
-
47
-
48
-    public function getMenuProperties(): array
49
-    {
50
-        return [
51
-            'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
52
-            'menu_group'      => 'management',
53
-            'menu_order'      => 10,
54
-            'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
55
-            'parent_slug'     => 'espresso_events',
56
-            'menu_slug'       => EE_MSG_PG_SLUG,
57
-            'menu_label'      => esc_html__('Messages', 'event_espresso'),
58
-            'capability'      => 'ee_read_global_messages',
59
-        ];
60
-    }
16
+	/**
17
+	 *constructor
18
+	 *
19
+	 * @Constructor
20
+	 * @access public
21
+	 * @return void
22
+	 */
23
+	public function __construct()
24
+	{
25
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
26
+
27
+		if (! defined('EE_MSG_PG_SLUG')) {
28
+			define('EE_MSG_PG_SLUG', 'espresso_messages');
29
+			define('EE_MSG_PG_NAME', ucwords(str_replace('_', '', EE_MSG_PG_SLUG)));
30
+			define('EE_MSG_ADMIN', EE_ADMIN_PAGES . 'messages/');
31
+			define('EE_MSG_ADMIN_URL', admin_url('admin.php?page=' . EE_MSG_PG_SLUG));
32
+			define('EE_MSG_ASSETS_PATH', EE_MSG_ADMIN . 'assets/');
33
+			define('EE_MSG_ASSETS_URL', EE_ADMIN_PAGES_URL . 'messages/assets/');
34
+			define('EE_MSG_TEMPLATE_PATH', EE_MSG_ADMIN . 'templates/');
35
+			define('EE_MSG_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'messages/templates/');
36
+		}
37
+
38
+		parent::__construct();
39
+	}
40
+
41
+
42
+	protected function _set_init_properties()
43
+	{
44
+		$this->label = esc_html__('Messages System', 'event_espresso');
45
+	}
46
+
47
+
48
+	public function getMenuProperties(): array
49
+	{
50
+		return [
51
+			'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
52
+			'menu_group'      => 'management',
53
+			'menu_order'      => 10,
54
+			'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
55
+			'parent_slug'     => 'espresso_events',
56
+			'menu_slug'       => EE_MSG_PG_SLUG,
57
+			'menu_label'      => esc_html__('Messages', 'event_espresso'),
58
+			'capability'      => 'ee_read_global_messages',
59
+		];
60
+	}
61 61
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -24,15 +24,15 @@
 block discarded – undo
24 24
     {
25 25
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
26 26
 
27
-        if (! defined('EE_MSG_PG_SLUG')) {
27
+        if ( ! defined('EE_MSG_PG_SLUG')) {
28 28
             define('EE_MSG_PG_SLUG', 'espresso_messages');
29 29
             define('EE_MSG_PG_NAME', ucwords(str_replace('_', '', EE_MSG_PG_SLUG)));
30
-            define('EE_MSG_ADMIN', EE_ADMIN_PAGES . 'messages/');
31
-            define('EE_MSG_ADMIN_URL', admin_url('admin.php?page=' . EE_MSG_PG_SLUG));
32
-            define('EE_MSG_ASSETS_PATH', EE_MSG_ADMIN . 'assets/');
33
-            define('EE_MSG_ASSETS_URL', EE_ADMIN_PAGES_URL . 'messages/assets/');
34
-            define('EE_MSG_TEMPLATE_PATH', EE_MSG_ADMIN . 'templates/');
35
-            define('EE_MSG_TEMPLATE_URL', EE_ADMIN_PAGES_URL . 'messages/templates/');
30
+            define('EE_MSG_ADMIN', EE_ADMIN_PAGES.'messages/');
31
+            define('EE_MSG_ADMIN_URL', admin_url('admin.php?page='.EE_MSG_PG_SLUG));
32
+            define('EE_MSG_ASSETS_PATH', EE_MSG_ADMIN.'assets/');
33
+            define('EE_MSG_ASSETS_URL', EE_ADMIN_PAGES_URL.'messages/assets/');
34
+            define('EE_MSG_TEMPLATE_PATH', EE_MSG_ADMIN.'templates/');
35
+            define('EE_MSG_TEMPLATE_URL', EE_ADMIN_PAGES_URL.'messages/templates/');
36 36
         }
37 37
 
38 38
         parent::__construct();
Please login to merge, or discard this patch.
admin_pages/general_settings/General_Settings_Admin_Page_Init.core.php 2 patches
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -17,38 +17,38 @@
 block discarded – undo
17 17
  */
18 18
 class General_Settings_Admin_Page_Init extends EE_Admin_Page_Init
19 19
 {
20
-    public function __construct()
21
-    {
22
-        // define some constants
23
-        if (! defined('GEN_SET_PG_SLUG')) {
24
-            define('GEN_SET_PG_SLUG', 'espresso_general_settings');
25
-            define('GEN_SET_LABEL', esc_html__('General Settings', 'event_espresso'));
26
-            define('GEN_SET_ADMIN', EE_ADMIN_PAGES . 'general_settings/');
27
-            define('GEN_SET_ADMIN_URL', admin_url('admin.php?page=' . GEN_SET_PG_SLUG));
28
-            define('GEN_SET_TEMPLATE_PATH', GEN_SET_ADMIN . 'templates/');
29
-            define('GEN_SET_ASSETS_URL', EE_ADMIN_PAGES_URL . 'general_settings/assets/');
30
-        }
31
-        parent::__construct();
32
-    }
20
+	public function __construct()
21
+	{
22
+		// define some constants
23
+		if (! defined('GEN_SET_PG_SLUG')) {
24
+			define('GEN_SET_PG_SLUG', 'espresso_general_settings');
25
+			define('GEN_SET_LABEL', esc_html__('General Settings', 'event_espresso'));
26
+			define('GEN_SET_ADMIN', EE_ADMIN_PAGES . 'general_settings/');
27
+			define('GEN_SET_ADMIN_URL', admin_url('admin.php?page=' . GEN_SET_PG_SLUG));
28
+			define('GEN_SET_TEMPLATE_PATH', GEN_SET_ADMIN . 'templates/');
29
+			define('GEN_SET_ASSETS_URL', EE_ADMIN_PAGES_URL . 'general_settings/assets/');
30
+		}
31
+		parent::__construct();
32
+	}
33 33
 
34 34
 
35
-    protected function _set_init_properties()
36
-    {
37
-        $this->label = GEN_SET_LABEL;
38
-    }
35
+	protected function _set_init_properties()
36
+	{
37
+		$this->label = GEN_SET_LABEL;
38
+	}
39 39
 
40 40
 
41
-    public function getMenuProperties(): array
42
-    {
43
-        return [
44
-            'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
45
-            'menu_group'      => 'settings',
46
-            'menu_order'      => 20,
47
-            'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
48
-            'parent_slug'     => 'espresso_events',
49
-            'menu_slug'       => GEN_SET_PG_SLUG,
50
-            'menu_label'      => GEN_SET_LABEL,
51
-            'capability'      => 'manage_options',
52
-        ];
53
-    }
41
+	public function getMenuProperties(): array
42
+	{
43
+		return [
44
+			'menu_type'       => AdminMenuItem::TYPE_MENU_SUB_ITEM,
45
+			'menu_group'      => 'settings',
46
+			'menu_order'      => 20,
47
+			'show_on_menu'    => AdminMenuItem::DISPLAY_BLOG_ONLY,
48
+			'parent_slug'     => 'espresso_events',
49
+			'menu_slug'       => GEN_SET_PG_SLUG,
50
+			'menu_label'      => GEN_SET_LABEL,
51
+			'capability'      => 'manage_options',
52
+		];
53
+	}
54 54
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -20,13 +20,13 @@
 block discarded – undo
20 20
     public function __construct()
21 21
     {
22 22
         // define some constants
23
-        if (! defined('GEN_SET_PG_SLUG')) {
23
+        if ( ! defined('GEN_SET_PG_SLUG')) {
24 24
             define('GEN_SET_PG_SLUG', 'espresso_general_settings');
25 25
             define('GEN_SET_LABEL', esc_html__('General Settings', 'event_espresso'));
26
-            define('GEN_SET_ADMIN', EE_ADMIN_PAGES . 'general_settings/');
27
-            define('GEN_SET_ADMIN_URL', admin_url('admin.php?page=' . GEN_SET_PG_SLUG));
28
-            define('GEN_SET_TEMPLATE_PATH', GEN_SET_ADMIN . 'templates/');
29
-            define('GEN_SET_ASSETS_URL', EE_ADMIN_PAGES_URL . 'general_settings/assets/');
26
+            define('GEN_SET_ADMIN', EE_ADMIN_PAGES.'general_settings/');
27
+            define('GEN_SET_ADMIN_URL', admin_url('admin.php?page='.GEN_SET_PG_SLUG));
28
+            define('GEN_SET_TEMPLATE_PATH', GEN_SET_ADMIN.'templates/');
29
+            define('GEN_SET_ASSETS_URL', EE_ADMIN_PAGES_URL.'general_settings/assets/');
30 30
         }
31 31
         parent::__construct();
32 32
     }
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +2518 added lines, -2518 removed lines patch added patch discarded remove patch
@@ -13,2522 +13,2522 @@
 block discarded – undo
13 13
  */
14 14
 class Transactions_Admin_Page extends EE_Admin_Page
15 15
 {
16
-    /**
17
-     * @var EE_Transaction
18
-     */
19
-    private $_transaction;
20
-
21
-    /**
22
-     * @var EE_Session
23
-     */
24
-    private $_session;
25
-
26
-    /**
27
-     * @var array $_txn_status
28
-     */
29
-    private static $_txn_status;
30
-
31
-    /**
32
-     * @var array $_pay_status
33
-     */
34
-    private static $_pay_status;
35
-
36
-    /**
37
-     * @var array $_existing_reg_payment_REG_IDs
38
-     */
39
-    protected $_existing_reg_payment_REG_IDs;
40
-
41
-
42
-    /**
43
-     *    _init_page_props
44
-     *
45
-     * @return void
46
-     */
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug        = TXN_PG_SLUG;
50
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
51
-        $this->_admin_base_url  = TXN_ADMIN_URL;
52
-        $this->_admin_base_path = TXN_ADMIN;
53
-    }
54
-
55
-
56
-    /**
57
-     *    _ajax_hooks
58
-     *
59
-     * @return void
60
-     */
61
-    protected function _ajax_hooks()
62
-    {
63
-        // add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
64
-        // add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
65
-        // add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
66
-    }
67
-
68
-
69
-    /**
70
-     *    _define_page_props
71
-     *
72
-     * @return void
73
-     */
74
-    protected function _define_page_props()
75
-    {
76
-        $this->_admin_page_title = $this->page_label;
77
-        $this->_labels           = [
78
-            'buttons' => [
79
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
-            ],
83
-        ];
84
-    }
85
-
86
-
87
-    /**
88
-     *        grab url requests and route them
89
-     *
90
-     * @access private
91
-     * @return void
92
-     * @throws EE_Error
93
-     * @throws InvalidArgumentException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidInterfaceException
96
-     */
97
-    public function _set_page_routes()
98
-    {
99
-
100
-        $this->_set_transaction_status_array();
101
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
102
-
103
-        $this->_page_routes = [
104
-
105
-            'default' => [
106
-                'func'       => '_transactions_overview_list_table',
107
-                'capability' => 'ee_read_transactions',
108
-            ],
109
-
110
-            'view_transaction' => [
111
-                'func'       => '_transaction_details',
112
-                'capability' => 'ee_read_transaction',
113
-                'obj_id'     => $TXN_ID,
114
-            ],
115
-
116
-            'send_payment_reminder' => [
117
-                'func'       => '_send_payment_reminder',
118
-                'noheader'   => true,
119
-                'capability' => 'ee_send_message',
120
-            ],
121
-
122
-            'espresso_apply_payment' => [
123
-                'func'       => 'apply_payments_or_refunds',
124
-                'noheader'   => true,
125
-                'capability' => 'ee_edit_payments',
126
-            ],
127
-
128
-            'espresso_apply_refund' => [
129
-                'func'       => 'apply_payments_or_refunds',
130
-                'noheader'   => true,
131
-                'capability' => 'ee_edit_payments',
132
-            ],
133
-
134
-            'espresso_delete_payment' => [
135
-                'func'       => [$this, 'delete_payment'],
136
-                'noheader'   => true,
137
-                'capability' => 'ee_delete_payments',
138
-            ],
139
-
140
-            'espresso_recalculate_line_items' => [
141
-                'func'       => 'recalculateLineItems',
142
-                'noheader'   => true,
143
-                'capability' => 'ee_edit_payments',
144
-            ],
145
-
146
-        ];
147
-    }
148
-
149
-
150
-    protected function _set_page_config()
151
-    {
152
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
153
-        $this->_page_config = [
154
-            'default'          => [
155
-                'nav'           => [
156
-                    'label' => esc_html__('Overview', 'event_espresso'),
157
-                    'icon' => 'dashicons-list-view',
158
-                    'order' => 10,
159
-                ],
160
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
161
-                'help_tabs'     => [
162
-                    'transactions_overview_help_tab'                       => [
163
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
164
-                        'filename' => 'transactions_overview',
165
-                    ],
166
-                    'transactions_overview_table_column_headings_help_tab' => [
167
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
168
-                        'filename' => 'transactions_overview_table_column_headings',
169
-                    ],
170
-                    'transactions_overview_views_filters_help_tab'         => [
171
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
172
-                        'filename' => 'transactions_overview_views_filters_search',
173
-                    ],
174
-                ],
175
-                'require_nonce' => false,
176
-            ],
177
-            'view_transaction' => [
178
-                'nav'       => [
179
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
180
-                    'icon' => 'dashicons-cart',
181
-                    'order'      => 5,
182
-                    'url'        => $TXN_ID
183
-                        ? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
184
-                        : $this->_admin_base_url,
185
-                    'persistent' => false,
186
-                ],
187
-                'help_tabs' => [
188
-                    'transactions_view_transaction_help_tab'                                              => [
189
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
190
-                        'filename' => 'transactions_view_transaction',
191
-                    ],
192
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => [
193
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
194
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
195
-                    ],
196
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => [
197
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
198
-                        'filename' => 'transactions_view_transaction_attendees_registered',
199
-                    ],
200
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
201
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
202
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
203
-                    ],
204
-                ],
205
-                'qtips'     => ['Transaction_Details_Tips'],
206
-                'metaboxes' => ['_transaction_details_metaboxes'],
207
-
208
-                'require_nonce' => false,
209
-            ],
210
-        ];
211
-    }
212
-
213
-
214
-    /**
215
-     * The below methods aren't used by this class currently
216
-     */
217
-    protected function _add_screen_options()
218
-    {
219
-        // noop
220
-    }
221
-
222
-
223
-    protected function _add_feature_pointers()
224
-    {
225
-        // noop
226
-    }
227
-
228
-
229
-    public function admin_init()
230
-    {
231
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
232
-        $event_name = $this->request->getRequestParam('event_name');
233
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
234
-        // IF a registration was JUST added via the admin...
235
-        if ($EVT_ID && $event_name && $redirect_from) {
236
-            // then set a cookie so that we can block any attempts to use
237
-            // the back button as a way to enter another registration.
238
-            setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
239
-            // and update the global
240
-            $_COOKIE['ee_registration_added'] = $EVT_ID;
241
-        }
242
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
243
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
244
-            'event_espresso'
245
-        );
246
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
247
-            'An error occurred! Please refresh the page and try again.',
248
-            'event_espresso'
249
-        );
250
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
251
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
252
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
253
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
254
-            'This transaction has been overpaid ! Payments Total',
255
-            'event_espresso'
256
-        );
257
-    }
258
-
259
-
260
-    public function admin_notices()
261
-    {
262
-        // noop
263
-    }
264
-
265
-
266
-    public function admin_footer_scripts()
267
-    {
268
-        // noop
269
-    }
270
-
271
-
272
-    /**
273
-     * _set_transaction_status_array
274
-     * sets list of transaction statuses
275
-     *
276
-     * @access private
277
-     * @return void
278
-     * @throws EE_Error
279
-     * @throws InvalidArgumentException
280
-     * @throws InvalidDataTypeException
281
-     * @throws InvalidInterfaceException
282
-     */
283
-    private function _set_transaction_status_array()
284
-    {
285
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
286
-    }
287
-
288
-
289
-    /**
290
-     * get_transaction_status_array
291
-     * return the transaction status array for wp_list_table
292
-     *
293
-     * @access public
294
-     * @return array
295
-     */
296
-    public function get_transaction_status_array()
297
-    {
298
-        return self::$_txn_status;
299
-    }
300
-
301
-
302
-    /**
303
-     *    get list of payment statuses
304
-     *
305
-     * @access private
306
-     * @return void
307
-     * @throws EE_Error
308
-     * @throws InvalidArgumentException
309
-     * @throws InvalidDataTypeException
310
-     * @throws InvalidInterfaceException
311
-     */
312
-    private function _get_payment_status_array()
313
-    {
314
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
315
-        $this->_template_args['payment_status'] = self::$_pay_status;
316
-    }
317
-
318
-
319
-    /**
320
-     *    _add_screen_options_default
321
-     *
322
-     * @access protected
323
-     * @return void
324
-     * @throws InvalidArgumentException
325
-     * @throws InvalidDataTypeException
326
-     * @throws InvalidInterfaceException
327
-     */
328
-    protected function _add_screen_options_default()
329
-    {
330
-        $this->_per_page_screen_option();
331
-    }
332
-
333
-
334
-    /**
335
-     * load_scripts_styles
336
-     *
337
-     * @access public
338
-     * @return void
339
-     */
340
-    public function load_scripts_styles()
341
-    {
342
-        // enqueue style
343
-        wp_register_style(
344
-            'espresso_txn',
345
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
346
-            [],
347
-            EVENT_ESPRESSO_VERSION
348
-        );
349
-        wp_enqueue_style('espresso_txn');
350
-        // scripts
351
-        wp_register_script(
352
-            'espresso_txn',
353
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
354
-            [
355
-                'ee_admin_js',
356
-                'ee-datepicker',
357
-                'jquery-ui-datepicker',
358
-                'jquery-ui-draggable',
359
-                'ee-dialog',
360
-                'ee-accounting',
361
-                'ee-serialize-full-array',
362
-            ],
363
-            EVENT_ESPRESSO_VERSION,
364
-            true
365
-        );
366
-        wp_enqueue_script('espresso_txn');
367
-    }
368
-
369
-
370
-    /**
371
-     *    load_scripts_styles_view_transaction
372
-     *
373
-     * @access public
374
-     * @return void
375
-     */
376
-    public function load_scripts_styles_view_transaction()
377
-    {
378
-        // styles
379
-        wp_enqueue_style('espresso-ui-theme');
380
-    }
381
-
382
-
383
-    /**
384
-     *    load_scripts_styles_default
385
-     *
386
-     * @access public
387
-     * @return void
388
-     */
389
-    public function load_scripts_styles_default()
390
-    {
391
-        // styles
392
-        wp_enqueue_style('espresso-ui-theme');
393
-    }
394
-
395
-
396
-    /**
397
-     *    _set_list_table_views_default
398
-     *
399
-     * @access protected
400
-     * @return void
401
-     */
402
-    protected function _set_list_table_views_default()
403
-    {
404
-        $this->_views = [
405
-            'all'        => [
406
-                'slug'  => 'all',
407
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
408
-                'count' => 0,
409
-            ],
410
-            'abandoned'  => [
411
-                'slug'  => 'abandoned',
412
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
413
-                'count' => 0,
414
-            ],
415
-            'incomplete' => [
416
-                'slug'  => 'incomplete',
417
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
418
-                'count' => 0,
419
-            ],
420
-        ];
421
-        if (
422
-            /**
423
-             * Filters whether a link to the "Failed Transactions" list table
424
-             * appears on the Transactions Admin Page list table.
425
-             * List display can be turned back on via the following:
426
-             * add_filter(
427
-             *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
428
-             *     '__return_true'
429
-             * );
430
-             *
431
-             * @param boolean                 $display_failed_txns_list
432
-             * @param Transactions_Admin_Page $this
433
-             * @since 4.9.70.p
434
-             */
435
-            apply_filters(
436
-                'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
437
-                false,
438
-                $this
439
-            )
440
-        ) {
441
-            $this->_views['failed'] = [
442
-                'slug'  => 'failed',
443
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
444
-                'count' => 0,
445
-            ];
446
-        }
447
-    }
448
-
449
-
450
-    /**
451
-     * _set_transaction_object
452
-     * This sets the _transaction property for the transaction details screen
453
-     *
454
-     * @access private
455
-     * @return void
456
-     * @throws EE_Error
457
-     * @throws InvalidArgumentException
458
-     * @throws RuntimeException
459
-     * @throws InvalidDataTypeException
460
-     * @throws InvalidInterfaceException
461
-     * @throws ReflectionException
462
-     */
463
-    private function _set_transaction_object()
464
-    {
465
-        if ($this->_transaction instanceof EE_Transaction) {
466
-            return;
467
-        } //get out we've already set the object
468
-
469
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
470
-
471
-        // get transaction object
472
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
473
-        $this->_session     = $this->_transaction instanceof EE_Transaction
474
-            ? $this->_transaction->session_data()
475
-            : null;
476
-        if ($this->_transaction instanceof EE_Transaction) {
477
-            $this->_transaction->verify_abandoned_transaction_status();
478
-        }
479
-
480
-        if (! $this->_transaction instanceof EE_Transaction) {
481
-            $error_msg = sprintf(
482
-                esc_html__(
483
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
484
-                    'event_espresso'
485
-                ),
486
-                $TXN_ID
487
-            );
488
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
489
-        }
490
-    }
491
-
492
-
493
-    /**
494
-     *    _transaction_legend_items
495
-     *
496
-     * @access protected
497
-     * @return array
498
-     * @throws EE_Error
499
-     * @throws InvalidArgumentException
500
-     * @throws ReflectionException
501
-     * @throws InvalidDataTypeException
502
-     * @throws InvalidInterfaceException
503
-     */
504
-    protected function _transaction_legend_items()
505
-    {
506
-        EE_Registry::instance()->load_helper('MSG_Template');
507
-        $items = [];
508
-
509
-        if (
510
-            EE_Registry::instance()->CAP->current_user_can(
511
-                'ee_read_global_messages',
512
-                'view_filtered_messages'
513
-            )
514
-        ) {
515
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
516
-            if (
517
-                is_array($related_for_icon)
518
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
519
-            ) {
520
-                $items['view_related_messages'] = [
521
-                    'class' => $related_for_icon['css_class'],
522
-                    'desc'  => $related_for_icon['label'],
523
-                ];
524
-            }
525
-        }
526
-
527
-        $items = apply_filters(
528
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
529
-            array_merge(
530
-                $items,
531
-                [
532
-                    'view_details'          => [
533
-                        'class' => 'dashicons dashicons-cart',
534
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
535
-                    ],
536
-                    'view_invoice'          => [
537
-                        'class' => 'dashicons dashicons-media-spreadsheet',
538
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
539
-                    ],
540
-                    'view_receipt'          => [
541
-                        'class' => 'dashicons dashicons-text-page',
542
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
543
-                    ],
544
-                    'view_registration'     => [
545
-                        'class' => 'dashicons dashicons-clipboard',
546
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
547
-                    ],
548
-                    'payment_overview_link' => [
549
-                        'class' => 'dashicons dashicons-money',
550
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
551
-                    ],
552
-                ]
553
-            )
554
-        );
555
-
556
-        if (
557
-            EEH_MSG_Template::is_mt_active('payment_reminder')
558
-            && EE_Registry::instance()->CAP->current_user_can(
559
-                'ee_send_message',
560
-                'espresso_transactions_send_payment_reminder'
561
-            )
562
-        ) {
563
-            $items['send_payment_reminder'] = [
564
-                'class' => 'dashicons dashicons-email-alt',
565
-                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
566
-            ];
567
-        } else {
568
-            $items['blank*'] = [
569
-                'class' => '',
570
-                'desc'  => '',
571
-            ];
572
-        }
573
-        $more_items = apply_filters(
574
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
575
-            [
576
-                'overpaid'   => [
577
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
578
-                    'desc'  => EEH_Template::pretty_status(
579
-                        EEM_Transaction::overpaid_status_code,
580
-                        false,
581
-                        'sentence'
582
-                    ),
583
-                ],
584
-                'complete'   => [
585
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
586
-                    'desc'  => EEH_Template::pretty_status(
587
-                        EEM_Transaction::complete_status_code,
588
-                        false,
589
-                        'sentence'
590
-                    ),
591
-                ],
592
-                'incomplete' => [
593
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
594
-                    'desc'  => EEH_Template::pretty_status(
595
-                        EEM_Transaction::incomplete_status_code,
596
-                        false,
597
-                        'sentence'
598
-                    ),
599
-                ],
600
-                'abandoned'  => [
601
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
602
-                    'desc'  => EEH_Template::pretty_status(
603
-                        EEM_Transaction::abandoned_status_code,
604
-                        false,
605
-                        'sentence'
606
-                    ),
607
-                ],
608
-                'failed'     => [
609
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
610
-                    'desc'  => EEH_Template::pretty_status(
611
-                        EEM_Transaction::failed_status_code,
612
-                        false,
613
-                        'sentence'
614
-                    ),
615
-                ],
616
-            ]
617
-        );
618
-
619
-        return array_merge($items, $more_items);
620
-    }
621
-
622
-
623
-    /**
624
-     *    _transactions_overview_list_table
625
-     *
626
-     * @access protected
627
-     * @return void
628
-     * @throws DomainException
629
-     * @throws EE_Error
630
-     * @throws InvalidArgumentException
631
-     * @throws InvalidDataTypeException
632
-     * @throws InvalidInterfaceException
633
-     * @throws ReflectionException
634
-     */
635
-    protected function _transactions_overview_list_table()
636
-    {
637
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
638
-
639
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
640
-        $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
641
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
642
-            ? sprintf(
643
-                esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
644
-                '<h3>',
645
-                '<a href="'
646
-                . EE_Admin_Page::add_query_args_and_nonce(
647
-                    ['action' => 'edit', 'post' => $event->ID()],
648
-                    EVENTS_ADMIN_URL
649
-                )
650
-                . '" title="'
651
-                . esc_attr__('Click to Edit event', 'event_espresso')
652
-                . '">' . $event->name() . '</a>',
653
-                '</h3>'
654
-            )
655
-            : '';
656
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
657
-        $this->display_admin_list_table_page_with_no_sidebar();
658
-    }
659
-
660
-
661
-    /**
662
-     *    _transaction_details
663
-     * generates HTML for the View Transaction Details Admin page
664
-     *
665
-     * @access protected
666
-     * @return void
667
-     * @throws DomainException
668
-     * @throws EE_Error
669
-     * @throws InvalidArgumentException
670
-     * @throws InvalidDataTypeException
671
-     * @throws InvalidInterfaceException
672
-     * @throws RuntimeException
673
-     * @throws ReflectionException
674
-     */
675
-    protected function _transaction_details()
676
-    {
677
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
678
-
679
-        $this->_set_transaction_status_array();
680
-
681
-        $this->_template_args                      = [];
682
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
683
-
684
-        $this->_set_transaction_object();
685
-
686
-        if (! $this->_transaction instanceof EE_Transaction) {
687
-            return;
688
-        }
689
-
690
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
691
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
692
-
693
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
694
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
695
-
696
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
697
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
698
-        $this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
699
-
700
-        $txn_total  = $this->_transaction->total();
701
-        $total_paid = $this->_transaction->paid();
702
-        $amount_due = $txn_total - $total_paid;
703
-
704
-        $this->_template_args['grand_total'] = $txn_total;
705
-        $this->_template_args['total_paid']  = $total_paid;
706
-
707
-        $this->_template_args['amount_due'] = EEH_Template::format_currency($amount_due, false, false);
708
-
709
-        $this->_template_args['amount_due_class'] = '';
710
-
711
-        if ($txn_total === (float) 0) {
712
-            // free event
713
-            $this->_template_args['amount_due'] = false;
714
-        } elseif ($amount_due < (float) 0) {
715
-            // overpaid
716
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
717
-        } elseif ($amount_due > (float) 0) {
718
-            // monies owing
719
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
720
-        } elseif ($total_paid === (float) 0) {
721
-            // no payments made yet
722
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
723
-        }
724
-
725
-        $payment_method = $this->_transaction->payment_method();
726
-
727
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
728
-            ? $payment_method->admin_name()
729
-            : esc_html__('Unknown', 'event_espresso');
730
-
731
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
732
-        // link back to overview
733
-        $this->_template_args['txn_overview_url'] = $this->request->getServerParam(
734
-            'HTTP_REFERER',
735
-            TXN_ADMIN_URL
736
-        );
737
-
738
-
739
-        // next link
740
-        $next_txn                                 = $this->_transaction->next(
741
-            null,
742
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
743
-            'TXN_ID'
744
-        );
745
-        $this->_template_args['next_transaction'] = $next_txn
746
-            ? $this->_next_link(
747
-                EE_Admin_Page::add_query_args_and_nonce(
748
-                    ['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
749
-                    TXN_ADMIN_URL
750
-                ),
751
-                'dashicons dashicons-arrow-right ee-icon-size-22'
752
-            )
753
-            : '';
754
-        // previous link
755
-        $previous_txn                                 = $this->_transaction->previous(
756
-            null,
757
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
758
-            'TXN_ID'
759
-        );
760
-        $this->_template_args['previous_transaction'] = $previous_txn
761
-            ? $this->_previous_link(
762
-                EE_Admin_Page::add_query_args_and_nonce(
763
-                    ['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
764
-                    TXN_ADMIN_URL
765
-                ),
766
-                'dashicons dashicons-arrow-left ee-icon-size-22'
767
-            )
768
-            : '';
769
-
770
-        $EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
771
-        $event_name    = $this->request->getRequestParam('event_name');
772
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
773
-
774
-        // were we just redirected here after adding a new registration ???
775
-        if ($EVT_ID && $event_name && $redirect_from) {
776
-            if (
777
-                EE_Registry::instance()->CAP->current_user_can(
778
-                    'ee_edit_registrations',
779
-                    'espresso_registrations_new_registration',
780
-                    $EVT_ID
781
-                )
782
-            ) {
783
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
784
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
785
-                    [
786
-                        'page'     => 'espresso_registrations',
787
-                        'action'   => 'new_registration',
788
-                        'return'   => 'default',
789
-                        'TXN_ID'   => $this->_transaction->ID(),
790
-                        'event_id' => $EVT_ID,
791
-                    ],
792
-                    REG_ADMIN_URL
793
-                );
794
-                $this->_admin_page_title .= '">';
795
-
796
-                $this->_admin_page_title .= sprintf(
797
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
798
-                    htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
799
-                );
800
-                $this->_admin_page_title .= '</a>';
801
-            }
802
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
803
-        }
804
-        // grab messages at the last second
805
-        $this->_template_args['notices'] = EE_Error::get_notices();
806
-        // path to template
807
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
808
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
809
-            $template_path,
810
-            $this->_template_args,
811
-            true
812
-        );
813
-
814
-        // the details template wrapper
815
-        $this->display_admin_page_with_sidebar();
816
-    }
817
-
818
-
819
-    /**
820
-     *        _transaction_details_metaboxes
821
-     *
822
-     * @access protected
823
-     * @return void
824
-     * @throws EE_Error
825
-     * @throws InvalidArgumentException
826
-     * @throws InvalidDataTypeException
827
-     * @throws InvalidInterfaceException
828
-     * @throws RuntimeException
829
-     * @throws ReflectionException
830
-     */
831
-    protected function _transaction_details_metaboxes()
832
-    {
833
-
834
-        $this->_set_transaction_object();
835
-
836
-        if (! $this->_transaction instanceof EE_Transaction) {
837
-            return;
838
-        }
839
-        $this->addMetaBox(
840
-            'edit-txn-details-mbox',
841
-            '<span>' . esc_html__('Transaction Details', 'event_espresso')
842
-            . '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
843
-            [$this, 'txn_details_meta_box'],
844
-            $this->_wp_page_slug
845
-        );
846
-        $this->addMetaBox(
847
-            'edit-txn-attendees-mbox',
848
-            '<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
849
-            . '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
850
-            [$this, 'txn_attendees_meta_box'],
851
-            $this->_wp_page_slug,
852
-            'normal',
853
-            'high',
854
-            ['TXN_ID' => $this->_transaction->ID()]
855
-        );
856
-        $this->addMetaBox(
857
-            'edit-txn-registrant-mbox',
858
-            esc_html__('Primary Contact', 'event_espresso'),
859
-            [$this, 'txn_registrant_side_meta_box'],
860
-            $this->_wp_page_slug,
861
-            'side'
862
-        );
863
-        $this->addMetaBox(
864
-            'edit-txn-billing-info-mbox',
865
-            esc_html__('Billing Information', 'event_espresso'),
866
-            [$this, 'txn_billing_info_side_meta_box'],
867
-            $this->_wp_page_slug,
868
-            'side'
869
-        );
870
-    }
871
-
872
-
873
-    /**
874
-     * Callback for transaction actions metabox.
875
-     *
876
-     * @param EE_Transaction|null $transaction
877
-     * @return string
878
-     * @throws DomainException
879
-     * @throws EE_Error
880
-     * @throws InvalidArgumentException
881
-     * @throws InvalidDataTypeException
882
-     * @throws InvalidInterfaceException
883
-     * @throws ReflectionException
884
-     * @throws RuntimeException
885
-     */
886
-    public function getActionButtons(EE_Transaction $transaction = null)
887
-    {
888
-        $content = '';
889
-        $actions = [];
890
-        if (! $transaction instanceof EE_Transaction) {
891
-            return $content;
892
-        }
893
-        /** @var EE_Registration $primary_registration */
894
-        $primary_registration = $transaction->primary_registration();
895
-        $attendee             = $primary_registration instanceof EE_Registration
896
-            ? $primary_registration->attendee()
897
-            : null;
898
-
899
-        if (
900
-            $attendee instanceof EE_Attendee
901
-            && EE_Registry::instance()->CAP->current_user_can(
902
-                'ee_send_message',
903
-                'espresso_transactions_send_payment_reminder'
904
-            )
905
-        ) {
906
-            $actions['payment_reminder'] =
907
-                EEH_MSG_Template::is_mt_active('payment_reminder')
908
-                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
909
-                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
910
-                    ? EEH_Template::get_button_or_link(
911
-                        EE_Admin_Page::add_query_args_and_nonce(
912
-                            [
913
-                            'action'      => 'send_payment_reminder',
914
-                            'TXN_ID'      => $this->_transaction->ID(),
915
-                            'redirect_to' => 'view_transaction',
916
-                            ],
917
-                            TXN_ADMIN_URL
918
-                        ),
919
-                        esc_html__(' Send Payment Reminder', 'event_espresso'),
920
-                        'button button--secondary',
921
-                        'dashicons dashicons-email-alt'
922
-                    )
923
-                    : '';
924
-        }
925
-
926
-        if (
927
-            EE_Registry::instance()->CAP->current_user_can(
928
-                'ee_edit_payments',
929
-                'espresso_transactions_recalculate_line_items'
930
-            )
931
-        ) {
932
-            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
933
-                EE_Admin_Page::add_query_args_and_nonce(
934
-                    [
935
-                        'action'      => 'espresso_recalculate_line_items',
936
-                        'TXN_ID'      => $this->_transaction->ID(),
937
-                        'redirect_to' => 'view_transaction',
938
-                    ],
939
-                    TXN_ADMIN_URL
940
-                ),
941
-                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
942
-                'button button--secondary',
943
-                'dashicons dashicons-update'
944
-            );
945
-        }
946
-
947
-        if (
948
-            $primary_registration instanceof EE_Registration
949
-            && EEH_MSG_Template::is_mt_active('receipt')
950
-        ) {
951
-            $actions['receipt'] = EEH_Template::get_button_or_link(
952
-                $primary_registration->receipt_url(),
953
-                esc_html__('View Receipt', 'event_espresso'),
954
-                'button button--secondary',
955
-                'dashicons dashicons-text-page'
956
-            );
957
-        }
958
-
959
-        if (
960
-            $primary_registration instanceof EE_Registration
961
-            && EEH_MSG_Template::is_mt_active('invoice')
962
-        ) {
963
-            $actions['invoice'] = EEH_Template::get_button_or_link(
964
-                $primary_registration->invoice_url(),
965
-                esc_html__('View Invoice', 'event_espresso'),
966
-                'button button--secondary',
967
-                'dashicons dashicons-media-spreadsheet'
968
-            );
969
-        }
970
-        $actions = array_filter(
971
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
972
-        );
973
-        if ($actions) {
974
-            $content .= implode('', $actions);
975
-        }
976
-        return $content;
977
-    }
978
-
979
-
980
-    /**
981
-     * txn_details_meta_box
982
-     * generates HTML for the Transaction main meta box
983
-     *
984
-     * @return void
985
-     * @throws DomainException
986
-     * @throws EE_Error
987
-     * @throws InvalidArgumentException
988
-     * @throws InvalidDataTypeException
989
-     * @throws InvalidInterfaceException
990
-     * @throws RuntimeException
991
-     * @throws ReflectionException
992
-     */
993
-    public function txn_details_meta_box()
994
-    {
995
-        $this->_set_transaction_object();
996
-        $this->_template_args['TXN_ID']              = $this->_transaction->ID();
997
-        $this->_template_args['attendee']            =
998
-            $this->_transaction->primary_registration() instanceof EE_Registration
999
-                ? $this->_transaction->primary_registration()->attendee()
1000
-                : null;
1001
-        $this->_template_args['can_edit_payments']   = EE_Registry::instance()->CAP->current_user_can(
1002
-            'ee_edit_payments',
1003
-            'apply_payment_or_refund_from_registration_details'
1004
-        );
1005
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1006
-            'ee_delete_payments',
1007
-            'delete_payment_from_registration_details'
1008
-        );
1009
-
1010
-        // get line table
1011
-        EEH_Autoloader::register_line_item_display_autoloaders();
1012
-        $Line_Item_Display                       = new EE_Line_Item_Display(
1013
-            'admin_table',
1014
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1015
-        );
1016
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1017
-            $this->_transaction->total_line_item()
1018
-        );
1019
-        $this->_template_args['REG_code']        =
1020
-            $this->_transaction->primary_registration() instanceof EE_Registration
1021
-                ? $this->_transaction->primary_registration()->reg_code()
1022
-                : null;
1023
-        // process taxes
1024
-        $taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1025
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1026
-
1027
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1028
-            $this->_transaction->total(),
1029
-            false,
1030
-            false
1031
-        );
1032
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1033
-        $this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1034
-
1035
-        // process payment details
1036
-        $payments = $this->_transaction->payments();
1037
-        if (! empty($payments)) {
1038
-            $this->_template_args['payments']              = $payments;
1039
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1040
-        } else {
1041
-            $this->_template_args['payments']              = false;
1042
-            $this->_template_args['existing_reg_payments'] = [];
1043
-        }
1044
-
1045
-        $this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1046
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1047
-            ['action' => 'espresso_delete_payment'],
1048
-            TXN_ADMIN_URL
1049
-        );
1050
-
1051
-        if (isset($txn_details['invoice_number'])) {
1052
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1053
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1054
-                'Invoice Number',
1055
-                'event_espresso'
1056
-            );
1057
-        }
1058
-
1059
-        $this->_template_args['txn_details']['registration_session']['value'] =
1060
-            $this->_transaction->primary_registration() instanceof EE_Registration
1061
-                ? $this->_transaction->primary_registration()->session_ID()
1062
-                : null;
1063
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1064
-            'Registration Session',
1065
-            'event_espresso'
1066
-        );
1067
-
1068
-        $this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1069
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1070
-            'Transaction placed from IP',
1071
-            'event_espresso'
1072
-        );
1073
-
1074
-        $this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1075
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1076
-            'Registrant User Agent',
1077
-            'event_espresso'
1078
-        );
1079
-
1080
-        $reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1081
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1082
-            if ($reg_step_status === true) {
1083
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1084
-                              . sprintf(
1085
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1086
-                                  ucwords(str_replace('_', ' ', $reg_step))
1087
-                              )
1088
-                              . '</div>';
1089
-            } elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1090
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1091
-                              . sprintf(
1092
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1093
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1094
-                                  date(
1095
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1096
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1097
-                                  )
1098
-                              )
1099
-                              . '</div>';
1100
-            } else {
1101
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1102
-                              . sprintf(
1103
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1104
-                                  ucwords(str_replace('_', ' ', $reg_step))
1105
-                              )
1106
-                              . '</div>';
1107
-            }
1108
-        }
1109
-        $reg_steps                                                 .= '</ul>';
1110
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1111
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1112
-            'Registration Step Progress',
1113
-            'event_espresso'
1114
-        );
1115
-
1116
-
1117
-        $this->_get_registrations_to_apply_payment_to();
1118
-        $this->_get_payment_methods($payments);
1119
-        $this->_get_payment_status_array();
1120
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1121
-
1122
-        $this->_template_args['transaction_form_url']    = add_query_arg(
1123
-            [
1124
-                'action'  => 'edit_transaction',
1125
-                'process' => 'transaction',
1126
-            ],
1127
-            TXN_ADMIN_URL
1128
-        );
1129
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(
1130
-            [
1131
-                'page'   => 'espresso_transactions',
1132
-                'action' => 'espresso_apply_payment',
1133
-            ],
1134
-            TXN_ADMIN_URL
1135
-        );
1136
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1137
-            [
1138
-                'page'   => 'espresso_transactions',
1139
-                'action' => 'espresso_delete_payment',
1140
-            ],
1141
-            TXN_ADMIN_URL
1142
-        );
1143
-
1144
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1145
-
1146
-        // 'espresso_delete_payment_nonce'
1147
-
1148
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1149
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1150
-    }
1151
-
1152
-
1153
-    /**
1154
-     * _get_registration_payment_IDs
1155
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1156
-     *
1157
-     * @access protected
1158
-     * @param EE_Payment[] $payments
1159
-     * @return array
1160
-     * @throws EE_Error
1161
-     * @throws InvalidArgumentException
1162
-     * @throws InvalidDataTypeException
1163
-     * @throws InvalidInterfaceException
1164
-     * @throws ReflectionException
1165
-     */
1166
-    protected function _get_registration_payment_IDs($payments = [])
1167
-    {
1168
-        $existing_reg_payments = [];
1169
-        // get all reg payments for these payments
1170
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1171
-            [
1172
-                [
1173
-                    'PAY_ID' => [
1174
-                        'IN',
1175
-                        array_keys($payments),
1176
-                    ],
1177
-                ],
1178
-            ]
1179
-        );
1180
-        if (! empty($reg_payments)) {
1181
-            foreach ($payments as $payment) {
1182
-                if (! $payment instanceof EE_Payment) {
1183
-                    continue;
1184
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1185
-                    $existing_reg_payments[ $payment->ID() ] = [];
1186
-                }
1187
-                foreach ($reg_payments as $reg_payment) {
1188
-                    if (
1189
-                        $reg_payment instanceof EE_Registration_Payment
1190
-                        && $reg_payment->payment_ID() === $payment->ID()
1191
-                    ) {
1192
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1193
-                    }
1194
-                }
1195
-            }
1196
-        }
1197
-
1198
-        return $existing_reg_payments;
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * _get_registrations_to_apply_payment_to
1204
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1205
-     * which allows the admin to only apply the payment to the specific registrations
1206
-     *
1207
-     * @access protected
1208
-     * @return void
1209
-     * @throws EE_Error
1210
-     * @throws InvalidArgumentException
1211
-     * @throws InvalidDataTypeException
1212
-     * @throws InvalidInterfaceException
1213
-     * @throws ReflectionException
1214
-     */
1215
-    protected function _get_registrations_to_apply_payment_to()
1216
-    {
1217
-        // we want any registration with an active status (ie: not deleted or cancelled)
1218
-        $query_params                      = [
1219
-            [
1220
-                'STS_ID' => [
1221
-                    'IN',
1222
-                    [
1223
-                        EEM_Registration::status_id_approved,
1224
-                        EEM_Registration::status_id_pending_payment,
1225
-                        EEM_Registration::status_id_not_approved,
1226
-                    ],
1227
-                ],
1228
-            ],
1229
-        ];
1230
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1231
-            '',
1232
-            'txn-admin-apply-payment-to-registrations-dv',
1233
-            '',
1234
-            'clear: both; margin: 1.5em 0 0; display: none;'
1235
-        );
1236
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1237
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1238
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1239
-            EEH_HTML::tr(
1240
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1241
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1242
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1243
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1244
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1245
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1246
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1247
-            )
1248
-        );
1249
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1250
-        // get registrations for TXN
1251
-        $registrations         = $this->_transaction->registrations($query_params);
1252
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1253
-        foreach ($registrations as $registration) {
1254
-            if ($registration instanceof EE_Registration) {
1255
-                $attendee_name                     = $registration->attendee() instanceof EE_Attendee
1256
-                    ? $registration->attendee()->full_name()
1257
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1258
-                $owing                             = $registration->final_price() - $registration->paid();
1259
-                $taxable                           = $registration->ticket()->taxable()
1260
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1261
-                    : '';
1262
-                $checked                           = empty($existing_reg_payments)
1263
-                                                     || in_array($registration->ID(), $existing_reg_payments, true)
1264
-                    ? ' checked'
1265
-                    : '';
1266
-                $disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1267
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1268
-                    EEH_HTML::td($registration->ID()) .
1269
-                    EEH_HTML::td($attendee_name) .
1270
-                    EEH_HTML::td(
1271
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1272
-                    ) .
1273
-                    EEH_HTML::td($registration->event_name()) .
1274
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1275
-                    EEH_HTML::td(
1276
-                        EEH_Template::format_currency($owing),
1277
-                        '',
1278
-                        'txn-admin-payment-owing-td jst-cntr'
1279
-                    ) .
1280
-                    EEH_HTML::td(
1281
-                        '<input type="checkbox" value="' . $registration->ID()
1282
-                        . '" name="txn_admin_payment[registrations]"'
1283
-                        . $checked . $disabled . '>',
1284
-                        '',
1285
-                        'jst-cntr'
1286
-                    ),
1287
-                    'apply-payment-registration-row-' . $registration->ID()
1288
-                );
1289
-            }
1290
-        }
1291
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1292
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1293
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1294
-        $registrations_to_apply_payment_to                         .= EEH_HTML::p(
1295
-            esc_html__(
1296
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1297
-                'event_espresso'
1298
-            ),
1299
-            '',
1300
-            'clear description'
1301
-        );
1302
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1303
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1304
-    }
1305
-
1306
-
1307
-    /**
1308
-     * _get_reg_status_selection
1309
-     *
1310
-     * @return void
1311
-     * @throws EE_Error
1312
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1313
-     *         instead of events.
1314
-     * @access protected
1315
-     */
1316
-    protected function _get_reg_status_selection()
1317
-    {
1318
-        // first get all possible statuses
1319
-        $statuses = EEM_Registration::reg_status_array([], true);
1320
-        // let's add a "don't change" option.
1321
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1322
-        $status_array                                        = array_merge($status_array, $statuses);
1323
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1324
-            'txn_reg_status_change[reg_status]',
1325
-            $status_array,
1326
-            'NAN',
1327
-            'id="txn-admin-payment-reg-status-inp"',
1328
-            'txn-reg-status-change-reg-status'
1329
-        );
1330
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1331
-            'delete_txn_reg_status_change[reg_status]',
1332
-            $status_array,
1333
-            'NAN',
1334
-            'delete-txn-admin-payment-reg-status-inp',
1335
-            'delete-txn-reg-status-change-reg-status'
1336
-        );
1337
-    }
1338
-
1339
-
1340
-    /**
1341
-     *    _get_payment_methods
1342
-     * Gets all the payment methods available generally, or the ones that are already
1343
-     * selected on these payments (in case their payment methods are no longer active).
1344
-     * Has the side-effect of updating the template args' payment_methods item
1345
-     *
1346
-     * @access private
1347
-     * @param EE_Payment[] to show on this page
1348
-     * @return void
1349
-     * @throws EE_Error
1350
-     * @throws InvalidArgumentException
1351
-     * @throws InvalidDataTypeException
1352
-     * @throws InvalidInterfaceException
1353
-     * @throws ReflectionException
1354
-     */
1355
-    private function _get_payment_methods($payments = [])
1356
-    {
1357
-        $payment_methods_of_payments = [];
1358
-        foreach ($payments as $payment) {
1359
-            if ($payment instanceof EE_Payment) {
1360
-                $payment_methods_of_payments[] = $payment->ID();
1361
-            }
1362
-        }
1363
-        if ($payment_methods_of_payments) {
1364
-            $query_args = [
1365
-                [
1366
-                    'OR*payment_method_for_payment' => [
1367
-                        'PMD_ID'    => ['IN', $payment_methods_of_payments],
1368
-                        'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1369
-                    ],
1370
-                ],
1371
-            ];
1372
-        } else {
1373
-            $query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1374
-        }
1375
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1376
-    }
1377
-
1378
-
1379
-    /**
1380
-     * txn_attendees_meta_box
1381
-     *    generates HTML for the Attendees Transaction main meta box
1382
-     *
1383
-     * @access public
1384
-     * @param WP_Post $post
1385
-     * @param array   $metabox
1386
-     * @return void
1387
-     * @throws DomainException
1388
-     * @throws EE_Error
1389
-     * @throws InvalidArgumentException
1390
-     * @throws InvalidDataTypeException
1391
-     * @throws InvalidInterfaceException
1392
-     * @throws ReflectionException
1393
-     */
1394
-    public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1395
-    {
1396
-
1397
-        /** @noinspection NonSecureExtractUsageInspection */
1398
-        extract($metabox['args']);
1399
-        $this->_template_args['post']            = $post;
1400
-        $this->_template_args['event_attendees'] = [];
1401
-        // process items in cart
1402
-        $line_items = $this->_transaction->get_many_related(
1403
-            'Line_Item',
1404
-            [['LIN_type' => 'line-item']]
1405
-        );
1406
-        if (! empty($line_items)) {
1407
-            foreach ($line_items as $item) {
1408
-                if ($item instanceof EE_Line_Item) {
1409
-                    switch ($item->OBJ_type()) {
1410
-                        case 'Event':
1411
-                            break;
1412
-                        case 'Ticket':
1413
-                            $ticket = $item->ticket();
1414
-                            // right now we're only handling tickets here.
1415
-                            // Cause its expected that only tickets will have attendees right?
1416
-                            if (! $ticket instanceof EE_Ticket) {
1417
-                                break;
1418
-                            }
1419
-                            try {
1420
-                                $event_name = $ticket->get_event_name();
1421
-                            } catch (Exception $e) {
1422
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1423
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1424
-                            }
1425
-                            $event_name   .= ' - ' . $item->name();
1426
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1427
-                            // now get all of the registrations for this transaction that use this ticket
1428
-                            $registrations = $ticket->registrations(
1429
-                                [['TXN_ID' => $this->_transaction->ID()]]
1430
-                            );
1431
-                            foreach ($registrations as $registration) {
1432
-                                if (! $registration instanceof EE_Registration) {
1433
-                                    break;
1434
-                                }
1435
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1436
-                                    = $registration->status_ID();
1437
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1438
-                                    = $registration->count();
1439
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1440
-                                    = $event_name;
1441
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1442
-                                    = $ticket_price;
1443
-                                // attendee info
1444
-                                $attendee = $registration->get_first_related('Attendee');
1445
-                                if ($attendee instanceof EE_Attendee) {
1446
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1447
-                                        = $attendee->ID();
1448
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1449
-                                        = $attendee->full_name();
1450
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1451
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1452
-                                          . esc_html__(
1453
-                                              ' Event',
1454
-                                              'event_espresso'
1455
-                                          )
1456
-                                          . '">' . $attendee->email() . '</a>';
1457
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1458
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1459
-                                } else {
1460
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1461
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1462
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1463
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1464
-                                }
1465
-                            }
1466
-                            break;
1467
-                    }
1468
-                }
1469
-            }
1470
-
1471
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1472
-                [
1473
-                    'action'  => 'edit_transaction',
1474
-                    'process' => 'attendees',
1475
-                ],
1476
-                TXN_ADMIN_URL
1477
-            );
1478
-            echo EEH_Template::display_template(
1479
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1480
-                $this->_template_args,
1481
-                true
1482
-            );
1483
-        } else {
1484
-            printf(
1485
-                esc_html__(
1486
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1487
-                    'event_espresso'
1488
-                ),
1489
-                '<p class="important-notice">',
1490
-                '</p>'
1491
-            );
1492
-        }
1493
-    }
1494
-
1495
-
1496
-    /**
1497
-     * txn_registrant_side_meta_box
1498
-     * generates HTML for the Edit Transaction side meta box
1499
-     *
1500
-     * @access public
1501
-     * @return void
1502
-     * @throws DomainException
1503
-     * @throws EE_Error
1504
-     * @throws InvalidArgumentException
1505
-     * @throws InvalidDataTypeException
1506
-     * @throws InvalidInterfaceException
1507
-     * @throws ReflectionException
1508
-     */
1509
-    public function txn_registrant_side_meta_box()
1510
-    {
1511
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1512
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1513
-            : null;
1514
-        if (! $primary_att instanceof EE_Attendee) {
1515
-            $this->_template_args['no_attendee_message'] = esc_html__(
1516
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1517
-                'event_espresso'
1518
-            );
1519
-            $primary_att                           = EEM_Attendee::instance()->create_default_object();
1520
-        }
1521
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1522
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1523
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1524
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1525
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1526
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1527
-            [
1528
-                'action' => 'edit_attendee',
1529
-                'post'   => $primary_att->ID(),
1530
-            ],
1531
-            REG_ADMIN_URL
1532
-        );
1533
-        // get formatted address for registrant
1534
-        $formatted_address = EEH_Address::format($primary_att);
1535
-        $formatted_address = $formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1536
-            ? $formatted_address
1537
-            : '';
1538
-        $this->_template_args['formatted_address'] = $formatted_address;
1539
-        echo EEH_Template::display_template(
1540
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1541
-            $this->_template_args,
1542
-            true
1543
-        );
1544
-    }
1545
-
1546
-
1547
-    /**
1548
-     * txn_billing_info_side_meta_box
1549
-     *    generates HTML for the Edit Transaction side meta box
1550
-     *
1551
-     * @access public
1552
-     * @return void
1553
-     * @throws DomainException
1554
-     * @throws EE_Error
1555
-     * @throws ReflectionException
1556
-     */
1557
-    public function txn_billing_info_side_meta_box()
1558
-    {
1559
-
1560
-        $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1561
-        $this->_template_args['billing_form_url'] = add_query_arg(
1562
-            ['action' => 'edit_transaction', 'process' => 'billing'],
1563
-            TXN_ADMIN_URL
1564
-        );
1565
-
1566
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1567
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1568
-    }
1569
-
1570
-
1571
-    /**
1572
-     * apply_payments_or_refunds
1573
-     *    registers a payment or refund made towards a transaction
1574
-     *
1575
-     * @access public
1576
-     * @return void
1577
-     * @throws EE_Error
1578
-     * @throws InvalidArgumentException
1579
-     * @throws ReflectionException
1580
-     * @throws RuntimeException
1581
-     * @throws InvalidDataTypeException
1582
-     * @throws InvalidInterfaceException
1583
-     */
1584
-    public function apply_payments_or_refunds()
1585
-    {
1586
-        $valid_data         = $this->_validate_payment_request_data();
1587
-        $has_access         = EE_Registry::instance()->CAP->current_user_can(
1588
-            'ee_edit_payments',
1589
-            'apply_payment_or_refund_from_registration_details'
1590
-        );
1591
-        $TXD_ID = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1592
-        $amount = 0;
1593
-        if (! empty($valid_data) && $has_access) {
1594
-            $PAY_ID = $valid_data['PAY_ID'];
1595
-            // save  the new payment
1596
-            $payment = $this->_create_payment_from_request_data($valid_data);
1597
-            $amount = $payment->amount();
1598
-            // get the TXN for this payment
1599
-            $transaction = $payment->transaction();
1600
-            // verify transaction
1601
-            if ($transaction instanceof EE_Transaction) {
1602
-                // calculate_total_payments_and_update_status
1603
-                $this->_process_transaction_payments($transaction);
1604
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1605
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1606
-                // apply payment to registrations (if applicable)
1607
-                if (! empty($REG_IDs)) {
1608
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1609
-                    $this->_maybe_send_notifications();
1610
-                    // now process status changes for the same registrations
1611
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1612
-                }
1613
-                $this->_maybe_send_notifications($payment);
1614
-                // prepare to render page
1615
-                do_action(
1616
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1617
-                    $transaction,
1618
-                    $payment
1619
-                );
1620
-            } else {
1621
-                EE_Error::add_error(
1622
-                    esc_html__(
1623
-                        'A valid Transaction for this payment could not be retrieved.',
1624
-                        'event_espresso'
1625
-                    ),
1626
-                    __FILE__,
1627
-                    __FUNCTION__,
1628
-                    __LINE__
1629
-                );
1630
-            }
1631
-        } elseif ($has_access) {
1632
-            EE_Error::add_error(
1633
-                esc_html__(
1634
-                    'The payment form data could not be processed. Please try again.',
1635
-                    'event_espresso'
1636
-                ),
1637
-                __FILE__,
1638
-                __FUNCTION__,
1639
-                __LINE__
1640
-            );
1641
-        } else {
1642
-            EE_Error::add_error(
1643
-                esc_html__(
1644
-                    'You do not have access to apply payments or refunds to a registration.',
1645
-                    'event_espresso'
1646
-                ),
1647
-                __FILE__,
1648
-                __FUNCTION__,
1649
-                __LINE__
1650
-            );
1651
-        }
1652
-        $query_args = [
1653
-            'page' => 'espresso_transactions',
1654
-             'action' => 'view_transaction',
1655
-             'TXN_ID' => $TXD_ID
1656
-        ];
1657
-
1658
-        $this->_redirect_after_action(
1659
-            ! EE_Error::has_error(),
1660
-            $amount > 0
1661
-                ? esc_html__('payment', 'event_espresso')
1662
-                : esc_html__('refund', 'event_espresso'),
1663
-            esc_html__('processed', 'event_espresso'),
1664
-            $query_args
1665
-        );
1666
-    }
1667
-
1668
-
1669
-    /**
1670
-     * _validate_payment_request_data
1671
-     *
1672
-     * @return array
1673
-     * @throws EE_Error
1674
-     * @throws InvalidArgumentException
1675
-     * @throws InvalidDataTypeException
1676
-     * @throws InvalidInterfaceException
1677
-     */
1678
-    protected function _validate_payment_request_data()
1679
-    {
1680
-        if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1681
-            return [];
1682
-        }
1683
-        $payment_form = $this->_generate_payment_form_section();
1684
-        try {
1685
-            if ($payment_form->was_submitted()) {
1686
-                $payment_form->receive_form_submission();
1687
-                if (! $payment_form->is_valid()) {
1688
-                    $submission_error_messages = [];
1689
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1690
-                        if ($validation_error instanceof EE_Validation_Error) {
1691
-                            $form_input = $validation_error->get_form_section();
1692
-                            $submission_error_messages[] = sprintf(
1693
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1694
-                                $form_input instanceof EE_Form_Input_Base ? $form_input->html_label_text() : '',
1695
-                                $validation_error->getMessage()
1696
-                            );
1697
-                        }
1698
-                    }
1699
-                    EE_Error::add_error(
1700
-                        implode('<br />', $submission_error_messages),
1701
-                        __FILE__,
1702
-                        __FUNCTION__,
1703
-                        __LINE__
1704
-                    );
1705
-                    return [];
1706
-                }
1707
-            }
1708
-        } catch (EE_Error $e) {
1709
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1710
-            return [];
1711
-        }
1712
-
1713
-        return $payment_form->valid_data();
1714
-    }
1715
-
1716
-
1717
-    /**
1718
-     * _generate_payment_form_section
1719
-     *
1720
-     * @return EE_Form_Section_Proper
1721
-     * @throws EE_Error
1722
-     */
1723
-    protected function _generate_payment_form_section()
1724
-    {
1725
-        return new EE_Form_Section_Proper(
1726
-            [
1727
-                'name'        => 'txn_admin_payment',
1728
-                'subsections' => [
1729
-                    'PAY_ID'          => new EE_Text_Input(
1730
-                        [
1731
-                            'default'               => 0,
1732
-                            'required'              => false,
1733
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1734
-                            'validation_strategies' => [new EE_Int_Normalization()],
1735
-                        ]
1736
-                    ),
1737
-                    'TXN_ID'          => new EE_Text_Input(
1738
-                        [
1739
-                            'default'               => 0,
1740
-                            'required'              => true,
1741
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1742
-                            'validation_strategies' => [new EE_Int_Normalization()],
1743
-                        ]
1744
-                    ),
1745
-                    'type'            => new EE_Text_Input(
1746
-                        [
1747
-                            'default'               => 1,
1748
-                            'required'              => true,
1749
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1750
-                            'validation_strategies' => [new EE_Int_Normalization()],
1751
-                        ]
1752
-                    ),
1753
-                    'amount'          => new EE_Text_Input(
1754
-                        [
1755
-                            'default'               => 0,
1756
-                            'required'              => true,
1757
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1758
-                            'validation_strategies' => [new EE_Float_Normalization()],
1759
-                        ]
1760
-                    ),
1761
-                    'status'          => new EE_Text_Input(
1762
-                        [
1763
-                            'default'         => EEM_Payment::status_id_approved,
1764
-                            'required'        => true,
1765
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1766
-                        ]
1767
-                    ),
1768
-                    'PMD_ID'          => new EE_Text_Input(
1769
-                        [
1770
-                            'default'               => 2,
1771
-                            'required'              => true,
1772
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1773
-                            'validation_strategies' => [new EE_Int_Normalization()],
1774
-                        ]
1775
-                    ),
1776
-                    'date'            => new EE_Text_Input(
1777
-                        [
1778
-                            'default'         => time(),
1779
-                            'required'        => true,
1780
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1781
-                        ]
1782
-                    ),
1783
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1784
-                        [
1785
-                            'default'               => '',
1786
-                            'required'              => false,
1787
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1788
-                            'validation_strategies' => [
1789
-                                new EE_Max_Length_Validation_Strategy(
1790
-                                    esc_html__('Input too long', 'event_espresso'),
1791
-                                    100
1792
-                                ),
1793
-                            ],
1794
-                        ]
1795
-                    ),
1796
-                    'po_number'       => new EE_Text_Input(
1797
-                        [
1798
-                            'default'               => '',
1799
-                            'required'              => false,
1800
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1801
-                            'validation_strategies' => [
1802
-                                new EE_Max_Length_Validation_Strategy(
1803
-                                    esc_html__('Input too long', 'event_espresso'),
1804
-                                    100
1805
-                                ),
1806
-                            ],
1807
-                        ]
1808
-                    ),
1809
-                    'accounting'      => new EE_Text_Input(
1810
-                        [
1811
-                            'default'               => '',
1812
-                            'required'              => false,
1813
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1814
-                            'validation_strategies' => [
1815
-                                new EE_Max_Length_Validation_Strategy(
1816
-                                    esc_html__('Input too long', 'event_espresso'),
1817
-                                    100
1818
-                                ),
1819
-                            ],
1820
-                        ]
1821
-                    ),
1822
-                ],
1823
-            ]
1824
-        );
1825
-    }
1826
-
1827
-
1828
-    /**
1829
-     * _create_payment_from_request_data
1830
-     *
1831
-     * @param array $valid_data
1832
-     * @return EE_Payment
1833
-     * @throws EE_Error
1834
-     * @throws InvalidArgumentException
1835
-     * @throws InvalidDataTypeException
1836
-     * @throws InvalidInterfaceException
1837
-     * @throws ReflectionException
1838
-     */
1839
-    protected function _create_payment_from_request_data($valid_data)
1840
-    {
1841
-        $PAY_ID = $valid_data['PAY_ID'];
1842
-        // get payment amount
1843
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1844
-        // payments have a type value of 1 and refunds have a type value of -1
1845
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1846
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1847
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1848
-        $date    = $valid_data['date']
1849
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1850
-            : date('Y-m-d g:i a', current_time('timestamp'));
1851
-        $payment = EE_Payment::new_instance(
1852
-            [
1853
-                'TXN_ID'              => $valid_data['TXN_ID'],
1854
-                'STS_ID'              => $valid_data['status'],
1855
-                'PAY_timestamp'       => $date,
1856
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1857
-                'PMD_ID'              => $valid_data['PMD_ID'],
1858
-                'PAY_amount'          => $amount,
1859
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1860
-                'PAY_po_number'       => $valid_data['po_number'],
1861
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1862
-                'PAY_details'         => $valid_data,
1863
-                'PAY_ID'              => $PAY_ID,
1864
-            ],
1865
-            '',
1866
-            ['Y-m-d', 'g:i a']
1867
-        );
1868
-
1869
-        if (! $payment->save()) {
1870
-            EE_Error::add_error(
1871
-                sprintf(
1872
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1873
-                    $payment->ID()
1874
-                ),
1875
-                __FILE__,
1876
-                __FUNCTION__,
1877
-                __LINE__
1878
-            );
1879
-        }
1880
-
1881
-        return $payment;
1882
-    }
1883
-
1884
-
1885
-    /**
1886
-     * _process_transaction_payments
1887
-     *
1888
-     * @param EE_Transaction $transaction
1889
-     * @return void
1890
-     * @throws EE_Error
1891
-     * @throws InvalidArgumentException
1892
-     * @throws ReflectionException
1893
-     * @throws InvalidDataTypeException
1894
-     * @throws InvalidInterfaceException
1895
-     */
1896
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1897
-    {
1898
-        /** @type EE_Transaction_Payments $transaction_payments */
1899
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1900
-        // update the transaction with this payment
1901
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1902
-            EE_Error::add_success(
1903
-                esc_html__(
1904
-                    'The payment has been processed successfully.',
1905
-                    'event_espresso'
1906
-                ),
1907
-                __FILE__,
1908
-                __FUNCTION__,
1909
-                __LINE__
1910
-            );
1911
-        } else {
1912
-            EE_Error::add_error(
1913
-                esc_html__(
1914
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1915
-                    'event_espresso'
1916
-                ),
1917
-                __FILE__,
1918
-                __FUNCTION__,
1919
-                __LINE__
1920
-            );
1921
-        }
1922
-    }
1923
-
1924
-
1925
-    /**
1926
-     * _get_REG_IDs_to_apply_payment_to
1927
-     * returns a list of registration IDs that the payment will apply to
1928
-     *
1929
-     * @param EE_Payment $payment
1930
-     * @return array
1931
-     * @throws EE_Error
1932
-     * @throws InvalidArgumentException
1933
-     * @throws InvalidDataTypeException
1934
-     * @throws InvalidInterfaceException
1935
-     * @throws ReflectionException
1936
-     */
1937
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1938
-    {
1939
-        // grab array of IDs for specific registrations to apply changes to
1940
-        $apply_to_all = $this->request->getRequestParam(
1941
-            'txn_admin_payment[apply_to_all_registrations]',
1942
-            false,
1943
-            DataType::BOOL
1944
-        );
1945
-        $REG_IDs = ! $apply_to_all
1946
-            ? $this->request->getRequestParam(
1947
-                'txn_admin_payment[registrations]',
1948
-                [],
1949
-                DataType::INT,
1950
-                true
1951
-            )
1952
-            : [];
1953
-        // nothing specified ? then get all reg IDs
1954
-        if ($apply_to_all || empty($REG_IDs)) {
1955
-            $registrations = $payment->transaction()->registrations();
1956
-            $REG_IDs       = ! empty($registrations)
1957
-                ? array_keys($registrations)
1958
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1959
-        }
1960
-        // ensure that REG_IDs are integers and NOT strings
1961
-        return array_map('absint', $REG_IDs);
1962
-    }
1963
-
1964
-
1965
-    /**
1966
-     * @return array
1967
-     */
1968
-    public function existing_reg_payment_REG_IDs()
1969
-    {
1970
-        return $this->_existing_reg_payment_REG_IDs;
1971
-    }
1972
-
1973
-
1974
-    /**
1975
-     * @param array $existing_reg_payment_REG_IDs
1976
-     */
1977
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1978
-    {
1979
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1980
-    }
1981
-
1982
-
1983
-    /**
1984
-     * _get_existing_reg_payment_REG_IDs
1985
-     * returns a list of registration IDs that the payment is currently related to
1986
-     * as recorded in the database
1987
-     *
1988
-     * @param EE_Payment $payment
1989
-     * @return array
1990
-     * @throws EE_Error
1991
-     * @throws InvalidArgumentException
1992
-     * @throws InvalidDataTypeException
1993
-     * @throws InvalidInterfaceException
1994
-     * @throws ReflectionException
1995
-     */
1996
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1997
-    {
1998
-        if ($this->existing_reg_payment_REG_IDs() === null) {
1999
-            // let's get any existing reg payment records for this payment
2000
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2001
-            // but we only want the REG IDs, so grab the array keys
2002
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2003
-                ? array_keys($existing_reg_payment_REG_IDs)
2004
-                : [];
2005
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2006
-        }
2007
-
2008
-        return $this->existing_reg_payment_REG_IDs();
2009
-    }
2010
-
2011
-
2012
-    /**
2013
-     * _remove_existing_registration_payments
2014
-     * this calculates the difference between existing relations
2015
-     * to the supplied payment and the new list registration IDs,
2016
-     * removes any related registrations that no longer apply,
2017
-     * and then updates the registration paid fields
2018
-     *
2019
-     * @param EE_Payment $payment
2020
-     * @param int        $PAY_ID
2021
-     * @return bool;
2022
-     * @throws EE_Error
2023
-     * @throws InvalidArgumentException
2024
-     * @throws ReflectionException
2025
-     * @throws InvalidDataTypeException
2026
-     * @throws InvalidInterfaceException
2027
-     */
2028
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2029
-    {
2030
-        // newly created payments will have nothing recorded for $PAY_ID
2031
-        if (absint($PAY_ID) === 0) {
2032
-            return false;
2033
-        }
2034
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2035
-        if (empty($existing_reg_payment_REG_IDs)) {
2036
-            return false;
2037
-        }
2038
-        /** @type EE_Transaction_Payments $transaction_payments */
2039
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2040
-
2041
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2042
-            $payment,
2043
-            [
2044
-                [
2045
-                    'PAY_ID' => $payment->ID(),
2046
-                    'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2047
-                ],
2048
-            ]
2049
-        );
2050
-    }
2051
-
2052
-
2053
-    /**
2054
-     * _update_registration_payments
2055
-     * this applies the payments to the selected registrations
2056
-     * but only if they have not already been paid for
2057
-     *
2058
-     * @param EE_Transaction $transaction
2059
-     * @param EE_Payment     $payment
2060
-     * @param array          $REG_IDs
2061
-     * @return void
2062
-     * @throws EE_Error
2063
-     * @throws InvalidArgumentException
2064
-     * @throws ReflectionException
2065
-     * @throws RuntimeException
2066
-     * @throws InvalidDataTypeException
2067
-     * @throws InvalidInterfaceException
2068
-     */
2069
-    protected function _update_registration_payments(
2070
-        EE_Transaction $transaction,
2071
-        EE_Payment $payment,
2072
-        $REG_IDs = []
2073
-    ) {
2074
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2075
-        // so let's do that using our set of REG_IDs from the form
2076
-        $registration_query_where_params = [
2077
-            'REG_ID' => ['IN', $REG_IDs],
2078
-        ];
2079
-        // but add in some conditions regarding payment,
2080
-        // so that we don't apply payments to registrations that are free or have already been paid for
2081
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2082
-        if (! $payment->is_a_refund()) {
2083
-            $registration_query_where_params['REG_final_price']  = ['!=', 0];
2084
-            $registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2085
-        }
2086
-        $registrations = $transaction->registrations([$registration_query_where_params]);
2087
-        if (! empty($registrations)) {
2088
-            /** @type EE_Payment_Processor $payment_processor */
2089
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2090
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2091
-        }
2092
-    }
2093
-
2094
-
2095
-    /**
2096
-     * _process_registration_status_change
2097
-     * This processes requested registration status changes for all the registrations
2098
-     * on a given transaction and (optionally) sends out notifications for the changes.
2099
-     *
2100
-     * @param EE_Transaction $transaction
2101
-     * @param array          $REG_IDs
2102
-     * @return bool
2103
-     * @throws EE_Error
2104
-     * @throws InvalidArgumentException
2105
-     * @throws ReflectionException
2106
-     * @throws InvalidDataTypeException
2107
-     * @throws InvalidInterfaceException
2108
-     */
2109
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2110
-    {
2111
-        // first if there is no change in status then we get out.
2112
-        $reg_status = $reg_status ?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2113
-        if ($reg_status === 'NAN') {
2114
-            // no error message, no change requested, just nothing to do man.
2115
-            return false;
2116
-        }
2117
-        /** @type EE_Transaction_Processor $transaction_processor */
2118
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2119
-
2120
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2121
-        return $transaction_processor->manually_update_registration_statuses(
2122
-            $transaction,
2123
-            $reg_status,
2124
-            [['REG_ID' => ['IN', $REG_IDs]]]
2125
-        );
2126
-    }
2127
-
2128
-
2129
-    /**
2130
-     * _build_payment_json_response
2131
-     *
2132
-     * @access public
2133
-     * @param EE_Payment  $payment
2134
-     * @param array       $REG_IDs
2135
-     * @param bool | null $delete_txn_reg_status_change
2136
-     * @return array
2137
-     * @throws EE_Error
2138
-     * @throws InvalidArgumentException
2139
-     * @throws InvalidDataTypeException
2140
-     * @throws InvalidInterfaceException
2141
-     * @throws ReflectionException
2142
-     */
2143
-    protected function _build_payment_json_response(
2144
-        EE_Payment $payment,
2145
-        $REG_IDs = [],
2146
-        $delete_txn_reg_status_change = null
2147
-    ) {
2148
-        // was the payment deleted ?
2149
-        if (is_bool($delete_txn_reg_status_change)) {
2150
-            return [
2151
-                'PAY_ID'                       => $payment->ID(),
2152
-                'amount'                       => $payment->amount(),
2153
-                'total_paid'                   => $payment->transaction()->paid(),
2154
-                'txn_status'                   => $payment->transaction()->status_ID(),
2155
-                'pay_status'                   => $payment->STS_ID(),
2156
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2157
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2158
-            ];
2159
-        }
2160
-
2161
-        $this->_get_payment_status_array();
2162
-        return [
2163
-            'amount'           => $payment->amount(),
2164
-            'total_paid'       => $payment->transaction()->paid(),
2165
-            'txn_status'       => $payment->transaction()->status_ID(),
2166
-            'pay_status'       => $payment->STS_ID(),
2167
-            'PAY_ID'           => $payment->ID(),
2168
-            'STS_ID'           => $payment->STS_ID(),
2169
-            'status'           => self::$_pay_status[ $payment->STS_ID() ],
2170
-            'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2171
-            'method'           => strtoupper($payment->source()),
2172
-            'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2173
-            'gateway'          => $payment->payment_method()
2174
-                ? $payment->payment_method()->admin_name()
2175
-                : esc_html__('Unknown', 'event_espresso'),
2176
-            'gateway_response' => $payment->gateway_response(),
2177
-            'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2178
-            'po_number'        => $payment->po_number(),
2179
-            'extra_accntng'    => $payment->extra_accntng(),
2180
-            'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2181
-        ];
2182
-    }
2183
-
2184
-
2185
-    /**
2186
-     * delete_payment
2187
-     *    delete a payment or refund made towards a transaction
2188
-     *
2189
-     * @access public
2190
-     * @return void
2191
-     * @throws EE_Error
2192
-     * @throws InvalidArgumentException
2193
-     * @throws ReflectionException
2194
-     * @throws InvalidDataTypeException
2195
-     * @throws InvalidInterfaceException
2196
-     */
2197
-    public function delete_payment()
2198
-    {
2199
-        $TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2200
-        // $json_response_data = ['return_data' => false];
2201
-        $PAY_ID = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2202
-        $amount = 0;
2203
-        $can_delete         = EE_Registry::instance()->CAP->current_user_can(
2204
-            'ee_delete_payments',
2205
-            'delete_payment_from_registration_details'
2206
-        );
2207
-        if ($PAY_ID && $can_delete) {
2208
-            $delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2209
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2210
-            if ($payment instanceof EE_Payment) {
2211
-                $amount = $payment->amount();
2212
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2213
-                /** @type EE_Transaction_Payments $transaction_payments */
2214
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2215
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2216
-                    if ($delete_txn_reg_status_change) {
2217
-                        $this->_maybe_send_notifications();
2218
-                        $this->_process_registration_status_change(
2219
-                            $payment->transaction(),
2220
-                            $REG_IDs,
2221
-                            $delete_txn_reg_status_change
2222
-                        );
2223
-                    }
2224
-                }
2225
-            } else {
2226
-                EE_Error::add_error(
2227
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2228
-                    __FILE__,
2229
-                    __FUNCTION__,
2230
-                    __LINE__
2231
-                );
2232
-            }
2233
-        } elseif ($can_delete) {
2234
-            EE_Error::add_error(
2235
-                esc_html__(
2236
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2237
-                    'event_espresso'
2238
-                ),
2239
-                __FILE__,
2240
-                __FUNCTION__,
2241
-                __LINE__
2242
-            );
2243
-        } else {
2244
-            EE_Error::add_error(
2245
-                esc_html__(
2246
-                    'You do not have access to delete a payment.',
2247
-                    'event_espresso'
2248
-                ),
2249
-                __FILE__,
2250
-                __FUNCTION__,
2251
-                __LINE__
2252
-            );
2253
-        }
2254
-        $query_args = [
2255
-            'page'   => 'espresso_transactions',
2256
-            'action' => 'view_transaction',
2257
-            'TXN_ID' => $TXD_ID
2258
-        ];
2259
-        $this->_redirect_after_action(
2260
-            ! EE_Error::has_error(),
2261
-            $amount > 0
2262
-                ? esc_html__('payment', 'event_espresso')
2263
-                : esc_html__('refund', 'event_espresso'),
2264
-            esc_html__('deleted', 'event_espresso'),
2265
-            $query_args
2266
-        );
2267
-    }
2268
-
2269
-
2270
-    /**
2271
-     * _registration_payment_data_array
2272
-     * adds info for 'owing' and 'paid' for each registration to the json response
2273
-     *
2274
-     * @access protected
2275
-     * @param array $REG_IDs
2276
-     * @return array
2277
-     * @throws EE_Error
2278
-     * @throws InvalidArgumentException
2279
-     * @throws InvalidDataTypeException
2280
-     * @throws InvalidInterfaceException
2281
-     * @throws ReflectionException
2282
-     */
2283
-    protected function _registration_payment_data_array($REG_IDs)
2284
-    {
2285
-        $registration_payment_data = [];
2286
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2287
-        if (! empty($REG_IDs)) {
2288
-            $registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2289
-            foreach ($registrations as $registration) {
2290
-                if ($registration instanceof EE_Registration) {
2291
-                    $registration_payment_data[ $registration->ID() ] = [
2292
-                        'paid'  => $registration->pretty_paid(),
2293
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2294
-                    ];
2295
-                }
2296
-            }
2297
-        }
2298
-
2299
-        return $registration_payment_data;
2300
-    }
2301
-
2302
-
2303
-    /**
2304
-     * _maybe_send_notifications
2305
-     * determines whether or not the admin has indicated that notifications should be sent.
2306
-     * If so, will toggle a filter switch for delivering registration notices.
2307
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2308
-     *
2309
-     * @access protected
2310
-     * @param EE_Payment | null $payment
2311
-     */
2312
-    protected function _maybe_send_notifications($payment = null)
2313
-    {
2314
-        switch ($payment instanceof EE_Payment) {
2315
-            // payment notifications
2316
-            case true:
2317
-                if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2318
-                    $this->_process_payment_notification($payment);
2319
-                }
2320
-                break;
2321
-            // registration notifications
2322
-            case false:
2323
-                if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2324
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2325
-                }
2326
-                break;
2327
-        }
2328
-    }
2329
-
2330
-
2331
-    /**
2332
-     * _send_payment_reminder
2333
-     *    generates HTML for the View Transaction Details Admin page
2334
-     *
2335
-     * @access protected
2336
-     * @return void
2337
-     * @throws EE_Error
2338
-     * @throws InvalidArgumentException
2339
-     * @throws InvalidDataTypeException
2340
-     * @throws InvalidInterfaceException
2341
-     */
2342
-    protected function _send_payment_reminder()
2343
-    {
2344
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2345
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2346
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2347
-        $query_args  = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2348
-        do_action(
2349
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2350
-            $transaction
2351
-        );
2352
-        $this->_redirect_after_action(
2353
-            false,
2354
-            esc_html__('payment reminder', 'event_espresso'),
2355
-            esc_html__('sent', 'event_espresso'),
2356
-            $query_args,
2357
-            true
2358
-        );
2359
-    }
2360
-
2361
-
2362
-    /**
2363
-     *  get_transactions
2364
-     *    get transactions for given parameters (used by list table)
2365
-     *
2366
-     * @param int     $per_page how many transactions displayed per page
2367
-     * @param boolean $count   return the count or objects
2368
-     * @param string  $view
2369
-     * @return EE_Transaction[]|int int = count || array of transaction objects
2370
-     * @throws EE_Error
2371
-     * @throws InvalidArgumentException
2372
-     * @throws InvalidDataTypeException
2373
-     * @throws InvalidInterfaceException
2374
-     */
2375
-    public function get_transactions($per_page, $count = false, $view = '')
2376
-    {
2377
-        $start_date = wp_strip_all_tags(
2378
-            $this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2379
-        );
2380
-        $end_date = wp_strip_all_tags(
2381
-            $this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2382
-        );
2383
-
2384
-        // make sure our timestamps start and end right at the boundaries for each day
2385
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2386
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2387
-
2388
-
2389
-        // convert to timestamps
2390
-        $start_date = strtotime($start_date);
2391
-        $end_date   = strtotime($end_date);
2392
-
2393
-        // makes sure start date is the lowest value and vice versa
2394
-        $start_date = min($start_date, $end_date);
2395
-        $end_date   = max($start_date, $end_date);
2396
-
2397
-        // convert to correct format for query
2398
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2399
-            'TXN_timestamp',
2400
-            date('Y-m-d H:i:s', $start_date),
2401
-            'Y-m-d H:i:s'
2402
-        );
2403
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2404
-            'TXN_timestamp',
2405
-            date('Y-m-d H:i:s', $end_date),
2406
-            'Y-m-d H:i:s'
2407
-        );
2408
-
2409
-
2410
-        // set orderby
2411
-        $orderby = $this->request->getRequestParam('orderby');
2412
-
2413
-        switch ($orderby) {
2414
-            case 'TXN_ID':
2415
-                break;
2416
-            case 'ATT_fname':
2417
-                $orderby = 'Registration.Attendee.ATT_fname';
2418
-                break;
2419
-            case 'event_name':
2420
-                $orderby = 'Registration.Event.EVT_name';
2421
-                break;
2422
-            default: // 'TXN_timestamp'
2423
-                $orderby = 'TXN_timestamp';
2424
-        }
2425
-
2426
-        $sort         = $this->request->getRequestParam('order', 'DESC');
2427
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
2428
-
2429
-        $per_page = absint($per_page) ? $per_page : 10;
2430
-        $per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2431
-
2432
-        $offset = ($current_page - 1) * $per_page;
2433
-        $limit  = [$offset, $per_page];
2434
-
2435
-        $_where = [
2436
-            'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2437
-            'Registration.REG_count' => 1,
2438
-        ];
2439
-
2440
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2441
-        if ($EVT_ID) {
2442
-            $_where['Registration.EVT_ID'] = $EVT_ID;
2443
-        }
2444
-
2445
-        $search_term = $this->request->getRequestParam('s');
2446
-        if ($search_term) {
2447
-            $search_term = '%' . $search_term . '%';
2448
-            $_where['OR']  = [
2449
-                'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2450
-                'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2451
-                'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2452
-                'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2453
-                'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2454
-                'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2455
-                'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2456
-                'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2457
-                'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2458
-                'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2459
-                'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2460
-                'Registration.REG_final_price'        => ['LIKE', $search_term],
2461
-                'Registration.REG_code'               => ['LIKE', $search_term],
2462
-                'Registration.REG_count'              => ['LIKE', $search_term],
2463
-                'Registration.REG_group_size'         => ['LIKE', $search_term],
2464
-                'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2465
-                'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2466
-                'Payment.PAY_source'                  => ['LIKE', $search_term],
2467
-                'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2468
-                'TXN_session_data'                    => ['LIKE', $search_term],
2469
-                'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2470
-            ];
2471
-        }
2472
-
2473
-        $status = $this->request->getRequestParam('status');
2474
-        // failed transactions
2475
-        $failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2476
-        $abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2477
-        $incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2478
-
2479
-        if ($failed) {
2480
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2481
-        } elseif ($abandoned) {
2482
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2483
-        } elseif ($incomplete) {
2484
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2485
-        } else {
2486
-            $_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2487
-            $_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2488
-        }
2489
-
2490
-        $query_params = apply_filters(
2491
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2492
-            [
2493
-                $_where,
2494
-                'order_by'                 => [$orderby => $sort],
2495
-                'limit'                    => $limit,
2496
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2497
-            ],
2498
-            $this->request->requestParams(),
2499
-            $view,
2500
-            $count
2501
-        );
2502
-
2503
-        return $count
2504
-            ? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2505
-            : EEM_Transaction::instance()->get_all($query_params);
2506
-    }
2507
-
2508
-
2509
-    /**
2510
-     * @throws EE_Error
2511
-     * @throws InvalidArgumentException
2512
-     * @throws InvalidDataTypeException
2513
-     * @throws InvalidInterfaceException
2514
-     * @throws ReflectionException
2515
-     * @throws RuntimeException
2516
-     * @since 4.9.79.p
2517
-     */
2518
-    public function recalculateLineItems()
2519
-    {
2520
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2521
-        /** @var EE_Transaction $transaction */
2522
-        $transaction     = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2523
-        $success         = $transaction->recalculateLineItems();
2524
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2525
-        $query_args = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2526
-        $this->_redirect_after_action(
2527
-            $success,
2528
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2529
-            esc_html__('recalculated', 'event_espresso'),
2530
-            $query_args,
2531
-            true
2532
-        );
2533
-    }
16
+	/**
17
+	 * @var EE_Transaction
18
+	 */
19
+	private $_transaction;
20
+
21
+	/**
22
+	 * @var EE_Session
23
+	 */
24
+	private $_session;
25
+
26
+	/**
27
+	 * @var array $_txn_status
28
+	 */
29
+	private static $_txn_status;
30
+
31
+	/**
32
+	 * @var array $_pay_status
33
+	 */
34
+	private static $_pay_status;
35
+
36
+	/**
37
+	 * @var array $_existing_reg_payment_REG_IDs
38
+	 */
39
+	protected $_existing_reg_payment_REG_IDs;
40
+
41
+
42
+	/**
43
+	 *    _init_page_props
44
+	 *
45
+	 * @return void
46
+	 */
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug        = TXN_PG_SLUG;
50
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
51
+		$this->_admin_base_url  = TXN_ADMIN_URL;
52
+		$this->_admin_base_path = TXN_ADMIN;
53
+	}
54
+
55
+
56
+	/**
57
+	 *    _ajax_hooks
58
+	 *
59
+	 * @return void
60
+	 */
61
+	protected function _ajax_hooks()
62
+	{
63
+		// add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
64
+		// add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
65
+		// add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
66
+	}
67
+
68
+
69
+	/**
70
+	 *    _define_page_props
71
+	 *
72
+	 * @return void
73
+	 */
74
+	protected function _define_page_props()
75
+	{
76
+		$this->_admin_page_title = $this->page_label;
77
+		$this->_labels           = [
78
+			'buttons' => [
79
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
+			],
83
+		];
84
+	}
85
+
86
+
87
+	/**
88
+	 *        grab url requests and route them
89
+	 *
90
+	 * @access private
91
+	 * @return void
92
+	 * @throws EE_Error
93
+	 * @throws InvalidArgumentException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidInterfaceException
96
+	 */
97
+	public function _set_page_routes()
98
+	{
99
+
100
+		$this->_set_transaction_status_array();
101
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
102
+
103
+		$this->_page_routes = [
104
+
105
+			'default' => [
106
+				'func'       => '_transactions_overview_list_table',
107
+				'capability' => 'ee_read_transactions',
108
+			],
109
+
110
+			'view_transaction' => [
111
+				'func'       => '_transaction_details',
112
+				'capability' => 'ee_read_transaction',
113
+				'obj_id'     => $TXN_ID,
114
+			],
115
+
116
+			'send_payment_reminder' => [
117
+				'func'       => '_send_payment_reminder',
118
+				'noheader'   => true,
119
+				'capability' => 'ee_send_message',
120
+			],
121
+
122
+			'espresso_apply_payment' => [
123
+				'func'       => 'apply_payments_or_refunds',
124
+				'noheader'   => true,
125
+				'capability' => 'ee_edit_payments',
126
+			],
127
+
128
+			'espresso_apply_refund' => [
129
+				'func'       => 'apply_payments_or_refunds',
130
+				'noheader'   => true,
131
+				'capability' => 'ee_edit_payments',
132
+			],
133
+
134
+			'espresso_delete_payment' => [
135
+				'func'       => [$this, 'delete_payment'],
136
+				'noheader'   => true,
137
+				'capability' => 'ee_delete_payments',
138
+			],
139
+
140
+			'espresso_recalculate_line_items' => [
141
+				'func'       => 'recalculateLineItems',
142
+				'noheader'   => true,
143
+				'capability' => 'ee_edit_payments',
144
+			],
145
+
146
+		];
147
+	}
148
+
149
+
150
+	protected function _set_page_config()
151
+	{
152
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
153
+		$this->_page_config = [
154
+			'default'          => [
155
+				'nav'           => [
156
+					'label' => esc_html__('Overview', 'event_espresso'),
157
+					'icon' => 'dashicons-list-view',
158
+					'order' => 10,
159
+				],
160
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
161
+				'help_tabs'     => [
162
+					'transactions_overview_help_tab'                       => [
163
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
164
+						'filename' => 'transactions_overview',
165
+					],
166
+					'transactions_overview_table_column_headings_help_tab' => [
167
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
168
+						'filename' => 'transactions_overview_table_column_headings',
169
+					],
170
+					'transactions_overview_views_filters_help_tab'         => [
171
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
172
+						'filename' => 'transactions_overview_views_filters_search',
173
+					],
174
+				],
175
+				'require_nonce' => false,
176
+			],
177
+			'view_transaction' => [
178
+				'nav'       => [
179
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
180
+					'icon' => 'dashicons-cart',
181
+					'order'      => 5,
182
+					'url'        => $TXN_ID
183
+						? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
184
+						: $this->_admin_base_url,
185
+					'persistent' => false,
186
+				],
187
+				'help_tabs' => [
188
+					'transactions_view_transaction_help_tab'                                              => [
189
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
190
+						'filename' => 'transactions_view_transaction',
191
+					],
192
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => [
193
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
194
+						'filename' => 'transactions_view_transaction_transaction_details_table',
195
+					],
196
+					'transactions_view_transaction_attendees_registered_help_tab'                         => [
197
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
198
+						'filename' => 'transactions_view_transaction_attendees_registered',
199
+					],
200
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
201
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
202
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
203
+					],
204
+				],
205
+				'qtips'     => ['Transaction_Details_Tips'],
206
+				'metaboxes' => ['_transaction_details_metaboxes'],
207
+
208
+				'require_nonce' => false,
209
+			],
210
+		];
211
+	}
212
+
213
+
214
+	/**
215
+	 * The below methods aren't used by this class currently
216
+	 */
217
+	protected function _add_screen_options()
218
+	{
219
+		// noop
220
+	}
221
+
222
+
223
+	protected function _add_feature_pointers()
224
+	{
225
+		// noop
226
+	}
227
+
228
+
229
+	public function admin_init()
230
+	{
231
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
232
+		$event_name = $this->request->getRequestParam('event_name');
233
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
234
+		// IF a registration was JUST added via the admin...
235
+		if ($EVT_ID && $event_name && $redirect_from) {
236
+			// then set a cookie so that we can block any attempts to use
237
+			// the back button as a way to enter another registration.
238
+			setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
239
+			// and update the global
240
+			$_COOKIE['ee_registration_added'] = $EVT_ID;
241
+		}
242
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
243
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
244
+			'event_espresso'
245
+		);
246
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
247
+			'An error occurred! Please refresh the page and try again.',
248
+			'event_espresso'
249
+		);
250
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
251
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
252
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
253
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
254
+			'This transaction has been overpaid ! Payments Total',
255
+			'event_espresso'
256
+		);
257
+	}
258
+
259
+
260
+	public function admin_notices()
261
+	{
262
+		// noop
263
+	}
264
+
265
+
266
+	public function admin_footer_scripts()
267
+	{
268
+		// noop
269
+	}
270
+
271
+
272
+	/**
273
+	 * _set_transaction_status_array
274
+	 * sets list of transaction statuses
275
+	 *
276
+	 * @access private
277
+	 * @return void
278
+	 * @throws EE_Error
279
+	 * @throws InvalidArgumentException
280
+	 * @throws InvalidDataTypeException
281
+	 * @throws InvalidInterfaceException
282
+	 */
283
+	private function _set_transaction_status_array()
284
+	{
285
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
286
+	}
287
+
288
+
289
+	/**
290
+	 * get_transaction_status_array
291
+	 * return the transaction status array for wp_list_table
292
+	 *
293
+	 * @access public
294
+	 * @return array
295
+	 */
296
+	public function get_transaction_status_array()
297
+	{
298
+		return self::$_txn_status;
299
+	}
300
+
301
+
302
+	/**
303
+	 *    get list of payment statuses
304
+	 *
305
+	 * @access private
306
+	 * @return void
307
+	 * @throws EE_Error
308
+	 * @throws InvalidArgumentException
309
+	 * @throws InvalidDataTypeException
310
+	 * @throws InvalidInterfaceException
311
+	 */
312
+	private function _get_payment_status_array()
313
+	{
314
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
315
+		$this->_template_args['payment_status'] = self::$_pay_status;
316
+	}
317
+
318
+
319
+	/**
320
+	 *    _add_screen_options_default
321
+	 *
322
+	 * @access protected
323
+	 * @return void
324
+	 * @throws InvalidArgumentException
325
+	 * @throws InvalidDataTypeException
326
+	 * @throws InvalidInterfaceException
327
+	 */
328
+	protected function _add_screen_options_default()
329
+	{
330
+		$this->_per_page_screen_option();
331
+	}
332
+
333
+
334
+	/**
335
+	 * load_scripts_styles
336
+	 *
337
+	 * @access public
338
+	 * @return void
339
+	 */
340
+	public function load_scripts_styles()
341
+	{
342
+		// enqueue style
343
+		wp_register_style(
344
+			'espresso_txn',
345
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
346
+			[],
347
+			EVENT_ESPRESSO_VERSION
348
+		);
349
+		wp_enqueue_style('espresso_txn');
350
+		// scripts
351
+		wp_register_script(
352
+			'espresso_txn',
353
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
354
+			[
355
+				'ee_admin_js',
356
+				'ee-datepicker',
357
+				'jquery-ui-datepicker',
358
+				'jquery-ui-draggable',
359
+				'ee-dialog',
360
+				'ee-accounting',
361
+				'ee-serialize-full-array',
362
+			],
363
+			EVENT_ESPRESSO_VERSION,
364
+			true
365
+		);
366
+		wp_enqueue_script('espresso_txn');
367
+	}
368
+
369
+
370
+	/**
371
+	 *    load_scripts_styles_view_transaction
372
+	 *
373
+	 * @access public
374
+	 * @return void
375
+	 */
376
+	public function load_scripts_styles_view_transaction()
377
+	{
378
+		// styles
379
+		wp_enqueue_style('espresso-ui-theme');
380
+	}
381
+
382
+
383
+	/**
384
+	 *    load_scripts_styles_default
385
+	 *
386
+	 * @access public
387
+	 * @return void
388
+	 */
389
+	public function load_scripts_styles_default()
390
+	{
391
+		// styles
392
+		wp_enqueue_style('espresso-ui-theme');
393
+	}
394
+
395
+
396
+	/**
397
+	 *    _set_list_table_views_default
398
+	 *
399
+	 * @access protected
400
+	 * @return void
401
+	 */
402
+	protected function _set_list_table_views_default()
403
+	{
404
+		$this->_views = [
405
+			'all'        => [
406
+				'slug'  => 'all',
407
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
408
+				'count' => 0,
409
+			],
410
+			'abandoned'  => [
411
+				'slug'  => 'abandoned',
412
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
413
+				'count' => 0,
414
+			],
415
+			'incomplete' => [
416
+				'slug'  => 'incomplete',
417
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
418
+				'count' => 0,
419
+			],
420
+		];
421
+		if (
422
+			/**
423
+			 * Filters whether a link to the "Failed Transactions" list table
424
+			 * appears on the Transactions Admin Page list table.
425
+			 * List display can be turned back on via the following:
426
+			 * add_filter(
427
+			 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
428
+			 *     '__return_true'
429
+			 * );
430
+			 *
431
+			 * @param boolean                 $display_failed_txns_list
432
+			 * @param Transactions_Admin_Page $this
433
+			 * @since 4.9.70.p
434
+			 */
435
+			apply_filters(
436
+				'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
437
+				false,
438
+				$this
439
+			)
440
+		) {
441
+			$this->_views['failed'] = [
442
+				'slug'  => 'failed',
443
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
444
+				'count' => 0,
445
+			];
446
+		}
447
+	}
448
+
449
+
450
+	/**
451
+	 * _set_transaction_object
452
+	 * This sets the _transaction property for the transaction details screen
453
+	 *
454
+	 * @access private
455
+	 * @return void
456
+	 * @throws EE_Error
457
+	 * @throws InvalidArgumentException
458
+	 * @throws RuntimeException
459
+	 * @throws InvalidDataTypeException
460
+	 * @throws InvalidInterfaceException
461
+	 * @throws ReflectionException
462
+	 */
463
+	private function _set_transaction_object()
464
+	{
465
+		if ($this->_transaction instanceof EE_Transaction) {
466
+			return;
467
+		} //get out we've already set the object
468
+
469
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
470
+
471
+		// get transaction object
472
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
473
+		$this->_session     = $this->_transaction instanceof EE_Transaction
474
+			? $this->_transaction->session_data()
475
+			: null;
476
+		if ($this->_transaction instanceof EE_Transaction) {
477
+			$this->_transaction->verify_abandoned_transaction_status();
478
+		}
479
+
480
+		if (! $this->_transaction instanceof EE_Transaction) {
481
+			$error_msg = sprintf(
482
+				esc_html__(
483
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
484
+					'event_espresso'
485
+				),
486
+				$TXN_ID
487
+			);
488
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
489
+		}
490
+	}
491
+
492
+
493
+	/**
494
+	 *    _transaction_legend_items
495
+	 *
496
+	 * @access protected
497
+	 * @return array
498
+	 * @throws EE_Error
499
+	 * @throws InvalidArgumentException
500
+	 * @throws ReflectionException
501
+	 * @throws InvalidDataTypeException
502
+	 * @throws InvalidInterfaceException
503
+	 */
504
+	protected function _transaction_legend_items()
505
+	{
506
+		EE_Registry::instance()->load_helper('MSG_Template');
507
+		$items = [];
508
+
509
+		if (
510
+			EE_Registry::instance()->CAP->current_user_can(
511
+				'ee_read_global_messages',
512
+				'view_filtered_messages'
513
+			)
514
+		) {
515
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
516
+			if (
517
+				is_array($related_for_icon)
518
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
519
+			) {
520
+				$items['view_related_messages'] = [
521
+					'class' => $related_for_icon['css_class'],
522
+					'desc'  => $related_for_icon['label'],
523
+				];
524
+			}
525
+		}
526
+
527
+		$items = apply_filters(
528
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
529
+			array_merge(
530
+				$items,
531
+				[
532
+					'view_details'          => [
533
+						'class' => 'dashicons dashicons-cart',
534
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
535
+					],
536
+					'view_invoice'          => [
537
+						'class' => 'dashicons dashicons-media-spreadsheet',
538
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
539
+					],
540
+					'view_receipt'          => [
541
+						'class' => 'dashicons dashicons-text-page',
542
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
543
+					],
544
+					'view_registration'     => [
545
+						'class' => 'dashicons dashicons-clipboard',
546
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
547
+					],
548
+					'payment_overview_link' => [
549
+						'class' => 'dashicons dashicons-money',
550
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
551
+					],
552
+				]
553
+			)
554
+		);
555
+
556
+		if (
557
+			EEH_MSG_Template::is_mt_active('payment_reminder')
558
+			&& EE_Registry::instance()->CAP->current_user_can(
559
+				'ee_send_message',
560
+				'espresso_transactions_send_payment_reminder'
561
+			)
562
+		) {
563
+			$items['send_payment_reminder'] = [
564
+				'class' => 'dashicons dashicons-email-alt',
565
+				'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
566
+			];
567
+		} else {
568
+			$items['blank*'] = [
569
+				'class' => '',
570
+				'desc'  => '',
571
+			];
572
+		}
573
+		$more_items = apply_filters(
574
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
575
+			[
576
+				'overpaid'   => [
577
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
578
+					'desc'  => EEH_Template::pretty_status(
579
+						EEM_Transaction::overpaid_status_code,
580
+						false,
581
+						'sentence'
582
+					),
583
+				],
584
+				'complete'   => [
585
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
586
+					'desc'  => EEH_Template::pretty_status(
587
+						EEM_Transaction::complete_status_code,
588
+						false,
589
+						'sentence'
590
+					),
591
+				],
592
+				'incomplete' => [
593
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
594
+					'desc'  => EEH_Template::pretty_status(
595
+						EEM_Transaction::incomplete_status_code,
596
+						false,
597
+						'sentence'
598
+					),
599
+				],
600
+				'abandoned'  => [
601
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
602
+					'desc'  => EEH_Template::pretty_status(
603
+						EEM_Transaction::abandoned_status_code,
604
+						false,
605
+						'sentence'
606
+					),
607
+				],
608
+				'failed'     => [
609
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
610
+					'desc'  => EEH_Template::pretty_status(
611
+						EEM_Transaction::failed_status_code,
612
+						false,
613
+						'sentence'
614
+					),
615
+				],
616
+			]
617
+		);
618
+
619
+		return array_merge($items, $more_items);
620
+	}
621
+
622
+
623
+	/**
624
+	 *    _transactions_overview_list_table
625
+	 *
626
+	 * @access protected
627
+	 * @return void
628
+	 * @throws DomainException
629
+	 * @throws EE_Error
630
+	 * @throws InvalidArgumentException
631
+	 * @throws InvalidDataTypeException
632
+	 * @throws InvalidInterfaceException
633
+	 * @throws ReflectionException
634
+	 */
635
+	protected function _transactions_overview_list_table()
636
+	{
637
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
638
+
639
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
640
+		$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
641
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
642
+			? sprintf(
643
+				esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
644
+				'<h3>',
645
+				'<a href="'
646
+				. EE_Admin_Page::add_query_args_and_nonce(
647
+					['action' => 'edit', 'post' => $event->ID()],
648
+					EVENTS_ADMIN_URL
649
+				)
650
+				. '" title="'
651
+				. esc_attr__('Click to Edit event', 'event_espresso')
652
+				. '">' . $event->name() . '</a>',
653
+				'</h3>'
654
+			)
655
+			: '';
656
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
657
+		$this->display_admin_list_table_page_with_no_sidebar();
658
+	}
659
+
660
+
661
+	/**
662
+	 *    _transaction_details
663
+	 * generates HTML for the View Transaction Details Admin page
664
+	 *
665
+	 * @access protected
666
+	 * @return void
667
+	 * @throws DomainException
668
+	 * @throws EE_Error
669
+	 * @throws InvalidArgumentException
670
+	 * @throws InvalidDataTypeException
671
+	 * @throws InvalidInterfaceException
672
+	 * @throws RuntimeException
673
+	 * @throws ReflectionException
674
+	 */
675
+	protected function _transaction_details()
676
+	{
677
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
678
+
679
+		$this->_set_transaction_status_array();
680
+
681
+		$this->_template_args                      = [];
682
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
683
+
684
+		$this->_set_transaction_object();
685
+
686
+		if (! $this->_transaction instanceof EE_Transaction) {
687
+			return;
688
+		}
689
+
690
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
691
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
692
+
693
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
694
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
695
+
696
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
697
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
698
+		$this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
699
+
700
+		$txn_total  = $this->_transaction->total();
701
+		$total_paid = $this->_transaction->paid();
702
+		$amount_due = $txn_total - $total_paid;
703
+
704
+		$this->_template_args['grand_total'] = $txn_total;
705
+		$this->_template_args['total_paid']  = $total_paid;
706
+
707
+		$this->_template_args['amount_due'] = EEH_Template::format_currency($amount_due, false, false);
708
+
709
+		$this->_template_args['amount_due_class'] = '';
710
+
711
+		if ($txn_total === (float) 0) {
712
+			// free event
713
+			$this->_template_args['amount_due'] = false;
714
+		} elseif ($amount_due < (float) 0) {
715
+			// overpaid
716
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
717
+		} elseif ($amount_due > (float) 0) {
718
+			// monies owing
719
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
720
+		} elseif ($total_paid === (float) 0) {
721
+			// no payments made yet
722
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
723
+		}
724
+
725
+		$payment_method = $this->_transaction->payment_method();
726
+
727
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
728
+			? $payment_method->admin_name()
729
+			: esc_html__('Unknown', 'event_espresso');
730
+
731
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
732
+		// link back to overview
733
+		$this->_template_args['txn_overview_url'] = $this->request->getServerParam(
734
+			'HTTP_REFERER',
735
+			TXN_ADMIN_URL
736
+		);
737
+
738
+
739
+		// next link
740
+		$next_txn                                 = $this->_transaction->next(
741
+			null,
742
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
743
+			'TXN_ID'
744
+		);
745
+		$this->_template_args['next_transaction'] = $next_txn
746
+			? $this->_next_link(
747
+				EE_Admin_Page::add_query_args_and_nonce(
748
+					['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
749
+					TXN_ADMIN_URL
750
+				),
751
+				'dashicons dashicons-arrow-right ee-icon-size-22'
752
+			)
753
+			: '';
754
+		// previous link
755
+		$previous_txn                                 = $this->_transaction->previous(
756
+			null,
757
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
758
+			'TXN_ID'
759
+		);
760
+		$this->_template_args['previous_transaction'] = $previous_txn
761
+			? $this->_previous_link(
762
+				EE_Admin_Page::add_query_args_and_nonce(
763
+					['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
764
+					TXN_ADMIN_URL
765
+				),
766
+				'dashicons dashicons-arrow-left ee-icon-size-22'
767
+			)
768
+			: '';
769
+
770
+		$EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
771
+		$event_name    = $this->request->getRequestParam('event_name');
772
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
773
+
774
+		// were we just redirected here after adding a new registration ???
775
+		if ($EVT_ID && $event_name && $redirect_from) {
776
+			if (
777
+				EE_Registry::instance()->CAP->current_user_can(
778
+					'ee_edit_registrations',
779
+					'espresso_registrations_new_registration',
780
+					$EVT_ID
781
+				)
782
+			) {
783
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
784
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
785
+					[
786
+						'page'     => 'espresso_registrations',
787
+						'action'   => 'new_registration',
788
+						'return'   => 'default',
789
+						'TXN_ID'   => $this->_transaction->ID(),
790
+						'event_id' => $EVT_ID,
791
+					],
792
+					REG_ADMIN_URL
793
+				);
794
+				$this->_admin_page_title .= '">';
795
+
796
+				$this->_admin_page_title .= sprintf(
797
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
798
+					htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
799
+				);
800
+				$this->_admin_page_title .= '</a>';
801
+			}
802
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
803
+		}
804
+		// grab messages at the last second
805
+		$this->_template_args['notices'] = EE_Error::get_notices();
806
+		// path to template
807
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
808
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
809
+			$template_path,
810
+			$this->_template_args,
811
+			true
812
+		);
813
+
814
+		// the details template wrapper
815
+		$this->display_admin_page_with_sidebar();
816
+	}
817
+
818
+
819
+	/**
820
+	 *        _transaction_details_metaboxes
821
+	 *
822
+	 * @access protected
823
+	 * @return void
824
+	 * @throws EE_Error
825
+	 * @throws InvalidArgumentException
826
+	 * @throws InvalidDataTypeException
827
+	 * @throws InvalidInterfaceException
828
+	 * @throws RuntimeException
829
+	 * @throws ReflectionException
830
+	 */
831
+	protected function _transaction_details_metaboxes()
832
+	{
833
+
834
+		$this->_set_transaction_object();
835
+
836
+		if (! $this->_transaction instanceof EE_Transaction) {
837
+			return;
838
+		}
839
+		$this->addMetaBox(
840
+			'edit-txn-details-mbox',
841
+			'<span>' . esc_html__('Transaction Details', 'event_espresso')
842
+			. '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
843
+			[$this, 'txn_details_meta_box'],
844
+			$this->_wp_page_slug
845
+		);
846
+		$this->addMetaBox(
847
+			'edit-txn-attendees-mbox',
848
+			'<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
849
+			. '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
850
+			[$this, 'txn_attendees_meta_box'],
851
+			$this->_wp_page_slug,
852
+			'normal',
853
+			'high',
854
+			['TXN_ID' => $this->_transaction->ID()]
855
+		);
856
+		$this->addMetaBox(
857
+			'edit-txn-registrant-mbox',
858
+			esc_html__('Primary Contact', 'event_espresso'),
859
+			[$this, 'txn_registrant_side_meta_box'],
860
+			$this->_wp_page_slug,
861
+			'side'
862
+		);
863
+		$this->addMetaBox(
864
+			'edit-txn-billing-info-mbox',
865
+			esc_html__('Billing Information', 'event_espresso'),
866
+			[$this, 'txn_billing_info_side_meta_box'],
867
+			$this->_wp_page_slug,
868
+			'side'
869
+		);
870
+	}
871
+
872
+
873
+	/**
874
+	 * Callback for transaction actions metabox.
875
+	 *
876
+	 * @param EE_Transaction|null $transaction
877
+	 * @return string
878
+	 * @throws DomainException
879
+	 * @throws EE_Error
880
+	 * @throws InvalidArgumentException
881
+	 * @throws InvalidDataTypeException
882
+	 * @throws InvalidInterfaceException
883
+	 * @throws ReflectionException
884
+	 * @throws RuntimeException
885
+	 */
886
+	public function getActionButtons(EE_Transaction $transaction = null)
887
+	{
888
+		$content = '';
889
+		$actions = [];
890
+		if (! $transaction instanceof EE_Transaction) {
891
+			return $content;
892
+		}
893
+		/** @var EE_Registration $primary_registration */
894
+		$primary_registration = $transaction->primary_registration();
895
+		$attendee             = $primary_registration instanceof EE_Registration
896
+			? $primary_registration->attendee()
897
+			: null;
898
+
899
+		if (
900
+			$attendee instanceof EE_Attendee
901
+			&& EE_Registry::instance()->CAP->current_user_can(
902
+				'ee_send_message',
903
+				'espresso_transactions_send_payment_reminder'
904
+			)
905
+		) {
906
+			$actions['payment_reminder'] =
907
+				EEH_MSG_Template::is_mt_active('payment_reminder')
908
+				&& $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
909
+				&& $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
910
+					? EEH_Template::get_button_or_link(
911
+						EE_Admin_Page::add_query_args_and_nonce(
912
+							[
913
+							'action'      => 'send_payment_reminder',
914
+							'TXN_ID'      => $this->_transaction->ID(),
915
+							'redirect_to' => 'view_transaction',
916
+							],
917
+							TXN_ADMIN_URL
918
+						),
919
+						esc_html__(' Send Payment Reminder', 'event_espresso'),
920
+						'button button--secondary',
921
+						'dashicons dashicons-email-alt'
922
+					)
923
+					: '';
924
+		}
925
+
926
+		if (
927
+			EE_Registry::instance()->CAP->current_user_can(
928
+				'ee_edit_payments',
929
+				'espresso_transactions_recalculate_line_items'
930
+			)
931
+		) {
932
+			$actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
933
+				EE_Admin_Page::add_query_args_and_nonce(
934
+					[
935
+						'action'      => 'espresso_recalculate_line_items',
936
+						'TXN_ID'      => $this->_transaction->ID(),
937
+						'redirect_to' => 'view_transaction',
938
+					],
939
+					TXN_ADMIN_URL
940
+				),
941
+				esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
942
+				'button button--secondary',
943
+				'dashicons dashicons-update'
944
+			);
945
+		}
946
+
947
+		if (
948
+			$primary_registration instanceof EE_Registration
949
+			&& EEH_MSG_Template::is_mt_active('receipt')
950
+		) {
951
+			$actions['receipt'] = EEH_Template::get_button_or_link(
952
+				$primary_registration->receipt_url(),
953
+				esc_html__('View Receipt', 'event_espresso'),
954
+				'button button--secondary',
955
+				'dashicons dashicons-text-page'
956
+			);
957
+		}
958
+
959
+		if (
960
+			$primary_registration instanceof EE_Registration
961
+			&& EEH_MSG_Template::is_mt_active('invoice')
962
+		) {
963
+			$actions['invoice'] = EEH_Template::get_button_or_link(
964
+				$primary_registration->invoice_url(),
965
+				esc_html__('View Invoice', 'event_espresso'),
966
+				'button button--secondary',
967
+				'dashicons dashicons-media-spreadsheet'
968
+			);
969
+		}
970
+		$actions = array_filter(
971
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
972
+		);
973
+		if ($actions) {
974
+			$content .= implode('', $actions);
975
+		}
976
+		return $content;
977
+	}
978
+
979
+
980
+	/**
981
+	 * txn_details_meta_box
982
+	 * generates HTML for the Transaction main meta box
983
+	 *
984
+	 * @return void
985
+	 * @throws DomainException
986
+	 * @throws EE_Error
987
+	 * @throws InvalidArgumentException
988
+	 * @throws InvalidDataTypeException
989
+	 * @throws InvalidInterfaceException
990
+	 * @throws RuntimeException
991
+	 * @throws ReflectionException
992
+	 */
993
+	public function txn_details_meta_box()
994
+	{
995
+		$this->_set_transaction_object();
996
+		$this->_template_args['TXN_ID']              = $this->_transaction->ID();
997
+		$this->_template_args['attendee']            =
998
+			$this->_transaction->primary_registration() instanceof EE_Registration
999
+				? $this->_transaction->primary_registration()->attendee()
1000
+				: null;
1001
+		$this->_template_args['can_edit_payments']   = EE_Registry::instance()->CAP->current_user_can(
1002
+			'ee_edit_payments',
1003
+			'apply_payment_or_refund_from_registration_details'
1004
+		);
1005
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1006
+			'ee_delete_payments',
1007
+			'delete_payment_from_registration_details'
1008
+		);
1009
+
1010
+		// get line table
1011
+		EEH_Autoloader::register_line_item_display_autoloaders();
1012
+		$Line_Item_Display                       = new EE_Line_Item_Display(
1013
+			'admin_table',
1014
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1015
+		);
1016
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1017
+			$this->_transaction->total_line_item()
1018
+		);
1019
+		$this->_template_args['REG_code']        =
1020
+			$this->_transaction->primary_registration() instanceof EE_Registration
1021
+				? $this->_transaction->primary_registration()->reg_code()
1022
+				: null;
1023
+		// process taxes
1024
+		$taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1025
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1026
+
1027
+		$this->_template_args['grand_total']     = EEH_Template::format_currency(
1028
+			$this->_transaction->total(),
1029
+			false,
1030
+			false
1031
+		);
1032
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1033
+		$this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1034
+
1035
+		// process payment details
1036
+		$payments = $this->_transaction->payments();
1037
+		if (! empty($payments)) {
1038
+			$this->_template_args['payments']              = $payments;
1039
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1040
+		} else {
1041
+			$this->_template_args['payments']              = false;
1042
+			$this->_template_args['existing_reg_payments'] = [];
1043
+		}
1044
+
1045
+		$this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1046
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1047
+			['action' => 'espresso_delete_payment'],
1048
+			TXN_ADMIN_URL
1049
+		);
1050
+
1051
+		if (isset($txn_details['invoice_number'])) {
1052
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1053
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1054
+				'Invoice Number',
1055
+				'event_espresso'
1056
+			);
1057
+		}
1058
+
1059
+		$this->_template_args['txn_details']['registration_session']['value'] =
1060
+			$this->_transaction->primary_registration() instanceof EE_Registration
1061
+				? $this->_transaction->primary_registration()->session_ID()
1062
+				: null;
1063
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1064
+			'Registration Session',
1065
+			'event_espresso'
1066
+		);
1067
+
1068
+		$this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1069
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1070
+			'Transaction placed from IP',
1071
+			'event_espresso'
1072
+		);
1073
+
1074
+		$this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1075
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1076
+			'Registrant User Agent',
1077
+			'event_espresso'
1078
+		);
1079
+
1080
+		$reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1081
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1082
+			if ($reg_step_status === true) {
1083
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1084
+							  . sprintf(
1085
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1086
+								  ucwords(str_replace('_', ' ', $reg_step))
1087
+							  )
1088
+							  . '</div>';
1089
+			} elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1090
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1091
+							  . sprintf(
1092
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1093
+								  ucwords(str_replace('_', ' ', $reg_step)),
1094
+								  date(
1095
+									  get_option('date_format') . ' ' . get_option('time_format'),
1096
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1097
+								  )
1098
+							  )
1099
+							  . '</div>';
1100
+			} else {
1101
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1102
+							  . sprintf(
1103
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1104
+								  ucwords(str_replace('_', ' ', $reg_step))
1105
+							  )
1106
+							  . '</div>';
1107
+			}
1108
+		}
1109
+		$reg_steps                                                 .= '</ul>';
1110
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1111
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1112
+			'Registration Step Progress',
1113
+			'event_espresso'
1114
+		);
1115
+
1116
+
1117
+		$this->_get_registrations_to_apply_payment_to();
1118
+		$this->_get_payment_methods($payments);
1119
+		$this->_get_payment_status_array();
1120
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1121
+
1122
+		$this->_template_args['transaction_form_url']    = add_query_arg(
1123
+			[
1124
+				'action'  => 'edit_transaction',
1125
+				'process' => 'transaction',
1126
+			],
1127
+			TXN_ADMIN_URL
1128
+		);
1129
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(
1130
+			[
1131
+				'page'   => 'espresso_transactions',
1132
+				'action' => 'espresso_apply_payment',
1133
+			],
1134
+			TXN_ADMIN_URL
1135
+		);
1136
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1137
+			[
1138
+				'page'   => 'espresso_transactions',
1139
+				'action' => 'espresso_delete_payment',
1140
+			],
1141
+			TXN_ADMIN_URL
1142
+		);
1143
+
1144
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1145
+
1146
+		// 'espresso_delete_payment_nonce'
1147
+
1148
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1149
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1150
+	}
1151
+
1152
+
1153
+	/**
1154
+	 * _get_registration_payment_IDs
1155
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1156
+	 *
1157
+	 * @access protected
1158
+	 * @param EE_Payment[] $payments
1159
+	 * @return array
1160
+	 * @throws EE_Error
1161
+	 * @throws InvalidArgumentException
1162
+	 * @throws InvalidDataTypeException
1163
+	 * @throws InvalidInterfaceException
1164
+	 * @throws ReflectionException
1165
+	 */
1166
+	protected function _get_registration_payment_IDs($payments = [])
1167
+	{
1168
+		$existing_reg_payments = [];
1169
+		// get all reg payments for these payments
1170
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1171
+			[
1172
+				[
1173
+					'PAY_ID' => [
1174
+						'IN',
1175
+						array_keys($payments),
1176
+					],
1177
+				],
1178
+			]
1179
+		);
1180
+		if (! empty($reg_payments)) {
1181
+			foreach ($payments as $payment) {
1182
+				if (! $payment instanceof EE_Payment) {
1183
+					continue;
1184
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1185
+					$existing_reg_payments[ $payment->ID() ] = [];
1186
+				}
1187
+				foreach ($reg_payments as $reg_payment) {
1188
+					if (
1189
+						$reg_payment instanceof EE_Registration_Payment
1190
+						&& $reg_payment->payment_ID() === $payment->ID()
1191
+					) {
1192
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1193
+					}
1194
+				}
1195
+			}
1196
+		}
1197
+
1198
+		return $existing_reg_payments;
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * _get_registrations_to_apply_payment_to
1204
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1205
+	 * which allows the admin to only apply the payment to the specific registrations
1206
+	 *
1207
+	 * @access protected
1208
+	 * @return void
1209
+	 * @throws EE_Error
1210
+	 * @throws InvalidArgumentException
1211
+	 * @throws InvalidDataTypeException
1212
+	 * @throws InvalidInterfaceException
1213
+	 * @throws ReflectionException
1214
+	 */
1215
+	protected function _get_registrations_to_apply_payment_to()
1216
+	{
1217
+		// we want any registration with an active status (ie: not deleted or cancelled)
1218
+		$query_params                      = [
1219
+			[
1220
+				'STS_ID' => [
1221
+					'IN',
1222
+					[
1223
+						EEM_Registration::status_id_approved,
1224
+						EEM_Registration::status_id_pending_payment,
1225
+						EEM_Registration::status_id_not_approved,
1226
+					],
1227
+				],
1228
+			],
1229
+		];
1230
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1231
+			'',
1232
+			'txn-admin-apply-payment-to-registrations-dv',
1233
+			'',
1234
+			'clear: both; margin: 1.5em 0 0; display: none;'
1235
+		);
1236
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1237
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1238
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1239
+			EEH_HTML::tr(
1240
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1241
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1242
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1243
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1244
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1245
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1246
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1247
+			)
1248
+		);
1249
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1250
+		// get registrations for TXN
1251
+		$registrations         = $this->_transaction->registrations($query_params);
1252
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1253
+		foreach ($registrations as $registration) {
1254
+			if ($registration instanceof EE_Registration) {
1255
+				$attendee_name                     = $registration->attendee() instanceof EE_Attendee
1256
+					? $registration->attendee()->full_name()
1257
+					: esc_html__('Unknown Attendee', 'event_espresso');
1258
+				$owing                             = $registration->final_price() - $registration->paid();
1259
+				$taxable                           = $registration->ticket()->taxable()
1260
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1261
+					: '';
1262
+				$checked                           = empty($existing_reg_payments)
1263
+													 || in_array($registration->ID(), $existing_reg_payments, true)
1264
+					? ' checked'
1265
+					: '';
1266
+				$disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1267
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1268
+					EEH_HTML::td($registration->ID()) .
1269
+					EEH_HTML::td($attendee_name) .
1270
+					EEH_HTML::td(
1271
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1272
+					) .
1273
+					EEH_HTML::td($registration->event_name()) .
1274
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1275
+					EEH_HTML::td(
1276
+						EEH_Template::format_currency($owing),
1277
+						'',
1278
+						'txn-admin-payment-owing-td jst-cntr'
1279
+					) .
1280
+					EEH_HTML::td(
1281
+						'<input type="checkbox" value="' . $registration->ID()
1282
+						. '" name="txn_admin_payment[registrations]"'
1283
+						. $checked . $disabled . '>',
1284
+						'',
1285
+						'jst-cntr'
1286
+					),
1287
+					'apply-payment-registration-row-' . $registration->ID()
1288
+				);
1289
+			}
1290
+		}
1291
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1292
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1293
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1294
+		$registrations_to_apply_payment_to                         .= EEH_HTML::p(
1295
+			esc_html__(
1296
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1297
+				'event_espresso'
1298
+			),
1299
+			'',
1300
+			'clear description'
1301
+		);
1302
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1303
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1304
+	}
1305
+
1306
+
1307
+	/**
1308
+	 * _get_reg_status_selection
1309
+	 *
1310
+	 * @return void
1311
+	 * @throws EE_Error
1312
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1313
+	 *         instead of events.
1314
+	 * @access protected
1315
+	 */
1316
+	protected function _get_reg_status_selection()
1317
+	{
1318
+		// first get all possible statuses
1319
+		$statuses = EEM_Registration::reg_status_array([], true);
1320
+		// let's add a "don't change" option.
1321
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1322
+		$status_array                                        = array_merge($status_array, $statuses);
1323
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1324
+			'txn_reg_status_change[reg_status]',
1325
+			$status_array,
1326
+			'NAN',
1327
+			'id="txn-admin-payment-reg-status-inp"',
1328
+			'txn-reg-status-change-reg-status'
1329
+		);
1330
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1331
+			'delete_txn_reg_status_change[reg_status]',
1332
+			$status_array,
1333
+			'NAN',
1334
+			'delete-txn-admin-payment-reg-status-inp',
1335
+			'delete-txn-reg-status-change-reg-status'
1336
+		);
1337
+	}
1338
+
1339
+
1340
+	/**
1341
+	 *    _get_payment_methods
1342
+	 * Gets all the payment methods available generally, or the ones that are already
1343
+	 * selected on these payments (in case their payment methods are no longer active).
1344
+	 * Has the side-effect of updating the template args' payment_methods item
1345
+	 *
1346
+	 * @access private
1347
+	 * @param EE_Payment[] to show on this page
1348
+	 * @return void
1349
+	 * @throws EE_Error
1350
+	 * @throws InvalidArgumentException
1351
+	 * @throws InvalidDataTypeException
1352
+	 * @throws InvalidInterfaceException
1353
+	 * @throws ReflectionException
1354
+	 */
1355
+	private function _get_payment_methods($payments = [])
1356
+	{
1357
+		$payment_methods_of_payments = [];
1358
+		foreach ($payments as $payment) {
1359
+			if ($payment instanceof EE_Payment) {
1360
+				$payment_methods_of_payments[] = $payment->ID();
1361
+			}
1362
+		}
1363
+		if ($payment_methods_of_payments) {
1364
+			$query_args = [
1365
+				[
1366
+					'OR*payment_method_for_payment' => [
1367
+						'PMD_ID'    => ['IN', $payment_methods_of_payments],
1368
+						'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1369
+					],
1370
+				],
1371
+			];
1372
+		} else {
1373
+			$query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1374
+		}
1375
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1376
+	}
1377
+
1378
+
1379
+	/**
1380
+	 * txn_attendees_meta_box
1381
+	 *    generates HTML for the Attendees Transaction main meta box
1382
+	 *
1383
+	 * @access public
1384
+	 * @param WP_Post $post
1385
+	 * @param array   $metabox
1386
+	 * @return void
1387
+	 * @throws DomainException
1388
+	 * @throws EE_Error
1389
+	 * @throws InvalidArgumentException
1390
+	 * @throws InvalidDataTypeException
1391
+	 * @throws InvalidInterfaceException
1392
+	 * @throws ReflectionException
1393
+	 */
1394
+	public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1395
+	{
1396
+
1397
+		/** @noinspection NonSecureExtractUsageInspection */
1398
+		extract($metabox['args']);
1399
+		$this->_template_args['post']            = $post;
1400
+		$this->_template_args['event_attendees'] = [];
1401
+		// process items in cart
1402
+		$line_items = $this->_transaction->get_many_related(
1403
+			'Line_Item',
1404
+			[['LIN_type' => 'line-item']]
1405
+		);
1406
+		if (! empty($line_items)) {
1407
+			foreach ($line_items as $item) {
1408
+				if ($item instanceof EE_Line_Item) {
1409
+					switch ($item->OBJ_type()) {
1410
+						case 'Event':
1411
+							break;
1412
+						case 'Ticket':
1413
+							$ticket = $item->ticket();
1414
+							// right now we're only handling tickets here.
1415
+							// Cause its expected that only tickets will have attendees right?
1416
+							if (! $ticket instanceof EE_Ticket) {
1417
+								break;
1418
+							}
1419
+							try {
1420
+								$event_name = $ticket->get_event_name();
1421
+							} catch (Exception $e) {
1422
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1423
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1424
+							}
1425
+							$event_name   .= ' - ' . $item->name();
1426
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1427
+							// now get all of the registrations for this transaction that use this ticket
1428
+							$registrations = $ticket->registrations(
1429
+								[['TXN_ID' => $this->_transaction->ID()]]
1430
+							);
1431
+							foreach ($registrations as $registration) {
1432
+								if (! $registration instanceof EE_Registration) {
1433
+									break;
1434
+								}
1435
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1436
+									= $registration->status_ID();
1437
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1438
+									= $registration->count();
1439
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1440
+									= $event_name;
1441
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1442
+									= $ticket_price;
1443
+								// attendee info
1444
+								$attendee = $registration->get_first_related('Attendee');
1445
+								if ($attendee instanceof EE_Attendee) {
1446
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1447
+										= $attendee->ID();
1448
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1449
+										= $attendee->full_name();
1450
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1451
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1452
+										  . esc_html__(
1453
+											  ' Event',
1454
+											  'event_espresso'
1455
+										  )
1456
+										  . '">' . $attendee->email() . '</a>';
1457
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1458
+										= EEH_Address::format($attendee, 'inline', false, false);
1459
+								} else {
1460
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1461
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1462
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1463
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1464
+								}
1465
+							}
1466
+							break;
1467
+					}
1468
+				}
1469
+			}
1470
+
1471
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1472
+				[
1473
+					'action'  => 'edit_transaction',
1474
+					'process' => 'attendees',
1475
+				],
1476
+				TXN_ADMIN_URL
1477
+			);
1478
+			echo EEH_Template::display_template(
1479
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1480
+				$this->_template_args,
1481
+				true
1482
+			);
1483
+		} else {
1484
+			printf(
1485
+				esc_html__(
1486
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1487
+					'event_espresso'
1488
+				),
1489
+				'<p class="important-notice">',
1490
+				'</p>'
1491
+			);
1492
+		}
1493
+	}
1494
+
1495
+
1496
+	/**
1497
+	 * txn_registrant_side_meta_box
1498
+	 * generates HTML for the Edit Transaction side meta box
1499
+	 *
1500
+	 * @access public
1501
+	 * @return void
1502
+	 * @throws DomainException
1503
+	 * @throws EE_Error
1504
+	 * @throws InvalidArgumentException
1505
+	 * @throws InvalidDataTypeException
1506
+	 * @throws InvalidInterfaceException
1507
+	 * @throws ReflectionException
1508
+	 */
1509
+	public function txn_registrant_side_meta_box()
1510
+	{
1511
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1512
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1513
+			: null;
1514
+		if (! $primary_att instanceof EE_Attendee) {
1515
+			$this->_template_args['no_attendee_message'] = esc_html__(
1516
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1517
+				'event_espresso'
1518
+			);
1519
+			$primary_att                           = EEM_Attendee::instance()->create_default_object();
1520
+		}
1521
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1522
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1523
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1524
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1525
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1526
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1527
+			[
1528
+				'action' => 'edit_attendee',
1529
+				'post'   => $primary_att->ID(),
1530
+			],
1531
+			REG_ADMIN_URL
1532
+		);
1533
+		// get formatted address for registrant
1534
+		$formatted_address = EEH_Address::format($primary_att);
1535
+		$formatted_address = $formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1536
+			? $formatted_address
1537
+			: '';
1538
+		$this->_template_args['formatted_address'] = $formatted_address;
1539
+		echo EEH_Template::display_template(
1540
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1541
+			$this->_template_args,
1542
+			true
1543
+		);
1544
+	}
1545
+
1546
+
1547
+	/**
1548
+	 * txn_billing_info_side_meta_box
1549
+	 *    generates HTML for the Edit Transaction side meta box
1550
+	 *
1551
+	 * @access public
1552
+	 * @return void
1553
+	 * @throws DomainException
1554
+	 * @throws EE_Error
1555
+	 * @throws ReflectionException
1556
+	 */
1557
+	public function txn_billing_info_side_meta_box()
1558
+	{
1559
+
1560
+		$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1561
+		$this->_template_args['billing_form_url'] = add_query_arg(
1562
+			['action' => 'edit_transaction', 'process' => 'billing'],
1563
+			TXN_ADMIN_URL
1564
+		);
1565
+
1566
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1567
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1568
+	}
1569
+
1570
+
1571
+	/**
1572
+	 * apply_payments_or_refunds
1573
+	 *    registers a payment or refund made towards a transaction
1574
+	 *
1575
+	 * @access public
1576
+	 * @return void
1577
+	 * @throws EE_Error
1578
+	 * @throws InvalidArgumentException
1579
+	 * @throws ReflectionException
1580
+	 * @throws RuntimeException
1581
+	 * @throws InvalidDataTypeException
1582
+	 * @throws InvalidInterfaceException
1583
+	 */
1584
+	public function apply_payments_or_refunds()
1585
+	{
1586
+		$valid_data         = $this->_validate_payment_request_data();
1587
+		$has_access         = EE_Registry::instance()->CAP->current_user_can(
1588
+			'ee_edit_payments',
1589
+			'apply_payment_or_refund_from_registration_details'
1590
+		);
1591
+		$TXD_ID = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1592
+		$amount = 0;
1593
+		if (! empty($valid_data) && $has_access) {
1594
+			$PAY_ID = $valid_data['PAY_ID'];
1595
+			// save  the new payment
1596
+			$payment = $this->_create_payment_from_request_data($valid_data);
1597
+			$amount = $payment->amount();
1598
+			// get the TXN for this payment
1599
+			$transaction = $payment->transaction();
1600
+			// verify transaction
1601
+			if ($transaction instanceof EE_Transaction) {
1602
+				// calculate_total_payments_and_update_status
1603
+				$this->_process_transaction_payments($transaction);
1604
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1605
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1606
+				// apply payment to registrations (if applicable)
1607
+				if (! empty($REG_IDs)) {
1608
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1609
+					$this->_maybe_send_notifications();
1610
+					// now process status changes for the same registrations
1611
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1612
+				}
1613
+				$this->_maybe_send_notifications($payment);
1614
+				// prepare to render page
1615
+				do_action(
1616
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1617
+					$transaction,
1618
+					$payment
1619
+				);
1620
+			} else {
1621
+				EE_Error::add_error(
1622
+					esc_html__(
1623
+						'A valid Transaction for this payment could not be retrieved.',
1624
+						'event_espresso'
1625
+					),
1626
+					__FILE__,
1627
+					__FUNCTION__,
1628
+					__LINE__
1629
+				);
1630
+			}
1631
+		} elseif ($has_access) {
1632
+			EE_Error::add_error(
1633
+				esc_html__(
1634
+					'The payment form data could not be processed. Please try again.',
1635
+					'event_espresso'
1636
+				),
1637
+				__FILE__,
1638
+				__FUNCTION__,
1639
+				__LINE__
1640
+			);
1641
+		} else {
1642
+			EE_Error::add_error(
1643
+				esc_html__(
1644
+					'You do not have access to apply payments or refunds to a registration.',
1645
+					'event_espresso'
1646
+				),
1647
+				__FILE__,
1648
+				__FUNCTION__,
1649
+				__LINE__
1650
+			);
1651
+		}
1652
+		$query_args = [
1653
+			'page' => 'espresso_transactions',
1654
+			 'action' => 'view_transaction',
1655
+			 'TXN_ID' => $TXD_ID
1656
+		];
1657
+
1658
+		$this->_redirect_after_action(
1659
+			! EE_Error::has_error(),
1660
+			$amount > 0
1661
+				? esc_html__('payment', 'event_espresso')
1662
+				: esc_html__('refund', 'event_espresso'),
1663
+			esc_html__('processed', 'event_espresso'),
1664
+			$query_args
1665
+		);
1666
+	}
1667
+
1668
+
1669
+	/**
1670
+	 * _validate_payment_request_data
1671
+	 *
1672
+	 * @return array
1673
+	 * @throws EE_Error
1674
+	 * @throws InvalidArgumentException
1675
+	 * @throws InvalidDataTypeException
1676
+	 * @throws InvalidInterfaceException
1677
+	 */
1678
+	protected function _validate_payment_request_data()
1679
+	{
1680
+		if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1681
+			return [];
1682
+		}
1683
+		$payment_form = $this->_generate_payment_form_section();
1684
+		try {
1685
+			if ($payment_form->was_submitted()) {
1686
+				$payment_form->receive_form_submission();
1687
+				if (! $payment_form->is_valid()) {
1688
+					$submission_error_messages = [];
1689
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1690
+						if ($validation_error instanceof EE_Validation_Error) {
1691
+							$form_input = $validation_error->get_form_section();
1692
+							$submission_error_messages[] = sprintf(
1693
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1694
+								$form_input instanceof EE_Form_Input_Base ? $form_input->html_label_text() : '',
1695
+								$validation_error->getMessage()
1696
+							);
1697
+						}
1698
+					}
1699
+					EE_Error::add_error(
1700
+						implode('<br />', $submission_error_messages),
1701
+						__FILE__,
1702
+						__FUNCTION__,
1703
+						__LINE__
1704
+					);
1705
+					return [];
1706
+				}
1707
+			}
1708
+		} catch (EE_Error $e) {
1709
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1710
+			return [];
1711
+		}
1712
+
1713
+		return $payment_form->valid_data();
1714
+	}
1715
+
1716
+
1717
+	/**
1718
+	 * _generate_payment_form_section
1719
+	 *
1720
+	 * @return EE_Form_Section_Proper
1721
+	 * @throws EE_Error
1722
+	 */
1723
+	protected function _generate_payment_form_section()
1724
+	{
1725
+		return new EE_Form_Section_Proper(
1726
+			[
1727
+				'name'        => 'txn_admin_payment',
1728
+				'subsections' => [
1729
+					'PAY_ID'          => new EE_Text_Input(
1730
+						[
1731
+							'default'               => 0,
1732
+							'required'              => false,
1733
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1734
+							'validation_strategies' => [new EE_Int_Normalization()],
1735
+						]
1736
+					),
1737
+					'TXN_ID'          => new EE_Text_Input(
1738
+						[
1739
+							'default'               => 0,
1740
+							'required'              => true,
1741
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1742
+							'validation_strategies' => [new EE_Int_Normalization()],
1743
+						]
1744
+					),
1745
+					'type'            => new EE_Text_Input(
1746
+						[
1747
+							'default'               => 1,
1748
+							'required'              => true,
1749
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1750
+							'validation_strategies' => [new EE_Int_Normalization()],
1751
+						]
1752
+					),
1753
+					'amount'          => new EE_Text_Input(
1754
+						[
1755
+							'default'               => 0,
1756
+							'required'              => true,
1757
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1758
+							'validation_strategies' => [new EE_Float_Normalization()],
1759
+						]
1760
+					),
1761
+					'status'          => new EE_Text_Input(
1762
+						[
1763
+							'default'         => EEM_Payment::status_id_approved,
1764
+							'required'        => true,
1765
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1766
+						]
1767
+					),
1768
+					'PMD_ID'          => new EE_Text_Input(
1769
+						[
1770
+							'default'               => 2,
1771
+							'required'              => true,
1772
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1773
+							'validation_strategies' => [new EE_Int_Normalization()],
1774
+						]
1775
+					),
1776
+					'date'            => new EE_Text_Input(
1777
+						[
1778
+							'default'         => time(),
1779
+							'required'        => true,
1780
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1781
+						]
1782
+					),
1783
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1784
+						[
1785
+							'default'               => '',
1786
+							'required'              => false,
1787
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1788
+							'validation_strategies' => [
1789
+								new EE_Max_Length_Validation_Strategy(
1790
+									esc_html__('Input too long', 'event_espresso'),
1791
+									100
1792
+								),
1793
+							],
1794
+						]
1795
+					),
1796
+					'po_number'       => new EE_Text_Input(
1797
+						[
1798
+							'default'               => '',
1799
+							'required'              => false,
1800
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1801
+							'validation_strategies' => [
1802
+								new EE_Max_Length_Validation_Strategy(
1803
+									esc_html__('Input too long', 'event_espresso'),
1804
+									100
1805
+								),
1806
+							],
1807
+						]
1808
+					),
1809
+					'accounting'      => new EE_Text_Input(
1810
+						[
1811
+							'default'               => '',
1812
+							'required'              => false,
1813
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1814
+							'validation_strategies' => [
1815
+								new EE_Max_Length_Validation_Strategy(
1816
+									esc_html__('Input too long', 'event_espresso'),
1817
+									100
1818
+								),
1819
+							],
1820
+						]
1821
+					),
1822
+				],
1823
+			]
1824
+		);
1825
+	}
1826
+
1827
+
1828
+	/**
1829
+	 * _create_payment_from_request_data
1830
+	 *
1831
+	 * @param array $valid_data
1832
+	 * @return EE_Payment
1833
+	 * @throws EE_Error
1834
+	 * @throws InvalidArgumentException
1835
+	 * @throws InvalidDataTypeException
1836
+	 * @throws InvalidInterfaceException
1837
+	 * @throws ReflectionException
1838
+	 */
1839
+	protected function _create_payment_from_request_data($valid_data)
1840
+	{
1841
+		$PAY_ID = $valid_data['PAY_ID'];
1842
+		// get payment amount
1843
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1844
+		// payments have a type value of 1 and refunds have a type value of -1
1845
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1846
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1847
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1848
+		$date    = $valid_data['date']
1849
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1850
+			: date('Y-m-d g:i a', current_time('timestamp'));
1851
+		$payment = EE_Payment::new_instance(
1852
+			[
1853
+				'TXN_ID'              => $valid_data['TXN_ID'],
1854
+				'STS_ID'              => $valid_data['status'],
1855
+				'PAY_timestamp'       => $date,
1856
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1857
+				'PMD_ID'              => $valid_data['PMD_ID'],
1858
+				'PAY_amount'          => $amount,
1859
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1860
+				'PAY_po_number'       => $valid_data['po_number'],
1861
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1862
+				'PAY_details'         => $valid_data,
1863
+				'PAY_ID'              => $PAY_ID,
1864
+			],
1865
+			'',
1866
+			['Y-m-d', 'g:i a']
1867
+		);
1868
+
1869
+		if (! $payment->save()) {
1870
+			EE_Error::add_error(
1871
+				sprintf(
1872
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1873
+					$payment->ID()
1874
+				),
1875
+				__FILE__,
1876
+				__FUNCTION__,
1877
+				__LINE__
1878
+			);
1879
+		}
1880
+
1881
+		return $payment;
1882
+	}
1883
+
1884
+
1885
+	/**
1886
+	 * _process_transaction_payments
1887
+	 *
1888
+	 * @param EE_Transaction $transaction
1889
+	 * @return void
1890
+	 * @throws EE_Error
1891
+	 * @throws InvalidArgumentException
1892
+	 * @throws ReflectionException
1893
+	 * @throws InvalidDataTypeException
1894
+	 * @throws InvalidInterfaceException
1895
+	 */
1896
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1897
+	{
1898
+		/** @type EE_Transaction_Payments $transaction_payments */
1899
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1900
+		// update the transaction with this payment
1901
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1902
+			EE_Error::add_success(
1903
+				esc_html__(
1904
+					'The payment has been processed successfully.',
1905
+					'event_espresso'
1906
+				),
1907
+				__FILE__,
1908
+				__FUNCTION__,
1909
+				__LINE__
1910
+			);
1911
+		} else {
1912
+			EE_Error::add_error(
1913
+				esc_html__(
1914
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1915
+					'event_espresso'
1916
+				),
1917
+				__FILE__,
1918
+				__FUNCTION__,
1919
+				__LINE__
1920
+			);
1921
+		}
1922
+	}
1923
+
1924
+
1925
+	/**
1926
+	 * _get_REG_IDs_to_apply_payment_to
1927
+	 * returns a list of registration IDs that the payment will apply to
1928
+	 *
1929
+	 * @param EE_Payment $payment
1930
+	 * @return array
1931
+	 * @throws EE_Error
1932
+	 * @throws InvalidArgumentException
1933
+	 * @throws InvalidDataTypeException
1934
+	 * @throws InvalidInterfaceException
1935
+	 * @throws ReflectionException
1936
+	 */
1937
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1938
+	{
1939
+		// grab array of IDs for specific registrations to apply changes to
1940
+		$apply_to_all = $this->request->getRequestParam(
1941
+			'txn_admin_payment[apply_to_all_registrations]',
1942
+			false,
1943
+			DataType::BOOL
1944
+		);
1945
+		$REG_IDs = ! $apply_to_all
1946
+			? $this->request->getRequestParam(
1947
+				'txn_admin_payment[registrations]',
1948
+				[],
1949
+				DataType::INT,
1950
+				true
1951
+			)
1952
+			: [];
1953
+		// nothing specified ? then get all reg IDs
1954
+		if ($apply_to_all || empty($REG_IDs)) {
1955
+			$registrations = $payment->transaction()->registrations();
1956
+			$REG_IDs       = ! empty($registrations)
1957
+				? array_keys($registrations)
1958
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1959
+		}
1960
+		// ensure that REG_IDs are integers and NOT strings
1961
+		return array_map('absint', $REG_IDs);
1962
+	}
1963
+
1964
+
1965
+	/**
1966
+	 * @return array
1967
+	 */
1968
+	public function existing_reg_payment_REG_IDs()
1969
+	{
1970
+		return $this->_existing_reg_payment_REG_IDs;
1971
+	}
1972
+
1973
+
1974
+	/**
1975
+	 * @param array $existing_reg_payment_REG_IDs
1976
+	 */
1977
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1978
+	{
1979
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1980
+	}
1981
+
1982
+
1983
+	/**
1984
+	 * _get_existing_reg_payment_REG_IDs
1985
+	 * returns a list of registration IDs that the payment is currently related to
1986
+	 * as recorded in the database
1987
+	 *
1988
+	 * @param EE_Payment $payment
1989
+	 * @return array
1990
+	 * @throws EE_Error
1991
+	 * @throws InvalidArgumentException
1992
+	 * @throws InvalidDataTypeException
1993
+	 * @throws InvalidInterfaceException
1994
+	 * @throws ReflectionException
1995
+	 */
1996
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1997
+	{
1998
+		if ($this->existing_reg_payment_REG_IDs() === null) {
1999
+			// let's get any existing reg payment records for this payment
2000
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2001
+			// but we only want the REG IDs, so grab the array keys
2002
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2003
+				? array_keys($existing_reg_payment_REG_IDs)
2004
+				: [];
2005
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2006
+		}
2007
+
2008
+		return $this->existing_reg_payment_REG_IDs();
2009
+	}
2010
+
2011
+
2012
+	/**
2013
+	 * _remove_existing_registration_payments
2014
+	 * this calculates the difference between existing relations
2015
+	 * to the supplied payment and the new list registration IDs,
2016
+	 * removes any related registrations that no longer apply,
2017
+	 * and then updates the registration paid fields
2018
+	 *
2019
+	 * @param EE_Payment $payment
2020
+	 * @param int        $PAY_ID
2021
+	 * @return bool;
2022
+	 * @throws EE_Error
2023
+	 * @throws InvalidArgumentException
2024
+	 * @throws ReflectionException
2025
+	 * @throws InvalidDataTypeException
2026
+	 * @throws InvalidInterfaceException
2027
+	 */
2028
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2029
+	{
2030
+		// newly created payments will have nothing recorded for $PAY_ID
2031
+		if (absint($PAY_ID) === 0) {
2032
+			return false;
2033
+		}
2034
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2035
+		if (empty($existing_reg_payment_REG_IDs)) {
2036
+			return false;
2037
+		}
2038
+		/** @type EE_Transaction_Payments $transaction_payments */
2039
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2040
+
2041
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2042
+			$payment,
2043
+			[
2044
+				[
2045
+					'PAY_ID' => $payment->ID(),
2046
+					'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2047
+				],
2048
+			]
2049
+		);
2050
+	}
2051
+
2052
+
2053
+	/**
2054
+	 * _update_registration_payments
2055
+	 * this applies the payments to the selected registrations
2056
+	 * but only if they have not already been paid for
2057
+	 *
2058
+	 * @param EE_Transaction $transaction
2059
+	 * @param EE_Payment     $payment
2060
+	 * @param array          $REG_IDs
2061
+	 * @return void
2062
+	 * @throws EE_Error
2063
+	 * @throws InvalidArgumentException
2064
+	 * @throws ReflectionException
2065
+	 * @throws RuntimeException
2066
+	 * @throws InvalidDataTypeException
2067
+	 * @throws InvalidInterfaceException
2068
+	 */
2069
+	protected function _update_registration_payments(
2070
+		EE_Transaction $transaction,
2071
+		EE_Payment $payment,
2072
+		$REG_IDs = []
2073
+	) {
2074
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2075
+		// so let's do that using our set of REG_IDs from the form
2076
+		$registration_query_where_params = [
2077
+			'REG_ID' => ['IN', $REG_IDs],
2078
+		];
2079
+		// but add in some conditions regarding payment,
2080
+		// so that we don't apply payments to registrations that are free or have already been paid for
2081
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2082
+		if (! $payment->is_a_refund()) {
2083
+			$registration_query_where_params['REG_final_price']  = ['!=', 0];
2084
+			$registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2085
+		}
2086
+		$registrations = $transaction->registrations([$registration_query_where_params]);
2087
+		if (! empty($registrations)) {
2088
+			/** @type EE_Payment_Processor $payment_processor */
2089
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2090
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2091
+		}
2092
+	}
2093
+
2094
+
2095
+	/**
2096
+	 * _process_registration_status_change
2097
+	 * This processes requested registration status changes for all the registrations
2098
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2099
+	 *
2100
+	 * @param EE_Transaction $transaction
2101
+	 * @param array          $REG_IDs
2102
+	 * @return bool
2103
+	 * @throws EE_Error
2104
+	 * @throws InvalidArgumentException
2105
+	 * @throws ReflectionException
2106
+	 * @throws InvalidDataTypeException
2107
+	 * @throws InvalidInterfaceException
2108
+	 */
2109
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2110
+	{
2111
+		// first if there is no change in status then we get out.
2112
+		$reg_status = $reg_status ?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2113
+		if ($reg_status === 'NAN') {
2114
+			// no error message, no change requested, just nothing to do man.
2115
+			return false;
2116
+		}
2117
+		/** @type EE_Transaction_Processor $transaction_processor */
2118
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2119
+
2120
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2121
+		return $transaction_processor->manually_update_registration_statuses(
2122
+			$transaction,
2123
+			$reg_status,
2124
+			[['REG_ID' => ['IN', $REG_IDs]]]
2125
+		);
2126
+	}
2127
+
2128
+
2129
+	/**
2130
+	 * _build_payment_json_response
2131
+	 *
2132
+	 * @access public
2133
+	 * @param EE_Payment  $payment
2134
+	 * @param array       $REG_IDs
2135
+	 * @param bool | null $delete_txn_reg_status_change
2136
+	 * @return array
2137
+	 * @throws EE_Error
2138
+	 * @throws InvalidArgumentException
2139
+	 * @throws InvalidDataTypeException
2140
+	 * @throws InvalidInterfaceException
2141
+	 * @throws ReflectionException
2142
+	 */
2143
+	protected function _build_payment_json_response(
2144
+		EE_Payment $payment,
2145
+		$REG_IDs = [],
2146
+		$delete_txn_reg_status_change = null
2147
+	) {
2148
+		// was the payment deleted ?
2149
+		if (is_bool($delete_txn_reg_status_change)) {
2150
+			return [
2151
+				'PAY_ID'                       => $payment->ID(),
2152
+				'amount'                       => $payment->amount(),
2153
+				'total_paid'                   => $payment->transaction()->paid(),
2154
+				'txn_status'                   => $payment->transaction()->status_ID(),
2155
+				'pay_status'                   => $payment->STS_ID(),
2156
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2157
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2158
+			];
2159
+		}
2160
+
2161
+		$this->_get_payment_status_array();
2162
+		return [
2163
+			'amount'           => $payment->amount(),
2164
+			'total_paid'       => $payment->transaction()->paid(),
2165
+			'txn_status'       => $payment->transaction()->status_ID(),
2166
+			'pay_status'       => $payment->STS_ID(),
2167
+			'PAY_ID'           => $payment->ID(),
2168
+			'STS_ID'           => $payment->STS_ID(),
2169
+			'status'           => self::$_pay_status[ $payment->STS_ID() ],
2170
+			'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2171
+			'method'           => strtoupper($payment->source()),
2172
+			'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2173
+			'gateway'          => $payment->payment_method()
2174
+				? $payment->payment_method()->admin_name()
2175
+				: esc_html__('Unknown', 'event_espresso'),
2176
+			'gateway_response' => $payment->gateway_response(),
2177
+			'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2178
+			'po_number'        => $payment->po_number(),
2179
+			'extra_accntng'    => $payment->extra_accntng(),
2180
+			'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2181
+		];
2182
+	}
2183
+
2184
+
2185
+	/**
2186
+	 * delete_payment
2187
+	 *    delete a payment or refund made towards a transaction
2188
+	 *
2189
+	 * @access public
2190
+	 * @return void
2191
+	 * @throws EE_Error
2192
+	 * @throws InvalidArgumentException
2193
+	 * @throws ReflectionException
2194
+	 * @throws InvalidDataTypeException
2195
+	 * @throws InvalidInterfaceException
2196
+	 */
2197
+	public function delete_payment()
2198
+	{
2199
+		$TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2200
+		// $json_response_data = ['return_data' => false];
2201
+		$PAY_ID = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2202
+		$amount = 0;
2203
+		$can_delete         = EE_Registry::instance()->CAP->current_user_can(
2204
+			'ee_delete_payments',
2205
+			'delete_payment_from_registration_details'
2206
+		);
2207
+		if ($PAY_ID && $can_delete) {
2208
+			$delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2209
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2210
+			if ($payment instanceof EE_Payment) {
2211
+				$amount = $payment->amount();
2212
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2213
+				/** @type EE_Transaction_Payments $transaction_payments */
2214
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2215
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2216
+					if ($delete_txn_reg_status_change) {
2217
+						$this->_maybe_send_notifications();
2218
+						$this->_process_registration_status_change(
2219
+							$payment->transaction(),
2220
+							$REG_IDs,
2221
+							$delete_txn_reg_status_change
2222
+						);
2223
+					}
2224
+				}
2225
+			} else {
2226
+				EE_Error::add_error(
2227
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2228
+					__FILE__,
2229
+					__FUNCTION__,
2230
+					__LINE__
2231
+				);
2232
+			}
2233
+		} elseif ($can_delete) {
2234
+			EE_Error::add_error(
2235
+				esc_html__(
2236
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2237
+					'event_espresso'
2238
+				),
2239
+				__FILE__,
2240
+				__FUNCTION__,
2241
+				__LINE__
2242
+			);
2243
+		} else {
2244
+			EE_Error::add_error(
2245
+				esc_html__(
2246
+					'You do not have access to delete a payment.',
2247
+					'event_espresso'
2248
+				),
2249
+				__FILE__,
2250
+				__FUNCTION__,
2251
+				__LINE__
2252
+			);
2253
+		}
2254
+		$query_args = [
2255
+			'page'   => 'espresso_transactions',
2256
+			'action' => 'view_transaction',
2257
+			'TXN_ID' => $TXD_ID
2258
+		];
2259
+		$this->_redirect_after_action(
2260
+			! EE_Error::has_error(),
2261
+			$amount > 0
2262
+				? esc_html__('payment', 'event_espresso')
2263
+				: esc_html__('refund', 'event_espresso'),
2264
+			esc_html__('deleted', 'event_espresso'),
2265
+			$query_args
2266
+		);
2267
+	}
2268
+
2269
+
2270
+	/**
2271
+	 * _registration_payment_data_array
2272
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2273
+	 *
2274
+	 * @access protected
2275
+	 * @param array $REG_IDs
2276
+	 * @return array
2277
+	 * @throws EE_Error
2278
+	 * @throws InvalidArgumentException
2279
+	 * @throws InvalidDataTypeException
2280
+	 * @throws InvalidInterfaceException
2281
+	 * @throws ReflectionException
2282
+	 */
2283
+	protected function _registration_payment_data_array($REG_IDs)
2284
+	{
2285
+		$registration_payment_data = [];
2286
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2287
+		if (! empty($REG_IDs)) {
2288
+			$registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2289
+			foreach ($registrations as $registration) {
2290
+				if ($registration instanceof EE_Registration) {
2291
+					$registration_payment_data[ $registration->ID() ] = [
2292
+						'paid'  => $registration->pretty_paid(),
2293
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2294
+					];
2295
+				}
2296
+			}
2297
+		}
2298
+
2299
+		return $registration_payment_data;
2300
+	}
2301
+
2302
+
2303
+	/**
2304
+	 * _maybe_send_notifications
2305
+	 * determines whether or not the admin has indicated that notifications should be sent.
2306
+	 * If so, will toggle a filter switch for delivering registration notices.
2307
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2308
+	 *
2309
+	 * @access protected
2310
+	 * @param EE_Payment | null $payment
2311
+	 */
2312
+	protected function _maybe_send_notifications($payment = null)
2313
+	{
2314
+		switch ($payment instanceof EE_Payment) {
2315
+			// payment notifications
2316
+			case true:
2317
+				if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2318
+					$this->_process_payment_notification($payment);
2319
+				}
2320
+				break;
2321
+			// registration notifications
2322
+			case false:
2323
+				if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2324
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2325
+				}
2326
+				break;
2327
+		}
2328
+	}
2329
+
2330
+
2331
+	/**
2332
+	 * _send_payment_reminder
2333
+	 *    generates HTML for the View Transaction Details Admin page
2334
+	 *
2335
+	 * @access protected
2336
+	 * @return void
2337
+	 * @throws EE_Error
2338
+	 * @throws InvalidArgumentException
2339
+	 * @throws InvalidDataTypeException
2340
+	 * @throws InvalidInterfaceException
2341
+	 */
2342
+	protected function _send_payment_reminder()
2343
+	{
2344
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2345
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2346
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2347
+		$query_args  = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2348
+		do_action(
2349
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2350
+			$transaction
2351
+		);
2352
+		$this->_redirect_after_action(
2353
+			false,
2354
+			esc_html__('payment reminder', 'event_espresso'),
2355
+			esc_html__('sent', 'event_espresso'),
2356
+			$query_args,
2357
+			true
2358
+		);
2359
+	}
2360
+
2361
+
2362
+	/**
2363
+	 *  get_transactions
2364
+	 *    get transactions for given parameters (used by list table)
2365
+	 *
2366
+	 * @param int     $per_page how many transactions displayed per page
2367
+	 * @param boolean $count   return the count or objects
2368
+	 * @param string  $view
2369
+	 * @return EE_Transaction[]|int int = count || array of transaction objects
2370
+	 * @throws EE_Error
2371
+	 * @throws InvalidArgumentException
2372
+	 * @throws InvalidDataTypeException
2373
+	 * @throws InvalidInterfaceException
2374
+	 */
2375
+	public function get_transactions($per_page, $count = false, $view = '')
2376
+	{
2377
+		$start_date = wp_strip_all_tags(
2378
+			$this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2379
+		);
2380
+		$end_date = wp_strip_all_tags(
2381
+			$this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2382
+		);
2383
+
2384
+		// make sure our timestamps start and end right at the boundaries for each day
2385
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2386
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2387
+
2388
+
2389
+		// convert to timestamps
2390
+		$start_date = strtotime($start_date);
2391
+		$end_date   = strtotime($end_date);
2392
+
2393
+		// makes sure start date is the lowest value and vice versa
2394
+		$start_date = min($start_date, $end_date);
2395
+		$end_date   = max($start_date, $end_date);
2396
+
2397
+		// convert to correct format for query
2398
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2399
+			'TXN_timestamp',
2400
+			date('Y-m-d H:i:s', $start_date),
2401
+			'Y-m-d H:i:s'
2402
+		);
2403
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2404
+			'TXN_timestamp',
2405
+			date('Y-m-d H:i:s', $end_date),
2406
+			'Y-m-d H:i:s'
2407
+		);
2408
+
2409
+
2410
+		// set orderby
2411
+		$orderby = $this->request->getRequestParam('orderby');
2412
+
2413
+		switch ($orderby) {
2414
+			case 'TXN_ID':
2415
+				break;
2416
+			case 'ATT_fname':
2417
+				$orderby = 'Registration.Attendee.ATT_fname';
2418
+				break;
2419
+			case 'event_name':
2420
+				$orderby = 'Registration.Event.EVT_name';
2421
+				break;
2422
+			default: // 'TXN_timestamp'
2423
+				$orderby = 'TXN_timestamp';
2424
+		}
2425
+
2426
+		$sort         = $this->request->getRequestParam('order', 'DESC');
2427
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
2428
+
2429
+		$per_page = absint($per_page) ? $per_page : 10;
2430
+		$per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2431
+
2432
+		$offset = ($current_page - 1) * $per_page;
2433
+		$limit  = [$offset, $per_page];
2434
+
2435
+		$_where = [
2436
+			'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2437
+			'Registration.REG_count' => 1,
2438
+		];
2439
+
2440
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2441
+		if ($EVT_ID) {
2442
+			$_where['Registration.EVT_ID'] = $EVT_ID;
2443
+		}
2444
+
2445
+		$search_term = $this->request->getRequestParam('s');
2446
+		if ($search_term) {
2447
+			$search_term = '%' . $search_term . '%';
2448
+			$_where['OR']  = [
2449
+				'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2450
+				'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2451
+				'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2452
+				'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2453
+				'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2454
+				'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2455
+				'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2456
+				'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2457
+				'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2458
+				'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2459
+				'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2460
+				'Registration.REG_final_price'        => ['LIKE', $search_term],
2461
+				'Registration.REG_code'               => ['LIKE', $search_term],
2462
+				'Registration.REG_count'              => ['LIKE', $search_term],
2463
+				'Registration.REG_group_size'         => ['LIKE', $search_term],
2464
+				'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2465
+				'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2466
+				'Payment.PAY_source'                  => ['LIKE', $search_term],
2467
+				'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2468
+				'TXN_session_data'                    => ['LIKE', $search_term],
2469
+				'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2470
+			];
2471
+		}
2472
+
2473
+		$status = $this->request->getRequestParam('status');
2474
+		// failed transactions
2475
+		$failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2476
+		$abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2477
+		$incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2478
+
2479
+		if ($failed) {
2480
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2481
+		} elseif ($abandoned) {
2482
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2483
+		} elseif ($incomplete) {
2484
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2485
+		} else {
2486
+			$_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2487
+			$_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2488
+		}
2489
+
2490
+		$query_params = apply_filters(
2491
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2492
+			[
2493
+				$_where,
2494
+				'order_by'                 => [$orderby => $sort],
2495
+				'limit'                    => $limit,
2496
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2497
+			],
2498
+			$this->request->requestParams(),
2499
+			$view,
2500
+			$count
2501
+		);
2502
+
2503
+		return $count
2504
+			? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2505
+			: EEM_Transaction::instance()->get_all($query_params);
2506
+	}
2507
+
2508
+
2509
+	/**
2510
+	 * @throws EE_Error
2511
+	 * @throws InvalidArgumentException
2512
+	 * @throws InvalidDataTypeException
2513
+	 * @throws InvalidInterfaceException
2514
+	 * @throws ReflectionException
2515
+	 * @throws RuntimeException
2516
+	 * @since 4.9.79.p
2517
+	 */
2518
+	public function recalculateLineItems()
2519
+	{
2520
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2521
+		/** @var EE_Transaction $transaction */
2522
+		$transaction     = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2523
+		$success         = $transaction->recalculateLineItems();
2524
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2525
+		$query_args = $redirect_to ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,] : [];
2526
+		$this->_redirect_after_action(
2527
+			$success,
2528
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2529
+			esc_html__('recalculated', 'event_espresso'),
2530
+			$query_args,
2531
+			true
2532
+		);
2533
+	}
2534 2534
 }
Please login to merge, or discard this patch.
admin_pages/registration_form/Registration_Form_Admin_Page.core.php 1 patch
Indentation   +756 added lines, -756 removed lines patch added patch discarded remove patch
@@ -15,699 +15,699 @@  discard block
 block discarded – undo
15 15
  */
16 16
 class Registration_Form_Admin_Page extends EE_Admin_Page
17 17
 {
18
-    /**
19
-     * holds the specific question object for the question details screen
20
-     *
21
-     * @var EE_Question $_question
22
-     */
23
-    protected $_question;
24
-
25
-    /**
26
-     * holds the specific question group object for the question group details screen
27
-     *
28
-     * @var EE_Question_Group $_question_group
29
-     */
30
-    protected $_question_group;
31
-
32
-    /**
33
-     *_question_model EEM_Question model instance (for queries)
34
-     *
35
-     * @var EEM_Question $_question_model ;
36
-     */
37
-    protected $_question_model;
38
-
39
-    /**
40
-     * _question_group_model EEM_Question_group instance (for queries)
41
-     *
42
-     * @var EEM_Question_Group $_question_group_model
43
-     */
44
-    protected $_question_group_model;
45
-
46
-
47
-    /**
48
-     * @Constructor
49
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
50
-     * @throws EE_Error
51
-     * @throws ReflectionException
52
-     */
53
-    public function __construct($routing = true)
54
-    {
55
-        require_once(EE_MODELS . 'EEM_Question.model.php');
56
-        require_once(EE_MODELS . 'EEM_Question_Group.model.php');
57
-        $this->_question_model       = EEM_Question::instance();
58
-        $this->_question_group_model = EEM_Question_Group::instance();
59
-        parent::__construct($routing);
60
-    }
61
-
62
-
63
-    protected function _init_page_props()
64
-    {
65
-        $this->page_slug        = REGISTRATION_FORM_PG_SLUG;
66
-        $this->page_label       = esc_html__('Registration Form', 'event_espresso');
67
-        $this->_admin_base_url  = REGISTRATION_FORM_ADMIN_URL;
68
-        $this->_admin_base_path = REGISTRATION_FORM_ADMIN;
69
-    }
70
-
71
-
72
-    protected function _ajax_hooks()
73
-    {
74
-    }
75
-
76
-
77
-    protected function _define_page_props()
78
-    {
79
-        $this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
80
-        $this->_labels           = [
81
-            'buttons' => [
82
-                'edit_question' => esc_html__('Edit Question', 'event_espresso'),
83
-            ],
84
-        ];
85
-    }
86
-
87
-
88
-    /**
89
-     *_set_page_routes
90
-     */
91
-    protected function _set_page_routes()
92
-    {
93
-        $qst_id             =
94
-            ! empty($this->_req_data['QST_ID'])
95
-                ? $this->_req_data['QST_ID']
96
-                : 0;
97
-        $this->_page_routes = [
98
-            'default' => [
99
-                'func'       => '_questions_overview_list_table',
100
-                'capability' => 'ee_read_questions',
101
-            ],
102
-
103
-            'edit_question' => [
104
-                'func'       => '_edit_question',
105
-                'capability' => 'ee_edit_question',
106
-                'obj_id'     => $qst_id,
107
-                'args'       => ['edit'],
108
-            ],
109
-
110
-            'question_groups' => [
111
-                'func'       => '_questions_groups_preview',
112
-                'capability' => 'ee_read_question_groups',
113
-            ],
114
-
115
-            'update_question' => [
116
-                'func'       => '_insert_or_update_question',
117
-                'args'       => ['new_question' => false],
118
-                'capability' => 'ee_edit_question',
119
-                'obj_id'     => $qst_id,
120
-                'noheader'   => true,
121
-            ],
122
-        ];
123
-    }
124
-
125
-
126
-    protected function _set_page_config()
127
-    {
128
-        $this->_page_config = [
129
-            'default' => [
130
-                'nav'           => [
131
-                    'label' =>  esc_html__('Questions', 'event_espresso'),
132
-                    'icon' => 'dashicons-editor-help',
133
-                    'order' => 10,
134
-                ],
135
-                'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
136
-                'metaboxes'     => $this->_default_espresso_metaboxes,
137
-                'help_tabs'     => [
138
-                    'registration_form_questions_overview_help_tab'                           => [
139
-                        'title'    => esc_html__('Questions Overview', 'event_espresso'),
140
-                        'filename' => 'registration_form_questions_overview',
141
-                    ],
142
-                    'registration_form_questions_overview_table_column_headings_help_tab'     => [
143
-                        'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
144
-                        'filename' => 'registration_form_questions_overview_table_column_headings',
145
-                    ],
146
-                    'registration_form_questions_overview_views_bulk_actions_search_help_tab' => [
147
-                        'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
148
-                        'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
149
-                    ],
150
-                ],
151
-                'require_nonce' => false,
152
-            ],
153
-
154
-            'question_groups' => [
155
-                'nav'           => [
156
-                    'label' =>  esc_html__('Question Groups', 'event_espresso'),
157
-                    'icon' => 'dashicons-forms',
158
-                    'order' => 20,
159
-                ],
160
-                'metaboxes'     => $this->_default_espresso_metaboxes,
161
-                'help_tabs'     => [
162
-                    'registration_form_question_groups_help_tab' => [
163
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
164
-                        'filename' => 'registration_form_question_groups',
165
-                    ],
166
-                ],
167
-                'require_nonce' => false,
168
-            ],
169
-
170
-            'edit_question' => [
171
-                'nav'           => [
172
-                    'label'      => esc_html__('Edit Question', 'event_espresso'),
173
-                    'icon' => 'dashicons-edit-large',
174
-                    'order'      => 15,
175
-                    'persistent' => false,
176
-                    'url'        => isset($this->_req_data['question_id'])
177
-                        ? add_query_arg(
178
-                            ['question_id' => $this->_req_data['question_id']],
179
-                            $this->_current_page_view_url
180
-                        )
181
-                        : $this->_admin_base_url,
182
-                ],
183
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
184
-                'help_tabs'     => [
185
-                    'registration_form_edit_question_group_help_tab' => [
186
-                        'title'    => esc_html__('Edit Question', 'event_espresso'),
187
-                        'filename' => 'registration_form_edit_question',
188
-                    ],
189
-                ],
190
-                'require_nonce' => false,
191
-            ],
192
-        ];
193
-    }
194
-
195
-
196
-    protected function _add_screen_options()
197
-    {
198
-        // todo
199
-    }
200
-
201
-
202
-    protected function _add_screen_options_default()
203
-    {
204
-        $page_title              = $this->_admin_page_title;
205
-        $this->_admin_page_title = esc_html__('Questions', 'event_espresso');
206
-        $this->_per_page_screen_option();
207
-        $this->_admin_page_title = $page_title;
208
-    }
209
-
210
-
211
-    protected function _add_screen_options_question_groups()
212
-    {
213
-        $page_title              = $this->_admin_page_title;
214
-        $this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
215
-        $this->_per_page_screen_option();
216
-        $this->_admin_page_title = $page_title;
217
-    }
218
-
219
-
220
-    // none of the below group are currently used for Event Categories
221
-    protected function _add_feature_pointers()
222
-    {
223
-    }
224
-
225
-
226
-    public function load_scripts_styles()
227
-    {
228
-        wp_register_style(
229
-            'espresso_registration',
230
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
231
-            [],
232
-            EVENT_ESPRESSO_VERSION
233
-        );
234
-        wp_enqueue_style('espresso_registration');
235
-    }
236
-
237
-
238
-    public function admin_init()
239
-    {
240
-    }
241
-
242
-
243
-    public function admin_notices()
244
-    {
245
-    }
246
-
247
-
248
-    public function admin_footer_scripts()
249
-    {
250
-    }
251
-
252
-
253
-    public function load_scripts_styles_default()
254
-    {
255
-    }
256
-
257
-
258
-    /**
259
-     * @throws EE_Error
260
-     */
261
-    public function load_scripts_styles_add_question()
262
-    {
263
-        $this->load_scripts_styles_question_details();
264
-    }
265
-
266
-
267
-    /**
268
-     * @throws EE_Error
269
-     */
270
-    public function load_scripts_styles_edit_question()
271
-    {
272
-        $this->load_scripts_styles_question_details();
273
-    }
274
-
275
-
276
-    /**
277
-     * Loads the JS required for adding or editing a question
278
-     *
279
-     * @throws EE_Error
280
-     * @throws EE_Error
281
-     */
282
-    protected function load_scripts_styles_question_details()
283
-    {
284
-        $this->load_scripts_styles_forms();
285
-        wp_register_script(
286
-            'espresso_registration_form_single',
287
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
288
-            ['jquery-ui-sortable'],
289
-            EVENT_ESPRESSO_VERSION,
290
-            true
291
-        );
292
-        wp_enqueue_script('espresso_registration_form_single');
293
-        wp_localize_script(
294
-            'espresso_registration_form_single',
295
-            'ee_question_data',
296
-            [
297
-                'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
298
-                'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
299
-            ]
300
-        );
301
-    }
302
-
303
-
304
-    public function recaptcha_info_help_tab()
305
-    {
306
-        $template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
307
-        EEH_Template::display_template($template, []);
308
-    }
309
-
310
-
311
-    public function load_scripts_styles_forms()
312
-    {
313
-        // styles
314
-        wp_enqueue_style('espresso-ui-theme');
315
-        // scripts
316
-        wp_enqueue_script('ee_admin_js');
317
-    }
318
-
319
-
320
-    protected function _set_list_table_views_default()
321
-    {
322
-        $this->_views = [
323
-            'all' => [
324
-                'slug'  => 'all',
325
-                'label' => esc_html__('View All Questions', 'event_espresso'),
326
-                'count' => 0,
327
-            ],
328
-        ];
329
-
330
-        if (
331
-            EE_Registry::instance()->CAP->current_user_can(
332
-                'ee_delete_questions',
333
-                'espresso_registration_form_trash_questions'
334
-            )
335
-        ) {
336
-            $this->_views['trash'] = [
337
-                'slug'  => 'trash',
338
-                'label' => esc_html__('Trash', 'event_espresso'),
339
-                'count' => 0,
340
-            ];
341
-        }
342
-    }
343
-
344
-
345
-    /**
346
-     * This just previews the question groups tab that comes in caffeinated.
347
-     *
348
-     * @return void html
349
-     * @throws EE_Error
350
-     */
351
-    protected function _questions_groups_preview()
352
-    {
353
-        $this->_admin_page_title              = esc_html__('Question Groups (Preview)', 'event_espresso');
354
-        $this->_template_args['preview_img']  =
355
-            '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
356
-            . esc_attr__(
357
-                'Preview Question Groups Overview List Table screenshot',
358
-                'event_espresso'
359
-            ) . '" />';
360
-        $this->_template_args['preview_text'] = '<strong>'
361
-                                                . esc_html__(
362
-                                                    'Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
363
-                                                    'event_espresso'
364
-                                                ) . '</strong>';
365
-        $this->display_admin_caf_preview_page('question_groups_tab');
366
-    }
367
-
368
-
369
-    /**
370
-     * Extracts the question field's values from the POST request to update or insert them
371
-     *
372
-     * @param EEM_Base $model
373
-     * @return array where each key is the name of a model's field/db column, and each value is its value.
374
-     * @throws EE_Error
375
-     */
376
-    protected function _set_column_values_for(EEM_Base $model)
377
-    {
378
-        $question_model = EEM_Question::instance();
379
-        $set_column_values = [];
380
-
381
-        // some initial checks for proper values.
382
-        // if QST_admin_only, then no matter what QST_required is we disable.
383
-        if (! empty($this->_req_data['QST_admin_only'])) {
384
-            $this->_req_data['QST_required'] = 0;
385
-        }
386
-        // if the question shouldn't have a max length, don't let them set one
387
-        if (
388
-            ! isset(
389
-                $this->_req_data['QST_type'],
390
-                $this->_req_data['QST_max']
391
-            )
392
-            || ! in_array(
393
-                $this->_req_data['QST_type'],
394
-                $question_model->questionTypesWithMaxLength(),
395
-                true
396
-            )
397
-        ) {
398
-            // they're not allowed to set the max
399
-            $this->_req_data['QST_max'] = null;
400
-        }
401
-        foreach ($model->field_settings() as $fieldName => $settings) {
402
-            // basically if QSG_identifier is empty or not set
403
-            if (
404
-                $fieldName === 'QSG_identifier'
405
-                && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))
406
-            ) {
407
-                $QSG_name = $this->_req_data['QSG_name'] ?? '';
408
-                $set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
409
-            } elseif (
410
-                $fieldName === 'QST_admin_label'
411
-                && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))
412
-            ) {
413
-                // the admin label is blank, use a slug version of the question text
414
-                $QST_text = $this->_req_data['QST_display_text'] ?? '';
415
-                $set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
416
-            } elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
417
-                $set_column_values[ $fieldName ] = 0;
418
-            } elseif ($fieldName === 'QST_max') {
419
-                $qst_system = $question_model->get_var(
420
-                    [
421
-                        [
422
-                            'QST_ID' => $this->_req_data['QST_ID'] ?? 0,
423
-                        ],
424
-                    ],
425
-                    'QST_system'
426
-                );
427
-                $max_max    = $question_model->absolute_max_for_system_question((string) $qst_system);
428
-                if (empty($this->_req_data['QST_max']) || $this->_req_data['QST_max'] > $max_max) {
429
-                    $set_column_values[ $fieldName ] = $max_max;
430
-                }
431
-            }
432
-
433
-
434
-            // only add a property to the array if it's not null (otherwise the model should just use the default value)
435
-            if (
436
-                ! isset($set_column_values[ $fieldName ]) && isset($this->_req_data[ $fieldName ])
437
-            ) {
438
-                $set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
439
-            }
440
-        }
441
-        // validation fo this data to be performed by the model before insertion.
442
-        return $set_column_values;
443
-    }
444
-
445
-
446
-    /**
447
-     *_questions_overview_list_table
448
-     *
449
-     * @throws EE_Error
450
-     */
451
-    protected function _questions_overview_list_table()
452
-    {
453
-        $this->_search_btn_label = esc_html__('Questions', 'event_espresso');
454
-        $this->display_admin_list_table_page_with_sidebar();
455
-    }
456
-
457
-
458
-    /**
459
-     * _edit_question
460
-     *
461
-     * @throws EE_Error
462
-     * @throws ReflectionException
463
-     */
464
-    protected function _edit_question()
465
-    {
466
-        $ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID'])
467
-            ? absint($this->_req_data['QST_ID'])
468
-            : false;
469
-
470
-        switch ($this->_req_action) {
471
-            case 'add_question':
472
-                $this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
473
-                break;
474
-            case 'edit_question':
475
-                $this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
476
-                break;
477
-            default:
478
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
479
-        }
480
-
481
-        // add PRC_ID to title if editing
482
-        $this->_admin_page_title =
483
-            $ID
484
-                ? $this->_admin_page_title . ' # ' . $ID
485
-                : $this->_admin_page_title;
486
-        if ($ID) {
487
-            $question                 = $this->_question_model->get_one_by_ID($ID);
488
-            $additional_hidden_fields = ['QST_ID' => ['type' => 'hidden', 'value' => $ID]];
489
-            $this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
490
-        } else {
491
-            $question = EE_Question::new_instance();
492
-            $question->set_order_to_latest();
493
-            $this->_set_add_edit_form_tags('insert_question');
494
-        }
495
-        if ($question->system_ID() === EEM_Attendee::system_question_phone) {
496
-            $question_types = array_intersect_key(
497
-                EEM_Question::instance()->allowed_question_types(),
498
-                array_flip(
499
-                    [
500
-                        EEM_Question::QST_type_text,
501
-                        EEM_Question::QST_type_us_phone,
502
-                    ]
503
-                )
504
-            );
505
-        } else {
506
-            $question_types = $question->has_answers()
507
-                ? $this->_question_model->question_types_in_same_category($question->type())
508
-                : $this->_question_model->allowed_question_types();
509
-        }
510
-        $this->_template_args['QST_ID']                     = $ID;
511
-        $this->_template_args['question']                   = $question;
512
-        $this->_template_args['question_types']             = $question_types;
513
-        $this->_template_args['max_max']                    =
514
-            EEM_Question::instance()->absolute_max_for_system_question(
515
-                $question->system_ID()
516
-            );
517
-        $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
518
-        $this->_set_publish_post_box_vars('id', $ID);
519
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
520
-            REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
521
-            $this->_template_args,
522
-            true
523
-        );
524
-
525
-        // the details template wrapper
526
-        $this->display_admin_page_with_sidebar();
527
-    }
528
-
529
-
530
-    /**
531
-     * @return string
532
-     * @throws EE_Error
533
-     * @throws ReflectionException
534
-     */
535
-    protected function _get_question_type_descriptions()
536
-    {
537
-        EE_Registry::instance()->load_helper('HTML');
538
-        $descriptions               = '';
539
-        $question_type_descriptions = EEM_Question::instance()->question_descriptions();
540
-        foreach ($question_type_descriptions as $type => $question_type_description) {
541
-            if ($type == 'HTML_TEXTAREA') {
542
-                $html                      = new EE_Simple_HTML_Validation_Strategy();
543
-                $question_type_description .= sprintf(
544
-                    esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
545
-                    '<br/>',
546
-                    $html->get_list_of_allowed_tags()
547
-                );
548
-            }
549
-            $descriptions .= EEH_HTML::p(
550
-                $question_type_description,
551
-                'question_type_description-' . $type,
552
-                'question_type_description description',
553
-                'display:none;'
554
-            );
555
-        }
556
-        return $descriptions;
557
-    }
558
-
559
-
560
-    /**
561
-     * @param bool|true $new_question
562
-     * @throws EE_Error
563
-     * @throws ReflectionException
564
-     */
565
-    protected function _insert_or_update_question($new_question = true)
566
-    {
567
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
568
-        $set_column_values = $this->_set_column_values_for($this->_question_model);
569
-        if ($new_question) {
570
-            $question    = EE_Question::new_instance($set_column_values);
571
-            $action_desc = 'added';
572
-        } else {
573
-            $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
574
-            foreach ($set_column_values as $field => $new_value) {
575
-                $question->set($field, $new_value);
576
-            }
577
-            $action_desc = 'updated';
578
-        }
579
-        $success = $question->save();
580
-        $ID      = $question->ID();
581
-        if ($ID && $question->should_have_question_options()) {
582
-            // save the related options
583
-            // trash removed options, save old ones
584
-            // get list of all options
585
-            $options = $question->options();
586
-            if (! empty($options)) {
587
-                foreach ($options as $option_ID => $option) {
588
-                    $option_req_index = $this->_get_option_req_data_index($option_ID);
589
-                    if ($option_req_index !== false) {
590
-                        $option->save($this->_req_data['question_options'][ $option_req_index ]);
591
-                    } else {
592
-                        // not found, remove it
593
-                        $option->delete();
594
-                    }
595
-                }
596
-            }
597
-            // save new related options
598
-            foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
599
-                // skip $index that is from our sample
600
-                if ($index === 'xxcountxx') {
601
-                    continue;
602
-                }
603
-                // note we allow saving blank options.
604
-                if (empty($option_req_data['QSO_ID'])) {
605
-                    // no ID! save it!
606
-                    $new_option = EE_Question_Option::new_instance(
607
-                        [
608
-                            'QSO_value' => $option_req_data['QSO_value'],
609
-                            'QSO_desc'  => $option_req_data['QSO_desc'],
610
-                            'QSO_order' => $option_req_data['QSO_order'],
611
-                            'QST_ID'    => $question->ID(),
612
-                        ]
613
-                    );
614
-                    $new_option->save();
615
-                }
616
-            }
617
-        }
618
-        $query_args = ['action' => 'edit_question', 'QST_ID' => $ID];
619
-        if ($success !== 0) {
620
-            $msg = $new_question
621
-                ? sprintf(
622
-                    esc_html__('The %s has been created', 'event_espresso'),
623
-                    $this->_question_model->item_name()
624
-                )
625
-                : sprintf(
626
-                    esc_html__('The %s has been updated', 'event_espresso'),
627
-                    $this->_question_model->item_name()
628
-                );
629
-            EE_Error::add_success($msg);
630
-        }
631
-
632
-        $this->_redirect_after_action(false, '', $action_desc, $query_args, true);
633
-    }
634
-
635
-
636
-    /**
637
-     * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
638
-     * by ID
639
-     * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
640
-     * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
641
-     *
642
-     * @param int $ID of the question option to find
643
-     * @return int index in question_options array if successful, FALSE if unsuccessful
644
-     */
645
-    protected function _get_option_req_data_index($ID)
646
-    {
647
-        $req_data_for_question_options = $this->_req_data['question_options'];
648
-        foreach ($req_data_for_question_options as $num => $option_data) {
649
-            if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
650
-                return $num;
651
-            }
652
-        }
653
-        return false;
654
-    }
655
-
656
-
657
-
658
-
659
-    /***********/
660
-    /* QUERIES */
661
-    /**
662
-     * For internal use in getting all the query parameters
663
-     * (because it's pretty well the same between question, question groups,
664
-     * and for both when searching for trashed and untrashed ones)
665
-     *
666
-     * @param EEM_Base $model either EEM_Question or EEM_Question_Group
667
-     * @param int      $per_page
668
-     * @param int      $current_page
669
-     * @return array model query params, @see
670
-     *               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
671
-     */
672
-    protected function get_query_params($model, $per_page = 10, $current_page = 10)
673
-    {
674
-        $query_params             = [];
675
-        $offset                   = ($current_page - 1) * $per_page;
676
-        $query_params['limit']    = [$offset, $per_page];
677
-        $order                    =
678
-            (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
679
-                ? $this->_req_data['order']
680
-                : 'ASC';
681
-        $orderby_field            =
682
-            $model instanceof EEM_Question
683
-                ? 'QST_ID'
684
-                : 'QSG_order';
685
-        $field_to_order_by        =
686
-            empty($this->_req_data['orderby'])
687
-                ? $orderby_field
688
-                : $this->_req_data['orderby'];
689
-        $query_params['order_by'] = [$field_to_order_by => $order];
690
-        $search_string            =
691
-            array_key_exists('s', $this->_req_data)
692
-                ? $this->_req_data['s']
693
-                : null;
694
-        if (! empty($search_string)) {
695
-            if ($model instanceof EEM_Question_Group) {
696
-                $query_params[0] = [
697
-                    'OR' => [
698
-                        'QSG_name' => ['LIKE', "%$search_string%"],
699
-                        'QSG_desc' => ['LIKE', "%$search_string%"],
700
-                    ],
701
-                ];
702
-            } else {
703
-                $query_params[0] = [
704
-                    'QST_display_text' => ['LIKE', "%$search_string%"],
705
-                ];
706
-            }
707
-        }
708
-
709
-        // capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
710
-        /*if ( $model instanceof EEM_Question_Group ) {
18
+	/**
19
+	 * holds the specific question object for the question details screen
20
+	 *
21
+	 * @var EE_Question $_question
22
+	 */
23
+	protected $_question;
24
+
25
+	/**
26
+	 * holds the specific question group object for the question group details screen
27
+	 *
28
+	 * @var EE_Question_Group $_question_group
29
+	 */
30
+	protected $_question_group;
31
+
32
+	/**
33
+	 *_question_model EEM_Question model instance (for queries)
34
+	 *
35
+	 * @var EEM_Question $_question_model ;
36
+	 */
37
+	protected $_question_model;
38
+
39
+	/**
40
+	 * _question_group_model EEM_Question_group instance (for queries)
41
+	 *
42
+	 * @var EEM_Question_Group $_question_group_model
43
+	 */
44
+	protected $_question_group_model;
45
+
46
+
47
+	/**
48
+	 * @Constructor
49
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
50
+	 * @throws EE_Error
51
+	 * @throws ReflectionException
52
+	 */
53
+	public function __construct($routing = true)
54
+	{
55
+		require_once(EE_MODELS . 'EEM_Question.model.php');
56
+		require_once(EE_MODELS . 'EEM_Question_Group.model.php');
57
+		$this->_question_model       = EEM_Question::instance();
58
+		$this->_question_group_model = EEM_Question_Group::instance();
59
+		parent::__construct($routing);
60
+	}
61
+
62
+
63
+	protected function _init_page_props()
64
+	{
65
+		$this->page_slug        = REGISTRATION_FORM_PG_SLUG;
66
+		$this->page_label       = esc_html__('Registration Form', 'event_espresso');
67
+		$this->_admin_base_url  = REGISTRATION_FORM_ADMIN_URL;
68
+		$this->_admin_base_path = REGISTRATION_FORM_ADMIN;
69
+	}
70
+
71
+
72
+	protected function _ajax_hooks()
73
+	{
74
+	}
75
+
76
+
77
+	protected function _define_page_props()
78
+	{
79
+		$this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
80
+		$this->_labels           = [
81
+			'buttons' => [
82
+				'edit_question' => esc_html__('Edit Question', 'event_espresso'),
83
+			],
84
+		];
85
+	}
86
+
87
+
88
+	/**
89
+	 *_set_page_routes
90
+	 */
91
+	protected function _set_page_routes()
92
+	{
93
+		$qst_id             =
94
+			! empty($this->_req_data['QST_ID'])
95
+				? $this->_req_data['QST_ID']
96
+				: 0;
97
+		$this->_page_routes = [
98
+			'default' => [
99
+				'func'       => '_questions_overview_list_table',
100
+				'capability' => 'ee_read_questions',
101
+			],
102
+
103
+			'edit_question' => [
104
+				'func'       => '_edit_question',
105
+				'capability' => 'ee_edit_question',
106
+				'obj_id'     => $qst_id,
107
+				'args'       => ['edit'],
108
+			],
109
+
110
+			'question_groups' => [
111
+				'func'       => '_questions_groups_preview',
112
+				'capability' => 'ee_read_question_groups',
113
+			],
114
+
115
+			'update_question' => [
116
+				'func'       => '_insert_or_update_question',
117
+				'args'       => ['new_question' => false],
118
+				'capability' => 'ee_edit_question',
119
+				'obj_id'     => $qst_id,
120
+				'noheader'   => true,
121
+			],
122
+		];
123
+	}
124
+
125
+
126
+	protected function _set_page_config()
127
+	{
128
+		$this->_page_config = [
129
+			'default' => [
130
+				'nav'           => [
131
+					'label' =>  esc_html__('Questions', 'event_espresso'),
132
+					'icon' => 'dashicons-editor-help',
133
+					'order' => 10,
134
+				],
135
+				'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
136
+				'metaboxes'     => $this->_default_espresso_metaboxes,
137
+				'help_tabs'     => [
138
+					'registration_form_questions_overview_help_tab'                           => [
139
+						'title'    => esc_html__('Questions Overview', 'event_espresso'),
140
+						'filename' => 'registration_form_questions_overview',
141
+					],
142
+					'registration_form_questions_overview_table_column_headings_help_tab'     => [
143
+						'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
144
+						'filename' => 'registration_form_questions_overview_table_column_headings',
145
+					],
146
+					'registration_form_questions_overview_views_bulk_actions_search_help_tab' => [
147
+						'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
148
+						'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
149
+					],
150
+				],
151
+				'require_nonce' => false,
152
+			],
153
+
154
+			'question_groups' => [
155
+				'nav'           => [
156
+					'label' =>  esc_html__('Question Groups', 'event_espresso'),
157
+					'icon' => 'dashicons-forms',
158
+					'order' => 20,
159
+				],
160
+				'metaboxes'     => $this->_default_espresso_metaboxes,
161
+				'help_tabs'     => [
162
+					'registration_form_question_groups_help_tab' => [
163
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
164
+						'filename' => 'registration_form_question_groups',
165
+					],
166
+				],
167
+				'require_nonce' => false,
168
+			],
169
+
170
+			'edit_question' => [
171
+				'nav'           => [
172
+					'label'      => esc_html__('Edit Question', 'event_espresso'),
173
+					'icon' => 'dashicons-edit-large',
174
+					'order'      => 15,
175
+					'persistent' => false,
176
+					'url'        => isset($this->_req_data['question_id'])
177
+						? add_query_arg(
178
+							['question_id' => $this->_req_data['question_id']],
179
+							$this->_current_page_view_url
180
+						)
181
+						: $this->_admin_base_url,
182
+				],
183
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
184
+				'help_tabs'     => [
185
+					'registration_form_edit_question_group_help_tab' => [
186
+						'title'    => esc_html__('Edit Question', 'event_espresso'),
187
+						'filename' => 'registration_form_edit_question',
188
+					],
189
+				],
190
+				'require_nonce' => false,
191
+			],
192
+		];
193
+	}
194
+
195
+
196
+	protected function _add_screen_options()
197
+	{
198
+		// todo
199
+	}
200
+
201
+
202
+	protected function _add_screen_options_default()
203
+	{
204
+		$page_title              = $this->_admin_page_title;
205
+		$this->_admin_page_title = esc_html__('Questions', 'event_espresso');
206
+		$this->_per_page_screen_option();
207
+		$this->_admin_page_title = $page_title;
208
+	}
209
+
210
+
211
+	protected function _add_screen_options_question_groups()
212
+	{
213
+		$page_title              = $this->_admin_page_title;
214
+		$this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
215
+		$this->_per_page_screen_option();
216
+		$this->_admin_page_title = $page_title;
217
+	}
218
+
219
+
220
+	// none of the below group are currently used for Event Categories
221
+	protected function _add_feature_pointers()
222
+	{
223
+	}
224
+
225
+
226
+	public function load_scripts_styles()
227
+	{
228
+		wp_register_style(
229
+			'espresso_registration',
230
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
231
+			[],
232
+			EVENT_ESPRESSO_VERSION
233
+		);
234
+		wp_enqueue_style('espresso_registration');
235
+	}
236
+
237
+
238
+	public function admin_init()
239
+	{
240
+	}
241
+
242
+
243
+	public function admin_notices()
244
+	{
245
+	}
246
+
247
+
248
+	public function admin_footer_scripts()
249
+	{
250
+	}
251
+
252
+
253
+	public function load_scripts_styles_default()
254
+	{
255
+	}
256
+
257
+
258
+	/**
259
+	 * @throws EE_Error
260
+	 */
261
+	public function load_scripts_styles_add_question()
262
+	{
263
+		$this->load_scripts_styles_question_details();
264
+	}
265
+
266
+
267
+	/**
268
+	 * @throws EE_Error
269
+	 */
270
+	public function load_scripts_styles_edit_question()
271
+	{
272
+		$this->load_scripts_styles_question_details();
273
+	}
274
+
275
+
276
+	/**
277
+	 * Loads the JS required for adding or editing a question
278
+	 *
279
+	 * @throws EE_Error
280
+	 * @throws EE_Error
281
+	 */
282
+	protected function load_scripts_styles_question_details()
283
+	{
284
+		$this->load_scripts_styles_forms();
285
+		wp_register_script(
286
+			'espresso_registration_form_single',
287
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
288
+			['jquery-ui-sortable'],
289
+			EVENT_ESPRESSO_VERSION,
290
+			true
291
+		);
292
+		wp_enqueue_script('espresso_registration_form_single');
293
+		wp_localize_script(
294
+			'espresso_registration_form_single',
295
+			'ee_question_data',
296
+			[
297
+				'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
298
+				'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
299
+			]
300
+		);
301
+	}
302
+
303
+
304
+	public function recaptcha_info_help_tab()
305
+	{
306
+		$template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
307
+		EEH_Template::display_template($template, []);
308
+	}
309
+
310
+
311
+	public function load_scripts_styles_forms()
312
+	{
313
+		// styles
314
+		wp_enqueue_style('espresso-ui-theme');
315
+		// scripts
316
+		wp_enqueue_script('ee_admin_js');
317
+	}
318
+
319
+
320
+	protected function _set_list_table_views_default()
321
+	{
322
+		$this->_views = [
323
+			'all' => [
324
+				'slug'  => 'all',
325
+				'label' => esc_html__('View All Questions', 'event_espresso'),
326
+				'count' => 0,
327
+			],
328
+		];
329
+
330
+		if (
331
+			EE_Registry::instance()->CAP->current_user_can(
332
+				'ee_delete_questions',
333
+				'espresso_registration_form_trash_questions'
334
+			)
335
+		) {
336
+			$this->_views['trash'] = [
337
+				'slug'  => 'trash',
338
+				'label' => esc_html__('Trash', 'event_espresso'),
339
+				'count' => 0,
340
+			];
341
+		}
342
+	}
343
+
344
+
345
+	/**
346
+	 * This just previews the question groups tab that comes in caffeinated.
347
+	 *
348
+	 * @return void html
349
+	 * @throws EE_Error
350
+	 */
351
+	protected function _questions_groups_preview()
352
+	{
353
+		$this->_admin_page_title              = esc_html__('Question Groups (Preview)', 'event_espresso');
354
+		$this->_template_args['preview_img']  =
355
+			'<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
356
+			. esc_attr__(
357
+				'Preview Question Groups Overview List Table screenshot',
358
+				'event_espresso'
359
+			) . '" />';
360
+		$this->_template_args['preview_text'] = '<strong>'
361
+												. esc_html__(
362
+													'Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
363
+													'event_espresso'
364
+												) . '</strong>';
365
+		$this->display_admin_caf_preview_page('question_groups_tab');
366
+	}
367
+
368
+
369
+	/**
370
+	 * Extracts the question field's values from the POST request to update or insert them
371
+	 *
372
+	 * @param EEM_Base $model
373
+	 * @return array where each key is the name of a model's field/db column, and each value is its value.
374
+	 * @throws EE_Error
375
+	 */
376
+	protected function _set_column_values_for(EEM_Base $model)
377
+	{
378
+		$question_model = EEM_Question::instance();
379
+		$set_column_values = [];
380
+
381
+		// some initial checks for proper values.
382
+		// if QST_admin_only, then no matter what QST_required is we disable.
383
+		if (! empty($this->_req_data['QST_admin_only'])) {
384
+			$this->_req_data['QST_required'] = 0;
385
+		}
386
+		// if the question shouldn't have a max length, don't let them set one
387
+		if (
388
+			! isset(
389
+				$this->_req_data['QST_type'],
390
+				$this->_req_data['QST_max']
391
+			)
392
+			|| ! in_array(
393
+				$this->_req_data['QST_type'],
394
+				$question_model->questionTypesWithMaxLength(),
395
+				true
396
+			)
397
+		) {
398
+			// they're not allowed to set the max
399
+			$this->_req_data['QST_max'] = null;
400
+		}
401
+		foreach ($model->field_settings() as $fieldName => $settings) {
402
+			// basically if QSG_identifier is empty or not set
403
+			if (
404
+				$fieldName === 'QSG_identifier'
405
+				&& (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))
406
+			) {
407
+				$QSG_name = $this->_req_data['QSG_name'] ?? '';
408
+				$set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
409
+			} elseif (
410
+				$fieldName === 'QST_admin_label'
411
+				&& (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))
412
+			) {
413
+				// the admin label is blank, use a slug version of the question text
414
+				$QST_text = $this->_req_data['QST_display_text'] ?? '';
415
+				$set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
416
+			} elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
417
+				$set_column_values[ $fieldName ] = 0;
418
+			} elseif ($fieldName === 'QST_max') {
419
+				$qst_system = $question_model->get_var(
420
+					[
421
+						[
422
+							'QST_ID' => $this->_req_data['QST_ID'] ?? 0,
423
+						],
424
+					],
425
+					'QST_system'
426
+				);
427
+				$max_max    = $question_model->absolute_max_for_system_question((string) $qst_system);
428
+				if (empty($this->_req_data['QST_max']) || $this->_req_data['QST_max'] > $max_max) {
429
+					$set_column_values[ $fieldName ] = $max_max;
430
+				}
431
+			}
432
+
433
+
434
+			// only add a property to the array if it's not null (otherwise the model should just use the default value)
435
+			if (
436
+				! isset($set_column_values[ $fieldName ]) && isset($this->_req_data[ $fieldName ])
437
+			) {
438
+				$set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
439
+			}
440
+		}
441
+		// validation fo this data to be performed by the model before insertion.
442
+		return $set_column_values;
443
+	}
444
+
445
+
446
+	/**
447
+	 *_questions_overview_list_table
448
+	 *
449
+	 * @throws EE_Error
450
+	 */
451
+	protected function _questions_overview_list_table()
452
+	{
453
+		$this->_search_btn_label = esc_html__('Questions', 'event_espresso');
454
+		$this->display_admin_list_table_page_with_sidebar();
455
+	}
456
+
457
+
458
+	/**
459
+	 * _edit_question
460
+	 *
461
+	 * @throws EE_Error
462
+	 * @throws ReflectionException
463
+	 */
464
+	protected function _edit_question()
465
+	{
466
+		$ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID'])
467
+			? absint($this->_req_data['QST_ID'])
468
+			: false;
469
+
470
+		switch ($this->_req_action) {
471
+			case 'add_question':
472
+				$this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
473
+				break;
474
+			case 'edit_question':
475
+				$this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
476
+				break;
477
+			default:
478
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
479
+		}
480
+
481
+		// add PRC_ID to title if editing
482
+		$this->_admin_page_title =
483
+			$ID
484
+				? $this->_admin_page_title . ' # ' . $ID
485
+				: $this->_admin_page_title;
486
+		if ($ID) {
487
+			$question                 = $this->_question_model->get_one_by_ID($ID);
488
+			$additional_hidden_fields = ['QST_ID' => ['type' => 'hidden', 'value' => $ID]];
489
+			$this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
490
+		} else {
491
+			$question = EE_Question::new_instance();
492
+			$question->set_order_to_latest();
493
+			$this->_set_add_edit_form_tags('insert_question');
494
+		}
495
+		if ($question->system_ID() === EEM_Attendee::system_question_phone) {
496
+			$question_types = array_intersect_key(
497
+				EEM_Question::instance()->allowed_question_types(),
498
+				array_flip(
499
+					[
500
+						EEM_Question::QST_type_text,
501
+						EEM_Question::QST_type_us_phone,
502
+					]
503
+				)
504
+			);
505
+		} else {
506
+			$question_types = $question->has_answers()
507
+				? $this->_question_model->question_types_in_same_category($question->type())
508
+				: $this->_question_model->allowed_question_types();
509
+		}
510
+		$this->_template_args['QST_ID']                     = $ID;
511
+		$this->_template_args['question']                   = $question;
512
+		$this->_template_args['question_types']             = $question_types;
513
+		$this->_template_args['max_max']                    =
514
+			EEM_Question::instance()->absolute_max_for_system_question(
515
+				$question->system_ID()
516
+			);
517
+		$this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
518
+		$this->_set_publish_post_box_vars('id', $ID);
519
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
520
+			REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
521
+			$this->_template_args,
522
+			true
523
+		);
524
+
525
+		// the details template wrapper
526
+		$this->display_admin_page_with_sidebar();
527
+	}
528
+
529
+
530
+	/**
531
+	 * @return string
532
+	 * @throws EE_Error
533
+	 * @throws ReflectionException
534
+	 */
535
+	protected function _get_question_type_descriptions()
536
+	{
537
+		EE_Registry::instance()->load_helper('HTML');
538
+		$descriptions               = '';
539
+		$question_type_descriptions = EEM_Question::instance()->question_descriptions();
540
+		foreach ($question_type_descriptions as $type => $question_type_description) {
541
+			if ($type == 'HTML_TEXTAREA') {
542
+				$html                      = new EE_Simple_HTML_Validation_Strategy();
543
+				$question_type_description .= sprintf(
544
+					esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
545
+					'<br/>',
546
+					$html->get_list_of_allowed_tags()
547
+				);
548
+			}
549
+			$descriptions .= EEH_HTML::p(
550
+				$question_type_description,
551
+				'question_type_description-' . $type,
552
+				'question_type_description description',
553
+				'display:none;'
554
+			);
555
+		}
556
+		return $descriptions;
557
+	}
558
+
559
+
560
+	/**
561
+	 * @param bool|true $new_question
562
+	 * @throws EE_Error
563
+	 * @throws ReflectionException
564
+	 */
565
+	protected function _insert_or_update_question($new_question = true)
566
+	{
567
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
568
+		$set_column_values = $this->_set_column_values_for($this->_question_model);
569
+		if ($new_question) {
570
+			$question    = EE_Question::new_instance($set_column_values);
571
+			$action_desc = 'added';
572
+		} else {
573
+			$question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
574
+			foreach ($set_column_values as $field => $new_value) {
575
+				$question->set($field, $new_value);
576
+			}
577
+			$action_desc = 'updated';
578
+		}
579
+		$success = $question->save();
580
+		$ID      = $question->ID();
581
+		if ($ID && $question->should_have_question_options()) {
582
+			// save the related options
583
+			// trash removed options, save old ones
584
+			// get list of all options
585
+			$options = $question->options();
586
+			if (! empty($options)) {
587
+				foreach ($options as $option_ID => $option) {
588
+					$option_req_index = $this->_get_option_req_data_index($option_ID);
589
+					if ($option_req_index !== false) {
590
+						$option->save($this->_req_data['question_options'][ $option_req_index ]);
591
+					} else {
592
+						// not found, remove it
593
+						$option->delete();
594
+					}
595
+				}
596
+			}
597
+			// save new related options
598
+			foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
599
+				// skip $index that is from our sample
600
+				if ($index === 'xxcountxx') {
601
+					continue;
602
+				}
603
+				// note we allow saving blank options.
604
+				if (empty($option_req_data['QSO_ID'])) {
605
+					// no ID! save it!
606
+					$new_option = EE_Question_Option::new_instance(
607
+						[
608
+							'QSO_value' => $option_req_data['QSO_value'],
609
+							'QSO_desc'  => $option_req_data['QSO_desc'],
610
+							'QSO_order' => $option_req_data['QSO_order'],
611
+							'QST_ID'    => $question->ID(),
612
+						]
613
+					);
614
+					$new_option->save();
615
+				}
616
+			}
617
+		}
618
+		$query_args = ['action' => 'edit_question', 'QST_ID' => $ID];
619
+		if ($success !== 0) {
620
+			$msg = $new_question
621
+				? sprintf(
622
+					esc_html__('The %s has been created', 'event_espresso'),
623
+					$this->_question_model->item_name()
624
+				)
625
+				: sprintf(
626
+					esc_html__('The %s has been updated', 'event_espresso'),
627
+					$this->_question_model->item_name()
628
+				);
629
+			EE_Error::add_success($msg);
630
+		}
631
+
632
+		$this->_redirect_after_action(false, '', $action_desc, $query_args, true);
633
+	}
634
+
635
+
636
+	/**
637
+	 * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
638
+	 * by ID
639
+	 * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
640
+	 * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
641
+	 *
642
+	 * @param int $ID of the question option to find
643
+	 * @return int index in question_options array if successful, FALSE if unsuccessful
644
+	 */
645
+	protected function _get_option_req_data_index($ID)
646
+	{
647
+		$req_data_for_question_options = $this->_req_data['question_options'];
648
+		foreach ($req_data_for_question_options as $num => $option_data) {
649
+			if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
650
+				return $num;
651
+			}
652
+		}
653
+		return false;
654
+	}
655
+
656
+
657
+
658
+
659
+	/***********/
660
+	/* QUERIES */
661
+	/**
662
+	 * For internal use in getting all the query parameters
663
+	 * (because it's pretty well the same between question, question groups,
664
+	 * and for both when searching for trashed and untrashed ones)
665
+	 *
666
+	 * @param EEM_Base $model either EEM_Question or EEM_Question_Group
667
+	 * @param int      $per_page
668
+	 * @param int      $current_page
669
+	 * @return array model query params, @see
670
+	 *               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
671
+	 */
672
+	protected function get_query_params($model, $per_page = 10, $current_page = 10)
673
+	{
674
+		$query_params             = [];
675
+		$offset                   = ($current_page - 1) * $per_page;
676
+		$query_params['limit']    = [$offset, $per_page];
677
+		$order                    =
678
+			(isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
679
+				? $this->_req_data['order']
680
+				: 'ASC';
681
+		$orderby_field            =
682
+			$model instanceof EEM_Question
683
+				? 'QST_ID'
684
+				: 'QSG_order';
685
+		$field_to_order_by        =
686
+			empty($this->_req_data['orderby'])
687
+				? $orderby_field
688
+				: $this->_req_data['orderby'];
689
+		$query_params['order_by'] = [$field_to_order_by => $order];
690
+		$search_string            =
691
+			array_key_exists('s', $this->_req_data)
692
+				? $this->_req_data['s']
693
+				: null;
694
+		if (! empty($search_string)) {
695
+			if ($model instanceof EEM_Question_Group) {
696
+				$query_params[0] = [
697
+					'OR' => [
698
+						'QSG_name' => ['LIKE', "%$search_string%"],
699
+						'QSG_desc' => ['LIKE', "%$search_string%"],
700
+					],
701
+				];
702
+			} else {
703
+				$query_params[0] = [
704
+					'QST_display_text' => ['LIKE', "%$search_string%"],
705
+				];
706
+			}
707
+		}
708
+
709
+		// capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
710
+		/*if ( $model instanceof EEM_Question_Group ) {
711 711
             if ( ! EE_Registry::instance()->CAP->current_user_can( 'edit_others_question_groups', 'espresso_registration_form_edit_question_group' ) ) {
712 712
                 $query_params[0] = array(
713 713
                     'AND' => array(
@@ -737,67 +737,67 @@  discard block
 block discarded – undo
737 737
             }
738 738
         }/**/
739 739
 
740
-        return $query_params;
741
-    }
742
-
743
-
744
-    /**
745
-     * @param int        $per_page
746
-     * @param int        $current_page
747
-     * @param bool|false $count
748
-     * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]|int
749
-     * @throws EE_Error
750
-     */
751
-    public function get_questions($per_page = 10, $current_page = 1, $count = false)
752
-    {
753
-        $QST          = EEM_Question::instance();
754
-        $query_params = $this->get_query_params($QST, $per_page, $current_page);
755
-        if ($count) {
756
-            $where   =
757
-                isset($query_params[0])
758
-                    ? [$query_params[0]]
759
-                    : [];
760
-            $results = $QST->count($where);
761
-        } else {
762
-            $results = $QST->get_all($query_params);
763
-        }
764
-        return $results;
765
-    }
766
-
767
-
768
-    /**
769
-     * @param            $per_page
770
-     * @param int        $current_page
771
-     * @param bool|false $count
772
-     * @return EE_Soft_Delete_Base_Class[]|int
773
-     * @throws EE_Error
774
-     */
775
-    public function get_trashed_questions($per_page, $current_page = 1, $count = false)
776
-    {
777
-        $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
778
-        $where        =
779
-            isset($query_params[0])
780
-                ? [$query_params[0]]
781
-                : [];
782
-        return $count
783
-            ? EEM_Question::instance()->count_deleted($where)
784
-            : EEM_Question::instance()->get_all_deleted($query_params);
785
-    }
786
-
787
-
788
-    /**
789
-     * @param            $per_page
790
-     * @param int        $current_page
791
-     * @param bool|false $count
792
-     * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]
793
-     * @throws EE_Error
794
-     */
795
-    public function get_question_groups($per_page, $current_page = 1, $count = false)
796
-    {
797
-        $questionGroupModel = EEM_Question_Group::instance();
798
-        // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
799
-        return $questionGroupModel->get_all(
800
-            $this->get_query_params($questionGroupModel, $per_page, $current_page)
801
-        );
802
-    }
740
+		return $query_params;
741
+	}
742
+
743
+
744
+	/**
745
+	 * @param int        $per_page
746
+	 * @param int        $current_page
747
+	 * @param bool|false $count
748
+	 * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]|int
749
+	 * @throws EE_Error
750
+	 */
751
+	public function get_questions($per_page = 10, $current_page = 1, $count = false)
752
+	{
753
+		$QST          = EEM_Question::instance();
754
+		$query_params = $this->get_query_params($QST, $per_page, $current_page);
755
+		if ($count) {
756
+			$where   =
757
+				isset($query_params[0])
758
+					? [$query_params[0]]
759
+					: [];
760
+			$results = $QST->count($where);
761
+		} else {
762
+			$results = $QST->get_all($query_params);
763
+		}
764
+		return $results;
765
+	}
766
+
767
+
768
+	/**
769
+	 * @param            $per_page
770
+	 * @param int        $current_page
771
+	 * @param bool|false $count
772
+	 * @return EE_Soft_Delete_Base_Class[]|int
773
+	 * @throws EE_Error
774
+	 */
775
+	public function get_trashed_questions($per_page, $current_page = 1, $count = false)
776
+	{
777
+		$query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
778
+		$where        =
779
+			isset($query_params[0])
780
+				? [$query_params[0]]
781
+				: [];
782
+		return $count
783
+			? EEM_Question::instance()->count_deleted($where)
784
+			: EEM_Question::instance()->get_all_deleted($query_params);
785
+	}
786
+
787
+
788
+	/**
789
+	 * @param            $per_page
790
+	 * @param int        $current_page
791
+	 * @param bool|false $count
792
+	 * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]
793
+	 * @throws EE_Error
794
+	 */
795
+	public function get_question_groups($per_page, $current_page = 1, $count = false)
796
+	{
797
+		$questionGroupModel = EEM_Question_Group::instance();
798
+		// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
799
+		return $questionGroupModel->get_all(
800
+			$this->get_query_params($questionGroupModel, $per_page, $current_page)
801
+		);
802
+	}
803 803
 }
Please login to merge, or discard this patch.
admin_pages/messages/Messages_Admin_Page.core.php 1 patch
Indentation   +4650 added lines, -4650 removed lines patch added patch discarded remove patch
@@ -17,2690 +17,2690 @@  discard block
 block discarded – undo
17 17
  */
18 18
 class Messages_Admin_Page extends EE_Admin_Page
19 19
 {
20
-    /**
21
-     * @var EEM_Message
22
-     */
23
-    private $MSG_MODEL;
24
-
25
-    /**
26
-     * @var EEM_Message_Template
27
-     */
28
-    private $MTP_MODEL;
29
-
30
-    /**
31
-     * @var EEM_Message_Template_Group
32
-     */
33
-    private $MTG_MODEL;
34
-
35
-    /**
36
-     * @var EE_Message_Resource_Manager $_message_resource_manager
37
-     */
38
-    protected $_message_resource_manager;
39
-
40
-    /**
41
-     * @var string
42
-     */
43
-    protected $_active_message_type_name = '';
44
-
45
-    /**
46
-     * @var string
47
-     */
48
-    protected $_active_messenger_name = '';
49
-
50
-    /**
51
-     * @var EE_messenger $_active_messenger
52
-     */
53
-    protected $_active_messenger;
54
-
55
-    protected $_activate_meta_box_type;
56
-
57
-    protected $_current_message_meta_box;
58
-
59
-    protected $_current_message_meta_box_object;
60
-
61
-    protected $_context_switcher;
62
-
63
-    protected $_shortcodes           = [];
64
-
65
-    protected $_active_messengers    = [];
66
-
67
-    protected $_active_message_types = [];
68
-
69
-    /**
70
-     * @var EE_Message_Template_Group $_message_template_group
71
-     */
72
-    protected $_message_template_group;
73
-
74
-    protected $_m_mt_settings = [];
75
-
76
-
77
-    /**
78
-     * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
79
-     * IF there is no group then it gets automatically set to the Default template pack.
80
-     *
81
-     * @since 4.5.0
82
-     *
83
-     * @var EE_Messages_Template_Pack
84
-     */
85
-    protected $_template_pack;
86
-
87
-
88
-    /**
89
-     * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
90
-     * group is.  If there is no group then it automatically gets set to default.
91
-     *
92
-     * @since 4.5.0
93
-     *
94
-     * @var string
95
-     */
96
-    protected $_variation;
97
-
98
-
99
-    /**
100
-     * @param bool $routing
101
-     * @throws EE_Error
102
-     * @throws ReflectionException
103
-     */
104
-    public function __construct($routing = true)
105
-    {
106
-        // make sure messages autoloader is running
107
-        EED_Messages::set_autoloaders();
108
-        parent::__construct($routing);
109
-    }
110
-
111
-
112
-    /**
113
-     * @return EEM_Message
114
-     * @throws EE_Error
115
-     */
116
-    public function getMsgModel()
117
-    {
118
-        if (! $this->MSG_MODEL instanceof EEM_Message) {
119
-            $this->MSG_MODEL = EEM_Message::instance();
120
-        }
121
-        return $this->MSG_MODEL;
122
-    }
123
-
124
-
125
-    /**
126
-     * @return EEM_Message_Template
127
-     * @throws EE_Error
128
-     */
129
-    public function getMtpModel()
130
-    {
131
-        if (! $this->MTP_MODEL instanceof EEM_Message_Template) {
132
-            $this->MTP_MODEL = EEM_Message_Template::instance();
133
-        }
134
-        return $this->MTP_MODEL;
135
-    }
136
-
137
-
138
-    /**
139
-     * @return EEM_Message_Template_Group
140
-     * @throws EE_Error
141
-     */
142
-    public function getMtgModel()
143
-    {
144
-        if (! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
145
-            $this->MTG_MODEL = EEM_Message_Template_Group::instance();
146
-        }
147
-        return $this->MTG_MODEL;
148
-    }
149
-
150
-
151
-    /**
152
-     * @throws EE_Error
153
-     * @throws ReflectionException
154
-     */
155
-    protected function _init_page_props()
156
-    {
157
-        $this->page_slug        = EE_MSG_PG_SLUG;
158
-        $this->page_label       = esc_html__('Messages Settings', 'event_espresso');
159
-        $this->_admin_base_url  = EE_MSG_ADMIN_URL;
160
-        $this->_admin_base_path = EE_MSG_ADMIN;
161
-
162
-        $messenger    = $this->request->getRequestParam('messenger', '');
163
-        $message_type = $this->request->getRequestParam('message_type', '');
164
-        $this->_active_messenger_name    = $this->request->getRequestParam('MTP_messenger', $messenger);
165
-        $this->_active_message_type_name = $this->request->getRequestParam('MTP_message_type', $message_type);
166
-
167
-        $this->_load_message_resource_manager();
168
-    }
169
-
170
-
171
-    /**
172
-     * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
173
-     *
174
-     * @throws EE_Error
175
-     * @throws InvalidDataTypeException
176
-     * @throws InvalidInterfaceException
177
-     * @throws InvalidArgumentException
178
-     * @throws ReflectionException
179
-     */
180
-    protected function _load_message_resource_manager()
181
-    {
182
-        $this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
183
-    }
184
-
185
-
186
-    /**
187
-     * @return array
188
-     * @throws EE_Error
189
-     * @throws InvalidArgumentException
190
-     * @throws InvalidDataTypeException
191
-     * @throws InvalidInterfaceException
192
-     * @deprecated 4.9.9.rc.014
193
-     */
194
-    public function get_messengers_for_list_table()
195
-    {
196
-        EE_Error::doing_it_wrong(
197
-            __METHOD__,
198
-            sprintf(
199
-                esc_html__(
200
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
201
-                    'event_espresso'
202
-                ),
203
-                'Messages_Admin_Page::get_messengers_select_input()'
204
-            ),
205
-            '4.9.9.rc.014'
206
-        );
207
-
208
-        $m_values          = [];
209
-        $active_messengers = $this->getMsgModel()->get_all(['group_by' => 'MSG_messenger']);
210
-        // setup messengers for selects
211
-        $i = 1;
212
-        foreach ($active_messengers as $active_messenger) {
213
-            if ($active_messenger instanceof EE_Message) {
214
-                $m_values[ $i ]['id']   = $active_messenger->messenger();
215
-                $m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
216
-                $i++;
217
-            }
218
-        }
219
-
220
-        return $m_values;
221
-    }
222
-
223
-
224
-    /**
225
-     * @return array
226
-     * @throws EE_Error
227
-     * @throws InvalidArgumentException
228
-     * @throws InvalidDataTypeException
229
-     * @throws InvalidInterfaceException
230
-     * @deprecated 4.9.9.rc.014
231
-     */
232
-    public function get_message_types_for_list_table()
233
-    {
234
-        EE_Error::doing_it_wrong(
235
-            __METHOD__,
236
-            sprintf(
237
-                esc_html__(
238
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
239
-                    'event_espresso'
240
-                ),
241
-                'Messages_Admin_Page::get_message_types_select_input()'
242
-            ),
243
-            '4.9.9.rc.014'
244
-        );
245
-
246
-        $mt_values       = [];
247
-        $active_messages = $this->getMsgModel()->get_all(['group_by' => 'MSG_message_type']);
248
-        $i               = 1;
249
-        foreach ($active_messages as $active_message) {
250
-            if ($active_message instanceof EE_Message) {
251
-                $mt_values[ $i ]['id']   = $active_message->message_type();
252
-                $mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
253
-                $i++;
254
-            }
255
-        }
256
-
257
-        return $mt_values;
258
-    }
259
-
260
-
261
-    /**
262
-     * @return array
263
-     * @throws EE_Error
264
-     * @throws InvalidArgumentException
265
-     * @throws InvalidDataTypeException
266
-     * @throws InvalidInterfaceException
267
-     * @deprecated 4.9.9.rc.014
268
-     */
269
-    public function get_contexts_for_message_types_for_list_table()
270
-    {
271
-        EE_Error::doing_it_wrong(
272
-            __METHOD__,
273
-            sprintf(
274
-                esc_html__(
275
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
276
-                    'event_espresso'
277
-                ),
278
-                'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
279
-            ),
280
-            '4.9.9.rc.014'
281
-        );
282
-
283
-        $contexts                = [];
284
-        $active_message_contexts = $this->getMsgModel()->get_all(['group_by' => 'MSG_context']);
285
-        foreach ($active_message_contexts as $active_message) {
286
-            if ($active_message instanceof EE_Message) {
287
-                $message_type = $active_message->message_type_object();
288
-                if ($message_type instanceof EE_message_type) {
289
-                    $message_type_contexts = $message_type->get_contexts();
290
-                    foreach ($message_type_contexts as $context => $context_details) {
291
-                        $contexts[ $context ] = $context_details['label'];
292
-                    }
293
-                }
294
-            }
295
-        }
296
-
297
-        return $contexts;
298
-    }
299
-
300
-
301
-    /**
302
-     * Generate select input with provided messenger options array.
303
-     *
304
-     * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
305
-     *                                 labels.
306
-     * @return string
307
-     * @throws EE_Error
308
-     */
309
-    public function get_messengers_select_input($messenger_options)
310
-    {
311
-        // if empty or just one value then just return an empty string
312
-        if (
313
-            empty($messenger_options)
314
-            || ! is_array($messenger_options)
315
-            || count($messenger_options) === 1
316
-        ) {
317
-            return '';
318
-        }
319
-        // merge in default
320
-        $messenger_options = array_merge(
321
-            ['none_selected' => esc_html__('Show All Messengers', 'event_espresso')],
322
-            $messenger_options
323
-        );
324
-        $input             = new EE_Select_Input(
325
-            $messenger_options,
326
-            [
327
-                'html_name'  => 'ee_messenger_filter_by',
328
-                'html_id'    => 'ee_messenger_filter_by',
329
-                'html_class' => 'wide',
330
-                'default'    => $this->request->getRequestParam('ee_messenger_filter_by', 'none_selected', 'title'),
331
-            ]
332
-        );
333
-
334
-        return $input->get_html_for_input();
335
-    }
336
-
337
-
338
-    /**
339
-     * Generate select input with provided message type options array.
340
-     *
341
-     * @param array $message_type_options Array of message types indexed by message type slug, and values are the
342
-     *                                    message type labels
343
-     * @return string
344
-     * @throws EE_Error
345
-     */
346
-    public function get_message_types_select_input($message_type_options)
347
-    {
348
-        // if empty or count of options is 1 then just return an empty string
349
-        if (
350
-            empty($message_type_options)
351
-            || ! is_array($message_type_options)
352
-            || count($message_type_options) === 1
353
-        ) {
354
-            return '';
355
-        }
356
-        // merge in default
357
-        $message_type_options = array_merge(
358
-            ['none_selected' => esc_html__('Show All Message Types', 'event_espresso')],
359
-            $message_type_options
360
-        );
361
-        $input                = new EE_Select_Input(
362
-            $message_type_options,
363
-            [
364
-                'html_name'  => 'ee_message_type_filter_by',
365
-                'html_id'    => 'ee_message_type_filter_by',
366
-                'html_class' => 'wide',
367
-                'default'    => $this->request->getRequestParam('ee_message_type_filter_by', 'none_selected', 'title'),
368
-            ]
369
-        );
370
-
371
-        return $input->get_html_for_input();
372
-    }
373
-
374
-
375
-    /**
376
-     * Generate select input with provide message type contexts array.
377
-     *
378
-     * @param array $context_options Array of message type contexts indexed by context slug, and values are the
379
-     *                               context label.
380
-     * @return string
381
-     * @throws EE_Error
382
-     */
383
-    public function get_contexts_for_message_types_select_input($context_options)
384
-    {
385
-        // if empty or count of options is one then just return empty string
386
-        if (
387
-            empty($context_options)
388
-            || ! is_array($context_options)
389
-            || count($context_options) === 1
390
-        ) {
391
-            return '';
392
-        }
393
-        // merge in default
394
-        $context_options = array_merge(
395
-            ['none_selected' => esc_html__('Show all Contexts', 'event_espresso')],
396
-            $context_options
397
-        );
398
-        $input           = new EE_Select_Input(
399
-            $context_options,
400
-            [
401
-                'html_name'  => 'ee_context_filter_by',
402
-                'html_id'    => 'ee_context_filter_by',
403
-                'html_class' => 'wide',
404
-                'default'    => $this->request->getRequestParam('ee_context_filter_by', 'none_selected', 'title'),
405
-            ]
406
-        );
407
-
408
-        return $input->get_html_for_input();
409
-    }
410
-
411
-
412
-    protected function _ajax_hooks()
413
-    {
414
-        add_action('wp_ajax_activate_messenger', [$this, 'activate_messenger_toggle']);
415
-        add_action('wp_ajax_activate_mt', [$this, 'activate_mt_toggle']);
416
-        add_action('wp_ajax_ee_msgs_save_settings', [$this, 'save_settings']);
417
-        add_action('wp_ajax_ee_msgs_update_mt_form', [$this, 'update_mt_form']);
418
-        add_action('wp_ajax_switch_template_pack', [$this, 'switch_template_pack']);
419
-        add_action('wp_ajax_toggle_context_template', [$this, 'toggle_context_template']);
420
-    }
421
-
422
-
423
-    protected function _define_page_props()
424
-    {
425
-        $this->_admin_page_title = $this->page_label;
426
-        $this->_labels           = [
427
-            'buttons'    => [
428
-                'add'    => esc_html__('Add New Message Template', 'event_espresso'),
429
-                'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
430
-                'delete' => esc_html__('Delete Message Template', 'event_espresso'),
431
-            ],
432
-            'publishbox' => esc_html__('Update Actions', 'event_espresso'),
433
-        ];
434
-    }
435
-
436
-
437
-    /**
438
-     *        an array for storing key => value pairs of request actions and their corresponding methods
439
-     *
440
-     * @access protected
441
-     * @return void
442
-     */
443
-    protected function _set_page_routes()
444
-    {
445
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
446
-        $GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
447
-        $MSG_ID = $this->request->getRequestParam('MSG_ID', 0, 'int');
448
-
449
-        $this->_page_routes = [
450
-            'default'                          => [
451
-                'func'       => '_message_queue_list_table',
452
-                'capability' => 'ee_read_global_messages',
453
-            ],
454
-            'global_mtps'                      => [
455
-                'func'       => '_ee_default_messages_overview_list_table',
456
-                'capability' => 'ee_read_global_messages',
457
-            ],
458
-            'custom_mtps'                      => [
459
-                'func'       => '_custom_mtps_preview',
460
-                'capability' => 'ee_read_messages',
461
-            ],
462
-            'add_new_message_template'         => [
463
-                'func'       => 'add_message_template',
464
-                'capability' => 'ee_edit_messages',
465
-                'noheader'   => true,
466
-            ],
467
-            'edit_message_template'            => [
468
-                'func'       => '_edit_message_template',
469
-                'capability' => 'ee_edit_message',
470
-                'obj_id'     => $GRP_ID,
471
-            ],
472
-            'preview_message'                  => [
473
-                'func'               => '_preview_message',
474
-                'capability'         => 'ee_read_message',
475
-                'obj_id'             => $GRP_ID,
476
-                'noheader'           => true,
477
-                'headers_sent_route' => 'display_preview_message',
478
-            ],
479
-            'display_preview_message'          => [
480
-                'func'       => '_display_preview_message',
481
-                'capability' => 'ee_read_message',
482
-                'obj_id'     => $GRP_ID,
483
-            ],
484
-            'insert_message_template'          => [
485
-                'func'       => '_insert_or_update_message_template',
486
-                'capability' => 'ee_edit_messages',
487
-                'args'       => ['new' => true],
488
-                'noheader'   => true,
489
-            ],
490
-            'update_message_template'          => [
491
-                'func'       => '_insert_or_update_message_template',
492
-                'capability' => 'ee_edit_message',
493
-                'obj_id'     => $GRP_ID,
494
-                'args'       => ['new' => false],
495
-                'noheader'   => true,
496
-            ],
497
-            'trash_message_template'           => [
498
-                'func'       => '_trash_or_restore_message_template',
499
-                'capability' => 'ee_delete_message',
500
-                'obj_id'     => $GRP_ID,
501
-                'args'       => ['trash' => true, 'all' => true],
502
-                'noheader'   => true,
503
-            ],
504
-            'trash_message_template_context'   => [
505
-                'func'       => '_trash_or_restore_message_template',
506
-                'capability' => 'ee_delete_message',
507
-                'obj_id'     => $GRP_ID,
508
-                'args'       => ['trash' => true],
509
-                'noheader'   => true,
510
-            ],
511
-            'restore_message_template'         => [
512
-                'func'       => '_trash_or_restore_message_template',
513
-                'capability' => 'ee_delete_message',
514
-                'obj_id'     => $GRP_ID,
515
-                'args'       => ['trash' => false, 'all' => true],
516
-                'noheader'   => true,
517
-            ],
518
-            'restore_message_template_context' => [
519
-                'func'       => '_trash_or_restore_message_template',
520
-                'capability' => 'ee_delete_message',
521
-                'obj_id'     => $GRP_ID,
522
-                'args'       => ['trash' => false],
523
-                'noheader'   => true,
524
-            ],
525
-            'delete_message_template'          => [
526
-                'func'       => '_delete_message_template',
527
-                'capability' => 'ee_delete_message',
528
-                'obj_id'     => $GRP_ID,
529
-                'noheader'   => true,
530
-            ],
531
-            'reset_to_default'                 => [
532
-                'func'       => '_reset_to_default_template',
533
-                'capability' => 'ee_edit_message',
534
-                'obj_id'     => $GRP_ID,
535
-                'noheader'   => true,
536
-            ],
537
-            'settings'                         => [
538
-                'func'       => '_settings',
539
-                'capability' => 'manage_options',
540
-            ],
541
-            'update_global_settings'           => [
542
-                'func'       => '_update_global_settings',
543
-                'capability' => 'manage_options',
544
-                'noheader'   => true,
545
-            ],
546
-            'generate_now'                     => [
547
-                'func'       => '_generate_now',
548
-                'capability' => 'ee_send_message',
549
-                'noheader'   => true,
550
-            ],
551
-            'generate_and_send_now'            => [
552
-                'func'       => '_generate_and_send_now',
553
-                'capability' => 'ee_send_message',
554
-                'noheader'   => true,
555
-            ],
556
-            'queue_for_resending'              => [
557
-                'func'       => '_queue_for_resending',
558
-                'capability' => 'ee_send_message',
559
-                'noheader'   => true,
560
-            ],
561
-            'send_now'                         => [
562
-                'func'       => '_send_now',
563
-                'capability' => 'ee_send_message',
564
-                'noheader'   => true,
565
-            ],
566
-            'delete_ee_message'                => [
567
-                'func'       => '_delete_ee_messages',
568
-                'capability' => 'ee_delete_messages',
569
-                'noheader'   => true,
570
-            ],
571
-            'delete_ee_messages'               => [
572
-                'func'       => '_delete_ee_messages',
573
-                'capability' => 'ee_delete_messages',
574
-                'noheader'   => true,
575
-                'obj_id'     => $MSG_ID,
576
-            ],
577
-        ];
578
-    }
579
-
580
-
581
-    protected function _set_page_config()
582
-    {
583
-        $this->_page_config = [
584
-            'default'                  => [
585
-                'nav'           => [
586
-                    'label' => esc_html__('Message Activity', 'event_espresso'),
587
-                    'icon' => 'dashicons-email',
588
-                    'order' => 10,
589
-                ],
590
-                'list_table'    => 'EE_Message_List_Table',
591
-                // 'qtips' => array( 'EE_Message_List_Table_Tips' ),
592
-                'require_nonce' => false,
593
-            ],
594
-            'global_mtps'              => [
595
-                'nav'           => [
596
-                    'label' => esc_html__('Default Message Templates', 'event_espresso'),
597
-                    'icon' => 'dashicons-layout',
598
-                    'order' => 20,
599
-                ],
600
-                'list_table'    => 'Messages_Template_List_Table',
601
-                'help_tabs'     => [
602
-                    'messages_overview_help_tab'                                => [
603
-                        'title'    => esc_html__('Messages Overview', 'event_espresso'),
604
-                        'filename' => 'messages_overview',
605
-                    ],
606
-                    'messages_overview_messages_table_column_headings_help_tab' => [
607
-                        'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
608
-                        'filename' => 'messages_overview_table_column_headings',
609
-                    ],
610
-                    'messages_overview_messages_filters_help_tab'               => [
611
-                        'title'    => esc_html__('Message Filters', 'event_espresso'),
612
-                        'filename' => 'messages_overview_filters',
613
-                    ],
614
-                    'messages_overview_messages_views_help_tab'                 => [
615
-                        'title'    => esc_html__('Message Views', 'event_espresso'),
616
-                        'filename' => 'messages_overview_views',
617
-                    ],
618
-                    'message_overview_message_types_help_tab'                   => [
619
-                        'title'    => esc_html__('Message Types', 'event_espresso'),
620
-                        'filename' => 'messages_overview_types',
621
-                    ],
622
-                    'messages_overview_messengers_help_tab'                     => [
623
-                        'title'    => esc_html__('Messengers', 'event_espresso'),
624
-                        'filename' => 'messages_overview_messengers',
625
-                    ],
626
-                ],
627
-                'require_nonce' => false,
628
-            ],
629
-            'custom_mtps'              => [
630
-                'nav'           => [
631
-                    'label' => esc_html__('Custom Message Templates', 'event_espresso'),
632
-                    'icon' => 'dashicons-admin-customizer',
633
-                    'order' => 30,
634
-                ],
635
-                'help_tabs'     => [],
636
-                'require_nonce' => false,
637
-            ],
638
-            'add_new_message_template' => [
639
-                'nav'           => [
640
-                    'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
641
-                    'icon' => 'dashicons-plus-alt',
642
-                    'order'      => 5,
643
-                    'persistent' => false,
644
-                ],
645
-                'require_nonce' => false,
646
-            ],
647
-            'edit_message_template'    => [
648
-                'labels'        => [
649
-                    'buttons'    => [
650
-                        'reset' => esc_html__('Reset Templates', 'event_espresso'),
651
-                    ],
652
-                    'publishbox' => esc_html__('Update Actions', 'event_espresso'),
653
-                ],
654
-                'nav'           => [
655
-                    'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
656
-                    'icon' => 'dashicons-edit-large',
657
-                    'order'      => 5,
658
-                    'persistent' => false,
659
-                    'url'        => '',
660
-                ],
661
-                'metaboxes'     => ['_publish_post_box', '_register_edit_meta_boxes'],
662
-                'has_metaboxes' => true,
663
-                'help_tabs'     => [
664
-                    'edit_message_template'            => [
665
-                        'title'    => esc_html__('Message Template Editor', 'event_espresso'),
666
-                        'callback' => 'edit_message_template_help_tab',
667
-                    ],
668
-                    'message_templates_help_tab'       => [
669
-                        'title'    => esc_html__('Message Templates', 'event_espresso'),
670
-                        'filename' => 'messages_templates',
671
-                    ],
672
-                    'message_template_shortcodes'      => [
673
-                        'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
674
-                        'callback' => 'message_template_shortcodes_help_tab',
675
-                    ],
676
-                    'message_preview_help_tab'         => [
677
-                        'title'    => esc_html__('Message Preview', 'event_espresso'),
678
-                        'filename' => 'messages_preview',
679
-                    ],
680
-                    'messages_overview_other_help_tab' => [
681
-                        'title'    => esc_html__('Messages Other', 'event_espresso'),
682
-                        'filename' => 'messages_overview_other',
683
-                    ],
684
-                ],
685
-                'require_nonce' => false,
686
-            ],
687
-            'display_preview_message'  => [
688
-                'nav'           => [
689
-                    'label'      => esc_html__('Message Preview', 'event_espresso'),
690
-                    'icon' => 'dashicons-visibility-bar',
691
-                    'order'      => 5,
692
-                    'url'        => '',
693
-                    'persistent' => false,
694
-                ],
695
-                'help_tabs'     => [
696
-                    'preview_message' => [
697
-                        'title'    => esc_html__('About Previews', 'event_espresso'),
698
-                        'callback' => 'preview_message_help_tab',
699
-                    ],
700
-                ],
701
-                'require_nonce' => false,
702
-            ],
703
-            'settings'                 => [
704
-                'nav'           => [
705
-                    'label' => esc_html__('Settings', 'event_espresso'),
706
-                    'icon' => 'dashicons-admin-generic',
707
-                    'order' => 40,
708
-                ],
709
-                'metaboxes'     => ['_messages_settings_metaboxes'],
710
-                'help_tabs'     => [
711
-                    'messages_settings_help_tab'               => [
712
-                        'title'    => esc_html__('Messages Settings', 'event_espresso'),
713
-                        'filename' => 'messages_settings',
714
-                    ],
715
-                    'messages_settings_message_types_help_tab' => [
716
-                        'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
717
-                        'filename' => 'messages_settings_message_types',
718
-                    ],
719
-                    'messages_settings_messengers_help_tab'    => [
720
-                        'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
721
-                        'filename' => 'messages_settings_messengers',
722
-                    ],
723
-                ],
724
-                'require_nonce' => false,
725
-            ],
726
-        ];
727
-    }
728
-
729
-
730
-    protected function _add_screen_options()
731
-    {
732
-        // todo
733
-    }
734
-
735
-
736
-    protected function _add_screen_options_global_mtps()
737
-    {
738
-        /**
739
-         * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
740
-         * uses the $_admin_page_title property and we want different outputs in the different spots.
741
-         */
742
-        $page_title              = $this->_admin_page_title;
743
-        $this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
744
-        $this->_per_page_screen_option();
745
-        $this->_admin_page_title = $page_title;
746
-    }
747
-
748
-
749
-    protected function _add_screen_options_default()
750
-    {
751
-        $this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
752
-        $this->_per_page_screen_option();
753
-    }
754
-
755
-
756
-    // none of the below group are currently used for Messages
757
-    protected function _add_feature_pointers()
758
-    {
759
-    }
760
-
761
-
762
-    public function admin_init()
763
-    {
764
-    }
765
-
766
-
767
-    public function admin_notices()
768
-    {
769
-    }
770
-
771
-
772
-    public function admin_footer_scripts()
773
-    {
774
-    }
775
-
776
-
777
-    public function messages_help_tab()
778
-    {
779
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
780
-    }
781
-
782
-
783
-    public function messengers_help_tab()
784
-    {
785
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
786
-    }
787
-
788
-
789
-    public function message_types_help_tab()
790
-    {
791
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
792
-    }
793
-
794
-
795
-    public function messages_overview_help_tab()
796
-    {
797
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
798
-    }
799
-
800
-
801
-    public function message_templates_help_tab()
802
-    {
803
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
804
-    }
805
-
806
-
807
-    public function edit_message_template_help_tab()
808
-    {
809
-        $args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
810
-                        . esc_attr__('Editor Title', 'event_espresso')
811
-                        . '" />';
812
-        $args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
813
-                        . esc_attr__('Context Switcher and Preview', 'event_espresso')
814
-                        . '" />';
815
-        $args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
816
-                        . esc_attr__('Message Template Form Fields', 'event_espresso')
817
-                        . '" />';
818
-        $args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
819
-                        . esc_attr__('Shortcodes Metabox', 'event_espresso')
820
-                        . '" />';
821
-        $args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
822
-                        . esc_attr__('Publish Metabox', 'event_espresso')
823
-                        . '" />';
824
-        EEH_Template::display_template(
825
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
826
-            $args
827
-        );
828
-    }
829
-
830
-
831
-    /**
832
-     * @throws ReflectionException
833
-     * @throws EE_Error
834
-     */
835
-    public function message_template_shortcodes_help_tab()
836
-    {
837
-        $this->_set_shortcodes();
838
-        $args['shortcodes'] = $this->_shortcodes;
839
-        EEH_Template::display_template(
840
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
841
-            $args
842
-        );
843
-    }
844
-
845
-
846
-    public function preview_message_help_tab()
847
-    {
848
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
849
-    }
850
-
851
-
852
-    public function settings_help_tab()
853
-    {
854
-        $args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
855
-                        . '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
856
-        $args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
857
-                        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
858
-        $args['img3'] = '<div class="switch">'
859
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
860
-                        . ' type="checkbox" checked>'
861
-                        . '<label for="ee-on-off-toggle-on"></label>'
862
-                        . '</div>';
863
-        $args['img4'] = '<div class="switch">'
864
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
865
-                        . ' type="checkbox">'
866
-                        . '<label for="ee-on-off-toggle-on"></label>'
867
-                        . '</div>';
868
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
869
-    }
870
-
871
-
872
-    public function load_scripts_styles()
873
-    {
874
-        wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
875
-        wp_enqueue_style('espresso_ee_msg');
876
-
877
-        wp_register_script(
878
-            'ee-messages-settings',
879
-            EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
880
-            ['jquery-ui-droppable', 'ee-serialize-full-array'],
881
-            EVENT_ESPRESSO_VERSION,
882
-            true
883
-        );
884
-        wp_register_script(
885
-            'ee-msg-list-table-js',
886
-            EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
887
-            ['ee-dialog'],
888
-            EVENT_ESPRESSO_VERSION
889
-        );
890
-    }
891
-
892
-
893
-    public function load_scripts_styles_default()
894
-    {
895
-        wp_enqueue_script('ee-msg-list-table-js');
896
-    }
897
-
898
-
899
-    public function wp_editor_css($mce_css)
900
-    {
901
-        // if we're on the edit_message_template route
902
-        if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
903
-            $message_type_name = $this->_active_message_type_name;
904
-
905
-            // we're going to REPLACE the existing mce css
906
-            // we need to get the css file location from the active messenger
907
-            $mce_css = $this->_active_messenger->get_variation(
908
-                $this->_template_pack,
909
-                $message_type_name,
910
-                true,
911
-                'wpeditor',
912
-                $this->_variation
913
-            );
914
-        }
915
-
916
-        return $mce_css;
917
-    }
918
-
919
-
920
-    /**
921
-     * @throws EE_Error
922
-     * @throws ReflectionException
923
-     */
924
-    public function load_scripts_styles_edit_message_template()
925
-    {
926
-
927
-        $this->_set_shortcodes();
928
-
929
-        EE_Registry::$i18n_js_strings['confirm_default_reset']        = sprintf(
930
-            esc_html__(
931
-                'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
932
-                'event_espresso'
933
-            ),
934
-            $this->_message_template_group->messenger_obj()->label['singular'],
935
-            $this->_message_template_group->message_type_obj()->label['singular']
936
-        );
937
-        EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
938
-            'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
939
-            'event_espresso'
940
-        );
941
-        EE_Registry::$i18n_js_strings['server_error']                 = esc_html__(
942
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
943
-            'event_espresso'
944
-        );
945
-
946
-        wp_register_script(
947
-            'ee_msgs_edit_js',
948
-            EE_MSG_ASSETS_URL . 'ee_message_editor.js',
949
-            ['jquery'],
950
-            EVENT_ESPRESSO_VERSION
951
-        );
952
-
953
-        wp_enqueue_script('ee_admin_js');
954
-        wp_enqueue_script('ee_msgs_edit_js');
955
-
956
-        // add in special css for tiny_mce
957
-        add_filter('mce_css', [$this, 'wp_editor_css']);
958
-    }
959
-
960
-
961
-    /**
962
-     * @throws EE_Error
963
-     * @throws ReflectionException
964
-     */
965
-    public function load_scripts_styles_display_preview_message()
966
-    {
967
-        $this->_set_message_template_group();
968
-        if ($this->_active_messenger_name) {
969
-            $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
970
-                $this->_active_messenger_name
971
-            );
972
-        }
973
-
974
-        wp_enqueue_style(
975
-            'espresso_preview_css',
976
-            $this->_active_messenger->get_variation(
977
-                $this->_template_pack,
978
-                $this->_active_message_type_name,
979
-                true,
980
-                'preview',
981
-                $this->_variation
982
-            )
983
-        );
984
-    }
985
-
986
-
987
-    public function load_scripts_styles_settings()
988
-    {
989
-        wp_register_style(
990
-            'ee-message-settings',
991
-            EE_MSG_ASSETS_URL . 'ee_message_settings.css',
992
-            [],
993
-            EVENT_ESPRESSO_VERSION
994
-        );
995
-        wp_enqueue_style('ee-text-links');
996
-        wp_enqueue_style('ee-message-settings');
997
-        wp_enqueue_script('ee-messages-settings');
998
-    }
999
-
1000
-
1001
-    /**
1002
-     * set views array for List Table
1003
-     */
1004
-    public function _set_list_table_views_global_mtps()
1005
-    {
1006
-        $this->_views = [
1007
-            'in_use' => [
1008
-                'slug'  => 'in_use',
1009
-                'label' => esc_html__('In Use', 'event_espresso'),
1010
-                'count' => 0,
1011
-            ],
1012
-        ];
1013
-    }
1014
-
1015
-
1016
-    /**
1017
-     * Set views array for the Custom Template List Table
1018
-     */
1019
-    public function _set_list_table_views_custom_mtps()
1020
-    {
1021
-        $this->_set_list_table_views_global_mtps();
1022
-        $this->_views['in_use']['bulk_action'] = [
1023
-            'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
1024
-        ];
1025
-    }
1026
-
1027
-
1028
-    /**
1029
-     * set views array for message queue list table
1030
-     *
1031
-     * @throws InvalidDataTypeException
1032
-     * @throws InvalidInterfaceException
1033
-     * @throws InvalidArgumentException
1034
-     * @throws EE_Error
1035
-     * @throws ReflectionException
1036
-     */
1037
-    public function _set_list_table_views_default()
1038
-    {
1039
-        EE_Registry::instance()->load_helper('Template');
1040
-
1041
-        $common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
1042
-            'ee_send_message',
1043
-            'message_list_table_bulk_actions'
1044
-        )
1045
-            ? [
1046
-                'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
1047
-                'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
1048
-                'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
1049
-                'send_now'              => esc_html__('Send Now', 'event_espresso'),
1050
-            ]
1051
-            : [];
1052
-
1053
-        $delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
1054
-            'ee_delete_messages',
1055
-            'message_list_table_bulk_actions'
1056
-        )
1057
-            ? ['delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso')]
1058
-            : [];
1059
-
1060
-
1061
-        $this->_views = [
1062
-            'all' => [
1063
-                'slug'        => 'all',
1064
-                'label'       => esc_html__('All', 'event_espresso'),
1065
-                'count'       => 0,
1066
-                'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
1067
-            ],
1068
-        ];
1069
-
1070
-
1071
-        foreach ($this->getMsgModel()->all_statuses() as $status) {
1072
-            if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1073
-                continue;
1074
-            }
1075
-            $status_bulk_actions = $common_bulk_actions;
1076
-            // unset bulk actions not applying to status
1077
-            if (! empty($status_bulk_actions)) {
1078
-                switch ($status) {
1079
-                    case EEM_Message::status_idle:
1080
-                    case EEM_Message::status_resend:
1081
-                        $status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1082
-                        break;
1083
-
1084
-                    case EEM_Message::status_failed:
1085
-                    case EEM_Message::status_debug_only:
1086
-                    case EEM_Message::status_messenger_executing:
1087
-                        $status_bulk_actions = [];
1088
-                        break;
1089
-
1090
-                    case EEM_Message::status_incomplete:
1091
-                        unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1092
-                        break;
1093
-
1094
-                    case EEM_Message::status_retry:
1095
-                    case EEM_Message::status_sent:
1096
-                        unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1097
-                        break;
1098
-                }
1099
-            }
1100
-
1101
-            // skip adding messenger executing status to views because it will be included with the Failed view.
1102
-            if ($status === EEM_Message::status_messenger_executing) {
1103
-                continue;
1104
-            }
1105
-
1106
-            $this->_views[ strtolower($status) ] = [
1107
-                'slug'        => strtolower($status),
1108
-                'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1109
-                'count'       => 0,
1110
-                'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1111
-            ];
1112
-        }
1113
-    }
1114
-
1115
-
1116
-    /**
1117
-     * @throws EE_Error
1118
-     */
1119
-    protected function _ee_default_messages_overview_list_table()
1120
-    {
1121
-        $this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1122
-        $this->display_admin_list_table_page_with_no_sidebar();
1123
-    }
1124
-
1125
-
1126
-    /**
1127
-     * @throws EE_Error
1128
-     * @throws ReflectionException
1129
-     */
1130
-    protected function _message_queue_list_table()
1131
-    {
1132
-        $this->_search_btn_label                   = esc_html__('Message Activity', 'event_espresso');
1133
-        $this->_template_args['per_column']        = 6;
1134
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_message_legend_items());
1135
-        $message_results = trim(EEM_Message::instance()->get_pretty_label_for_results());
1136
-        $this->_template_args['before_list_table'] = ! empty($message_results) ? "<h3>{$message_results}</h3>" : '';
1137
-        $this->display_admin_list_table_page_with_no_sidebar();
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * @throws EE_Error
1143
-     */
1144
-    protected function _message_legend_items()
1145
-    {
1146
-
1147
-        $action_css_classes = EEH_MSG_Template::get_message_action_icons();
1148
-        $action_items       = [];
1149
-
1150
-        foreach ($action_css_classes as $action_item => $action_details) {
1151
-            if ($action_item === 'see_notifications_for') {
1152
-                continue;
1153
-            }
1154
-            $action_items[ $action_item ] = [
1155
-                'class' => $action_details['css_class'],
1156
-                'desc'  => $action_details['label'],
1157
-            ];
1158
-        }
1159
-
1160
-        /** @var array $status_items status legend setup */
1161
-        $status_items = [
1162
-            'sent_status'                => [
1163
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_sent,
1164
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1165
-            ],
1166
-            'idle_status'                => [
1167
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_idle,
1168
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1169
-            ],
1170
-            'failed_status'              => [
1171
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_failed,
1172
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1173
-            ],
1174
-            'messenger_executing_status' => [
1175
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_messenger_executing,
1176
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1177
-            ],
1178
-            'resend_status'              => [
1179
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_resend,
1180
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1181
-            ],
1182
-            'incomplete_status'          => [
1183
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_incomplete,
1184
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1185
-            ],
1186
-            'retry_status'               => [
1187
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_retry,
1188
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1189
-            ],
1190
-        ];
1191
-        if (EEM_Message::debug()) {
1192
-            $status_items['debug_only_status'] = [
1193
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_debug_only,
1194
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1195
-            ];
1196
-        }
1197
-
1198
-        return array_merge($action_items, $status_items);
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * @throws EE_Error
1204
-     */
1205
-    protected function _custom_mtps_preview()
1206
-    {
1207
-        $this->_admin_page_title              = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1208
-        $this->_template_args['preview_img']  = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1209
-                                                . ' alt="' . esc_attr__(
1210
-                                                    'Preview Custom Message Templates screenshot',
1211
-                                                    'event_espresso'
1212
-                                                ) . '" />';
1213
-        $this->_template_args['preview_text'] = '<strong>'
1214
-                                                . esc_html__(
1215
-                                                    'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1216
-                                                    'event_espresso'
1217
-                                                )
1218
-                                                . '</strong>';
1219
-
1220
-        $this->display_admin_caf_preview_page('custom_message_types', false);
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * get_message_templates
1226
-     * This gets all the message templates for listing on the overview list.
1227
-     *
1228
-     * @access public
1229
-     * @param int    $per_page the amount of templates groups to show per page
1230
-     * @param string $type     the current _view we're getting templates for
1231
-     * @param bool   $count    return count?
1232
-     * @param bool   $all      disregard any paging info (get all data);
1233
-     * @param bool   $global   whether to return just global (true) or custom templates (false)
1234
-     * @return array
1235
-     * @throws EE_Error
1236
-     * @throws InvalidArgumentException
1237
-     * @throws InvalidDataTypeException
1238
-     * @throws InvalidInterfaceException
1239
-     */
1240
-    public function get_message_templates(
1241
-        $per_page = 10,
1242
-        $type = 'in_use',
1243
-        $count = false,
1244
-        $all = false,
1245
-        $global = true
1246
-    ) {
1247
-        $orderby = $this->request->getRequestParam('orderby', 'GRP_ID');
1248
-        $this->request->setRequestParam('orderby', $orderby);
1249
-
1250
-        $order        = $this->request->getRequestParam('order', 'ASC');
1251
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1252
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1253
-
1254
-        $offset = ($current_page - 1) * $per_page;
1255
-        $limit  = $all ? null : [$offset, $per_page];
1256
-
1257
-        // options will match what is in the _views array property
1258
-        return $type === 'in_use'
1259
-            ? $this->getMtgModel()->get_all_active_message_templates(
1260
-                $orderby,
1261
-                $order,
1262
-                $limit,
1263
-                $count,
1264
-                $global,
1265
-                true
1266
-            )
1267
-            : $this->getMtgModel()->get_all_trashed_grouped_message_templates(
1268
-                $orderby,
1269
-                $order,
1270
-                $limit,
1271
-                $count,
1272
-                $global
1273
-            );
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     * filters etc might need a list of installed message_types
1279
-     *
1280
-     * @return array an array of message type objects
1281
-     */
1282
-    public function get_installed_message_types()
1283
-    {
1284
-        $installed_message_types = $this->_message_resource_manager->installed_message_types();
1285
-        $installed               = [];
1286
-
1287
-        foreach ($installed_message_types as $message_type) {
1288
-            $installed[ $message_type->name ] = $message_type;
1289
-        }
1290
-
1291
-        return $installed;
1292
-    }
1293
-
1294
-
1295
-    /**
1296
-     * This is used when creating a custom template. All Custom Templates start based off another template.
1297
-     *
1298
-     * @param string $message_type
1299
-     * @param string $messenger
1300
-     * @param string $GRP_ID
1301
-     *
1302
-     * @throws EE_error
1303
-     * @throws ReflectionException
1304
-     */
1305
-    public function add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1306
-    {
1307
-        // set values override any request data
1308
-        $message_type = ! empty($message_type) ? $message_type : $this->_active_message_type_name;
1309
-        $messenger    = ! empty($messenger) ? $messenger : $this->_active_messenger_name;
1310
-        $GRP_ID       = ! empty($GRP_ID) ? $GRP_ID : $this->request->getRequestParam('GRP_ID', 0, 'int');
1311
-
1312
-        // we need messenger and message type.  They should be coming from the event editor. If not here then return error
1313
-        if (empty($message_type) || empty($messenger)) {
1314
-            throw new EE_Error(
1315
-                esc_html__(
1316
-                    'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1317
-                    'event_espresso'
1318
-                )
1319
-            );
1320
-        }
1321
-
1322
-        // we need the GRP_ID for the template being used as the base for the new template
1323
-        if (empty($GRP_ID)) {
1324
-            throw new EE_Error(
1325
-                esc_html__(
1326
-                    'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1327
-                    'event_espresso'
1328
-                )
1329
-            );
1330
-        }
1331
-
1332
-        // let's just make sure the template gets generated!
1333
-
1334
-        // we need to reassign some variables for what the insert is expecting
1335
-        $this->request->setRequestParam('MTP_messenger', $messenger);
1336
-        $this->request->setRequestParam('MTP_message_type', $message_type);
1337
-        $this->request->setRequestParam('GRP_ID', $GRP_ID);
1338
-
1339
-        $this->_insert_or_update_message_template(true);
1340
-    }
1341
-
1342
-
1343
-    /**
1344
-     * @param string $message_type     message type slug
1345
-     * @param string $messenger        messenger slug
1346
-     * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1347
-     *                                 off of.
1348
-     * @throws EE_error
1349
-     * @throws ReflectionException
1350
-     * @deprecated 4.10.29.p
1351
-     */
1352
-    protected function _add_message_template($message_type, $messenger, $GRP_ID)
1353
-    {
1354
-        $this->add_message_template($message_type, $messenger, $GRP_ID);
1355
-    }
1356
-
1357
-
1358
-    /**
1359
-     * _edit_message_template
1360
-     *
1361
-     * @access protected
1362
-     * @return void
1363
-     * @throws InvalidIdentifierException
1364
-     * @throws DomainException
1365
-     * @throws EE_Error
1366
-     * @throws InvalidArgumentException
1367
-     * @throws ReflectionException
1368
-     * @throws InvalidDataTypeException
1369
-     * @throws InvalidInterfaceException
1370
-     */
1371
-    protected function _edit_message_template()
1372
-    {
1373
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1374
-        $template_fields = '';
1375
-        $sidebar_fields  = '';
1376
-        // we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1377
-        // valid html in the templates.
1378
-        add_filter('tiny_mce_before_init', [$this, 'filter_tinymce_init'], 10, 2);
1379
-
1380
-        $GRP_ID = $this->request->getRequestParam('id', 0, 'int');
1381
-        $EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
1382
-
1383
-        $this->_set_shortcodes(); // this also sets the _message_template property.
1384
-        $message_template_group = $this->_message_template_group;
1385
-        $c_label                = $message_template_group->context_label();
1386
-        $c_config               = $message_template_group->contexts_config();
1387
-
1388
-        reset($c_config);
1389
-        $context = $this->request->getRequestParam('context', key($c_config));
1390
-        $context = strtolower($context);
1391
-
1392
-        $action = empty($GRP_ID) ? 'insert_message_template' : 'update_message_template';
1393
-
1394
-        $edit_message_template_form_url = add_query_arg(
1395
-            ['action' => $action, 'noheader' => true],
1396
-            EE_MSG_ADMIN_URL
1397
-        );
1398
-
1399
-        // set active messenger for this view
1400
-        $this->_active_messenger         = $this->_message_resource_manager->get_active_messenger(
1401
-            $message_template_group->messenger()
1402
-        );
1403
-        $this->_active_message_type_name = $message_template_group->message_type();
1404
-
1405
-
1406
-        // Do we have any validation errors?
1407
-        $validators = $this->_get_transient();
1408
-        $v_fields   = ! empty($validators) ? array_keys($validators) : [];
1409
-
1410
-
1411
-        // we need to assemble the title from Various details
1412
-        $context_label = sprintf(
1413
-            esc_html__('(%s %s)', 'event_espresso'),
1414
-            $c_config[ $context ]['label'],
1415
-            ucwords($c_label['label'])
1416
-        );
1417
-
1418
-        $title = sprintf(
1419
-            esc_html__(' %s %s Template %s', 'event_espresso'),
1420
-            ucwords($message_template_group->messenger_obj()->label['singular']),
1421
-            ucwords($message_template_group->message_type_obj()->label['singular']),
1422
-            $context_label
1423
-        );
1424
-
1425
-        $this->_template_args['GRP_ID']           = $GRP_ID;
1426
-        $this->_template_args['message_template'] = $message_template_group;
1427
-        $this->_template_args['is_extra_fields']  = false;
1428
-
1429
-
1430
-        // let's get EEH_MSG_Template so we can get template form fields
1431
-        $template_field_structure = EEH_MSG_Template::get_fields(
1432
-            $message_template_group->messenger(),
1433
-            $message_template_group->message_type()
1434
-        );
1435
-
1436
-        if (! $template_field_structure) {
1437
-            $template_field_structure = false;
1438
-            $template_fields          = esc_html__(
1439
-                'There was an error in assembling the fields for this display (you should see an error message)',
1440
-                'event_espresso'
1441
-            );
1442
-        }
1443
-
1444
-
1445
-        $message_templates = $message_template_group->context_templates();
1446
-
1447
-
1448
-        // if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1449
-        // will get handled in the "extra" array.
1450
-        if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1451
-            foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1452
-                unset($template_field_structure[ $context ][ $reference_field ]);
1453
-            }
1454
-        }
1455
-
1456
-        // let's loop through the template_field_structure and actually assemble the input fields!
1457
-        if (! empty($template_field_structure)) {
1458
-            foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1459
-                // if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1460
-                // the extra array and reset them.
1461
-                if ($template_field === 'extra') {
1462
-                    $this->_template_args['is_extra_fields'] = true;
1463
-                    foreach ($field_setup_array as $reference_field => $new_fields_array) {
1464
-                        $message_template = $message_templates[ $context ][ $reference_field ];
1465
-                        $content          = $message_template instanceof EE_Message_Template
1466
-                            ? $message_template->get('MTP_content')
1467
-                            : '';
1468
-                        foreach ($new_fields_array as $extra_field => $extra_array) {
1469
-                            // let's verify if we need this extra field via the shortcodes parameter.
1470
-                            $continue = false;
1471
-                            if (isset($extra_array['shortcodes_required'])) {
1472
-                                foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1473
-                                    if (! array_key_exists($shortcode, $this->_shortcodes)) {
1474
-                                        $continue = true;
1475
-                                    }
1476
-                                }
1477
-                                if ($continue) {
1478
-                                    continue;
1479
-                                }
1480
-                            }
1481
-
1482
-                            $field_id = $reference_field . '-' . $extra_field . '-content';
1483
-
1484
-                            $template_form_fields[ $field_id ]         = $extra_array;
1485
-                            $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1486
-                                                                         . $reference_field
1487
-                                                                         . '][content]['
1488
-                                                                         . $extra_field . ']';
1489
-                            $css_class                                 = isset($extra_array['css_class'])
1490
-                                ? $extra_array['css_class']
1491
-                                : '';
1492
-
1493
-                            $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1494
-                                                                              && in_array($extra_field, $v_fields, true)
1495
-                                                                              && (
1496
-                                                                                  is_array($validators[ $extra_field ])
1497
-                                                                                  && isset($validators[ $extra_field ]['msg'])
1498
-                                                                              )
1499
-                                ? 'validate-error ' . $css_class
1500
-                                : $css_class;
1501
-
1502
-                            $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1503
-                                                                          && isset($content[ $extra_field ])
1504
-                                ? $content[ $extra_field ]
1505
-                                : '';
1506
-
1507
-                            // do we have a validation error?  if we do then let's use that value instead
1508
-                            $template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1509
-                                ? $validators[ $extra_field ]['value']
1510
-                                : $template_form_fields[ $field_id ]['value'];
1511
-
1512
-
1513
-                            $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1514
-
1515
-                            // shortcode selector
1516
-                            $field_name_to_use                                   = $extra_field === 'main'
1517
-                                ? 'content'
1518
-                                : $extra_field;
1519
-                            $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1520
-                                $field_name_to_use,
1521
-                                $field_id
1522
-                            );
1523
-                        }
1524
-                        $template_field_MTP_id           = $reference_field . '-MTP_ID';
1525
-                        $template_field_template_name_id = $reference_field . '-name';
1526
-
1527
-                        $template_form_fields[ $template_field_MTP_id ] = [
1528
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1529
-                            'label'      => null,
1530
-                            'input'      => 'hidden',
1531
-                            'type'       => 'int',
1532
-                            'required'   => false,
1533
-                            'validation' => false,
1534
-                            'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1535
-                            'css_class'  => '',
1536
-                            'format'     => '%d',
1537
-                            'db-col'     => 'MTP_ID',
1538
-                        ];
1539
-
1540
-                        $template_form_fields[ $template_field_template_name_id ] = [
1541
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1542
-                            'label'      => null,
1543
-                            'input'      => 'hidden',
1544
-                            'type'       => 'string',
1545
-                            'required'   => false,
1546
-                            'validation' => true,
1547
-                            'value'      => $reference_field,
1548
-                            'css_class'  => '',
1549
-                            'format'     => '%s',
1550
-                            'db-col'     => 'MTP_template_field',
1551
-                        ];
1552
-                    }
1553
-                    continue; // skip the next stuff, we got the necessary fields here for this dataset.
1554
-                } else {
1555
-                    $field_id                                   = $template_field . '-content';
1556
-                    $template_form_fields[ $field_id ]          = $field_setup_array;
1557
-                    $template_form_fields[ $field_id ]['name']  =
1558
-                        'MTP_template_fields[' . $template_field . '][content]';
1559
-                    $message_template                           =
1560
-                        isset($message_templates[ $context ][ $template_field ])
1561
-                            ? $message_templates[ $context ][ $template_field ]
1562
-                            : null;
1563
-                    $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1564
-                                                                  && is_array($message_templates[ $context ])
1565
-                                                                  && $message_template instanceof EE_Message_Template
1566
-                        ? $message_template->get('MTP_content')
1567
-                        : '';
1568
-
1569
-                    // do we have a validator error for this field?  if we do then we'll use that value instead
1570
-                    $template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1571
-                        ? $validators[ $template_field ]['value']
1572
-                        : $template_form_fields[ $field_id ]['value'];
1573
-
1574
-
1575
-                    $template_form_fields[ $field_id ]['db-col']    = 'MTP_content';
1576
-                    $css_class                                      = isset($field_setup_array['css_class'])
1577
-                        ? $field_setup_array['css_class']
1578
-                        : '';
1579
-                    $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1580
-                                                                      && in_array($template_field, $v_fields, true)
1581
-                                                                      && isset($validators[ $template_field ]['msg'])
1582
-                        ? 'validate-error ' . $css_class
1583
-                        : $css_class;
1584
-
1585
-                    // shortcode selector
1586
-                    $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1587
-                        $template_field,
1588
-                        $field_id
1589
-                    );
1590
-                }
1591
-
1592
-                // k took care of content field(s) now let's take care of others.
1593
-
1594
-                $template_field_MTP_id                 = $template_field . '-MTP_ID';
1595
-                $template_field_field_template_name_id = $template_field . '-name';
1596
-
1597
-                // foreach template field there are actually two form fields created
1598
-                $template_form_fields[ $template_field_MTP_id ] = [
1599
-                    'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1600
-                    'label'      => null,
1601
-                    'input'      => 'hidden',
1602
-                    'type'       => 'int',
1603
-                    'required'   => false,
1604
-                    'validation' => true,
1605
-                    'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1606
-                    'css_class'  => '',
1607
-                    'format'     => '%d',
1608
-                    'db-col'     => 'MTP_ID',
1609
-                ];
1610
-
1611
-                $template_form_fields[ $template_field_field_template_name_id ] = [
1612
-                    'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1613
-                    'label'      => null,
1614
-                    'input'      => 'hidden',
1615
-                    'type'       => 'string',
1616
-                    'required'   => false,
1617
-                    'validation' => true,
1618
-                    'value'      => $template_field,
1619
-                    'css_class'  => '',
1620
-                    'format'     => '%s',
1621
-                    'db-col'     => 'MTP_template_field',
1622
-                ];
1623
-            }
1624
-
1625
-            // add other fields
1626
-            $template_form_fields['ee-msg-current-context'] = [
1627
-                'name'       => 'MTP_context',
1628
-                'label'      => null,
1629
-                'input'      => 'hidden',
1630
-                'type'       => 'string',
1631
-                'required'   => false,
1632
-                'validation' => true,
1633
-                'value'      => $context,
1634
-                'css_class'  => '',
1635
-                'format'     => '%s',
1636
-                'db-col'     => 'MTP_context',
1637
-            ];
1638
-
1639
-            $template_form_fields['ee-msg-grp-id'] = [
1640
-                'name'       => 'GRP_ID',
1641
-                'label'      => null,
1642
-                'input'      => 'hidden',
1643
-                'type'       => 'int',
1644
-                'required'   => false,
1645
-                'validation' => true,
1646
-                'value'      => $GRP_ID,
1647
-                'css_class'  => '',
1648
-                'format'     => '%d',
1649
-                'db-col'     => 'GRP_ID',
1650
-            ];
1651
-
1652
-            $template_form_fields['ee-msg-messenger'] = [
1653
-                'name'       => 'MTP_messenger',
1654
-                'label'      => null,
1655
-                'input'      => 'hidden',
1656
-                'type'       => 'string',
1657
-                'required'   => false,
1658
-                'validation' => true,
1659
-                'value'      => $message_template_group->messenger(),
1660
-                'css_class'  => '',
1661
-                'format'     => '%s',
1662
-                'db-col'     => 'MTP_messenger',
1663
-            ];
1664
-
1665
-            $template_form_fields['ee-msg-message-type'] = [
1666
-                'name'       => 'MTP_message_type',
1667
-                'label'      => null,
1668
-                'input'      => 'hidden',
1669
-                'type'       => 'string',
1670
-                'required'   => false,
1671
-                'validation' => true,
1672
-                'value'      => $message_template_group->message_type(),
1673
-                'css_class'  => '',
1674
-                'format'     => '%s',
1675
-                'db-col'     => 'MTP_message_type',
1676
-            ];
1677
-
1678
-            $sidebar_form_fields['ee-msg-is-global'] = [
1679
-                'name'       => 'MTP_is_global',
1680
-                'label'      => esc_html__('Global Template', 'event_espresso'),
1681
-                'input'      => 'hidden',
1682
-                'type'       => 'int',
1683
-                'required'   => false,
1684
-                'validation' => true,
1685
-                'value'      => $message_template_group->get('MTP_is_global'),
1686
-                'css_class'  => '',
1687
-                'format'     => '%d',
1688
-                'db-col'     => 'MTP_is_global',
1689
-            ];
1690
-
1691
-            $sidebar_form_fields['ee-msg-is-override'] = [
1692
-                'name'       => 'MTP_is_override',
1693
-                'label'      => esc_html__('Override all custom', 'event_espresso'),
1694
-                'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1695
-                'type'       => 'int',
1696
-                'required'   => false,
1697
-                'validation' => true,
1698
-                'value'      => $message_template_group->get('MTP_is_override'),
1699
-                'css_class'  => '',
1700
-                'format'     => '%d',
1701
-                'db-col'     => 'MTP_is_override',
1702
-            ];
1703
-
1704
-            $sidebar_form_fields['ee-msg-is-active'] = [
1705
-                'name'       => 'MTP_is_active',
1706
-                'label'      => esc_html__('Active Template', 'event_espresso'),
1707
-                'input'      => 'hidden',
1708
-                'type'       => 'int',
1709
-                'required'   => false,
1710
-                'validation' => true,
1711
-                'value'      => $message_template_group->is_active(),
1712
-                'css_class'  => '',
1713
-                'format'     => '%d',
1714
-                'db-col'     => 'MTP_is_active',
1715
-            ];
1716
-
1717
-            $sidebar_form_fields['ee-msg-deleted'] = [
1718
-                'name'       => 'MTP_deleted',
1719
-                'label'      => null,
1720
-                'input'      => 'hidden',
1721
-                'type'       => 'int',
1722
-                'required'   => false,
1723
-                'validation' => true,
1724
-                'value'      => $message_template_group->get('MTP_deleted'),
1725
-                'css_class'  => '',
1726
-                'format'     => '%d',
1727
-                'db-col'     => 'MTP_deleted',
1728
-            ];
1729
-            $sidebar_form_fields['ee-msg-author']  = [
1730
-                'name'       => 'MTP_user_id',
1731
-                'label'      => esc_html__('Author', 'event_espresso'),
1732
-                'input'      => 'hidden',
1733
-                'type'       => 'int',
1734
-                'required'   => false,
1735
-                'validation' => false,
1736
-                'value'      => $message_template_group->user(),
1737
-                'format'     => '%d',
1738
-                'db-col'     => 'MTP_user_id',
1739
-            ];
1740
-
1741
-            $sidebar_form_fields['ee-msg-route'] = [
1742
-                'name'  => 'action',
1743
-                'input' => 'hidden',
1744
-                'type'  => 'string',
1745
-                'value' => $action,
1746
-            ];
1747
-
1748
-            $sidebar_form_fields['ee-msg-id']        = [
1749
-                'name'  => 'id',
1750
-                'input' => 'hidden',
1751
-                'type'  => 'int',
1752
-                'value' => $GRP_ID,
1753
-            ];
1754
-            $sidebar_form_fields['ee-msg-evt-nonce'] = [
1755
-                'name'  => $action . '_nonce',
1756
-                'input' => 'hidden',
1757
-                'type'  => 'string',
1758
-                'value' => wp_create_nonce($action . '_nonce'),
1759
-            ];
1760
-
1761
-            $template_switch = $this->request->getRequestParam('template_switch');
1762
-            if ($template_switch) {
1763
-                $sidebar_form_fields['ee-msg-template-switch'] = [
1764
-                    'name'  => 'template_switch',
1765
-                    'input' => 'hidden',
1766
-                    'type'  => 'int',
1767
-                    'value' => 1,
1768
-                ];
1769
-            }
1770
-
1771
-
1772
-            $template_fields = $this->_generate_admin_form_fields($template_form_fields);
1773
-            $sidebar_fields  = $this->_generate_admin_form_fields($sidebar_form_fields);
1774
-        } //end if ( !empty($template_field_structure) )
1775
-
1776
-        // set extra content for publish box
1777
-        $this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1778
-        $this->_set_publish_post_box_vars(
1779
-            'id',
1780
-            $GRP_ID,
1781
-            false,
1782
-            add_query_arg(
1783
-                ['action' => 'global_mtps'],
1784
-                $this->_admin_base_url
1785
-            )
1786
-        );
1787
-
1788
-        // add preview button
1789
-        $preview_url    = parent::add_query_args_and_nonce(
1790
-            [
1791
-                'message_type' => $message_template_group->message_type(),
1792
-                'messenger'    => $message_template_group->messenger(),
1793
-                'context'      => $context,
1794
-                'GRP_ID'       => $GRP_ID,
1795
-                'evt_id'       => $EVT_ID ?: false,
1796
-                'action'       => 'preview_message',
1797
-            ],
1798
-            $this->_admin_base_url
1799
-        );
1800
-        $preview_button = '<a href="' . $preview_url . '" class="button--secondary messages-preview-button">'
1801
-                          . esc_html__('Preview', 'event_espresso')
1802
-                          . '</a>';
1803
-
1804
-
1805
-        // setup context switcher
1806
-        $this->_set_context_switcher(
1807
-            $message_template_group,
1808
-            [
1809
-                'page'    => 'espresso_messages',
1810
-                'action'  => 'edit_message_template',
1811
-                'id'      => $GRP_ID,
1812
-                'evt_id'  => $EVT_ID,
1813
-                'context' => $context,
1814
-                'extra'   => $preview_button,
1815
-            ]
1816
-        );
1817
-
1818
-
1819
-        // main box
1820
-        $this->_template_args['template_fields']                         = $template_fields;
1821
-        $this->_template_args['sidebar_box_id']                          = 'details';
1822
-        $this->_template_args['action']                                  = $action;
1823
-        $this->_template_args['context']                                 = $context;
1824
-        $this->_template_args['edit_message_template_form_url']          = $edit_message_template_form_url;
1825
-        $this->_template_args['learn_more_about_message_templates_link'] =
1826
-            $this->_learn_more_about_message_templates_link();
1827
-
1828
-
1829
-        $this->_template_args['before_admin_page_content'] = '<div class="ee-msg-admin-header">';
1830
-        $this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1831
-            $message_template_group,
1832
-            $context,
1833
-            $context_label
1834
-        );
1835
-        $this->_template_args['before_admin_page_content'] .= $this->add_context_switcher();
1836
-        $this->_template_args['before_admin_page_content'] .= '</div>';
1837
-        $this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1838
-        $this->_template_args['after_admin_page_content']  = $this->_add_form_element_after();
1839
-
1840
-        $this->_template_path = $this->_template_args['GRP_ID']
1841
-            ? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1842
-            : EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1843
-
1844
-        // send along EE_Message_Template_Group object for further template use.
1845
-        $this->_template_args['MTP'] = $message_template_group;
1846
-
1847
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1848
-            $this->_template_path,
1849
-            $this->_template_args,
1850
-            true
1851
-        );
1852
-
1853
-
1854
-        // finally, let's set the admin_page title
1855
-        $this->_admin_page_title = sprintf(esc_html__('Editing %s', 'event_espresso'), $title);
1856
-
1857
-
1858
-        // we need to take care of setting the shortcodes property for use elsewhere.
1859
-        $this->_set_shortcodes();
1860
-
1861
-
1862
-        // final template wrapper
1863
-        $this->display_admin_page_with_sidebar();
1864
-    }
1865
-
1866
-
1867
-    public function filter_tinymce_init($mceInit, $editor_id)
1868
-    {
1869
-        return $mceInit;
1870
-    }
1871
-
1872
-
1873
-    public function add_context_switcher()
1874
-    {
1875
-        return $this->_context_switcher;
1876
-    }
1877
-
1878
-
1879
-    /**
1880
-     * Adds the activation/deactivation toggle for the message template context.
1881
-     *
1882
-     * @param EE_Message_Template_Group $message_template_group
1883
-     * @param string                    $context
1884
-     * @param string                    $context_label
1885
-     * @return string
1886
-     * @throws DomainException
1887
-     * @throws EE_Error
1888
-     * @throws InvalidIdentifierException
1889
-     * @throws ReflectionException
1890
-     */
1891
-    protected function add_active_context_element(
1892
-        EE_Message_Template_Group $message_template_group,
1893
-        $context,
1894
-        $context_label
1895
-    ) {
1896
-        $template_args = [
1897
-            'context'                   => $context,
1898
-            'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1899
-            'is_active'                 => $message_template_group->is_context_active($context),
1900
-            'on_off_action'             => $message_template_group->is_context_active($context)
1901
-                ? 'context-off'
1902
-                : 'context-on',
1903
-            'context_label'             => str_replace(['(', ')'], '', $context_label),
1904
-            'message_template_group_id' => $message_template_group->ID(),
1905
-        ];
1906
-        return EEH_Template::display_template(
1907
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1908
-            $template_args,
1909
-            true
1910
-        );
1911
-    }
1912
-
1913
-
1914
-    /**
1915
-     * Ajax callback for `toggle_context_template` ajax action.
1916
-     * Handles toggling the message context on or off.
1917
-     *
1918
-     * @throws EE_Error
1919
-     * @throws InvalidArgumentException
1920
-     * @throws InvalidDataTypeException
1921
-     * @throws InvalidIdentifierException
1922
-     * @throws InvalidInterfaceException
1923
-     */
1924
-    public function toggle_context_template()
1925
-    {
1926
-        $success = true;
1927
-        // check for required data
1928
-        if (
1929
-            ! (
1930
-                $this->request->requestParamIsSet('message_template_group_id')
1931
-                && $this->request->requestParamIsSet('context')
1932
-                && $this->request->requestParamIsSet('status')
1933
-            )
1934
-        ) {
1935
-            EE_Error::add_error(
1936
-                esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1937
-                __FILE__,
1938
-                __FUNCTION__,
1939
-                __LINE__
1940
-            );
1941
-            $success = false;
1942
-        }
1943
-
1944
-        $nonce   = $this->request->getRequestParam('toggle_context_nonce', '');
1945
-        $context = $this->request->getRequestParam('context', '');
1946
-        $status  = $this->request->getRequestParam('status', '');
1947
-
1948
-        $this->_verify_nonce($nonce, "activate_{$context}_toggle_nonce");
1949
-
1950
-        if ($status !== 'off' && $status !== 'on') {
1951
-            EE_Error::add_error(
1952
-                sprintf(
1953
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1954
-                    $status
1955
-                ),
1956
-                __FILE__,
1957
-                __FUNCTION__,
1958
-                __LINE__
1959
-            );
1960
-            $success = false;
1961
-        }
1962
-        $message_template_group_id = $this->request->getRequestParam('message_template_group_id', 0, 'int');
1963
-        $message_template_group    = $this->getMtgModel()->get_one_by_ID($message_template_group_id);
1964
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
1965
-            EE_Error::add_error(
1966
-                sprintf(
1967
-                    esc_html__(
1968
-                        'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1969
-                        'event_espresso'
1970
-                    ),
1971
-                    $message_template_group_id,
1972
-                    'EE_Message_Template_Group'
1973
-                ),
1974
-                __FILE__,
1975
-                __FUNCTION__,
1976
-                __LINE__
1977
-            );
1978
-            $success = false;
1979
-        }
1980
-        if ($success) {
1981
-            $success = $status === 'off'
1982
-                ? $message_template_group->deactivate_context($context)
1983
-                : $message_template_group->activate_context($context);
1984
-        }
1985
-        $this->_template_args['success'] = $success;
1986
-        $this->_return_json();
1987
-    }
1988
-
1989
-
1990
-    public function _add_form_element_before()
1991
-    {
1992
-        return '<form method="post" action="'
1993
-               . $this->_template_args['edit_message_template_form_url']
1994
-               . '" id="ee-msg-edit-frm">';
1995
-    }
1996
-
1997
-
1998
-    public function _add_form_element_after()
1999
-    {
2000
-        return '</form>';
2001
-    }
2002
-
2003
-
2004
-    /**
2005
-     * This executes switching the template pack for a message template.
2006
-     *
2007
-     * @throws EE_Error
2008
-     * @throws InvalidDataTypeException
2009
-     * @throws InvalidInterfaceException
2010
-     * @throws InvalidArgumentException
2011
-     * @throws ReflectionException
2012
-     * @since 4.5.0
2013
-     */
2014
-    public function switch_template_pack()
2015
-    {
2016
-
2017
-        $GRP_ID        = $this->request->getRequestParam('GRP_ID', 0, 'int');
2018
-        $template_pack = $this->request->getRequestParam('template_pack', '');
2019
-
2020
-        // verify we have needed values.
2021
-        if (empty($GRP_ID) || empty($template_pack)) {
2022
-            $this->_template_args['error'] = true;
2023
-            EE_Error::add_error(
2024
-                esc_html__('The required date for switching templates is not available.', 'event_espresso'),
2025
-                __FILE__,
2026
-                __FUNCTION__,
2027
-                __LINE__
2028
-            );
2029
-        } else {
2030
-            // get template, set the new template_pack and then reset to default
2031
-            /** @var EE_Message_Template_Group $message_template_group */
2032
-            $message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
2033
-
2034
-            $message_template_group->set_template_pack_name($template_pack);
2035
-            $this->request->setRequestParam('msgr', $message_template_group->messenger());
2036
-            $this->request->setRequestParam('mt', $message_template_group->message_type());
2037
-
2038
-            $query_args = $this->_reset_to_default_template();
2039
-
2040
-            if (empty($query_args['id'])) {
2041
-                EE_Error::add_error(
2042
-                    esc_html__(
2043
-                        'Something went wrong with switching the template pack. Please try again or contact EE support',
2044
-                        'event_espresso'
2045
-                    ),
2046
-                    __FILE__,
2047
-                    __FUNCTION__,
2048
-                    __LINE__
2049
-                );
2050
-                $this->_template_args['error'] = true;
2051
-            } else {
2052
-                $template_label       = $message_template_group->get_template_pack()->label;
2053
-                $template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
2054
-                EE_Error::add_success(
2055
-                    sprintf(
2056
-                        esc_html__(
2057
-                            'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2058
-                            'event_espresso'
2059
-                        ),
2060
-                        $template_label,
2061
-                        $template_pack_labels->template_pack
2062
-                    )
2063
-                );
2064
-                // generate the redirect url for js.
2065
-                $url = self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2066
-
2067
-                $this->_template_args['data']['redirect_url'] = $url;
2068
-                $this->_template_args['success']              = true;
2069
-            }
2070
-
2071
-            $this->_return_json();
2072
-        }
2073
-    }
2074
-
2075
-
2076
-    /**
2077
-     * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2078
-     * they want.
2079
-     *
2080
-     * @access protected
2081
-     * @return array|void
2082
-     * @throws EE_Error
2083
-     * @throws InvalidArgumentException
2084
-     * @throws InvalidDataTypeException
2085
-     * @throws InvalidInterfaceException
2086
-     * @throws ReflectionException
2087
-     */
2088
-    protected function _reset_to_default_template()
2089
-    {
2090
-        $templates    = [];
2091
-        $GRP_ID       = $this->request->getRequestParam('GRP_ID', 0, 'int');
2092
-        $messenger    = $this->request->getRequestParam('msgr');
2093
-        $message_type = $this->request->getRequestParam('mt');
2094
-        // we need to make sure we've got the info we need.
2095
-        if (! ($GRP_ID && $messenger && $message_type)) {
2096
-            EE_Error::add_error(
2097
-                esc_html__(
2098
-                    'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2099
-                    'event_espresso'
2100
-                ),
2101
-                __FILE__,
2102
-                __FUNCTION__,
2103
-                __LINE__
2104
-            );
2105
-        }
2106
-
2107
-        // all templates will be reset to whatever the defaults are
2108
-        // for the global template matching the messenger and message type.
2109
-        $success = ! empty($GRP_ID);
2110
-
2111
-        if ($success) {
2112
-            // let's first determine if the incoming template is a global template,
2113
-            // if it isn't then we need to get the global template matching messenger and message type.
2114
-            // $MTPG = $this->getMtgModel()->get_one_by_ID( $GRP_ID );
2115
-
2116
-
2117
-            // note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2118
-            $success = $this->_delete_mtp_permanently($GRP_ID, false);
2119
-
2120
-            if ($success) {
2121
-                // if successfully deleted, lets generate the new ones.
2122
-                // Note. We set GLOBAL to true, because resets on ANY template
2123
-                // will use the related global template defaults for regeneration.
2124
-                // This means that if a custom template is reset it resets to whatever the related global template is.
2125
-                // HOWEVER, we DO keep the template pack and template variation set
2126
-                // for the current custom template when resetting.
2127
-                $templates = $this->_generate_new_templates($messenger, $message_type, $GRP_ID, true);
2128
-            }
2129
-        }
2130
-
2131
-        // any error messages?
2132
-        if (! $success) {
2133
-            EE_Error::add_error(
2134
-                esc_html__(
2135
-                    'Something went wrong with deleting existing templates. Unable to reset to default',
2136
-                    'event_espresso'
2137
-                ),
2138
-                __FILE__,
2139
-                __FUNCTION__,
2140
-                __LINE__
2141
-            );
2142
-        }
2143
-
2144
-        // all good, let's add a success message!
2145
-        if ($success && ! empty($templates)) {
2146
-            // the info for the template we generated is the first element in the returned array
2147
-            EE_Error::overwrite_success();
2148
-            EE_Error::add_success(esc_html__('Templates have been reset to defaults.', 'event_espresso'));
2149
-        }
2150
-
2151
-
2152
-        $query_args = [
2153
-            'id'      => isset($templates['GRP_ID']) ? $templates['GRP_ID'] : null,
2154
-            'context' => isset($templates['MTP_context']) ? $templates['MTP_context'] : null,
2155
-            'action'  => isset($templates['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2156
-        ];
2157
-
2158
-        // if called via ajax then we return query args otherwise redirect
2159
-        if ($this->request->isAjax()) {
2160
-            return $query_args;
2161
-        }
2162
-        $this->_redirect_after_action(false, '', '', $query_args, true);
2163
-    }
2164
-
2165
-
2166
-    /**
2167
-     * Retrieve and set the message preview for display.
2168
-     *
2169
-     * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2170
-     * @return string
2171
-     * @throws ReflectionException
2172
-     * @throws EE_Error
2173
-     * @throws InvalidArgumentException
2174
-     * @throws InvalidDataTypeException
2175
-     * @throws InvalidInterfaceException
2176
-     */
2177
-    public function _preview_message($send = false)
2178
-    {
2179
-        // first make sure we've got the necessary parameters
2180
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2181
-        if (! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2182
-            EE_Error::add_error(
2183
-                esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2184
-                __FILE__,
2185
-                __FUNCTION__,
2186
-                __LINE__
2187
-            );
2188
-        }
2189
-
2190
-        $context = $this->request->getRequestParam('context');
2191
-        // get the preview!
2192
-        $preview = EED_Messages::preview_message(
2193
-            $this->_active_message_type_name,
2194
-            $context,
2195
-            $this->_active_messenger_name,
2196
-            $send
2197
-        );
2198
-
2199
-        if ($send) {
2200
-            return $preview;
2201
-        }
2202
-
2203
-        // if we have an evt_id set on the request, use it.
2204
-        $EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
2205
-
2206
-        // let's add a button to go back to the edit view
2207
-        $query_args             = [
2208
-            'id'      => $GRP_ID,
2209
-            'evt_id'  => $EVT_ID,
2210
-            'context' => $context,
2211
-            'action'  => 'edit_message_template',
2212
-        ];
2213
-        $go_back_url            = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2214
-        $preview_button         = '<a href="'
2215
-                                  . $go_back_url
2216
-                                  . '" class="button--secondary messages-preview-go-back-button">'
2217
-                                  . esc_html__('Go Back to Edit', 'event_espresso')
2218
-                                  . '</a>';
2219
-        $message_types          = $this->get_installed_message_types();
2220
-        $active_messenger       = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
2221
-        $active_messenger_label = $active_messenger instanceof EE_messenger
2222
-            ? ucwords($active_messenger->label['singular'])
2223
-            : esc_html__('Unknown Messenger', 'event_espresso');
2224
-        // let's provide a helpful title for context
2225
-        $preview_title = sprintf(
2226
-            esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2227
-            $active_messenger_label,
2228
-            ucwords($message_types[ $this->_active_message_type_name ]->label['singular'])
2229
-        );
2230
-        if (empty($preview)) {
2231
-            $this->noEventsErrorMessage();
2232
-        }
2233
-        // setup display of preview.
2234
-        $this->_admin_page_title                    = $preview_title;
2235
-        $this->_template_args['admin_page_title']   = $preview_title;
2236
-        $this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2237
-        $this->_template_args['data']['force_json'] = true;
2238
-
2239
-        return '';
2240
-    }
2241
-
2242
-
2243
-    /**
2244
-     * Used to set an error if there are no events available for generating a preview/test send.
2245
-     *
2246
-     * @param bool $test_send Whether the error should be generated for the context of a test send.
2247
-     */
2248
-    protected function noEventsErrorMessage($test_send = false)
2249
-    {
2250
-        $events_url = parent::add_query_args_and_nonce(
2251
-            [
2252
-                'action' => 'default',
2253
-                'page'   => 'espresso_events',
2254
-            ],
2255
-            admin_url('admin.php')
2256
-        );
2257
-        $message    = $test_send
2258
-            ? esc_html__(
2259
-                'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2260
-                'event_espresso'
2261
-            )
2262
-            : esc_html__(
2263
-                'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2264
-                'event_espresso'
2265
-            );
2266
-
2267
-        EE_Error::add_attention(
2268
-            sprintf(
2269
-                $message,
2270
-                "<a href='{$events_url}'>",
2271
-                '</a>'
2272
-            )
2273
-        );
2274
-    }
2275
-
2276
-
2277
-    /**
2278
-     * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2279
-     * gets called automatically.
2280
-     *
2281
-     * @return void
2282
-     * @throws EE_Error
2283
-     * @since 4.5.0
2284
-     *
2285
-     */
2286
-    protected function _display_preview_message()
2287
-    {
2288
-        $this->display_admin_page_with_no_sidebar();
2289
-    }
2290
-
2291
-
2292
-    /**
2293
-     * registers metaboxes that should show up on the "edit_message_template" page
2294
-     *
2295
-     * @access protected
2296
-     * @return void
2297
-     */
2298
-    protected function _register_edit_meta_boxes()
2299
-    {
2300
-        $this->addMetaBox(
2301
-            'mtp_valid_shortcodes',
2302
-            esc_html__('Valid Shortcodes', 'event_espresso'),
2303
-            [$this, 'shortcode_meta_box'],
2304
-            $this->_current_screen->id,
2305
-            'side'
2306
-        );
2307
-        $this->addMetaBox(
2308
-            'mtp_extra_actions',
2309
-            esc_html__('Extra Actions', 'event_espresso'),
2310
-            [$this, 'extra_actions_meta_box'],
2311
-            $this->_current_screen->id,
2312
-            'side',
2313
-            'high'
2314
-        );
2315
-        $this->addMetaBox(
2316
-            'mtp_templates',
2317
-            esc_html__('Template Styles', 'event_espresso'),
2318
-            [$this, 'template_pack_meta_box'],
2319
-            $this->_current_screen->id,
2320
-            'side',
2321
-            'high'
2322
-        );
2323
-    }
2324
-
2325
-
2326
-    /**
2327
-     * metabox content for all template pack and variation selection.
2328
-     *
2329
-     * @return void
2330
-     * @throws DomainException
2331
-     * @throws EE_Error
2332
-     * @throws InvalidArgumentException
2333
-     * @throws ReflectionException
2334
-     * @throws InvalidDataTypeException
2335
-     * @throws InvalidInterfaceException
2336
-     * @since 4.5.0
2337
-     */
2338
-    public function template_pack_meta_box()
2339
-    {
2340
-        $this->_set_message_template_group();
2341
-
2342
-        $tp_collection = EEH_MSG_Template::get_template_pack_collection();
2343
-
2344
-        $tp_select_values = [];
2345
-
2346
-        foreach ($tp_collection as $tp) {
2347
-            // only include template packs that support this messenger and message type!
2348
-            $supports = $tp->get_supports();
2349
-            if (
2350
-                ! isset($supports[ $this->_message_template_group->messenger() ])
2351
-                || ! in_array(
2352
-                    $this->_message_template_group->message_type(),
2353
-                    $supports[ $this->_message_template_group->messenger() ],
2354
-                    true
2355
-                )
2356
-            ) {
2357
-                // not supported
2358
-                continue;
2359
-            }
2360
-
2361
-            $tp_select_values[] = [
2362
-                'text' => $tp->label,
2363
-                'id'   => $tp->dbref,
2364
-            ];
2365
-        }
2366
-
2367
-        // if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2368
-        // the default template pack.  This still allows for the odd template pack to override.
2369
-        if (empty($tp_select_values)) {
2370
-            $tp_select_values[] = [
2371
-                'text' => esc_html__('Default', 'event_espresso'),
2372
-                'id'   => 'default',
2373
-            ];
2374
-        }
2375
-
2376
-        // setup variation select values for the currently selected template.
2377
-        $variations               = $this->_message_template_group->get_template_pack()->get_variations(
2378
-            $this->_message_template_group->messenger(),
2379
-            $this->_message_template_group->message_type()
2380
-        );
2381
-        $variations_select_values = [];
2382
-        foreach ($variations as $variation => $label) {
2383
-            $variations_select_values[] = [
2384
-                'text' => $label,
2385
-                'id'   => $variation,
2386
-            ];
2387
-        }
2388
-
2389
-        $template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2390
-
2391
-        $template_args['template_packs_selector']        = EEH_Form_Fields::select_input(
2392
-            'MTP_template_pack',
2393
-            $tp_select_values,
2394
-            $this->_message_template_group->get_template_pack_name()
2395
-        );
2396
-        $template_args['variations_selector']            = EEH_Form_Fields::select_input(
2397
-            'MTP_template_variation',
2398
-            $variations_select_values,
2399
-            $this->_message_template_group->get_template_pack_variation()
2400
-        );
2401
-        $template_args['template_pack_label']            = $template_pack_labels->template_pack;
2402
-        $template_args['template_variation_label']       = $template_pack_labels->template_variation;
2403
-        $template_args['template_pack_description']      = $template_pack_labels->template_pack_description;
2404
-        $template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2405
-
2406
-        $template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2407
-
2408
-        EEH_Template::display_template($template, $template_args);
2409
-    }
2410
-
2411
-
2412
-    /**
2413
-     * This meta box holds any extra actions related to Message Templates
2414
-     * For now, this includes Resetting templates to defaults and sending a test email.
2415
-     *
2416
-     * @access  public
2417
-     * @return void
2418
-     * @throws EE_Error
2419
-     */
2420
-    public function extra_actions_meta_box()
2421
-    {
2422
-        $template_form_fields = [];
2423
-
2424
-        $extra_args = [
2425
-            'msgr'   => $this->_message_template_group->messenger(),
2426
-            'mt'     => $this->_message_template_group->message_type(),
2427
-            'GRP_ID' => $this->_message_template_group->GRP_ID(),
2428
-        ];
2429
-        // first we need to see if there are any fields
2430
-        $fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2431
-
2432
-        if (! empty($fields)) {
2433
-            // yup there be fields
2434
-            foreach ($fields as $field => $config) {
2435
-                $field_id = $this->_message_template_group->messenger() . '_' . $field;
2436
-                $existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2437
-                $default  = isset($config['default']) ? $config['default'] : '';
2438
-                $default  = isset($config['value']) ? $config['value'] : $default;
2439
-
2440
-                // if type is hidden and the value is empty
2441
-                // something may have gone wrong so let's correct with the defaults
2442
-                $fix                = $config['input'] === 'hidden'
2443
-                                      && isset($existing[ $field ])
2444
-                                      && empty($existing[ $field ])
2445
-                    ? $default
2446
-                    : '';
2447
-                $existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2448
-                    ? $existing[ $field ]
2449
-                    : $fix;
2450
-
2451
-                $template_form_fields[ $field_id ] = [
2452
-                    'name'       => 'test_settings_fld[' . $field . ']',
2453
-                    'label'      => $config['label'],
2454
-                    'input'      => $config['input'],
2455
-                    'type'       => $config['type'],
2456
-                    'required'   => $config['required'],
2457
-                    'validation' => $config['validation'],
2458
-                    'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2459
-                    'css_class'  => $config['css_class'],
2460
-                    'options'    => isset($config['options']) ? $config['options'] : [],
2461
-                    'default'    => $default,
2462
-                    'format'     => $config['format'],
2463
-                ];
2464
-            }
2465
-        }
2466
-
2467
-        $test_settings_html = ! empty($template_form_fields)
2468
-            ? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2469
-            : '';
2470
-
2471
-        // print out $test_settings_fields
2472
-        if (! empty($test_settings_html)) {
2473
-            $test_settings_html .= '<input type="submit" class="button--primary mtp-test-button alignright" ';
2474
-            $test_settings_html .= 'name="test_button" value="';
2475
-            $test_settings_html .= esc_html__('Test Send', 'event_espresso');
2476
-            $test_settings_html .= '" /><div style="clear:both"></div>';
2477
-        }
2478
-
2479
-        // and button
2480
-        $test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2481
-        $test_settings_html .= '<p>';
2482
-        $test_settings_html .= esc_html__('Need to reset this message type and start over?', 'event_espresso');
2483
-        $test_settings_html .= '</p>';
2484
-        $test_settings_html .= $this->get_action_link_or_button(
2485
-            'reset_to_default',
2486
-            'reset',
2487
-            $extra_args,
2488
-            'button--primary reset-default-button'
2489
-        );
2490
-        $test_settings_html .= '</div><div style="clear:both"></div>';
2491
-        echo wp_kses($test_settings_html, AllowedTags::getWithFormTags());
2492
-    }
2493
-
2494
-
2495
-    /**
2496
-     * This returns the shortcode selector skeleton for a given context and field.
2497
-     *
2498
-     * @param string $field           The name of the field retrieving shortcodes for.
2499
-     * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2500
-     * @return string
2501
-     * @throws DomainException
2502
-     * @throws EE_Error
2503
-     * @throws InvalidArgumentException
2504
-     * @throws ReflectionException
2505
-     * @throws InvalidDataTypeException
2506
-     * @throws InvalidInterfaceException
2507
-     * @since 4.9.rc.000
2508
-     */
2509
-    protected function _get_shortcode_selector($field, $linked_input_id)
2510
-    {
2511
-        $template_args = [
2512
-            'shortcodes'      => $this->_get_shortcodes([$field]),
2513
-            'fieldname'       => $field,
2514
-            'linked_input_id' => $linked_input_id,
2515
-        ];
2516
-
2517
-        return EEH_Template::display_template(
2518
-            EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2519
-            $template_args,
2520
-            true
2521
-        );
2522
-    }
2523
-
2524
-
2525
-    /**
2526
-     * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2527
-     * page)
2528
-     *
2529
-     * @access public
2530
-     * @return void
2531
-     * @throws EE_Error
2532
-     * @throws InvalidArgumentException
2533
-     * @throws ReflectionException
2534
-     * @throws InvalidDataTypeException
2535
-     * @throws InvalidInterfaceException
2536
-     */
2537
-    public function shortcode_meta_box()
2538
-    {
2539
-        $shortcodes = $this->_get_shortcodes([], false);
2540
-        // just make sure the shortcodes property is set
2541
-        // $messenger = $this->_message_template_group->messenger_obj();
2542
-        // now let's set the content depending on the status of the shortcodes array
2543
-        if (empty($shortcodes)) {
2544
-            echo '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2545
-            return;
2546
-        }
2547
-        ?>
20
+	/**
21
+	 * @var EEM_Message
22
+	 */
23
+	private $MSG_MODEL;
24
+
25
+	/**
26
+	 * @var EEM_Message_Template
27
+	 */
28
+	private $MTP_MODEL;
29
+
30
+	/**
31
+	 * @var EEM_Message_Template_Group
32
+	 */
33
+	private $MTG_MODEL;
34
+
35
+	/**
36
+	 * @var EE_Message_Resource_Manager $_message_resource_manager
37
+	 */
38
+	protected $_message_resource_manager;
39
+
40
+	/**
41
+	 * @var string
42
+	 */
43
+	protected $_active_message_type_name = '';
44
+
45
+	/**
46
+	 * @var string
47
+	 */
48
+	protected $_active_messenger_name = '';
49
+
50
+	/**
51
+	 * @var EE_messenger $_active_messenger
52
+	 */
53
+	protected $_active_messenger;
54
+
55
+	protected $_activate_meta_box_type;
56
+
57
+	protected $_current_message_meta_box;
58
+
59
+	protected $_current_message_meta_box_object;
60
+
61
+	protected $_context_switcher;
62
+
63
+	protected $_shortcodes           = [];
64
+
65
+	protected $_active_messengers    = [];
66
+
67
+	protected $_active_message_types = [];
68
+
69
+	/**
70
+	 * @var EE_Message_Template_Group $_message_template_group
71
+	 */
72
+	protected $_message_template_group;
73
+
74
+	protected $_m_mt_settings = [];
75
+
76
+
77
+	/**
78
+	 * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
79
+	 * IF there is no group then it gets automatically set to the Default template pack.
80
+	 *
81
+	 * @since 4.5.0
82
+	 *
83
+	 * @var EE_Messages_Template_Pack
84
+	 */
85
+	protected $_template_pack;
86
+
87
+
88
+	/**
89
+	 * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
90
+	 * group is.  If there is no group then it automatically gets set to default.
91
+	 *
92
+	 * @since 4.5.0
93
+	 *
94
+	 * @var string
95
+	 */
96
+	protected $_variation;
97
+
98
+
99
+	/**
100
+	 * @param bool $routing
101
+	 * @throws EE_Error
102
+	 * @throws ReflectionException
103
+	 */
104
+	public function __construct($routing = true)
105
+	{
106
+		// make sure messages autoloader is running
107
+		EED_Messages::set_autoloaders();
108
+		parent::__construct($routing);
109
+	}
110
+
111
+
112
+	/**
113
+	 * @return EEM_Message
114
+	 * @throws EE_Error
115
+	 */
116
+	public function getMsgModel()
117
+	{
118
+		if (! $this->MSG_MODEL instanceof EEM_Message) {
119
+			$this->MSG_MODEL = EEM_Message::instance();
120
+		}
121
+		return $this->MSG_MODEL;
122
+	}
123
+
124
+
125
+	/**
126
+	 * @return EEM_Message_Template
127
+	 * @throws EE_Error
128
+	 */
129
+	public function getMtpModel()
130
+	{
131
+		if (! $this->MTP_MODEL instanceof EEM_Message_Template) {
132
+			$this->MTP_MODEL = EEM_Message_Template::instance();
133
+		}
134
+		return $this->MTP_MODEL;
135
+	}
136
+
137
+
138
+	/**
139
+	 * @return EEM_Message_Template_Group
140
+	 * @throws EE_Error
141
+	 */
142
+	public function getMtgModel()
143
+	{
144
+		if (! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
145
+			$this->MTG_MODEL = EEM_Message_Template_Group::instance();
146
+		}
147
+		return $this->MTG_MODEL;
148
+	}
149
+
150
+
151
+	/**
152
+	 * @throws EE_Error
153
+	 * @throws ReflectionException
154
+	 */
155
+	protected function _init_page_props()
156
+	{
157
+		$this->page_slug        = EE_MSG_PG_SLUG;
158
+		$this->page_label       = esc_html__('Messages Settings', 'event_espresso');
159
+		$this->_admin_base_url  = EE_MSG_ADMIN_URL;
160
+		$this->_admin_base_path = EE_MSG_ADMIN;
161
+
162
+		$messenger    = $this->request->getRequestParam('messenger', '');
163
+		$message_type = $this->request->getRequestParam('message_type', '');
164
+		$this->_active_messenger_name    = $this->request->getRequestParam('MTP_messenger', $messenger);
165
+		$this->_active_message_type_name = $this->request->getRequestParam('MTP_message_type', $message_type);
166
+
167
+		$this->_load_message_resource_manager();
168
+	}
169
+
170
+
171
+	/**
172
+	 * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
173
+	 *
174
+	 * @throws EE_Error
175
+	 * @throws InvalidDataTypeException
176
+	 * @throws InvalidInterfaceException
177
+	 * @throws InvalidArgumentException
178
+	 * @throws ReflectionException
179
+	 */
180
+	protected function _load_message_resource_manager()
181
+	{
182
+		$this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
183
+	}
184
+
185
+
186
+	/**
187
+	 * @return array
188
+	 * @throws EE_Error
189
+	 * @throws InvalidArgumentException
190
+	 * @throws InvalidDataTypeException
191
+	 * @throws InvalidInterfaceException
192
+	 * @deprecated 4.9.9.rc.014
193
+	 */
194
+	public function get_messengers_for_list_table()
195
+	{
196
+		EE_Error::doing_it_wrong(
197
+			__METHOD__,
198
+			sprintf(
199
+				esc_html__(
200
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
201
+					'event_espresso'
202
+				),
203
+				'Messages_Admin_Page::get_messengers_select_input()'
204
+			),
205
+			'4.9.9.rc.014'
206
+		);
207
+
208
+		$m_values          = [];
209
+		$active_messengers = $this->getMsgModel()->get_all(['group_by' => 'MSG_messenger']);
210
+		// setup messengers for selects
211
+		$i = 1;
212
+		foreach ($active_messengers as $active_messenger) {
213
+			if ($active_messenger instanceof EE_Message) {
214
+				$m_values[ $i ]['id']   = $active_messenger->messenger();
215
+				$m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
216
+				$i++;
217
+			}
218
+		}
219
+
220
+		return $m_values;
221
+	}
222
+
223
+
224
+	/**
225
+	 * @return array
226
+	 * @throws EE_Error
227
+	 * @throws InvalidArgumentException
228
+	 * @throws InvalidDataTypeException
229
+	 * @throws InvalidInterfaceException
230
+	 * @deprecated 4.9.9.rc.014
231
+	 */
232
+	public function get_message_types_for_list_table()
233
+	{
234
+		EE_Error::doing_it_wrong(
235
+			__METHOD__,
236
+			sprintf(
237
+				esc_html__(
238
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
239
+					'event_espresso'
240
+				),
241
+				'Messages_Admin_Page::get_message_types_select_input()'
242
+			),
243
+			'4.9.9.rc.014'
244
+		);
245
+
246
+		$mt_values       = [];
247
+		$active_messages = $this->getMsgModel()->get_all(['group_by' => 'MSG_message_type']);
248
+		$i               = 1;
249
+		foreach ($active_messages as $active_message) {
250
+			if ($active_message instanceof EE_Message) {
251
+				$mt_values[ $i ]['id']   = $active_message->message_type();
252
+				$mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
253
+				$i++;
254
+			}
255
+		}
256
+
257
+		return $mt_values;
258
+	}
259
+
260
+
261
+	/**
262
+	 * @return array
263
+	 * @throws EE_Error
264
+	 * @throws InvalidArgumentException
265
+	 * @throws InvalidDataTypeException
266
+	 * @throws InvalidInterfaceException
267
+	 * @deprecated 4.9.9.rc.014
268
+	 */
269
+	public function get_contexts_for_message_types_for_list_table()
270
+	{
271
+		EE_Error::doing_it_wrong(
272
+			__METHOD__,
273
+			sprintf(
274
+				esc_html__(
275
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
276
+					'event_espresso'
277
+				),
278
+				'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
279
+			),
280
+			'4.9.9.rc.014'
281
+		);
282
+
283
+		$contexts                = [];
284
+		$active_message_contexts = $this->getMsgModel()->get_all(['group_by' => 'MSG_context']);
285
+		foreach ($active_message_contexts as $active_message) {
286
+			if ($active_message instanceof EE_Message) {
287
+				$message_type = $active_message->message_type_object();
288
+				if ($message_type instanceof EE_message_type) {
289
+					$message_type_contexts = $message_type->get_contexts();
290
+					foreach ($message_type_contexts as $context => $context_details) {
291
+						$contexts[ $context ] = $context_details['label'];
292
+					}
293
+				}
294
+			}
295
+		}
296
+
297
+		return $contexts;
298
+	}
299
+
300
+
301
+	/**
302
+	 * Generate select input with provided messenger options array.
303
+	 *
304
+	 * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
305
+	 *                                 labels.
306
+	 * @return string
307
+	 * @throws EE_Error
308
+	 */
309
+	public function get_messengers_select_input($messenger_options)
310
+	{
311
+		// if empty or just one value then just return an empty string
312
+		if (
313
+			empty($messenger_options)
314
+			|| ! is_array($messenger_options)
315
+			|| count($messenger_options) === 1
316
+		) {
317
+			return '';
318
+		}
319
+		// merge in default
320
+		$messenger_options = array_merge(
321
+			['none_selected' => esc_html__('Show All Messengers', 'event_espresso')],
322
+			$messenger_options
323
+		);
324
+		$input             = new EE_Select_Input(
325
+			$messenger_options,
326
+			[
327
+				'html_name'  => 'ee_messenger_filter_by',
328
+				'html_id'    => 'ee_messenger_filter_by',
329
+				'html_class' => 'wide',
330
+				'default'    => $this->request->getRequestParam('ee_messenger_filter_by', 'none_selected', 'title'),
331
+			]
332
+		);
333
+
334
+		return $input->get_html_for_input();
335
+	}
336
+
337
+
338
+	/**
339
+	 * Generate select input with provided message type options array.
340
+	 *
341
+	 * @param array $message_type_options Array of message types indexed by message type slug, and values are the
342
+	 *                                    message type labels
343
+	 * @return string
344
+	 * @throws EE_Error
345
+	 */
346
+	public function get_message_types_select_input($message_type_options)
347
+	{
348
+		// if empty or count of options is 1 then just return an empty string
349
+		if (
350
+			empty($message_type_options)
351
+			|| ! is_array($message_type_options)
352
+			|| count($message_type_options) === 1
353
+		) {
354
+			return '';
355
+		}
356
+		// merge in default
357
+		$message_type_options = array_merge(
358
+			['none_selected' => esc_html__('Show All Message Types', 'event_espresso')],
359
+			$message_type_options
360
+		);
361
+		$input                = new EE_Select_Input(
362
+			$message_type_options,
363
+			[
364
+				'html_name'  => 'ee_message_type_filter_by',
365
+				'html_id'    => 'ee_message_type_filter_by',
366
+				'html_class' => 'wide',
367
+				'default'    => $this->request->getRequestParam('ee_message_type_filter_by', 'none_selected', 'title'),
368
+			]
369
+		);
370
+
371
+		return $input->get_html_for_input();
372
+	}
373
+
374
+
375
+	/**
376
+	 * Generate select input with provide message type contexts array.
377
+	 *
378
+	 * @param array $context_options Array of message type contexts indexed by context slug, and values are the
379
+	 *                               context label.
380
+	 * @return string
381
+	 * @throws EE_Error
382
+	 */
383
+	public function get_contexts_for_message_types_select_input($context_options)
384
+	{
385
+		// if empty or count of options is one then just return empty string
386
+		if (
387
+			empty($context_options)
388
+			|| ! is_array($context_options)
389
+			|| count($context_options) === 1
390
+		) {
391
+			return '';
392
+		}
393
+		// merge in default
394
+		$context_options = array_merge(
395
+			['none_selected' => esc_html__('Show all Contexts', 'event_espresso')],
396
+			$context_options
397
+		);
398
+		$input           = new EE_Select_Input(
399
+			$context_options,
400
+			[
401
+				'html_name'  => 'ee_context_filter_by',
402
+				'html_id'    => 'ee_context_filter_by',
403
+				'html_class' => 'wide',
404
+				'default'    => $this->request->getRequestParam('ee_context_filter_by', 'none_selected', 'title'),
405
+			]
406
+		);
407
+
408
+		return $input->get_html_for_input();
409
+	}
410
+
411
+
412
+	protected function _ajax_hooks()
413
+	{
414
+		add_action('wp_ajax_activate_messenger', [$this, 'activate_messenger_toggle']);
415
+		add_action('wp_ajax_activate_mt', [$this, 'activate_mt_toggle']);
416
+		add_action('wp_ajax_ee_msgs_save_settings', [$this, 'save_settings']);
417
+		add_action('wp_ajax_ee_msgs_update_mt_form', [$this, 'update_mt_form']);
418
+		add_action('wp_ajax_switch_template_pack', [$this, 'switch_template_pack']);
419
+		add_action('wp_ajax_toggle_context_template', [$this, 'toggle_context_template']);
420
+	}
421
+
422
+
423
+	protected function _define_page_props()
424
+	{
425
+		$this->_admin_page_title = $this->page_label;
426
+		$this->_labels           = [
427
+			'buttons'    => [
428
+				'add'    => esc_html__('Add New Message Template', 'event_espresso'),
429
+				'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
430
+				'delete' => esc_html__('Delete Message Template', 'event_espresso'),
431
+			],
432
+			'publishbox' => esc_html__('Update Actions', 'event_espresso'),
433
+		];
434
+	}
435
+
436
+
437
+	/**
438
+	 *        an array for storing key => value pairs of request actions and their corresponding methods
439
+	 *
440
+	 * @access protected
441
+	 * @return void
442
+	 */
443
+	protected function _set_page_routes()
444
+	{
445
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
446
+		$GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
447
+		$MSG_ID = $this->request->getRequestParam('MSG_ID', 0, 'int');
448
+
449
+		$this->_page_routes = [
450
+			'default'                          => [
451
+				'func'       => '_message_queue_list_table',
452
+				'capability' => 'ee_read_global_messages',
453
+			],
454
+			'global_mtps'                      => [
455
+				'func'       => '_ee_default_messages_overview_list_table',
456
+				'capability' => 'ee_read_global_messages',
457
+			],
458
+			'custom_mtps'                      => [
459
+				'func'       => '_custom_mtps_preview',
460
+				'capability' => 'ee_read_messages',
461
+			],
462
+			'add_new_message_template'         => [
463
+				'func'       => 'add_message_template',
464
+				'capability' => 'ee_edit_messages',
465
+				'noheader'   => true,
466
+			],
467
+			'edit_message_template'            => [
468
+				'func'       => '_edit_message_template',
469
+				'capability' => 'ee_edit_message',
470
+				'obj_id'     => $GRP_ID,
471
+			],
472
+			'preview_message'                  => [
473
+				'func'               => '_preview_message',
474
+				'capability'         => 'ee_read_message',
475
+				'obj_id'             => $GRP_ID,
476
+				'noheader'           => true,
477
+				'headers_sent_route' => 'display_preview_message',
478
+			],
479
+			'display_preview_message'          => [
480
+				'func'       => '_display_preview_message',
481
+				'capability' => 'ee_read_message',
482
+				'obj_id'     => $GRP_ID,
483
+			],
484
+			'insert_message_template'          => [
485
+				'func'       => '_insert_or_update_message_template',
486
+				'capability' => 'ee_edit_messages',
487
+				'args'       => ['new' => true],
488
+				'noheader'   => true,
489
+			],
490
+			'update_message_template'          => [
491
+				'func'       => '_insert_or_update_message_template',
492
+				'capability' => 'ee_edit_message',
493
+				'obj_id'     => $GRP_ID,
494
+				'args'       => ['new' => false],
495
+				'noheader'   => true,
496
+			],
497
+			'trash_message_template'           => [
498
+				'func'       => '_trash_or_restore_message_template',
499
+				'capability' => 'ee_delete_message',
500
+				'obj_id'     => $GRP_ID,
501
+				'args'       => ['trash' => true, 'all' => true],
502
+				'noheader'   => true,
503
+			],
504
+			'trash_message_template_context'   => [
505
+				'func'       => '_trash_or_restore_message_template',
506
+				'capability' => 'ee_delete_message',
507
+				'obj_id'     => $GRP_ID,
508
+				'args'       => ['trash' => true],
509
+				'noheader'   => true,
510
+			],
511
+			'restore_message_template'         => [
512
+				'func'       => '_trash_or_restore_message_template',
513
+				'capability' => 'ee_delete_message',
514
+				'obj_id'     => $GRP_ID,
515
+				'args'       => ['trash' => false, 'all' => true],
516
+				'noheader'   => true,
517
+			],
518
+			'restore_message_template_context' => [
519
+				'func'       => '_trash_or_restore_message_template',
520
+				'capability' => 'ee_delete_message',
521
+				'obj_id'     => $GRP_ID,
522
+				'args'       => ['trash' => false],
523
+				'noheader'   => true,
524
+			],
525
+			'delete_message_template'          => [
526
+				'func'       => '_delete_message_template',
527
+				'capability' => 'ee_delete_message',
528
+				'obj_id'     => $GRP_ID,
529
+				'noheader'   => true,
530
+			],
531
+			'reset_to_default'                 => [
532
+				'func'       => '_reset_to_default_template',
533
+				'capability' => 'ee_edit_message',
534
+				'obj_id'     => $GRP_ID,
535
+				'noheader'   => true,
536
+			],
537
+			'settings'                         => [
538
+				'func'       => '_settings',
539
+				'capability' => 'manage_options',
540
+			],
541
+			'update_global_settings'           => [
542
+				'func'       => '_update_global_settings',
543
+				'capability' => 'manage_options',
544
+				'noheader'   => true,
545
+			],
546
+			'generate_now'                     => [
547
+				'func'       => '_generate_now',
548
+				'capability' => 'ee_send_message',
549
+				'noheader'   => true,
550
+			],
551
+			'generate_and_send_now'            => [
552
+				'func'       => '_generate_and_send_now',
553
+				'capability' => 'ee_send_message',
554
+				'noheader'   => true,
555
+			],
556
+			'queue_for_resending'              => [
557
+				'func'       => '_queue_for_resending',
558
+				'capability' => 'ee_send_message',
559
+				'noheader'   => true,
560
+			],
561
+			'send_now'                         => [
562
+				'func'       => '_send_now',
563
+				'capability' => 'ee_send_message',
564
+				'noheader'   => true,
565
+			],
566
+			'delete_ee_message'                => [
567
+				'func'       => '_delete_ee_messages',
568
+				'capability' => 'ee_delete_messages',
569
+				'noheader'   => true,
570
+			],
571
+			'delete_ee_messages'               => [
572
+				'func'       => '_delete_ee_messages',
573
+				'capability' => 'ee_delete_messages',
574
+				'noheader'   => true,
575
+				'obj_id'     => $MSG_ID,
576
+			],
577
+		];
578
+	}
579
+
580
+
581
+	protected function _set_page_config()
582
+	{
583
+		$this->_page_config = [
584
+			'default'                  => [
585
+				'nav'           => [
586
+					'label' => esc_html__('Message Activity', 'event_espresso'),
587
+					'icon' => 'dashicons-email',
588
+					'order' => 10,
589
+				],
590
+				'list_table'    => 'EE_Message_List_Table',
591
+				// 'qtips' => array( 'EE_Message_List_Table_Tips' ),
592
+				'require_nonce' => false,
593
+			],
594
+			'global_mtps'              => [
595
+				'nav'           => [
596
+					'label' => esc_html__('Default Message Templates', 'event_espresso'),
597
+					'icon' => 'dashicons-layout',
598
+					'order' => 20,
599
+				],
600
+				'list_table'    => 'Messages_Template_List_Table',
601
+				'help_tabs'     => [
602
+					'messages_overview_help_tab'                                => [
603
+						'title'    => esc_html__('Messages Overview', 'event_espresso'),
604
+						'filename' => 'messages_overview',
605
+					],
606
+					'messages_overview_messages_table_column_headings_help_tab' => [
607
+						'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
608
+						'filename' => 'messages_overview_table_column_headings',
609
+					],
610
+					'messages_overview_messages_filters_help_tab'               => [
611
+						'title'    => esc_html__('Message Filters', 'event_espresso'),
612
+						'filename' => 'messages_overview_filters',
613
+					],
614
+					'messages_overview_messages_views_help_tab'                 => [
615
+						'title'    => esc_html__('Message Views', 'event_espresso'),
616
+						'filename' => 'messages_overview_views',
617
+					],
618
+					'message_overview_message_types_help_tab'                   => [
619
+						'title'    => esc_html__('Message Types', 'event_espresso'),
620
+						'filename' => 'messages_overview_types',
621
+					],
622
+					'messages_overview_messengers_help_tab'                     => [
623
+						'title'    => esc_html__('Messengers', 'event_espresso'),
624
+						'filename' => 'messages_overview_messengers',
625
+					],
626
+				],
627
+				'require_nonce' => false,
628
+			],
629
+			'custom_mtps'              => [
630
+				'nav'           => [
631
+					'label' => esc_html__('Custom Message Templates', 'event_espresso'),
632
+					'icon' => 'dashicons-admin-customizer',
633
+					'order' => 30,
634
+				],
635
+				'help_tabs'     => [],
636
+				'require_nonce' => false,
637
+			],
638
+			'add_new_message_template' => [
639
+				'nav'           => [
640
+					'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
641
+					'icon' => 'dashicons-plus-alt',
642
+					'order'      => 5,
643
+					'persistent' => false,
644
+				],
645
+				'require_nonce' => false,
646
+			],
647
+			'edit_message_template'    => [
648
+				'labels'        => [
649
+					'buttons'    => [
650
+						'reset' => esc_html__('Reset Templates', 'event_espresso'),
651
+					],
652
+					'publishbox' => esc_html__('Update Actions', 'event_espresso'),
653
+				],
654
+				'nav'           => [
655
+					'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
656
+					'icon' => 'dashicons-edit-large',
657
+					'order'      => 5,
658
+					'persistent' => false,
659
+					'url'        => '',
660
+				],
661
+				'metaboxes'     => ['_publish_post_box', '_register_edit_meta_boxes'],
662
+				'has_metaboxes' => true,
663
+				'help_tabs'     => [
664
+					'edit_message_template'            => [
665
+						'title'    => esc_html__('Message Template Editor', 'event_espresso'),
666
+						'callback' => 'edit_message_template_help_tab',
667
+					],
668
+					'message_templates_help_tab'       => [
669
+						'title'    => esc_html__('Message Templates', 'event_espresso'),
670
+						'filename' => 'messages_templates',
671
+					],
672
+					'message_template_shortcodes'      => [
673
+						'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
674
+						'callback' => 'message_template_shortcodes_help_tab',
675
+					],
676
+					'message_preview_help_tab'         => [
677
+						'title'    => esc_html__('Message Preview', 'event_espresso'),
678
+						'filename' => 'messages_preview',
679
+					],
680
+					'messages_overview_other_help_tab' => [
681
+						'title'    => esc_html__('Messages Other', 'event_espresso'),
682
+						'filename' => 'messages_overview_other',
683
+					],
684
+				],
685
+				'require_nonce' => false,
686
+			],
687
+			'display_preview_message'  => [
688
+				'nav'           => [
689
+					'label'      => esc_html__('Message Preview', 'event_espresso'),
690
+					'icon' => 'dashicons-visibility-bar',
691
+					'order'      => 5,
692
+					'url'        => '',
693
+					'persistent' => false,
694
+				],
695
+				'help_tabs'     => [
696
+					'preview_message' => [
697
+						'title'    => esc_html__('About Previews', 'event_espresso'),
698
+						'callback' => 'preview_message_help_tab',
699
+					],
700
+				],
701
+				'require_nonce' => false,
702
+			],
703
+			'settings'                 => [
704
+				'nav'           => [
705
+					'label' => esc_html__('Settings', 'event_espresso'),
706
+					'icon' => 'dashicons-admin-generic',
707
+					'order' => 40,
708
+				],
709
+				'metaboxes'     => ['_messages_settings_metaboxes'],
710
+				'help_tabs'     => [
711
+					'messages_settings_help_tab'               => [
712
+						'title'    => esc_html__('Messages Settings', 'event_espresso'),
713
+						'filename' => 'messages_settings',
714
+					],
715
+					'messages_settings_message_types_help_tab' => [
716
+						'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
717
+						'filename' => 'messages_settings_message_types',
718
+					],
719
+					'messages_settings_messengers_help_tab'    => [
720
+						'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
721
+						'filename' => 'messages_settings_messengers',
722
+					],
723
+				],
724
+				'require_nonce' => false,
725
+			],
726
+		];
727
+	}
728
+
729
+
730
+	protected function _add_screen_options()
731
+	{
732
+		// todo
733
+	}
734
+
735
+
736
+	protected function _add_screen_options_global_mtps()
737
+	{
738
+		/**
739
+		 * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
740
+		 * uses the $_admin_page_title property and we want different outputs in the different spots.
741
+		 */
742
+		$page_title              = $this->_admin_page_title;
743
+		$this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
744
+		$this->_per_page_screen_option();
745
+		$this->_admin_page_title = $page_title;
746
+	}
747
+
748
+
749
+	protected function _add_screen_options_default()
750
+	{
751
+		$this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
752
+		$this->_per_page_screen_option();
753
+	}
754
+
755
+
756
+	// none of the below group are currently used for Messages
757
+	protected function _add_feature_pointers()
758
+	{
759
+	}
760
+
761
+
762
+	public function admin_init()
763
+	{
764
+	}
765
+
766
+
767
+	public function admin_notices()
768
+	{
769
+	}
770
+
771
+
772
+	public function admin_footer_scripts()
773
+	{
774
+	}
775
+
776
+
777
+	public function messages_help_tab()
778
+	{
779
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
780
+	}
781
+
782
+
783
+	public function messengers_help_tab()
784
+	{
785
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
786
+	}
787
+
788
+
789
+	public function message_types_help_tab()
790
+	{
791
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
792
+	}
793
+
794
+
795
+	public function messages_overview_help_tab()
796
+	{
797
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
798
+	}
799
+
800
+
801
+	public function message_templates_help_tab()
802
+	{
803
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
804
+	}
805
+
806
+
807
+	public function edit_message_template_help_tab()
808
+	{
809
+		$args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
810
+						. esc_attr__('Editor Title', 'event_espresso')
811
+						. '" />';
812
+		$args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
813
+						. esc_attr__('Context Switcher and Preview', 'event_espresso')
814
+						. '" />';
815
+		$args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
816
+						. esc_attr__('Message Template Form Fields', 'event_espresso')
817
+						. '" />';
818
+		$args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
819
+						. esc_attr__('Shortcodes Metabox', 'event_espresso')
820
+						. '" />';
821
+		$args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
822
+						. esc_attr__('Publish Metabox', 'event_espresso')
823
+						. '" />';
824
+		EEH_Template::display_template(
825
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
826
+			$args
827
+		);
828
+	}
829
+
830
+
831
+	/**
832
+	 * @throws ReflectionException
833
+	 * @throws EE_Error
834
+	 */
835
+	public function message_template_shortcodes_help_tab()
836
+	{
837
+		$this->_set_shortcodes();
838
+		$args['shortcodes'] = $this->_shortcodes;
839
+		EEH_Template::display_template(
840
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
841
+			$args
842
+		);
843
+	}
844
+
845
+
846
+	public function preview_message_help_tab()
847
+	{
848
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
849
+	}
850
+
851
+
852
+	public function settings_help_tab()
853
+	{
854
+		$args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
855
+						. '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
856
+		$args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
857
+						. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
858
+		$args['img3'] = '<div class="switch">'
859
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
860
+						. ' type="checkbox" checked>'
861
+						. '<label for="ee-on-off-toggle-on"></label>'
862
+						. '</div>';
863
+		$args['img4'] = '<div class="switch">'
864
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
865
+						. ' type="checkbox">'
866
+						. '<label for="ee-on-off-toggle-on"></label>'
867
+						. '</div>';
868
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
869
+	}
870
+
871
+
872
+	public function load_scripts_styles()
873
+	{
874
+		wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
875
+		wp_enqueue_style('espresso_ee_msg');
876
+
877
+		wp_register_script(
878
+			'ee-messages-settings',
879
+			EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
880
+			['jquery-ui-droppable', 'ee-serialize-full-array'],
881
+			EVENT_ESPRESSO_VERSION,
882
+			true
883
+		);
884
+		wp_register_script(
885
+			'ee-msg-list-table-js',
886
+			EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
887
+			['ee-dialog'],
888
+			EVENT_ESPRESSO_VERSION
889
+		);
890
+	}
891
+
892
+
893
+	public function load_scripts_styles_default()
894
+	{
895
+		wp_enqueue_script('ee-msg-list-table-js');
896
+	}
897
+
898
+
899
+	public function wp_editor_css($mce_css)
900
+	{
901
+		// if we're on the edit_message_template route
902
+		if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
903
+			$message_type_name = $this->_active_message_type_name;
904
+
905
+			// we're going to REPLACE the existing mce css
906
+			// we need to get the css file location from the active messenger
907
+			$mce_css = $this->_active_messenger->get_variation(
908
+				$this->_template_pack,
909
+				$message_type_name,
910
+				true,
911
+				'wpeditor',
912
+				$this->_variation
913
+			);
914
+		}
915
+
916
+		return $mce_css;
917
+	}
918
+
919
+
920
+	/**
921
+	 * @throws EE_Error
922
+	 * @throws ReflectionException
923
+	 */
924
+	public function load_scripts_styles_edit_message_template()
925
+	{
926
+
927
+		$this->_set_shortcodes();
928
+
929
+		EE_Registry::$i18n_js_strings['confirm_default_reset']        = sprintf(
930
+			esc_html__(
931
+				'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
932
+				'event_espresso'
933
+			),
934
+			$this->_message_template_group->messenger_obj()->label['singular'],
935
+			$this->_message_template_group->message_type_obj()->label['singular']
936
+		);
937
+		EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
938
+			'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
939
+			'event_espresso'
940
+		);
941
+		EE_Registry::$i18n_js_strings['server_error']                 = esc_html__(
942
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
943
+			'event_espresso'
944
+		);
945
+
946
+		wp_register_script(
947
+			'ee_msgs_edit_js',
948
+			EE_MSG_ASSETS_URL . 'ee_message_editor.js',
949
+			['jquery'],
950
+			EVENT_ESPRESSO_VERSION
951
+		);
952
+
953
+		wp_enqueue_script('ee_admin_js');
954
+		wp_enqueue_script('ee_msgs_edit_js');
955
+
956
+		// add in special css for tiny_mce
957
+		add_filter('mce_css', [$this, 'wp_editor_css']);
958
+	}
959
+
960
+
961
+	/**
962
+	 * @throws EE_Error
963
+	 * @throws ReflectionException
964
+	 */
965
+	public function load_scripts_styles_display_preview_message()
966
+	{
967
+		$this->_set_message_template_group();
968
+		if ($this->_active_messenger_name) {
969
+			$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
970
+				$this->_active_messenger_name
971
+			);
972
+		}
973
+
974
+		wp_enqueue_style(
975
+			'espresso_preview_css',
976
+			$this->_active_messenger->get_variation(
977
+				$this->_template_pack,
978
+				$this->_active_message_type_name,
979
+				true,
980
+				'preview',
981
+				$this->_variation
982
+			)
983
+		);
984
+	}
985
+
986
+
987
+	public function load_scripts_styles_settings()
988
+	{
989
+		wp_register_style(
990
+			'ee-message-settings',
991
+			EE_MSG_ASSETS_URL . 'ee_message_settings.css',
992
+			[],
993
+			EVENT_ESPRESSO_VERSION
994
+		);
995
+		wp_enqueue_style('ee-text-links');
996
+		wp_enqueue_style('ee-message-settings');
997
+		wp_enqueue_script('ee-messages-settings');
998
+	}
999
+
1000
+
1001
+	/**
1002
+	 * set views array for List Table
1003
+	 */
1004
+	public function _set_list_table_views_global_mtps()
1005
+	{
1006
+		$this->_views = [
1007
+			'in_use' => [
1008
+				'slug'  => 'in_use',
1009
+				'label' => esc_html__('In Use', 'event_espresso'),
1010
+				'count' => 0,
1011
+			],
1012
+		];
1013
+	}
1014
+
1015
+
1016
+	/**
1017
+	 * Set views array for the Custom Template List Table
1018
+	 */
1019
+	public function _set_list_table_views_custom_mtps()
1020
+	{
1021
+		$this->_set_list_table_views_global_mtps();
1022
+		$this->_views['in_use']['bulk_action'] = [
1023
+			'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
1024
+		];
1025
+	}
1026
+
1027
+
1028
+	/**
1029
+	 * set views array for message queue list table
1030
+	 *
1031
+	 * @throws InvalidDataTypeException
1032
+	 * @throws InvalidInterfaceException
1033
+	 * @throws InvalidArgumentException
1034
+	 * @throws EE_Error
1035
+	 * @throws ReflectionException
1036
+	 */
1037
+	public function _set_list_table_views_default()
1038
+	{
1039
+		EE_Registry::instance()->load_helper('Template');
1040
+
1041
+		$common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
1042
+			'ee_send_message',
1043
+			'message_list_table_bulk_actions'
1044
+		)
1045
+			? [
1046
+				'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
1047
+				'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
1048
+				'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
1049
+				'send_now'              => esc_html__('Send Now', 'event_espresso'),
1050
+			]
1051
+			: [];
1052
+
1053
+		$delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
1054
+			'ee_delete_messages',
1055
+			'message_list_table_bulk_actions'
1056
+		)
1057
+			? ['delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso')]
1058
+			: [];
1059
+
1060
+
1061
+		$this->_views = [
1062
+			'all' => [
1063
+				'slug'        => 'all',
1064
+				'label'       => esc_html__('All', 'event_espresso'),
1065
+				'count'       => 0,
1066
+				'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
1067
+			],
1068
+		];
1069
+
1070
+
1071
+		foreach ($this->getMsgModel()->all_statuses() as $status) {
1072
+			if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1073
+				continue;
1074
+			}
1075
+			$status_bulk_actions = $common_bulk_actions;
1076
+			// unset bulk actions not applying to status
1077
+			if (! empty($status_bulk_actions)) {
1078
+				switch ($status) {
1079
+					case EEM_Message::status_idle:
1080
+					case EEM_Message::status_resend:
1081
+						$status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1082
+						break;
1083
+
1084
+					case EEM_Message::status_failed:
1085
+					case EEM_Message::status_debug_only:
1086
+					case EEM_Message::status_messenger_executing:
1087
+						$status_bulk_actions = [];
1088
+						break;
1089
+
1090
+					case EEM_Message::status_incomplete:
1091
+						unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1092
+						break;
1093
+
1094
+					case EEM_Message::status_retry:
1095
+					case EEM_Message::status_sent:
1096
+						unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1097
+						break;
1098
+				}
1099
+			}
1100
+
1101
+			// skip adding messenger executing status to views because it will be included with the Failed view.
1102
+			if ($status === EEM_Message::status_messenger_executing) {
1103
+				continue;
1104
+			}
1105
+
1106
+			$this->_views[ strtolower($status) ] = [
1107
+				'slug'        => strtolower($status),
1108
+				'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1109
+				'count'       => 0,
1110
+				'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1111
+			];
1112
+		}
1113
+	}
1114
+
1115
+
1116
+	/**
1117
+	 * @throws EE_Error
1118
+	 */
1119
+	protected function _ee_default_messages_overview_list_table()
1120
+	{
1121
+		$this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1122
+		$this->display_admin_list_table_page_with_no_sidebar();
1123
+	}
1124
+
1125
+
1126
+	/**
1127
+	 * @throws EE_Error
1128
+	 * @throws ReflectionException
1129
+	 */
1130
+	protected function _message_queue_list_table()
1131
+	{
1132
+		$this->_search_btn_label                   = esc_html__('Message Activity', 'event_espresso');
1133
+		$this->_template_args['per_column']        = 6;
1134
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_message_legend_items());
1135
+		$message_results = trim(EEM_Message::instance()->get_pretty_label_for_results());
1136
+		$this->_template_args['before_list_table'] = ! empty($message_results) ? "<h3>{$message_results}</h3>" : '';
1137
+		$this->display_admin_list_table_page_with_no_sidebar();
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * @throws EE_Error
1143
+	 */
1144
+	protected function _message_legend_items()
1145
+	{
1146
+
1147
+		$action_css_classes = EEH_MSG_Template::get_message_action_icons();
1148
+		$action_items       = [];
1149
+
1150
+		foreach ($action_css_classes as $action_item => $action_details) {
1151
+			if ($action_item === 'see_notifications_for') {
1152
+				continue;
1153
+			}
1154
+			$action_items[ $action_item ] = [
1155
+				'class' => $action_details['css_class'],
1156
+				'desc'  => $action_details['label'],
1157
+			];
1158
+		}
1159
+
1160
+		/** @var array $status_items status legend setup */
1161
+		$status_items = [
1162
+			'sent_status'                => [
1163
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_sent,
1164
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1165
+			],
1166
+			'idle_status'                => [
1167
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_idle,
1168
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1169
+			],
1170
+			'failed_status'              => [
1171
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_failed,
1172
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1173
+			],
1174
+			'messenger_executing_status' => [
1175
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_messenger_executing,
1176
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1177
+			],
1178
+			'resend_status'              => [
1179
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_resend,
1180
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1181
+			],
1182
+			'incomplete_status'          => [
1183
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_incomplete,
1184
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1185
+			],
1186
+			'retry_status'               => [
1187
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_retry,
1188
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1189
+			],
1190
+		];
1191
+		if (EEM_Message::debug()) {
1192
+			$status_items['debug_only_status'] = [
1193
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_debug_only,
1194
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1195
+			];
1196
+		}
1197
+
1198
+		return array_merge($action_items, $status_items);
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * @throws EE_Error
1204
+	 */
1205
+	protected function _custom_mtps_preview()
1206
+	{
1207
+		$this->_admin_page_title              = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1208
+		$this->_template_args['preview_img']  = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1209
+												. ' alt="' . esc_attr__(
1210
+													'Preview Custom Message Templates screenshot',
1211
+													'event_espresso'
1212
+												) . '" />';
1213
+		$this->_template_args['preview_text'] = '<strong>'
1214
+												. esc_html__(
1215
+													'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1216
+													'event_espresso'
1217
+												)
1218
+												. '</strong>';
1219
+
1220
+		$this->display_admin_caf_preview_page('custom_message_types', false);
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * get_message_templates
1226
+	 * This gets all the message templates for listing on the overview list.
1227
+	 *
1228
+	 * @access public
1229
+	 * @param int    $per_page the amount of templates groups to show per page
1230
+	 * @param string $type     the current _view we're getting templates for
1231
+	 * @param bool   $count    return count?
1232
+	 * @param bool   $all      disregard any paging info (get all data);
1233
+	 * @param bool   $global   whether to return just global (true) or custom templates (false)
1234
+	 * @return array
1235
+	 * @throws EE_Error
1236
+	 * @throws InvalidArgumentException
1237
+	 * @throws InvalidDataTypeException
1238
+	 * @throws InvalidInterfaceException
1239
+	 */
1240
+	public function get_message_templates(
1241
+		$per_page = 10,
1242
+		$type = 'in_use',
1243
+		$count = false,
1244
+		$all = false,
1245
+		$global = true
1246
+	) {
1247
+		$orderby = $this->request->getRequestParam('orderby', 'GRP_ID');
1248
+		$this->request->setRequestParam('orderby', $orderby);
1249
+
1250
+		$order        = $this->request->getRequestParam('order', 'ASC');
1251
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1252
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1253
+
1254
+		$offset = ($current_page - 1) * $per_page;
1255
+		$limit  = $all ? null : [$offset, $per_page];
1256
+
1257
+		// options will match what is in the _views array property
1258
+		return $type === 'in_use'
1259
+			? $this->getMtgModel()->get_all_active_message_templates(
1260
+				$orderby,
1261
+				$order,
1262
+				$limit,
1263
+				$count,
1264
+				$global,
1265
+				true
1266
+			)
1267
+			: $this->getMtgModel()->get_all_trashed_grouped_message_templates(
1268
+				$orderby,
1269
+				$order,
1270
+				$limit,
1271
+				$count,
1272
+				$global
1273
+			);
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 * filters etc might need a list of installed message_types
1279
+	 *
1280
+	 * @return array an array of message type objects
1281
+	 */
1282
+	public function get_installed_message_types()
1283
+	{
1284
+		$installed_message_types = $this->_message_resource_manager->installed_message_types();
1285
+		$installed               = [];
1286
+
1287
+		foreach ($installed_message_types as $message_type) {
1288
+			$installed[ $message_type->name ] = $message_type;
1289
+		}
1290
+
1291
+		return $installed;
1292
+	}
1293
+
1294
+
1295
+	/**
1296
+	 * This is used when creating a custom template. All Custom Templates start based off another template.
1297
+	 *
1298
+	 * @param string $message_type
1299
+	 * @param string $messenger
1300
+	 * @param string $GRP_ID
1301
+	 *
1302
+	 * @throws EE_error
1303
+	 * @throws ReflectionException
1304
+	 */
1305
+	public function add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1306
+	{
1307
+		// set values override any request data
1308
+		$message_type = ! empty($message_type) ? $message_type : $this->_active_message_type_name;
1309
+		$messenger    = ! empty($messenger) ? $messenger : $this->_active_messenger_name;
1310
+		$GRP_ID       = ! empty($GRP_ID) ? $GRP_ID : $this->request->getRequestParam('GRP_ID', 0, 'int');
1311
+
1312
+		// we need messenger and message type.  They should be coming from the event editor. If not here then return error
1313
+		if (empty($message_type) || empty($messenger)) {
1314
+			throw new EE_Error(
1315
+				esc_html__(
1316
+					'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1317
+					'event_espresso'
1318
+				)
1319
+			);
1320
+		}
1321
+
1322
+		// we need the GRP_ID for the template being used as the base for the new template
1323
+		if (empty($GRP_ID)) {
1324
+			throw new EE_Error(
1325
+				esc_html__(
1326
+					'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1327
+					'event_espresso'
1328
+				)
1329
+			);
1330
+		}
1331
+
1332
+		// let's just make sure the template gets generated!
1333
+
1334
+		// we need to reassign some variables for what the insert is expecting
1335
+		$this->request->setRequestParam('MTP_messenger', $messenger);
1336
+		$this->request->setRequestParam('MTP_message_type', $message_type);
1337
+		$this->request->setRequestParam('GRP_ID', $GRP_ID);
1338
+
1339
+		$this->_insert_or_update_message_template(true);
1340
+	}
1341
+
1342
+
1343
+	/**
1344
+	 * @param string $message_type     message type slug
1345
+	 * @param string $messenger        messenger slug
1346
+	 * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1347
+	 *                                 off of.
1348
+	 * @throws EE_error
1349
+	 * @throws ReflectionException
1350
+	 * @deprecated 4.10.29.p
1351
+	 */
1352
+	protected function _add_message_template($message_type, $messenger, $GRP_ID)
1353
+	{
1354
+		$this->add_message_template($message_type, $messenger, $GRP_ID);
1355
+	}
1356
+
1357
+
1358
+	/**
1359
+	 * _edit_message_template
1360
+	 *
1361
+	 * @access protected
1362
+	 * @return void
1363
+	 * @throws InvalidIdentifierException
1364
+	 * @throws DomainException
1365
+	 * @throws EE_Error
1366
+	 * @throws InvalidArgumentException
1367
+	 * @throws ReflectionException
1368
+	 * @throws InvalidDataTypeException
1369
+	 * @throws InvalidInterfaceException
1370
+	 */
1371
+	protected function _edit_message_template()
1372
+	{
1373
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1374
+		$template_fields = '';
1375
+		$sidebar_fields  = '';
1376
+		// we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1377
+		// valid html in the templates.
1378
+		add_filter('tiny_mce_before_init', [$this, 'filter_tinymce_init'], 10, 2);
1379
+
1380
+		$GRP_ID = $this->request->getRequestParam('id', 0, 'int');
1381
+		$EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
1382
+
1383
+		$this->_set_shortcodes(); // this also sets the _message_template property.
1384
+		$message_template_group = $this->_message_template_group;
1385
+		$c_label                = $message_template_group->context_label();
1386
+		$c_config               = $message_template_group->contexts_config();
1387
+
1388
+		reset($c_config);
1389
+		$context = $this->request->getRequestParam('context', key($c_config));
1390
+		$context = strtolower($context);
1391
+
1392
+		$action = empty($GRP_ID) ? 'insert_message_template' : 'update_message_template';
1393
+
1394
+		$edit_message_template_form_url = add_query_arg(
1395
+			['action' => $action, 'noheader' => true],
1396
+			EE_MSG_ADMIN_URL
1397
+		);
1398
+
1399
+		// set active messenger for this view
1400
+		$this->_active_messenger         = $this->_message_resource_manager->get_active_messenger(
1401
+			$message_template_group->messenger()
1402
+		);
1403
+		$this->_active_message_type_name = $message_template_group->message_type();
1404
+
1405
+
1406
+		// Do we have any validation errors?
1407
+		$validators = $this->_get_transient();
1408
+		$v_fields   = ! empty($validators) ? array_keys($validators) : [];
1409
+
1410
+
1411
+		// we need to assemble the title from Various details
1412
+		$context_label = sprintf(
1413
+			esc_html__('(%s %s)', 'event_espresso'),
1414
+			$c_config[ $context ]['label'],
1415
+			ucwords($c_label['label'])
1416
+		);
1417
+
1418
+		$title = sprintf(
1419
+			esc_html__(' %s %s Template %s', 'event_espresso'),
1420
+			ucwords($message_template_group->messenger_obj()->label['singular']),
1421
+			ucwords($message_template_group->message_type_obj()->label['singular']),
1422
+			$context_label
1423
+		);
1424
+
1425
+		$this->_template_args['GRP_ID']           = $GRP_ID;
1426
+		$this->_template_args['message_template'] = $message_template_group;
1427
+		$this->_template_args['is_extra_fields']  = false;
1428
+
1429
+
1430
+		// let's get EEH_MSG_Template so we can get template form fields
1431
+		$template_field_structure = EEH_MSG_Template::get_fields(
1432
+			$message_template_group->messenger(),
1433
+			$message_template_group->message_type()
1434
+		);
1435
+
1436
+		if (! $template_field_structure) {
1437
+			$template_field_structure = false;
1438
+			$template_fields          = esc_html__(
1439
+				'There was an error in assembling the fields for this display (you should see an error message)',
1440
+				'event_espresso'
1441
+			);
1442
+		}
1443
+
1444
+
1445
+		$message_templates = $message_template_group->context_templates();
1446
+
1447
+
1448
+		// if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1449
+		// will get handled in the "extra" array.
1450
+		if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1451
+			foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1452
+				unset($template_field_structure[ $context ][ $reference_field ]);
1453
+			}
1454
+		}
1455
+
1456
+		// let's loop through the template_field_structure and actually assemble the input fields!
1457
+		if (! empty($template_field_structure)) {
1458
+			foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1459
+				// if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1460
+				// the extra array and reset them.
1461
+				if ($template_field === 'extra') {
1462
+					$this->_template_args['is_extra_fields'] = true;
1463
+					foreach ($field_setup_array as $reference_field => $new_fields_array) {
1464
+						$message_template = $message_templates[ $context ][ $reference_field ];
1465
+						$content          = $message_template instanceof EE_Message_Template
1466
+							? $message_template->get('MTP_content')
1467
+							: '';
1468
+						foreach ($new_fields_array as $extra_field => $extra_array) {
1469
+							// let's verify if we need this extra field via the shortcodes parameter.
1470
+							$continue = false;
1471
+							if (isset($extra_array['shortcodes_required'])) {
1472
+								foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1473
+									if (! array_key_exists($shortcode, $this->_shortcodes)) {
1474
+										$continue = true;
1475
+									}
1476
+								}
1477
+								if ($continue) {
1478
+									continue;
1479
+								}
1480
+							}
1481
+
1482
+							$field_id = $reference_field . '-' . $extra_field . '-content';
1483
+
1484
+							$template_form_fields[ $field_id ]         = $extra_array;
1485
+							$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1486
+																		 . $reference_field
1487
+																		 . '][content]['
1488
+																		 . $extra_field . ']';
1489
+							$css_class                                 = isset($extra_array['css_class'])
1490
+								? $extra_array['css_class']
1491
+								: '';
1492
+
1493
+							$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1494
+																			  && in_array($extra_field, $v_fields, true)
1495
+																			  && (
1496
+																				  is_array($validators[ $extra_field ])
1497
+																				  && isset($validators[ $extra_field ]['msg'])
1498
+																			  )
1499
+								? 'validate-error ' . $css_class
1500
+								: $css_class;
1501
+
1502
+							$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1503
+																		  && isset($content[ $extra_field ])
1504
+								? $content[ $extra_field ]
1505
+								: '';
1506
+
1507
+							// do we have a validation error?  if we do then let's use that value instead
1508
+							$template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1509
+								? $validators[ $extra_field ]['value']
1510
+								: $template_form_fields[ $field_id ]['value'];
1511
+
1512
+
1513
+							$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1514
+
1515
+							// shortcode selector
1516
+							$field_name_to_use                                   = $extra_field === 'main'
1517
+								? 'content'
1518
+								: $extra_field;
1519
+							$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1520
+								$field_name_to_use,
1521
+								$field_id
1522
+							);
1523
+						}
1524
+						$template_field_MTP_id           = $reference_field . '-MTP_ID';
1525
+						$template_field_template_name_id = $reference_field . '-name';
1526
+
1527
+						$template_form_fields[ $template_field_MTP_id ] = [
1528
+							'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1529
+							'label'      => null,
1530
+							'input'      => 'hidden',
1531
+							'type'       => 'int',
1532
+							'required'   => false,
1533
+							'validation' => false,
1534
+							'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1535
+							'css_class'  => '',
1536
+							'format'     => '%d',
1537
+							'db-col'     => 'MTP_ID',
1538
+						];
1539
+
1540
+						$template_form_fields[ $template_field_template_name_id ] = [
1541
+							'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1542
+							'label'      => null,
1543
+							'input'      => 'hidden',
1544
+							'type'       => 'string',
1545
+							'required'   => false,
1546
+							'validation' => true,
1547
+							'value'      => $reference_field,
1548
+							'css_class'  => '',
1549
+							'format'     => '%s',
1550
+							'db-col'     => 'MTP_template_field',
1551
+						];
1552
+					}
1553
+					continue; // skip the next stuff, we got the necessary fields here for this dataset.
1554
+				} else {
1555
+					$field_id                                   = $template_field . '-content';
1556
+					$template_form_fields[ $field_id ]          = $field_setup_array;
1557
+					$template_form_fields[ $field_id ]['name']  =
1558
+						'MTP_template_fields[' . $template_field . '][content]';
1559
+					$message_template                           =
1560
+						isset($message_templates[ $context ][ $template_field ])
1561
+							? $message_templates[ $context ][ $template_field ]
1562
+							: null;
1563
+					$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1564
+																  && is_array($message_templates[ $context ])
1565
+																  && $message_template instanceof EE_Message_Template
1566
+						? $message_template->get('MTP_content')
1567
+						: '';
1568
+
1569
+					// do we have a validator error for this field?  if we do then we'll use that value instead
1570
+					$template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1571
+						? $validators[ $template_field ]['value']
1572
+						: $template_form_fields[ $field_id ]['value'];
1573
+
1574
+
1575
+					$template_form_fields[ $field_id ]['db-col']    = 'MTP_content';
1576
+					$css_class                                      = isset($field_setup_array['css_class'])
1577
+						? $field_setup_array['css_class']
1578
+						: '';
1579
+					$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1580
+																	  && in_array($template_field, $v_fields, true)
1581
+																	  && isset($validators[ $template_field ]['msg'])
1582
+						? 'validate-error ' . $css_class
1583
+						: $css_class;
1584
+
1585
+					// shortcode selector
1586
+					$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1587
+						$template_field,
1588
+						$field_id
1589
+					);
1590
+				}
1591
+
1592
+				// k took care of content field(s) now let's take care of others.
1593
+
1594
+				$template_field_MTP_id                 = $template_field . '-MTP_ID';
1595
+				$template_field_field_template_name_id = $template_field . '-name';
1596
+
1597
+				// foreach template field there are actually two form fields created
1598
+				$template_form_fields[ $template_field_MTP_id ] = [
1599
+					'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1600
+					'label'      => null,
1601
+					'input'      => 'hidden',
1602
+					'type'       => 'int',
1603
+					'required'   => false,
1604
+					'validation' => true,
1605
+					'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1606
+					'css_class'  => '',
1607
+					'format'     => '%d',
1608
+					'db-col'     => 'MTP_ID',
1609
+				];
1610
+
1611
+				$template_form_fields[ $template_field_field_template_name_id ] = [
1612
+					'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1613
+					'label'      => null,
1614
+					'input'      => 'hidden',
1615
+					'type'       => 'string',
1616
+					'required'   => false,
1617
+					'validation' => true,
1618
+					'value'      => $template_field,
1619
+					'css_class'  => '',
1620
+					'format'     => '%s',
1621
+					'db-col'     => 'MTP_template_field',
1622
+				];
1623
+			}
1624
+
1625
+			// add other fields
1626
+			$template_form_fields['ee-msg-current-context'] = [
1627
+				'name'       => 'MTP_context',
1628
+				'label'      => null,
1629
+				'input'      => 'hidden',
1630
+				'type'       => 'string',
1631
+				'required'   => false,
1632
+				'validation' => true,
1633
+				'value'      => $context,
1634
+				'css_class'  => '',
1635
+				'format'     => '%s',
1636
+				'db-col'     => 'MTP_context',
1637
+			];
1638
+
1639
+			$template_form_fields['ee-msg-grp-id'] = [
1640
+				'name'       => 'GRP_ID',
1641
+				'label'      => null,
1642
+				'input'      => 'hidden',
1643
+				'type'       => 'int',
1644
+				'required'   => false,
1645
+				'validation' => true,
1646
+				'value'      => $GRP_ID,
1647
+				'css_class'  => '',
1648
+				'format'     => '%d',
1649
+				'db-col'     => 'GRP_ID',
1650
+			];
1651
+
1652
+			$template_form_fields['ee-msg-messenger'] = [
1653
+				'name'       => 'MTP_messenger',
1654
+				'label'      => null,
1655
+				'input'      => 'hidden',
1656
+				'type'       => 'string',
1657
+				'required'   => false,
1658
+				'validation' => true,
1659
+				'value'      => $message_template_group->messenger(),
1660
+				'css_class'  => '',
1661
+				'format'     => '%s',
1662
+				'db-col'     => 'MTP_messenger',
1663
+			];
1664
+
1665
+			$template_form_fields['ee-msg-message-type'] = [
1666
+				'name'       => 'MTP_message_type',
1667
+				'label'      => null,
1668
+				'input'      => 'hidden',
1669
+				'type'       => 'string',
1670
+				'required'   => false,
1671
+				'validation' => true,
1672
+				'value'      => $message_template_group->message_type(),
1673
+				'css_class'  => '',
1674
+				'format'     => '%s',
1675
+				'db-col'     => 'MTP_message_type',
1676
+			];
1677
+
1678
+			$sidebar_form_fields['ee-msg-is-global'] = [
1679
+				'name'       => 'MTP_is_global',
1680
+				'label'      => esc_html__('Global Template', 'event_espresso'),
1681
+				'input'      => 'hidden',
1682
+				'type'       => 'int',
1683
+				'required'   => false,
1684
+				'validation' => true,
1685
+				'value'      => $message_template_group->get('MTP_is_global'),
1686
+				'css_class'  => '',
1687
+				'format'     => '%d',
1688
+				'db-col'     => 'MTP_is_global',
1689
+			];
1690
+
1691
+			$sidebar_form_fields['ee-msg-is-override'] = [
1692
+				'name'       => 'MTP_is_override',
1693
+				'label'      => esc_html__('Override all custom', 'event_espresso'),
1694
+				'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1695
+				'type'       => 'int',
1696
+				'required'   => false,
1697
+				'validation' => true,
1698
+				'value'      => $message_template_group->get('MTP_is_override'),
1699
+				'css_class'  => '',
1700
+				'format'     => '%d',
1701
+				'db-col'     => 'MTP_is_override',
1702
+			];
1703
+
1704
+			$sidebar_form_fields['ee-msg-is-active'] = [
1705
+				'name'       => 'MTP_is_active',
1706
+				'label'      => esc_html__('Active Template', 'event_espresso'),
1707
+				'input'      => 'hidden',
1708
+				'type'       => 'int',
1709
+				'required'   => false,
1710
+				'validation' => true,
1711
+				'value'      => $message_template_group->is_active(),
1712
+				'css_class'  => '',
1713
+				'format'     => '%d',
1714
+				'db-col'     => 'MTP_is_active',
1715
+			];
1716
+
1717
+			$sidebar_form_fields['ee-msg-deleted'] = [
1718
+				'name'       => 'MTP_deleted',
1719
+				'label'      => null,
1720
+				'input'      => 'hidden',
1721
+				'type'       => 'int',
1722
+				'required'   => false,
1723
+				'validation' => true,
1724
+				'value'      => $message_template_group->get('MTP_deleted'),
1725
+				'css_class'  => '',
1726
+				'format'     => '%d',
1727
+				'db-col'     => 'MTP_deleted',
1728
+			];
1729
+			$sidebar_form_fields['ee-msg-author']  = [
1730
+				'name'       => 'MTP_user_id',
1731
+				'label'      => esc_html__('Author', 'event_espresso'),
1732
+				'input'      => 'hidden',
1733
+				'type'       => 'int',
1734
+				'required'   => false,
1735
+				'validation' => false,
1736
+				'value'      => $message_template_group->user(),
1737
+				'format'     => '%d',
1738
+				'db-col'     => 'MTP_user_id',
1739
+			];
1740
+
1741
+			$sidebar_form_fields['ee-msg-route'] = [
1742
+				'name'  => 'action',
1743
+				'input' => 'hidden',
1744
+				'type'  => 'string',
1745
+				'value' => $action,
1746
+			];
1747
+
1748
+			$sidebar_form_fields['ee-msg-id']        = [
1749
+				'name'  => 'id',
1750
+				'input' => 'hidden',
1751
+				'type'  => 'int',
1752
+				'value' => $GRP_ID,
1753
+			];
1754
+			$sidebar_form_fields['ee-msg-evt-nonce'] = [
1755
+				'name'  => $action . '_nonce',
1756
+				'input' => 'hidden',
1757
+				'type'  => 'string',
1758
+				'value' => wp_create_nonce($action . '_nonce'),
1759
+			];
1760
+
1761
+			$template_switch = $this->request->getRequestParam('template_switch');
1762
+			if ($template_switch) {
1763
+				$sidebar_form_fields['ee-msg-template-switch'] = [
1764
+					'name'  => 'template_switch',
1765
+					'input' => 'hidden',
1766
+					'type'  => 'int',
1767
+					'value' => 1,
1768
+				];
1769
+			}
1770
+
1771
+
1772
+			$template_fields = $this->_generate_admin_form_fields($template_form_fields);
1773
+			$sidebar_fields  = $this->_generate_admin_form_fields($sidebar_form_fields);
1774
+		} //end if ( !empty($template_field_structure) )
1775
+
1776
+		// set extra content for publish box
1777
+		$this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1778
+		$this->_set_publish_post_box_vars(
1779
+			'id',
1780
+			$GRP_ID,
1781
+			false,
1782
+			add_query_arg(
1783
+				['action' => 'global_mtps'],
1784
+				$this->_admin_base_url
1785
+			)
1786
+		);
1787
+
1788
+		// add preview button
1789
+		$preview_url    = parent::add_query_args_and_nonce(
1790
+			[
1791
+				'message_type' => $message_template_group->message_type(),
1792
+				'messenger'    => $message_template_group->messenger(),
1793
+				'context'      => $context,
1794
+				'GRP_ID'       => $GRP_ID,
1795
+				'evt_id'       => $EVT_ID ?: false,
1796
+				'action'       => 'preview_message',
1797
+			],
1798
+			$this->_admin_base_url
1799
+		);
1800
+		$preview_button = '<a href="' . $preview_url . '" class="button--secondary messages-preview-button">'
1801
+						  . esc_html__('Preview', 'event_espresso')
1802
+						  . '</a>';
1803
+
1804
+
1805
+		// setup context switcher
1806
+		$this->_set_context_switcher(
1807
+			$message_template_group,
1808
+			[
1809
+				'page'    => 'espresso_messages',
1810
+				'action'  => 'edit_message_template',
1811
+				'id'      => $GRP_ID,
1812
+				'evt_id'  => $EVT_ID,
1813
+				'context' => $context,
1814
+				'extra'   => $preview_button,
1815
+			]
1816
+		);
1817
+
1818
+
1819
+		// main box
1820
+		$this->_template_args['template_fields']                         = $template_fields;
1821
+		$this->_template_args['sidebar_box_id']                          = 'details';
1822
+		$this->_template_args['action']                                  = $action;
1823
+		$this->_template_args['context']                                 = $context;
1824
+		$this->_template_args['edit_message_template_form_url']          = $edit_message_template_form_url;
1825
+		$this->_template_args['learn_more_about_message_templates_link'] =
1826
+			$this->_learn_more_about_message_templates_link();
1827
+
1828
+
1829
+		$this->_template_args['before_admin_page_content'] = '<div class="ee-msg-admin-header">';
1830
+		$this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1831
+			$message_template_group,
1832
+			$context,
1833
+			$context_label
1834
+		);
1835
+		$this->_template_args['before_admin_page_content'] .= $this->add_context_switcher();
1836
+		$this->_template_args['before_admin_page_content'] .= '</div>';
1837
+		$this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1838
+		$this->_template_args['after_admin_page_content']  = $this->_add_form_element_after();
1839
+
1840
+		$this->_template_path = $this->_template_args['GRP_ID']
1841
+			? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1842
+			: EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1843
+
1844
+		// send along EE_Message_Template_Group object for further template use.
1845
+		$this->_template_args['MTP'] = $message_template_group;
1846
+
1847
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1848
+			$this->_template_path,
1849
+			$this->_template_args,
1850
+			true
1851
+		);
1852
+
1853
+
1854
+		// finally, let's set the admin_page title
1855
+		$this->_admin_page_title = sprintf(esc_html__('Editing %s', 'event_espresso'), $title);
1856
+
1857
+
1858
+		// we need to take care of setting the shortcodes property for use elsewhere.
1859
+		$this->_set_shortcodes();
1860
+
1861
+
1862
+		// final template wrapper
1863
+		$this->display_admin_page_with_sidebar();
1864
+	}
1865
+
1866
+
1867
+	public function filter_tinymce_init($mceInit, $editor_id)
1868
+	{
1869
+		return $mceInit;
1870
+	}
1871
+
1872
+
1873
+	public function add_context_switcher()
1874
+	{
1875
+		return $this->_context_switcher;
1876
+	}
1877
+
1878
+
1879
+	/**
1880
+	 * Adds the activation/deactivation toggle for the message template context.
1881
+	 *
1882
+	 * @param EE_Message_Template_Group $message_template_group
1883
+	 * @param string                    $context
1884
+	 * @param string                    $context_label
1885
+	 * @return string
1886
+	 * @throws DomainException
1887
+	 * @throws EE_Error
1888
+	 * @throws InvalidIdentifierException
1889
+	 * @throws ReflectionException
1890
+	 */
1891
+	protected function add_active_context_element(
1892
+		EE_Message_Template_Group $message_template_group,
1893
+		$context,
1894
+		$context_label
1895
+	) {
1896
+		$template_args = [
1897
+			'context'                   => $context,
1898
+			'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1899
+			'is_active'                 => $message_template_group->is_context_active($context),
1900
+			'on_off_action'             => $message_template_group->is_context_active($context)
1901
+				? 'context-off'
1902
+				: 'context-on',
1903
+			'context_label'             => str_replace(['(', ')'], '', $context_label),
1904
+			'message_template_group_id' => $message_template_group->ID(),
1905
+		];
1906
+		return EEH_Template::display_template(
1907
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1908
+			$template_args,
1909
+			true
1910
+		);
1911
+	}
1912
+
1913
+
1914
+	/**
1915
+	 * Ajax callback for `toggle_context_template` ajax action.
1916
+	 * Handles toggling the message context on or off.
1917
+	 *
1918
+	 * @throws EE_Error
1919
+	 * @throws InvalidArgumentException
1920
+	 * @throws InvalidDataTypeException
1921
+	 * @throws InvalidIdentifierException
1922
+	 * @throws InvalidInterfaceException
1923
+	 */
1924
+	public function toggle_context_template()
1925
+	{
1926
+		$success = true;
1927
+		// check for required data
1928
+		if (
1929
+			! (
1930
+				$this->request->requestParamIsSet('message_template_group_id')
1931
+				&& $this->request->requestParamIsSet('context')
1932
+				&& $this->request->requestParamIsSet('status')
1933
+			)
1934
+		) {
1935
+			EE_Error::add_error(
1936
+				esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1937
+				__FILE__,
1938
+				__FUNCTION__,
1939
+				__LINE__
1940
+			);
1941
+			$success = false;
1942
+		}
1943
+
1944
+		$nonce   = $this->request->getRequestParam('toggle_context_nonce', '');
1945
+		$context = $this->request->getRequestParam('context', '');
1946
+		$status  = $this->request->getRequestParam('status', '');
1947
+
1948
+		$this->_verify_nonce($nonce, "activate_{$context}_toggle_nonce");
1949
+
1950
+		if ($status !== 'off' && $status !== 'on') {
1951
+			EE_Error::add_error(
1952
+				sprintf(
1953
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1954
+					$status
1955
+				),
1956
+				__FILE__,
1957
+				__FUNCTION__,
1958
+				__LINE__
1959
+			);
1960
+			$success = false;
1961
+		}
1962
+		$message_template_group_id = $this->request->getRequestParam('message_template_group_id', 0, 'int');
1963
+		$message_template_group    = $this->getMtgModel()->get_one_by_ID($message_template_group_id);
1964
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
1965
+			EE_Error::add_error(
1966
+				sprintf(
1967
+					esc_html__(
1968
+						'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1969
+						'event_espresso'
1970
+					),
1971
+					$message_template_group_id,
1972
+					'EE_Message_Template_Group'
1973
+				),
1974
+				__FILE__,
1975
+				__FUNCTION__,
1976
+				__LINE__
1977
+			);
1978
+			$success = false;
1979
+		}
1980
+		if ($success) {
1981
+			$success = $status === 'off'
1982
+				? $message_template_group->deactivate_context($context)
1983
+				: $message_template_group->activate_context($context);
1984
+		}
1985
+		$this->_template_args['success'] = $success;
1986
+		$this->_return_json();
1987
+	}
1988
+
1989
+
1990
+	public function _add_form_element_before()
1991
+	{
1992
+		return '<form method="post" action="'
1993
+			   . $this->_template_args['edit_message_template_form_url']
1994
+			   . '" id="ee-msg-edit-frm">';
1995
+	}
1996
+
1997
+
1998
+	public function _add_form_element_after()
1999
+	{
2000
+		return '</form>';
2001
+	}
2002
+
2003
+
2004
+	/**
2005
+	 * This executes switching the template pack for a message template.
2006
+	 *
2007
+	 * @throws EE_Error
2008
+	 * @throws InvalidDataTypeException
2009
+	 * @throws InvalidInterfaceException
2010
+	 * @throws InvalidArgumentException
2011
+	 * @throws ReflectionException
2012
+	 * @since 4.5.0
2013
+	 */
2014
+	public function switch_template_pack()
2015
+	{
2016
+
2017
+		$GRP_ID        = $this->request->getRequestParam('GRP_ID', 0, 'int');
2018
+		$template_pack = $this->request->getRequestParam('template_pack', '');
2019
+
2020
+		// verify we have needed values.
2021
+		if (empty($GRP_ID) || empty($template_pack)) {
2022
+			$this->_template_args['error'] = true;
2023
+			EE_Error::add_error(
2024
+				esc_html__('The required date for switching templates is not available.', 'event_espresso'),
2025
+				__FILE__,
2026
+				__FUNCTION__,
2027
+				__LINE__
2028
+			);
2029
+		} else {
2030
+			// get template, set the new template_pack and then reset to default
2031
+			/** @var EE_Message_Template_Group $message_template_group */
2032
+			$message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
2033
+
2034
+			$message_template_group->set_template_pack_name($template_pack);
2035
+			$this->request->setRequestParam('msgr', $message_template_group->messenger());
2036
+			$this->request->setRequestParam('mt', $message_template_group->message_type());
2037
+
2038
+			$query_args = $this->_reset_to_default_template();
2039
+
2040
+			if (empty($query_args['id'])) {
2041
+				EE_Error::add_error(
2042
+					esc_html__(
2043
+						'Something went wrong with switching the template pack. Please try again or contact EE support',
2044
+						'event_espresso'
2045
+					),
2046
+					__FILE__,
2047
+					__FUNCTION__,
2048
+					__LINE__
2049
+				);
2050
+				$this->_template_args['error'] = true;
2051
+			} else {
2052
+				$template_label       = $message_template_group->get_template_pack()->label;
2053
+				$template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
2054
+				EE_Error::add_success(
2055
+					sprintf(
2056
+						esc_html__(
2057
+							'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2058
+							'event_espresso'
2059
+						),
2060
+						$template_label,
2061
+						$template_pack_labels->template_pack
2062
+					)
2063
+				);
2064
+				// generate the redirect url for js.
2065
+				$url = self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2066
+
2067
+				$this->_template_args['data']['redirect_url'] = $url;
2068
+				$this->_template_args['success']              = true;
2069
+			}
2070
+
2071
+			$this->_return_json();
2072
+		}
2073
+	}
2074
+
2075
+
2076
+	/**
2077
+	 * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2078
+	 * they want.
2079
+	 *
2080
+	 * @access protected
2081
+	 * @return array|void
2082
+	 * @throws EE_Error
2083
+	 * @throws InvalidArgumentException
2084
+	 * @throws InvalidDataTypeException
2085
+	 * @throws InvalidInterfaceException
2086
+	 * @throws ReflectionException
2087
+	 */
2088
+	protected function _reset_to_default_template()
2089
+	{
2090
+		$templates    = [];
2091
+		$GRP_ID       = $this->request->getRequestParam('GRP_ID', 0, 'int');
2092
+		$messenger    = $this->request->getRequestParam('msgr');
2093
+		$message_type = $this->request->getRequestParam('mt');
2094
+		// we need to make sure we've got the info we need.
2095
+		if (! ($GRP_ID && $messenger && $message_type)) {
2096
+			EE_Error::add_error(
2097
+				esc_html__(
2098
+					'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2099
+					'event_espresso'
2100
+				),
2101
+				__FILE__,
2102
+				__FUNCTION__,
2103
+				__LINE__
2104
+			);
2105
+		}
2106
+
2107
+		// all templates will be reset to whatever the defaults are
2108
+		// for the global template matching the messenger and message type.
2109
+		$success = ! empty($GRP_ID);
2110
+
2111
+		if ($success) {
2112
+			// let's first determine if the incoming template is a global template,
2113
+			// if it isn't then we need to get the global template matching messenger and message type.
2114
+			// $MTPG = $this->getMtgModel()->get_one_by_ID( $GRP_ID );
2115
+
2116
+
2117
+			// note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2118
+			$success = $this->_delete_mtp_permanently($GRP_ID, false);
2119
+
2120
+			if ($success) {
2121
+				// if successfully deleted, lets generate the new ones.
2122
+				// Note. We set GLOBAL to true, because resets on ANY template
2123
+				// will use the related global template defaults for regeneration.
2124
+				// This means that if a custom template is reset it resets to whatever the related global template is.
2125
+				// HOWEVER, we DO keep the template pack and template variation set
2126
+				// for the current custom template when resetting.
2127
+				$templates = $this->_generate_new_templates($messenger, $message_type, $GRP_ID, true);
2128
+			}
2129
+		}
2130
+
2131
+		// any error messages?
2132
+		if (! $success) {
2133
+			EE_Error::add_error(
2134
+				esc_html__(
2135
+					'Something went wrong with deleting existing templates. Unable to reset to default',
2136
+					'event_espresso'
2137
+				),
2138
+				__FILE__,
2139
+				__FUNCTION__,
2140
+				__LINE__
2141
+			);
2142
+		}
2143
+
2144
+		// all good, let's add a success message!
2145
+		if ($success && ! empty($templates)) {
2146
+			// the info for the template we generated is the first element in the returned array
2147
+			EE_Error::overwrite_success();
2148
+			EE_Error::add_success(esc_html__('Templates have been reset to defaults.', 'event_espresso'));
2149
+		}
2150
+
2151
+
2152
+		$query_args = [
2153
+			'id'      => isset($templates['GRP_ID']) ? $templates['GRP_ID'] : null,
2154
+			'context' => isset($templates['MTP_context']) ? $templates['MTP_context'] : null,
2155
+			'action'  => isset($templates['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2156
+		];
2157
+
2158
+		// if called via ajax then we return query args otherwise redirect
2159
+		if ($this->request->isAjax()) {
2160
+			return $query_args;
2161
+		}
2162
+		$this->_redirect_after_action(false, '', '', $query_args, true);
2163
+	}
2164
+
2165
+
2166
+	/**
2167
+	 * Retrieve and set the message preview for display.
2168
+	 *
2169
+	 * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2170
+	 * @return string
2171
+	 * @throws ReflectionException
2172
+	 * @throws EE_Error
2173
+	 * @throws InvalidArgumentException
2174
+	 * @throws InvalidDataTypeException
2175
+	 * @throws InvalidInterfaceException
2176
+	 */
2177
+	public function _preview_message($send = false)
2178
+	{
2179
+		// first make sure we've got the necessary parameters
2180
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2181
+		if (! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2182
+			EE_Error::add_error(
2183
+				esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2184
+				__FILE__,
2185
+				__FUNCTION__,
2186
+				__LINE__
2187
+			);
2188
+		}
2189
+
2190
+		$context = $this->request->getRequestParam('context');
2191
+		// get the preview!
2192
+		$preview = EED_Messages::preview_message(
2193
+			$this->_active_message_type_name,
2194
+			$context,
2195
+			$this->_active_messenger_name,
2196
+			$send
2197
+		);
2198
+
2199
+		if ($send) {
2200
+			return $preview;
2201
+		}
2202
+
2203
+		// if we have an evt_id set on the request, use it.
2204
+		$EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
2205
+
2206
+		// let's add a button to go back to the edit view
2207
+		$query_args             = [
2208
+			'id'      => $GRP_ID,
2209
+			'evt_id'  => $EVT_ID,
2210
+			'context' => $context,
2211
+			'action'  => 'edit_message_template',
2212
+		];
2213
+		$go_back_url            = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2214
+		$preview_button         = '<a href="'
2215
+								  . $go_back_url
2216
+								  . '" class="button--secondary messages-preview-go-back-button">'
2217
+								  . esc_html__('Go Back to Edit', 'event_espresso')
2218
+								  . '</a>';
2219
+		$message_types          = $this->get_installed_message_types();
2220
+		$active_messenger       = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
2221
+		$active_messenger_label = $active_messenger instanceof EE_messenger
2222
+			? ucwords($active_messenger->label['singular'])
2223
+			: esc_html__('Unknown Messenger', 'event_espresso');
2224
+		// let's provide a helpful title for context
2225
+		$preview_title = sprintf(
2226
+			esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2227
+			$active_messenger_label,
2228
+			ucwords($message_types[ $this->_active_message_type_name ]->label['singular'])
2229
+		);
2230
+		if (empty($preview)) {
2231
+			$this->noEventsErrorMessage();
2232
+		}
2233
+		// setup display of preview.
2234
+		$this->_admin_page_title                    = $preview_title;
2235
+		$this->_template_args['admin_page_title']   = $preview_title;
2236
+		$this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2237
+		$this->_template_args['data']['force_json'] = true;
2238
+
2239
+		return '';
2240
+	}
2241
+
2242
+
2243
+	/**
2244
+	 * Used to set an error if there are no events available for generating a preview/test send.
2245
+	 *
2246
+	 * @param bool $test_send Whether the error should be generated for the context of a test send.
2247
+	 */
2248
+	protected function noEventsErrorMessage($test_send = false)
2249
+	{
2250
+		$events_url = parent::add_query_args_and_nonce(
2251
+			[
2252
+				'action' => 'default',
2253
+				'page'   => 'espresso_events',
2254
+			],
2255
+			admin_url('admin.php')
2256
+		);
2257
+		$message    = $test_send
2258
+			? esc_html__(
2259
+				'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2260
+				'event_espresso'
2261
+			)
2262
+			: esc_html__(
2263
+				'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2264
+				'event_espresso'
2265
+			);
2266
+
2267
+		EE_Error::add_attention(
2268
+			sprintf(
2269
+				$message,
2270
+				"<a href='{$events_url}'>",
2271
+				'</a>'
2272
+			)
2273
+		);
2274
+	}
2275
+
2276
+
2277
+	/**
2278
+	 * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2279
+	 * gets called automatically.
2280
+	 *
2281
+	 * @return void
2282
+	 * @throws EE_Error
2283
+	 * @since 4.5.0
2284
+	 *
2285
+	 */
2286
+	protected function _display_preview_message()
2287
+	{
2288
+		$this->display_admin_page_with_no_sidebar();
2289
+	}
2290
+
2291
+
2292
+	/**
2293
+	 * registers metaboxes that should show up on the "edit_message_template" page
2294
+	 *
2295
+	 * @access protected
2296
+	 * @return void
2297
+	 */
2298
+	protected function _register_edit_meta_boxes()
2299
+	{
2300
+		$this->addMetaBox(
2301
+			'mtp_valid_shortcodes',
2302
+			esc_html__('Valid Shortcodes', 'event_espresso'),
2303
+			[$this, 'shortcode_meta_box'],
2304
+			$this->_current_screen->id,
2305
+			'side'
2306
+		);
2307
+		$this->addMetaBox(
2308
+			'mtp_extra_actions',
2309
+			esc_html__('Extra Actions', 'event_espresso'),
2310
+			[$this, 'extra_actions_meta_box'],
2311
+			$this->_current_screen->id,
2312
+			'side',
2313
+			'high'
2314
+		);
2315
+		$this->addMetaBox(
2316
+			'mtp_templates',
2317
+			esc_html__('Template Styles', 'event_espresso'),
2318
+			[$this, 'template_pack_meta_box'],
2319
+			$this->_current_screen->id,
2320
+			'side',
2321
+			'high'
2322
+		);
2323
+	}
2324
+
2325
+
2326
+	/**
2327
+	 * metabox content for all template pack and variation selection.
2328
+	 *
2329
+	 * @return void
2330
+	 * @throws DomainException
2331
+	 * @throws EE_Error
2332
+	 * @throws InvalidArgumentException
2333
+	 * @throws ReflectionException
2334
+	 * @throws InvalidDataTypeException
2335
+	 * @throws InvalidInterfaceException
2336
+	 * @since 4.5.0
2337
+	 */
2338
+	public function template_pack_meta_box()
2339
+	{
2340
+		$this->_set_message_template_group();
2341
+
2342
+		$tp_collection = EEH_MSG_Template::get_template_pack_collection();
2343
+
2344
+		$tp_select_values = [];
2345
+
2346
+		foreach ($tp_collection as $tp) {
2347
+			// only include template packs that support this messenger and message type!
2348
+			$supports = $tp->get_supports();
2349
+			if (
2350
+				! isset($supports[ $this->_message_template_group->messenger() ])
2351
+				|| ! in_array(
2352
+					$this->_message_template_group->message_type(),
2353
+					$supports[ $this->_message_template_group->messenger() ],
2354
+					true
2355
+				)
2356
+			) {
2357
+				// not supported
2358
+				continue;
2359
+			}
2360
+
2361
+			$tp_select_values[] = [
2362
+				'text' => $tp->label,
2363
+				'id'   => $tp->dbref,
2364
+			];
2365
+		}
2366
+
2367
+		// if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2368
+		// the default template pack.  This still allows for the odd template pack to override.
2369
+		if (empty($tp_select_values)) {
2370
+			$tp_select_values[] = [
2371
+				'text' => esc_html__('Default', 'event_espresso'),
2372
+				'id'   => 'default',
2373
+			];
2374
+		}
2375
+
2376
+		// setup variation select values for the currently selected template.
2377
+		$variations               = $this->_message_template_group->get_template_pack()->get_variations(
2378
+			$this->_message_template_group->messenger(),
2379
+			$this->_message_template_group->message_type()
2380
+		);
2381
+		$variations_select_values = [];
2382
+		foreach ($variations as $variation => $label) {
2383
+			$variations_select_values[] = [
2384
+				'text' => $label,
2385
+				'id'   => $variation,
2386
+			];
2387
+		}
2388
+
2389
+		$template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2390
+
2391
+		$template_args['template_packs_selector']        = EEH_Form_Fields::select_input(
2392
+			'MTP_template_pack',
2393
+			$tp_select_values,
2394
+			$this->_message_template_group->get_template_pack_name()
2395
+		);
2396
+		$template_args['variations_selector']            = EEH_Form_Fields::select_input(
2397
+			'MTP_template_variation',
2398
+			$variations_select_values,
2399
+			$this->_message_template_group->get_template_pack_variation()
2400
+		);
2401
+		$template_args['template_pack_label']            = $template_pack_labels->template_pack;
2402
+		$template_args['template_variation_label']       = $template_pack_labels->template_variation;
2403
+		$template_args['template_pack_description']      = $template_pack_labels->template_pack_description;
2404
+		$template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2405
+
2406
+		$template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2407
+
2408
+		EEH_Template::display_template($template, $template_args);
2409
+	}
2410
+
2411
+
2412
+	/**
2413
+	 * This meta box holds any extra actions related to Message Templates
2414
+	 * For now, this includes Resetting templates to defaults and sending a test email.
2415
+	 *
2416
+	 * @access  public
2417
+	 * @return void
2418
+	 * @throws EE_Error
2419
+	 */
2420
+	public function extra_actions_meta_box()
2421
+	{
2422
+		$template_form_fields = [];
2423
+
2424
+		$extra_args = [
2425
+			'msgr'   => $this->_message_template_group->messenger(),
2426
+			'mt'     => $this->_message_template_group->message_type(),
2427
+			'GRP_ID' => $this->_message_template_group->GRP_ID(),
2428
+		];
2429
+		// first we need to see if there are any fields
2430
+		$fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2431
+
2432
+		if (! empty($fields)) {
2433
+			// yup there be fields
2434
+			foreach ($fields as $field => $config) {
2435
+				$field_id = $this->_message_template_group->messenger() . '_' . $field;
2436
+				$existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2437
+				$default  = isset($config['default']) ? $config['default'] : '';
2438
+				$default  = isset($config['value']) ? $config['value'] : $default;
2439
+
2440
+				// if type is hidden and the value is empty
2441
+				// something may have gone wrong so let's correct with the defaults
2442
+				$fix                = $config['input'] === 'hidden'
2443
+									  && isset($existing[ $field ])
2444
+									  && empty($existing[ $field ])
2445
+					? $default
2446
+					: '';
2447
+				$existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2448
+					? $existing[ $field ]
2449
+					: $fix;
2450
+
2451
+				$template_form_fields[ $field_id ] = [
2452
+					'name'       => 'test_settings_fld[' . $field . ']',
2453
+					'label'      => $config['label'],
2454
+					'input'      => $config['input'],
2455
+					'type'       => $config['type'],
2456
+					'required'   => $config['required'],
2457
+					'validation' => $config['validation'],
2458
+					'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2459
+					'css_class'  => $config['css_class'],
2460
+					'options'    => isset($config['options']) ? $config['options'] : [],
2461
+					'default'    => $default,
2462
+					'format'     => $config['format'],
2463
+				];
2464
+			}
2465
+		}
2466
+
2467
+		$test_settings_html = ! empty($template_form_fields)
2468
+			? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2469
+			: '';
2470
+
2471
+		// print out $test_settings_fields
2472
+		if (! empty($test_settings_html)) {
2473
+			$test_settings_html .= '<input type="submit" class="button--primary mtp-test-button alignright" ';
2474
+			$test_settings_html .= 'name="test_button" value="';
2475
+			$test_settings_html .= esc_html__('Test Send', 'event_espresso');
2476
+			$test_settings_html .= '" /><div style="clear:both"></div>';
2477
+		}
2478
+
2479
+		// and button
2480
+		$test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2481
+		$test_settings_html .= '<p>';
2482
+		$test_settings_html .= esc_html__('Need to reset this message type and start over?', 'event_espresso');
2483
+		$test_settings_html .= '</p>';
2484
+		$test_settings_html .= $this->get_action_link_or_button(
2485
+			'reset_to_default',
2486
+			'reset',
2487
+			$extra_args,
2488
+			'button--primary reset-default-button'
2489
+		);
2490
+		$test_settings_html .= '</div><div style="clear:both"></div>';
2491
+		echo wp_kses($test_settings_html, AllowedTags::getWithFormTags());
2492
+	}
2493
+
2494
+
2495
+	/**
2496
+	 * This returns the shortcode selector skeleton for a given context and field.
2497
+	 *
2498
+	 * @param string $field           The name of the field retrieving shortcodes for.
2499
+	 * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2500
+	 * @return string
2501
+	 * @throws DomainException
2502
+	 * @throws EE_Error
2503
+	 * @throws InvalidArgumentException
2504
+	 * @throws ReflectionException
2505
+	 * @throws InvalidDataTypeException
2506
+	 * @throws InvalidInterfaceException
2507
+	 * @since 4.9.rc.000
2508
+	 */
2509
+	protected function _get_shortcode_selector($field, $linked_input_id)
2510
+	{
2511
+		$template_args = [
2512
+			'shortcodes'      => $this->_get_shortcodes([$field]),
2513
+			'fieldname'       => $field,
2514
+			'linked_input_id' => $linked_input_id,
2515
+		];
2516
+
2517
+		return EEH_Template::display_template(
2518
+			EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2519
+			$template_args,
2520
+			true
2521
+		);
2522
+	}
2523
+
2524
+
2525
+	/**
2526
+	 * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2527
+	 * page)
2528
+	 *
2529
+	 * @access public
2530
+	 * @return void
2531
+	 * @throws EE_Error
2532
+	 * @throws InvalidArgumentException
2533
+	 * @throws ReflectionException
2534
+	 * @throws InvalidDataTypeException
2535
+	 * @throws InvalidInterfaceException
2536
+	 */
2537
+	public function shortcode_meta_box()
2538
+	{
2539
+		$shortcodes = $this->_get_shortcodes([], false);
2540
+		// just make sure the shortcodes property is set
2541
+		// $messenger = $this->_message_template_group->messenger_obj();
2542
+		// now let's set the content depending on the status of the shortcodes array
2543
+		if (empty($shortcodes)) {
2544
+			echo '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2545
+			return;
2546
+		}
2547
+		?>
2548 2548
         <div style="float:right; margin-top:10px">
2549 2549
             <?php echo wp_kses($this->_get_help_tab_link('message_template_shortcodes'), AllowedTags::getAllowedTags());
2550
-            ?>
2550
+			?>
2551 2551
         </div>
2552 2552
         <p class="small-text">
2553 2553
             <?php printf(
2554
-                esc_html__(
2555
-                    'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2556
-                    'event_espresso'
2557
-                ),
2558
-                '<span class="dashicons dashicons-shortcode"></span>'
2559
-            ); ?>
2554
+				esc_html__(
2555
+					'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2556
+					'event_espresso'
2557
+				),
2558
+				'<span class="dashicons dashicons-shortcode"></span>'
2559
+			); ?>
2560 2560
         </p>
2561 2561
         <?php
2562
-    }
2563
-
2564
-
2565
-    /**
2566
-     * used to set the $_shortcodes property for when its needed elsewhere.
2567
-     *
2568
-     * @access protected
2569
-     * @return void
2570
-     * @throws EE_Error
2571
-     * @throws InvalidArgumentException
2572
-     * @throws ReflectionException
2573
-     * @throws InvalidDataTypeException
2574
-     * @throws InvalidInterfaceException
2575
-     */
2576
-    protected function _set_shortcodes()
2577
-    {
2578
-
2579
-        // no need to run this if the property is already set
2580
-        if (! empty($this->_shortcodes)) {
2581
-            return;
2582
-        }
2583
-
2584
-        $this->_shortcodes = $this->_get_shortcodes();
2585
-    }
2586
-
2587
-
2588
-    /**
2589
-     * gets all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2590
-     * property)
2591
-     *
2592
-     * @access  protected
2593
-     * @param array   $fields  include an array of specific field names that you want to be used to get the shortcodes
2594
-     *                         for. Defaults to all (for the given context)
2595
-     * @param boolean $merged  Whether to merge all the shortcodes into one list of unique shortcodes
2596
-     * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2597
-     *                         true just an array of shortcode/label pairs.
2598
-     * @throws EE_Error
2599
-     * @throws InvalidArgumentException
2600
-     * @throws ReflectionException
2601
-     * @throws InvalidDataTypeException
2602
-     * @throws InvalidInterfaceException
2603
-     */
2604
-    protected function _get_shortcodes($fields = [], $merged = true)
2605
-    {
2606
-        $this->_set_message_template_group();
2607
-
2608
-        // we need the messenger and message template to retrieve the valid shortcodes array.
2609
-        $GRP_ID = $this->request->getRequestParam('id', 0, 'int');
2610
-        if (empty($GRP_ID)) {
2611
-            return [];
2612
-        }
2613
-        $context = $this->request->getRequestParam(
2614
-            'messenger',
2615
-            key($this->_message_template_group->contexts_config())
2616
-        );
2617
-        return $this->_message_template_group->get_shortcodes($context, $fields, $merged);
2618
-    }
2619
-
2620
-
2621
-    /**
2622
-     * This sets the _message_template property (containing the called message_template object)
2623
-     *
2624
-     * @access protected
2625
-     * @return void
2626
-     * @throws EE_Error
2627
-     * @throws InvalidArgumentException
2628
-     * @throws ReflectionException
2629
-     * @throws InvalidDataTypeException
2630
-     * @throws InvalidInterfaceException
2631
-     */
2632
-    protected function _set_message_template_group()
2633
-    {
2634
-        // get out if this is already set.
2635
-        if (! empty($this->_message_template_group)) {
2636
-            return;
2637
-        }
2638
-
2639
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2640
-        $GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
2641
-
2642
-        // let's get the message templates
2643
-        $this->_message_template_group = ! empty($GRP_ID)
2644
-            ? $this->getMtgModel()->get_one_by_ID($GRP_ID)
2645
-            : $this->getMtgModel()->create_default_object();
2646
-
2647
-        $this->_template_pack = $this->_message_template_group->get_template_pack();
2648
-        $this->_variation     = $this->_message_template_group->get_template_pack_variation();
2649
-    }
2650
-
2651
-
2652
-    /**
2653
-     * sets up a context switcher for edit forms
2654
-     *
2655
-     * @access  protected
2656
-     * @param EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2657
-     * @param array                     $args                  various things the context switcher needs.
2658
-     * @throws EE_Error
2659
-     */
2660
-    protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2661
-    {
2662
-        $context_details = $template_group_object->contexts_config();
2663
-        $context_label   = $template_group_object->context_label();
2664
-        ob_start();
2665
-        ?>
2562
+	}
2563
+
2564
+
2565
+	/**
2566
+	 * used to set the $_shortcodes property for when its needed elsewhere.
2567
+	 *
2568
+	 * @access protected
2569
+	 * @return void
2570
+	 * @throws EE_Error
2571
+	 * @throws InvalidArgumentException
2572
+	 * @throws ReflectionException
2573
+	 * @throws InvalidDataTypeException
2574
+	 * @throws InvalidInterfaceException
2575
+	 */
2576
+	protected function _set_shortcodes()
2577
+	{
2578
+
2579
+		// no need to run this if the property is already set
2580
+		if (! empty($this->_shortcodes)) {
2581
+			return;
2582
+		}
2583
+
2584
+		$this->_shortcodes = $this->_get_shortcodes();
2585
+	}
2586
+
2587
+
2588
+	/**
2589
+	 * gets all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2590
+	 * property)
2591
+	 *
2592
+	 * @access  protected
2593
+	 * @param array   $fields  include an array of specific field names that you want to be used to get the shortcodes
2594
+	 *                         for. Defaults to all (for the given context)
2595
+	 * @param boolean $merged  Whether to merge all the shortcodes into one list of unique shortcodes
2596
+	 * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2597
+	 *                         true just an array of shortcode/label pairs.
2598
+	 * @throws EE_Error
2599
+	 * @throws InvalidArgumentException
2600
+	 * @throws ReflectionException
2601
+	 * @throws InvalidDataTypeException
2602
+	 * @throws InvalidInterfaceException
2603
+	 */
2604
+	protected function _get_shortcodes($fields = [], $merged = true)
2605
+	{
2606
+		$this->_set_message_template_group();
2607
+
2608
+		// we need the messenger and message template to retrieve the valid shortcodes array.
2609
+		$GRP_ID = $this->request->getRequestParam('id', 0, 'int');
2610
+		if (empty($GRP_ID)) {
2611
+			return [];
2612
+		}
2613
+		$context = $this->request->getRequestParam(
2614
+			'messenger',
2615
+			key($this->_message_template_group->contexts_config())
2616
+		);
2617
+		return $this->_message_template_group->get_shortcodes($context, $fields, $merged);
2618
+	}
2619
+
2620
+
2621
+	/**
2622
+	 * This sets the _message_template property (containing the called message_template object)
2623
+	 *
2624
+	 * @access protected
2625
+	 * @return void
2626
+	 * @throws EE_Error
2627
+	 * @throws InvalidArgumentException
2628
+	 * @throws ReflectionException
2629
+	 * @throws InvalidDataTypeException
2630
+	 * @throws InvalidInterfaceException
2631
+	 */
2632
+	protected function _set_message_template_group()
2633
+	{
2634
+		// get out if this is already set.
2635
+		if (! empty($this->_message_template_group)) {
2636
+			return;
2637
+		}
2638
+
2639
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2640
+		$GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
2641
+
2642
+		// let's get the message templates
2643
+		$this->_message_template_group = ! empty($GRP_ID)
2644
+			? $this->getMtgModel()->get_one_by_ID($GRP_ID)
2645
+			: $this->getMtgModel()->create_default_object();
2646
+
2647
+		$this->_template_pack = $this->_message_template_group->get_template_pack();
2648
+		$this->_variation     = $this->_message_template_group->get_template_pack_variation();
2649
+	}
2650
+
2651
+
2652
+	/**
2653
+	 * sets up a context switcher for edit forms
2654
+	 *
2655
+	 * @access  protected
2656
+	 * @param EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2657
+	 * @param array                     $args                  various things the context switcher needs.
2658
+	 * @throws EE_Error
2659
+	 */
2660
+	protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2661
+	{
2662
+		$context_details = $template_group_object->contexts_config();
2663
+		$context_label   = $template_group_object->context_label();
2664
+		ob_start();
2665
+		?>
2666 2666
         <div class="ee-msg-switcher-container">
2667 2667
             <form method="get" action="<?php echo esc_url_raw(EE_MSG_ADMIN_URL); ?>" id="ee-msg-context-switcher-frm">
2668 2668
                 <?php
2669
-                foreach ($args as $name => $value) {
2670
-                    if ($name === 'context' || empty($value) || $name === 'extra') {
2671
-                        continue;
2672
-                    }
2673
-                    ?>
2669
+				foreach ($args as $name => $value) {
2670
+					if ($name === 'context' || empty($value) || $name === 'extra') {
2671
+						continue;
2672
+					}
2673
+					?>
2674 2674
                     <input type="hidden"
2675 2675
                            name="<?php echo esc_attr($name); ?>"
2676 2676
                            value="<?php echo esc_attr($value); ?>"
2677 2677
                     />
2678 2678
                     <?php
2679
-                }
2680
-                // setup nonce_url
2681
-                wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2682
-                $id = 'ee-' . sanitize_key($context_label['label']) . '-select';
2683
-                ?>
2679
+				}
2680
+				// setup nonce_url
2681
+				wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2682
+				$id = 'ee-' . sanitize_key($context_label['label']) . '-select';
2683
+				?>
2684 2684
                 <label for='<?php echo esc_attr($id); ?>' class='screen-reader-text'>
2685 2685
                     <?php esc_html_e('message context options', 'event_espresso'); ?>
2686 2686
                 </label>
2687 2687
                 <select id="<?php echo esc_attr($id); ?>" name="context">
2688 2688
                     <?php
2689
-                    $context_templates = $template_group_object->context_templates();
2690
-                    if (is_array($context_templates)) :
2691
-                        foreach ($context_templates as $context => $template_fields) :
2692
-                            $checked = ($context === $args['context']) ? 'selected' : '';
2693
-                            ?>
2689
+					$context_templates = $template_group_object->context_templates();
2690
+					if (is_array($context_templates)) :
2691
+						foreach ($context_templates as $context => $template_fields) :
2692
+							$checked = ($context === $args['context']) ? 'selected' : '';
2693
+							?>
2694 2694
                             <option value="<?php echo esc_attr($context); ?>" <?php echo esc_attr($checked); ?>>
2695 2695
                                 <?php echo esc_html($context_details[ $context ]['label']); ?>
2696 2696
                             </option>
2697 2697
                         <?php endforeach;
2698
-                    endif; ?>
2698
+					endif; ?>
2699 2699
                 </select>
2700 2700
                 <?php $button_text = sprintf(
2701
-                    esc_html__('Switch %s', 'event_espresso'),
2702
-                    ucwords($context_label['label'])
2703
-                ); ?>
2701
+					esc_html__('Switch %s', 'event_espresso'),
2702
+					ucwords($context_label['label'])
2703
+				); ?>
2704 2704
                 <input class='button--secondary'
2705 2705
                        id="submit-msg-context-switcher-sbmt"
2706 2706
                        type="submit"
@@ -2710,1996 +2710,1996 @@  discard block
 block discarded – undo
2710 2710
             <?php echo wp_kses($args['extra'], AllowedTags::getWithFormTags()); ?>
2711 2711
         </div> <!-- end .ee-msg-switcher-container -->
2712 2712
         <?php $this->_context_switcher = ob_get_clean();
2713
-    }
2714
-
2715
-
2716
-    /**
2717
-     * @param bool $new
2718
-     * @throws EE_Error
2719
-     * @throws ReflectionException
2720
-     */
2721
-    protected function _insert_or_update_message_template($new = false)
2722
-    {
2723
-        $form_data    = $this->getMessageTemplateFormData();
2724
-        $GRP_ID       = $form_data['GRP_ID'];
2725
-        $messenger    = $form_data['MTP_messenger'];
2726
-        $message_type = $form_data['MTP_message_type'];
2727
-        $context      = $form_data['MTP_context'];
2728
-
2729
-        // if this is "new" then we need to generate the default contexts
2730
-        // for the selected messenger/message_type for user to edit.
2731
-        [$success, $query_args] = $new
2732
-            ? $this->generateNewTemplates($GRP_ID, $messenger, $message_type)
2733
-            : $this->updateExistingTemplates($GRP_ID, $messenger, $message_type, $context, $form_data);
2734
-
2735
-        $success     = $success ? 1 : 0;
2736
-        $action_desc = $new ? 'created' : 'updated';
2737
-        $item_desc   = $this->generateUpdateDescription($messenger, $message_type, $context);
2738
-        $override    = $this->performTestSendAfterUpdate($messenger, $message_type, $context);
2739
-
2740
-        $this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
2741
-    }
2742
-
2743
-
2744
-    /**
2745
-     * retrieve and sanitize form data
2746
-     *
2747
-     * @return array
2748
-     * @since 4.10.29.p
2749
-     */
2750
-    protected function getMessageTemplateFormData()
2751
-    {
2752
-        return [
2753
-            'GRP_ID'           => $this->request->getRequestParam('GRP_ID', 0, 'int'),
2754
-            'MTP_context'      => strtolower($this->request->getRequestParam('MTP_context', '')),
2755
-            'MTP_messenger'    => strtolower($this->request->getRequestParam('MTP_messenger', '')),
2756
-            'MTP_message_type' => strtolower($this->request->getRequestParam('MTP_message_type', '')),
2757
-            'MTP_user_id'      => $this->request->getRequestParam('MTP_user_id', 0, 'int'),
2758
-            'MTP_is_global'    => $this->request->getRequestParam('MTP_is_global', 0, 'int'),
2759
-            'MTP_is_override'  => $this->request->getRequestParam('MTP_is_override', 0, 'int'),
2760
-            'MTP_deleted'      => $this->request->getRequestParam('MTP_deleted', 0, 'int'),
2761
-            'MTP_is_active'    => $this->request->getRequestParam('MTP_is_active', 0, 'int'),
2762
-        ];
2763
-    }
2764
-
2765
-
2766
-    /**
2767
-     * @param int    $GRP_ID
2768
-     * @param string $messenger
2769
-     * @param string $message_type
2770
-     * @return array no return on AJAX requests
2771
-     * @throws EE_Error
2772
-     * @throws ReflectionException
2773
-     * @since 4.10.29.p
2774
-     */
2775
-    private function generateNewTemplates($GRP_ID, $messenger, $message_type)
2776
-    {
2777
-        $new_templates = $this->_generate_new_templates($messenger, [$message_type], $GRP_ID);
2778
-        $success       = ! empty($new_templates);
2779
-
2780
-        // we return things differently if doing ajax
2781
-        if ($this->request->isAjax()) {
2782
-            $this->_template_args['success'] = $success;
2783
-            $this->_template_args['error']   = ! $success;
2784
-            $this->_template_args['content'] = '';
2785
-            $this->_template_args['data']    = [
2786
-                'grpID'        => $new_templates['GRP_ID'],
2787
-                'templateName' => $new_templates['template_name'],
2788
-            ];
2789
-            if ($success) {
2790
-                EE_Error::overwrite_success();
2791
-                EE_Error::add_success(
2792
-                    esc_html__(
2793
-                        'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2794
-                        'event_espresso'
2795
-                    )
2796
-                );
2797
-            }
2798
-            $this->_return_json();
2799
-        }
2800
-        return [
2801
-            $success,
2802
-            // 'query_args'
2803
-            [
2804
-                'id'      => $new_templates['GRP_ID'],
2805
-                'context' => $new_templates['MTP_context'],
2806
-                'action'  => 'edit_message_template',
2807
-            ],
2808
-        ];
2809
-    }
2810
-
2811
-
2812
-    /**
2813
-     * @param int    $GRP_ID
2814
-     * @param string $messenger
2815
-     * @param string $message_type
2816
-     * @param string $context
2817
-     * @param array  $form_data
2818
-     * @return array
2819
-     * @throws EE_Error
2820
-     * @since 4.10.29.p
2821
-     */
2822
-    private function updateExistingTemplates(
2823
-        $GRP_ID,
2824
-        $messenger,
2825
-        $message_type,
2826
-        $context,
2827
-        array $form_data
2828
-    ) {
2829
-        $success         = false;
2830
-        $template_fields = $this->getTemplateFields();
2831
-        if ($template_fields) {
2832
-            // if field data is valid, then success will be true
2833
-            $success = $this->validateTemplateFields(
2834
-                $messenger,
2835
-                $message_type,
2836
-                $context,
2837
-                $template_fields
2838
-            );
2839
-            if ($success) {
2840
-                $field_data = [];
2841
-                foreach ($template_fields as $template_field => $content) {
2842
-                    // combine top-level form data with content for this field
2843
-                    $field_data = $this->getTemplateFieldFormData($content, $form_data);
2844
-                    $success    = $this->updateMessageTemplates($template_field, $field_data) ? $success : false;
2845
-                }
2846
-                // we can use the last set_column_values for the MTPG update
2847
-                // (because its the same for all of these specific MTPs)
2848
-                $success = $this->updateMessageTemplateGroup($field_data) ? $success : false;
2849
-            }
2850
-        }
2851
-
2852
-        return [
2853
-            $success,
2854
-            // 'query_args'
2855
-            [
2856
-                'id'      => $GRP_ID,
2857
-                'context' => $context,
2858
-                'action'  => 'edit_message_template',
2859
-            ],
2860
-        ];
2861
-    }
2862
-
2863
-
2864
-    /**
2865
-     * @return array
2866
-     * @since 4.10.29.p
2867
-     */
2868
-    private function getTemplateFields()
2869
-    {
2870
-        $template_fields = $this->request->getRequestParam('MTP_template_fields', null, 'html', true);
2871
-        if (empty($template_fields)) {
2872
-            EE_Error::add_error(
2873
-                esc_html__(
2874
-                    'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2875
-                    'event_espresso'
2876
-                ),
2877
-                __FILE__,
2878
-                __FUNCTION__,
2879
-                __LINE__
2880
-            );
2881
-            return null;
2882
-        }
2883
-        // messages content is expected to be escaped
2884
-        return EEH_Array::addSlashesRecursively($template_fields);
2885
-    }
2886
-
2887
-
2888
-    /**
2889
-     * @param string $messenger
2890
-     * @param string $message_type
2891
-     * @param string $context
2892
-     * @param array  $template_fields
2893
-     * @return bool
2894
-     * @throws EE_Error
2895
-     * @since   4.10.29.p
2896
-     */
2897
-    private function validateTemplateFields(
2898
-        $messenger,
2899
-        $message_type,
2900
-        $context,
2901
-        array $template_fields
2902
-    ) {
2903
-        // first validate all fields!
2904
-        // this filter allows client code to add its own validation to the template fields as well.
2905
-        // returning an empty array means everything passed validation.
2906
-        // errors in validation should be represented in an array with the following shape:
2907
-        // array(
2908
-        //   'fieldname' => array(
2909
-        //          'msg' => 'error message'
2910
-        //          'value' => 'value for field producing error'
2911
-        // )
2912
-        $custom_validation = (array) apply_filters(
2913
-            'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2914
-            [],
2915
-            $template_fields,
2916
-            $context,
2917
-            $messenger,
2918
-            $message_type
2919
-        );
2920
-
2921
-        $system_validation = $this->getMtgModel()->validate(
2922
-            $template_fields,
2923
-            $context,
2924
-            $messenger,
2925
-            $message_type
2926
-        );
2927
-
2928
-        $system_validation = ! is_array($system_validation) && $system_validation ? [] : $system_validation;
2929
-        $validates         = array_merge($custom_validation, $system_validation);
2930
-
2931
-        // if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2932
-        // appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2933
-        //  WE need to make sure there is no actual error messages in validates.
2934
-        if (empty($validates)) {
2935
-            return true;
2936
-        }
2937
-
2938
-        // add the transient so when the form loads we know which fields to highlight
2939
-        $this->_add_transient('edit_message_template', $validates);
2940
-        // setup notices
2941
-        foreach ($validates as $error) {
2942
-            if (isset($error['msg'])) {
2943
-                EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2944
-            }
2945
-        }
2946
-        return false;
2947
-    }
2948
-
2949
-
2950
-    /**
2951
-     * @param array $field_data
2952
-     * @param array $form_data
2953
-     * @return array
2954
-     * @since   4.10.29.p
2955
-     */
2956
-    private function getTemplateFieldFormData(array $field_data, array $form_data)
2957
-    {
2958
-        return $form_data + [
2959
-                'MTP_ID'             => $field_data['MTP_ID'],
2960
-                'MTP_template_field' => $field_data['name'],
2961
-                // if they aren't allowed to use all JS, restrict them to standard allowed post tags
2962
-                'MTP_content'        => ! current_user_can('unfiltered_html')
2963
-                    ? $this->sanitizeMessageTemplateContent($field_data['content'])
2964
-                    : $field_data['content'],
2965
-            ];
2966
-    }
2967
-
2968
-
2969
-    /**
2970
-     * @param string $template_field
2971
-     * @param array  $form_data
2972
-     * @return bool
2973
-     * @throws EE_Error
2974
-     * @since 4.10.29.p
2975
-     */
2976
-    private function updateMessageTemplates($template_field, array $form_data)
2977
-    {
2978
-        $MTP_ID                  = $form_data['MTP_ID'];
2979
-        $message_template_fields = [
2980
-            'GRP_ID'             => $form_data['GRP_ID'],
2981
-            'MTP_template_field' => $form_data['MTP_template_field'],
2982
-            'MTP_context'        => $form_data['MTP_context'],
2983
-            'MTP_content'        => $form_data['MTP_content'],
2984
-        ];
2985
-
2986
-        $hasMtpID = ! empty($MTP_ID);
2987
-        // if we have a MTP_ID for this field then update it, otherwise insert.
2988
-        // this has already been through the template field validator and sanitized, so it will be
2989
-        // safe to insert this field.  Why insert?  This typically happens when we introduce a new
2990
-        // message template field in a messenger/message type and existing users don't have the
2991
-        // default setup for it.
2992
-        // @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2993
-        $updated = $hasMtpID
2994
-            ? $this->getMtpModel()->update($message_template_fields, [['MTP_ID' => $MTP_ID]])
2995
-            : $this->getMtpModel()->insert($message_template_fields);
2996
-
2997
-        $insert_failed = ! $hasMtpID && ! $updated;
2998
-        // updates will return 0 if the field was not changed (ie: no changes = nothing actually updated)
2999
-        // but we won't consider that a problem, but if it returns false, then something went BOOM!
3000
-        $update_failed = $hasMtpID && $updated === false;
3001
-
3002
-        if ($insert_failed || $update_failed) {
3003
-            EE_Error::add_error(
3004
-                sprintf(
3005
-                    esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
3006
-                    $template_field
3007
-                ),
3008
-                __FILE__,
3009
-                __FUNCTION__,
3010
-                __LINE__
3011
-            );
3012
-            return false;
3013
-        }
3014
-        return true;
3015
-    }
3016
-
3017
-
3018
-    /**
3019
-     * @param array $form_data
3020
-     * @return bool
3021
-     * @throws EE_Error
3022
-     * @since 4.10.29.p
3023
-     */
3024
-    private function updateMessageTemplateGroup(array $form_data)
3025
-    {
3026
-        $GRP_ID  = $form_data['GRP_ID'];
3027
-        $updated = $this->getMtgModel()->update(
3028
-        // fields and values
3029
-            [
3030
-                'MTP_user_id'      => $form_data['MTP_user_id'],
3031
-                'MTP_messenger'    => $form_data['MTP_messenger'],
3032
-                'MTP_message_type' => $form_data['MTP_message_type'],
3033
-                'MTP_is_global'    => $form_data['MTP_is_global'],
3034
-                'MTP_is_override'  => $form_data['MTP_is_override'],
3035
-                'MTP_deleted'      => $form_data['MTP_deleted'],
3036
-                'MTP_is_active'    => $form_data['MTP_is_active'],
3037
-                'MTP_name'         => $this->request->getRequestParam('ee_msg_non_global_fields[MTP_name]', ''),
3038
-                'MTP_description'  => $this->request->getRequestParam(
3039
-                    'ee_msg_non_global_fields[MTP_description]',
3040
-                    ''
3041
-                ),
3042
-            ],
3043
-            // where
3044
-            [['GRP_ID' => $GRP_ID]]
3045
-        );
3046
-
3047
-        if ($updated === false) {
3048
-            EE_Error::add_error(
3049
-                sprintf(
3050
-                    esc_html__(
3051
-                        'The Message Template Group (%d) was NOT updated for some reason',
3052
-                        'event_espresso'
3053
-                    ),
3054
-                    $form_data['GRP_ID']
3055
-                ),
3056
-                __FILE__,
3057
-                __FUNCTION__,
3058
-                __LINE__
3059
-            );
3060
-            return false;
3061
-        }
3062
-        // k now we need to ensure the template_pack and template_variation fields are set.
3063
-        $template_pack      = $this->request->getRequestParam('MTP_template_pack', 'default');
3064
-        $template_variation = $this->request->getRequestParam('MTP_template_variation', 'default');
3065
-
3066
-        $message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3067
-        if ($message_template_group instanceof EE_Message_Template_Group) {
3068
-            $message_template_group->set_template_pack_name($template_pack);
3069
-            $message_template_group->set_template_pack_variation($template_variation);
3070
-        }
3071
-        return true;
3072
-    }
3073
-
3074
-
3075
-    /**
3076
-     * recursively runs wp_kses() on message template content in a model safe manner
3077
-     *
3078
-     * @param array|string $content
3079
-     * @return array|string
3080
-     * @since   4.10.29.p
3081
-     */
3082
-    private function sanitizeMessageTemplateContent($content)
3083
-    {
3084
-        if (is_array($content)) {
3085
-            foreach ($content as $key => $value) {
3086
-                $content[ $key ] = $this->sanitizeMessageTemplateContent($value);
3087
-            }
3088
-            return $content;
3089
-        }
3090
-        // remove slashes so wp_kses() works properly
3091
-        // wp_kses_stripslashes() only removes slashes from double-quotes,
3092
-        // so attributes using single quotes always appear invalid.
3093
-        $content = stripslashes($content);
3094
-        $content = wp_kses($content, wp_kses_allowed_html('post'));
3095
-        // But currently the models expect slashed data, so after wp_kses()
3096
-        // runs we need to re-slash the data. Sheesh.
3097
-        // See https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
3098
-        return addslashes($content);
3099
-    }
3100
-
3101
-
3102
-    /**
3103
-     * @param string $messenger
3104
-     * @param string $message_type
3105
-     * @param string $context
3106
-     * @return string
3107
-     * @since 4.10.29.p
3108
-     */
3109
-    private function generateUpdateDescription($messenger, $message_type, $context)
3110
-    {
3111
-        // need the message type and messenger objects to be able to use the labels for the notices
3112
-        $messenger_object = $this->_message_resource_manager->get_messenger($messenger);
3113
-        $messenger_label  = $messenger_object instanceof EE_messenger
3114
-            ? ucwords($messenger_object->label['singular'])
3115
-            : '';
3116
-
3117
-        $message_type_object = $this->_message_resource_manager->get_message_type($message_type);
3118
-        $message_type_label  = $message_type_object instanceof EE_message_type
3119
-            ? ucwords($message_type_object->label['singular'])
3120
-            : '';
3121
-
3122
-        $context   = ucwords(str_replace('_', ' ', $context));
3123
-        $item_desc = $messenger_label && $message_type_label
3124
-            ? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
3125
-            : '';
3126
-        $item_desc .= 'Message Template';
3127
-        return $item_desc;
3128
-    }
3129
-
3130
-
3131
-    /**
3132
-     * @param string $messenger
3133
-     * @param string $message_type
3134
-     * @param string $context
3135
-     * @return bool
3136
-     * @throws EE_Error
3137
-     * @throws ReflectionException
3138
-     * @since 4.10.29.p
3139
-     */
3140
-    private function performTestSendAfterUpdate($messenger, $message_type, $context)
3141
-    {
3142
-        // was a test send triggered?
3143
-        if ($this->request->requestParamIsSet('test_button')) {
3144
-            EE_Error::overwrite_success();
3145
-            $this->_do_test_send($context, $messenger, $message_type);
3146
-            return true;
3147
-        }
3148
-        return false;
3149
-    }
3150
-
3151
-
3152
-    /**
3153
-     * processes a test send request to do an actual messenger delivery test for the given message template being tested
3154
-     *
3155
-     * @param string $context      what context being tested
3156
-     * @param string $messenger    messenger being tested
3157
-     * @param string $message_type message type being tested
3158
-     * @throws EE_Error
3159
-     * @throws InvalidArgumentException
3160
-     * @throws InvalidDataTypeException
3161
-     * @throws InvalidInterfaceException
3162
-     * @throws ReflectionException
3163
-     */
3164
-    protected function _do_test_send($context, $messenger, $message_type)
3165
-    {
3166
-        // set things up for preview
3167
-        $this->request->setRequestParam('messenger', $messenger);
3168
-        $this->request->setRequestParam('message_type', $message_type);
3169
-        $this->request->setRequestParam('context', $context);
3170
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
3171
-        $this->request->setRequestParam('GRP_ID', $GRP_ID);
3172
-
3173
-        $active_messenger  = $this->_message_resource_manager->get_active_messenger($messenger);
3174
-        $test_settings_fld = $this->request->getRequestParam('test_settings_fld', [], 'string', true);
3175
-
3176
-        // let's save any existing fields that might be required by the messenger
3177
-        if (
3178
-            ! empty($test_settings_fld)
3179
-            && $active_messenger instanceof EE_messenger
3180
-            && apply_filters(
3181
-                'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3182
-                true,
3183
-                $test_settings_fld,
3184
-                $active_messenger
3185
-            )
3186
-        ) {
3187
-            $active_messenger->set_existing_test_settings($test_settings_fld);
3188
-        }
3189
-
3190
-        /**
3191
-         * Use filter to add additional controls on whether message can send or not
3192
-         */
3193
-        if (
3194
-            apply_filters(
3195
-                'FHEE__Messages_Admin_Page__do_test_send__can_send',
3196
-                true,
3197
-                $context,
3198
-                $this->request->requestParams(),
3199
-                $messenger,
3200
-                $message_type
3201
-            )
3202
-        ) {
3203
-            if (EEM_Event::instance()->count() > 0) {
3204
-                $success = $this->_preview_message(true);
3205
-                if ($success) {
3206
-                    EE_Error::add_success(esc_html__('Test message sent', 'event_espresso'));
3207
-                } else {
3208
-                    EE_Error::add_error(
3209
-                        esc_html__('The test message was not sent', 'event_espresso'),
3210
-                        __FILE__,
3211
-                        __FUNCTION__,
3212
-                        __LINE__
3213
-                    );
3214
-                }
3215
-            } else {
3216
-                $this->noEventsErrorMessage(true);
3217
-            }
3218
-        }
3219
-    }
3220
-
3221
-
3222
-    /**
3223
-     * _generate_new_templates
3224
-     * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3225
-     * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3226
-     * for the event.
3227
-     *
3228
-     *
3229
-     * @param string $messenger      the messenger we are generating templates for
3230
-     * @param array  $message_types  array of message types that the templates are generated for.
3231
-     * @param int    $GRP_ID         If this is a custom template being generated then a GRP_ID needs to be included to
3232
-     *                               indicate the message_template_group being used as the base.
3233
-     *
3234
-     * @param bool   $global
3235
-     *
3236
-     * @return array|bool array of data required for the redirect to the correct edit page or bool if
3237
-     *                               encountering problems.
3238
-     * @throws EE_Error
3239
-     * @throws ReflectionException
3240
-     */
3241
-    protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3242
-    {
3243
-        // if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3244
-        // just don't generate any templates.
3245
-        if (empty($message_types)) {
3246
-            return [];
3247
-        }
3248
-
3249
-        $templates = EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3250
-        return $templates[0];
3251
-    }
3252
-
3253
-
3254
-    /**
3255
-     * [_trash_or_restore_message_template]
3256
-     *
3257
-     * @param boolean $trash  whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3258
-     * @param boolean $all    whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3259
-     *                        an individual context (FALSE).
3260
-     * @return void
3261
-     * @throws EE_Error
3262
-     * @throws InvalidArgumentException
3263
-     * @throws InvalidDataTypeException
3264
-     * @throws InvalidInterfaceException
3265
-     */
3266
-    protected function _trash_or_restore_message_template($trash = true, $all = false)
3267
-    {
3268
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3269
-
3270
-        $success = 1;
3271
-
3272
-        // incoming GRP_IDs
3273
-        if ($all) {
3274
-            // Checkboxes
3275
-            $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3276
-            if (! empty($checkboxes)) {
3277
-                // if array has more than one element then success message should be plural.
3278
-                // todo: what about nonce?
3279
-                $success = count($checkboxes) > 1 ? 2 : 1;
3280
-
3281
-                // cycle through checkboxes
3282
-                while (list($GRP_ID, $value) = each($checkboxes)) {
3283
-                    $trashed_or_restored = $trash
3284
-                        ? $this->getMtgModel()->delete_by_ID($GRP_ID)
3285
-                        : $this->getMtgModel()->restore_by_ID($GRP_ID);
3286
-                    if (! $trashed_or_restored) {
3287
-                        $success = 0;
3288
-                    }
3289
-                }
3290
-            } else {
3291
-                // grab single GRP_ID and handle
3292
-                $GRP_ID = $this->request->getRequestParam('id', 0, 'int');
3293
-                if (! empty($GRP_ID)) {
3294
-                    $trashed_or_restored = $trash
3295
-                        ? $this->getMtgModel()->delete_by_ID($GRP_ID)
3296
-                        : $this->getMtgModel()->restore_by_ID($GRP_ID);
3297
-                    if (! $trashed_or_restored) {
3298
-                        $success = 0;
3299
-                    }
3300
-                } else {
3301
-                    $success = 0;
3302
-                }
3303
-            }
3304
-        }
3305
-
3306
-        $action_desc = $trash
3307
-            ? esc_html__('moved to the trash', 'event_espresso')
3308
-            : esc_html__('restored', 'event_espresso');
3309
-
3310
-        $template_switch = $this->request->getRequestParam('template_switch', false, 'bool');
3311
-        $action_desc     = $template_switch ? esc_html__('switched', 'event_espresso') : $action_desc;
3312
-
3313
-        $item_desc = $all ? _n(
3314
-            'Message Template Group',
3315
-            'Message Template Groups',
3316
-            $success,
3317
-            'event_espresso'
3318
-        ) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3319
-
3320
-        $item_desc = $template_switch
3321
-            ? _n('template', 'templates', $success, 'event_espresso')
3322
-            : $item_desc;
3323
-
3324
-        $this->_redirect_after_action($success, $item_desc, $action_desc, []);
3325
-    }
3326
-
3327
-
3328
-    /**
3329
-     * [_delete_message_template]
3330
-     * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3331
-     *
3332
-     * @return void
3333
-     * @throws EE_Error
3334
-     * @throws InvalidArgumentException
3335
-     * @throws InvalidDataTypeException
3336
-     * @throws InvalidInterfaceException
3337
-     * @throws ReflectionException
3338
-     */
3339
-    protected function _delete_message_template()
3340
-    {
3341
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3342
-
3343
-        // checkboxes
3344
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3345
-        if (! empty($checkboxes)) {
3346
-            // if array has more than one element then success message should be plural
3347
-            $success = count($checkboxes) > 1 ? 2 : 1;
3348
-
3349
-            // cycle through bulk action checkboxes
3350
-            while (list($GRP_ID, $value) = each($checkboxes)) {
3351
-                $success = $this->_delete_mtp_permanently($GRP_ID) ? $success : false;
3352
-            }
3353
-        } else {
3354
-            // grab single grp_id and delete
3355
-            $GRP_ID  = $this->request->getRequestParam('id', 0, 'int');
3356
-            $success = $this->_delete_mtp_permanently($GRP_ID);
3357
-        }
3358
-
3359
-        $this->_redirect_after_action($success, 'Message Templates', 'deleted', []);
3360
-    }
3361
-
3362
-
3363
-    /**
3364
-     * helper for permanently deleting a mtP group and all related message_templates
3365
-     *
3366
-     * @param int  $GRP_ID        The group being deleted
3367
-     * @param bool $include_group whether to delete the Message Template Group as well.
3368
-     * @return bool boolean to indicate the success of the deletes or not.
3369
-     * @throws EE_Error
3370
-     * @throws InvalidArgumentException
3371
-     * @throws InvalidDataTypeException
3372
-     * @throws InvalidInterfaceException
3373
-     * @throws ReflectionException
3374
-     * @throws ReflectionException
3375
-     */
3376
-    private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3377
-    {
3378
-        $success = true;
3379
-        // first let's GET this group
3380
-        $MTG = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3381
-        // then delete permanently all the related Message Templates
3382
-        $deleted = $MTG->delete_related_permanently('Message_Template');
3383
-
3384
-        if ($deleted === 0) {
3385
-            $success = false;
3386
-        }
3387
-
3388
-        // now delete permanently this particular group
3389
-
3390
-        if ($include_group && ! $MTG->delete_permanently()) {
3391
-            $success = false;
3392
-        }
3393
-
3394
-        return $success;
3395
-    }
3396
-
3397
-
3398
-    /**
3399
-     *    _learn_more_about_message_templates_link
3400
-     *
3401
-     * @access protected
3402
-     * @return string
3403
-     */
3404
-    protected function _learn_more_about_message_templates_link()
3405
-    {
3406
-        return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3407
-               . esc_html__('learn more about how message templates works', 'event_espresso')
3408
-               . '</a>';
3409
-    }
3410
-
3411
-
3412
-    /**
3413
-     * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3414
-     * ajax and other routes.
3415
-     *
3416
-     * @return void
3417
-     * @throws DomainException
3418
-     * @throws EE_Error
3419
-     */
3420
-    protected function _settings()
3421
-    {
3422
-        $this->_set_m_mt_settings();
3423
-
3424
-        // let's setup the messenger tabs
3425
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3426
-            $this->_m_mt_settings['messenger_tabs'],
3427
-            'messenger_links',
3428
-            '|',
3429
-            $this->request->getRequestParam('selected_messenger', 'email')
3430
-        );
3431
-
3432
-        $this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3433
-        $this->_template_args['after_admin_page_content']  = '</div><!-- end .ui-widget -->';
3434
-
3435
-        $this->display_admin_page_with_sidebar();
3436
-    }
3437
-
3438
-
3439
-    /**
3440
-     * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3441
-     *
3442
-     * @access protected
3443
-     * @return void
3444
-     * @throws DomainException
3445
-     */
3446
-    protected function _set_m_mt_settings()
3447
-    {
3448
-        // first if this is already set then lets get out no need to regenerate data.
3449
-        if (! empty($this->_m_mt_settings)) {
3450
-            return;
3451
-        }
3452
-
3453
-        // get all installed messengers and message_types
3454
-        $messengers    = $this->_message_resource_manager->installed_messengers();
3455
-        $message_types = $this->_message_resource_manager->installed_message_types();
3456
-
3457
-
3458
-        // assemble the array for the _tab_text_links helper
3459
-
3460
-        foreach ($messengers as $messenger) {
3461
-            $active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3462
-            $class = 'ee-messenger-' .  sanitize_key($messenger->label['singular']);
3463
-            $this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = [
3464
-                'label' => ucwords($messenger->label['singular']),
3465
-                'class' => $active ? "{$class} messenger-active" : $class,
3466
-                'href'  => $messenger->name,
3467
-                'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3468
-                'slug'  => $messenger->name,
3469
-                'obj'   => $messenger,
3470
-                'icon' => $active
3471
-                    ? '<span class="dashicons dashicons-yes-alt"></span>'
3472
-                    : '<span class="dashicons dashicons-remove"></span>',
3473
-            ];
3474
-
3475
-
3476
-            $message_types_for_messenger = $messenger->get_valid_message_types();
3477
-
3478
-            foreach ($message_types as $message_type) {
3479
-                // first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3480
-                // it shouldn't show in either the inactive OR active metabox.
3481
-                if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3482
-                    continue;
3483
-                }
3484
-
3485
-                $a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3486
-                    $messenger->name,
3487
-                    $message_type->name
3488
-                )
3489
-                    ? 'active'
3490
-                    : 'inactive';
3491
-
3492
-                $this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = [
3493
-                    'label'    => ucwords($message_type->label['singular']),
3494
-                    'class'    => 'message-type-' . $a_or_i,
3495
-                    'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3496
-                    'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3497
-                    'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3498
-                    'title'    => $a_or_i === 'active'
3499
-                        ? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3500
-                        : esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3501
-                    'content'  => $a_or_i === 'active'
3502
-                        ? $this->_message_type_settings_content($message_type, $messenger, true)
3503
-                        : $this->_message_type_settings_content($message_type, $messenger),
3504
-                    'slug'     => $message_type->name,
3505
-                    'active'   => $a_or_i === 'active',
3506
-                    'obj'      => $message_type,
3507
-                ];
3508
-            }
3509
-        }
3510
-    }
3511
-
3512
-
3513
-    /**
3514
-     * This just prepares the content for the message type settings
3515
-     *
3516
-     * @param EE_message_type $message_type The message type object
3517
-     * @param EE_messenger    $messenger    The messenger object
3518
-     * @param boolean         $active       Whether the message type is active or not
3519
-     * @return string html output for the content
3520
-     * @throws DomainException
3521
-     */
3522
-    protected function _message_type_settings_content($message_type, $messenger, $active = false)
3523
-    {
3524
-        // get message type fields
3525
-        $fields                                         = $message_type->get_admin_settings_fields();
3526
-        $settings_template_args['template_form_fields'] = '';
3527
-
3528
-        if (! empty($fields) && $active) {
3529
-            $existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3530
-            foreach ($fields as $fldname => $fldprops) {
3531
-                $field_id                         = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3532
-                $template_form_field[ $field_id ] = [
3533
-                    'name'       => 'message_type_settings[' . $fldname . ']',
3534
-                    'label'      => $fldprops['label'],
3535
-                    'input'      => $fldprops['field_type'],
3536
-                    'type'       => $fldprops['value_type'],
3537
-                    'required'   => $fldprops['required'],
3538
-                    'validation' => $fldprops['validation'],
3539
-                    'value'      => isset($existing_settings[ $fldname ])
3540
-                        ? $existing_settings[ $fldname ]
3541
-                        : $fldprops['default'],
3542
-                    'options'    => isset($fldprops['options'])
3543
-                        ? $fldprops['options']
3544
-                        : [],
3545
-                    'default'    => isset($existing_settings[ $fldname ])
3546
-                        ? $existing_settings[ $fldname ]
3547
-                        : $fldprops['default'],
3548
-                    'css_class'  => 'no-drag',
3549
-                    'format'     => $fldprops['format'],
3550
-                ];
3551
-            }
3552
-
3553
-
3554
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3555
-                ? $this->_generate_admin_form_fields(
3556
-                    $template_form_field,
3557
-                    'string',
3558
-                    'ee_mt_activate_form'
3559
-                )
3560
-                : '';
3561
-        }
3562
-
3563
-        $settings_template_args['description'] = $message_type->description;
3564
-        // we also need some hidden fields
3565
-        $hidden_fields = [
3566
-            'message_type_settings[messenger]' . $message_type->name    => [
3567
-                'type'  => 'hidden',
3568
-                'value' => $messenger->name,
3569
-            ],
3570
-            'message_type_settings[message_type]' . $message_type->name => [
3571
-                'type'  => 'hidden',
3572
-                'value' => $message_type->name,
3573
-            ],
3574
-            'type' . $message_type->name                                => [
3575
-                'type'  => 'hidden',
3576
-                'value' => 'message_type',
3577
-            ],
3578
-        ];
3579
-
3580
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3581
-            $hidden_fields,
3582
-            'array'
3583
-        );
3584
-        $settings_template_args['show_form']     = empty($settings_template_args['template_form_fields'])
3585
-            ? ' hidden'
3586
-            : '';
3587
-
3588
-
3589
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3590
-        return EEH_Template::display_template($template, $settings_template_args, true);
3591
-    }
3592
-
3593
-
3594
-    /**
3595
-     * Generate all the metaboxes for the message types and register them for the messages settings page.
3596
-     *
3597
-     * @access protected
3598
-     * @return void
3599
-     * @throws DomainException
3600
-     */
3601
-    protected function _messages_settings_metaboxes()
3602
-    {
3603
-        $this->_set_m_mt_settings();
3604
-        $m_boxes         = $mt_boxes = [];
3605
-        $m_template_args = $mt_template_args = [];
3606
-
3607
-        $selected_messenger = $this->request->getRequestParam('selected_messenger', 'email');
3608
-
3609
-        if (isset($this->_m_mt_settings['messenger_tabs'])) {
3610
-            foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3611
-                $is_messenger_active = $this->_message_resource_manager->is_messenger_active($messenger);
3612
-                $hide_on_message     = $is_messenger_active ? '' : 'hidden';
3613
-                $hide_off_message    = $is_messenger_active ? 'hidden' : '';
3614
-
3615
-                // messenger meta boxes
3616
-                $active         = $selected_messenger === $messenger;
3617
-                $active_mt_tabs = isset($this->_m_mt_settings['message_type_tabs'][ $messenger ]['active'])
3618
-                    ? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3619
-                    : '';
3620
-
3621
-                $m_boxes[ $messenger . '_a_box' ] = sprintf(
3622
-                    esc_html__('%s Settings', 'event_espresso'),
3623
-                    $tab_array['label']
3624
-                );
3625
-
3626
-                $m_template_args[ $messenger . '_a_box' ] = [
3627
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3628
-                    'inactive_message_types' => isset(
3629
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3630
-                    )
3631
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3632
-                        : '',
3633
-                    'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3634
-                    'hidden'                 => $active ? '' : ' hidden',
3635
-                    'hide_on_message'        => $hide_on_message,
3636
-                    'messenger'              => $messenger,
3637
-                    'active'                 => $active,
3638
-                ];
3639
-
3640
-                // message type meta boxes
3641
-                // (which is really just the inactive container for each messenger
3642
-                // showing inactive message types for that messenger)
3643
-                $mt_boxes[ $messenger . '_i_box' ]         = esc_html__('Inactive Message Types', 'event_espresso');
3644
-                $mt_template_args[ $messenger . '_i_box' ] = [
3645
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3646
-                    'inactive_message_types' => isset(
3647
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3648
-                    )
3649
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3650
-                        : '',
3651
-                    'hidden'                 => $active ? '' : ' hidden',
3652
-                    'hide_on_message'        => $hide_on_message,
3653
-                    'hide_off_message'       => $hide_off_message,
3654
-                    'messenger'              => $messenger,
3655
-                    'active'                 => $active,
3656
-                ];
3657
-            }
3658
-        }
3659
-
3660
-
3661
-        // register messenger metaboxes
3662
-        $m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3663
-        foreach ($m_boxes as $box => $label) {
3664
-            $callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]];
3665
-            $msgr          = str_replace('_a_box', '', $box);
3666
-            $this->addMetaBox(
3667
-                'espresso_' . $msgr . '_settings',
3668
-                $label,
3669
-                function ($post, $metabox) {
3670
-                    EEH_Template::display_template(
3671
-                        $metabox['args']['template_path'],
3672
-                        $metabox['args']['template_args']
3673
-                    );
3674
-                },
3675
-                $this->_current_screen->id,
3676
-                'normal',
3677
-                'high',
3678
-                $callback_args
3679
-            );
3680
-        }
3681
-
3682
-        // register message type metaboxes
3683
-        $mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3684
-        foreach ($mt_boxes as $box => $label) {
3685
-            $callback_args = [
3686
-                'template_path' => $mt_template_path,
3687
-                'template_args' => $mt_template_args[ $box ],
3688
-            ];
3689
-            $mt            = str_replace('_i_box', '', $box);
3690
-            $this->addMetaBox(
3691
-                'espresso_' . $mt . '_inactive_mts',
3692
-                $label,
3693
-                function ($post, $metabox) {
3694
-                    EEH_Template::display_template(
3695
-                        $metabox['args']['template_path'],
3696
-                        $metabox['args']['template_args']
3697
-                    );
3698
-                },
3699
-                $this->_current_screen->id,
3700
-                'side',
3701
-                'high',
3702
-                $callback_args
3703
-            );
3704
-        }
3705
-
3706
-        // register metabox for global messages settings but only when on the main site.  On single site installs this
3707
-        // will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3708
-        if (is_main_site()) {
3709
-            $this->addMetaBox(
3710
-                'espresso_global_message_settings',
3711
-                esc_html__('Global Message Settings', 'event_espresso'),
3712
-                [$this, 'global_messages_settings_metabox_content'],
3713
-                $this->_current_screen->id,
3714
-                'normal',
3715
-                'low',
3716
-                []
3717
-            );
3718
-        }
3719
-    }
3720
-
3721
-
3722
-    /**
3723
-     *  This generates the content for the global messages settings metabox.
3724
-     *
3725
-     * @return void
3726
-     * @throws EE_Error
3727
-     * @throws InvalidArgumentException
3728
-     * @throws ReflectionException
3729
-     * @throws InvalidDataTypeException
3730
-     * @throws InvalidInterfaceException
3731
-     */
3732
-    public function global_messages_settings_metabox_content()
3733
-    {
3734
-        $form = $this->_generate_global_settings_form();
3735
-        echo wp_kses(
3736
-            $form->form_open(
3737
-                $this->add_query_args_and_nonce(['action' => 'update_global_settings'], EE_MSG_ADMIN_URL),
3738
-                'POST'
3739
-            ),
3740
-            AllowedTags::getWithFormTags()
3741
-        );
3742
-        echo wp_kses($form->get_html(), AllowedTags::getWithFormTags());
3743
-        echo wp_kses($form->form_close(), AllowedTags::getWithFormTags());
3744
-    }
3745
-
3746
-
3747
-    /**
3748
-     * This generates and returns the form object for the global messages settings.
3749
-     *
3750
-     * @return EE_Form_Section_Proper
3751
-     * @throws EE_Error
3752
-     * @throws InvalidArgumentException
3753
-     * @throws ReflectionException
3754
-     * @throws InvalidDataTypeException
3755
-     * @throws InvalidInterfaceException
3756
-     */
3757
-    protected function _generate_global_settings_form()
3758
-    {
3759
-        /** @var EE_Network_Core_Config $network_config */
3760
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3761
-
3762
-        return new EE_Form_Section_Proper(
3763
-            [
3764
-                'name'            => 'global_messages_settings',
3765
-                'html_id'         => 'global_messages_settings',
3766
-                'html_class'      => 'form-table',
3767
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3768
-                'subsections'     => apply_filters(
3769
-                    'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3770
-                    [
3771
-                        'do_messages_on_same_request' => new EE_Select_Input(
3772
-                            [
3773
-                                true  => esc_html__('On the same request', 'event_espresso'),
3774
-                                false => esc_html__('On a separate request', 'event_espresso'),
3775
-                            ],
3776
-                            [
3777
-                                'default'         => $network_config->do_messages_on_same_request,
3778
-                                'html_label_text' => esc_html__(
3779
-                                    'Generate and send all messages:',
3780
-                                    'event_espresso'
3781
-                                ),
3782
-                                'html_help_text'  => esc_html__(
3783
-                                    'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3784
-                                    'event_espresso'
3785
-                                ),
3786
-                            ]
3787
-                        ),
3788
-                        'delete_threshold'            => new EE_Select_Input(
3789
-                            [
3790
-                                0  => esc_html__('Forever', 'event_espresso'),
3791
-                                3  => esc_html__('3 Months', 'event_espresso'),
3792
-                                6  => esc_html__('6 Months', 'event_espresso'),
3793
-                                9  => esc_html__('9 Months', 'event_espresso'),
3794
-                                12 => esc_html__('12 Months', 'event_espresso'),
3795
-                                24 => esc_html__('24 Months', 'event_espresso'),
3796
-                                36 => esc_html__('36 Months', 'event_espresso'),
3797
-                            ],
3798
-                            [
3799
-                                'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3800
-                                'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3801
-                                'html_help_text'  => esc_html__(
3802
-                                    'You can control how long a record of processed messages is kept via this option.',
3803
-                                    'event_espresso'
3804
-                                ),
3805
-                            ]
3806
-                        ),
3807
-                        'update_settings'             => new EE_Submit_Input(
3808
-                            [
3809
-                                'default'         => esc_html__('Update', 'event_espresso'),
3810
-                                'html_label_text' => '',
3811
-                            ]
3812
-                        ),
3813
-                    ]
3814
-                ),
3815
-            ]
3816
-        );
3817
-    }
3818
-
3819
-
3820
-    /**
3821
-     * This handles updating the global settings set on the admin page.
3822
-     *
3823
-     * @throws EE_Error
3824
-     * @throws InvalidDataTypeException
3825
-     * @throws InvalidInterfaceException
3826
-     * @throws InvalidArgumentException
3827
-     * @throws ReflectionException
3828
-     */
3829
-    protected function _update_global_settings()
3830
-    {
3831
-        /** @var EE_Network_Core_Config $network_config */
3832
-        $network_config  = EE_Registry::instance()->NET_CFG->core;
3833
-        $messages_config = EE_Registry::instance()->CFG->messages;
3834
-        $form            = $this->_generate_global_settings_form();
3835
-        if ($form->was_submitted()) {
3836
-            $form->receive_form_submission();
3837
-            if ($form->is_valid()) {
3838
-                $valid_data = $form->valid_data();
3839
-                foreach ($valid_data as $property => $value) {
3840
-                    $setter = 'set_' . $property;
3841
-                    if (method_exists($network_config, $setter)) {
3842
-                        $network_config->{$setter}($value);
3843
-                    } elseif (
3844
-                        property_exists($network_config, $property)
3845
-                        && $network_config->{$property} !== $value
3846
-                    ) {
3847
-                        $network_config->{$property} = $value;
3848
-                    } elseif (
3849
-                        property_exists($messages_config, $property)
3850
-                        && $messages_config->{$property} !== $value
3851
-                    ) {
3852
-                        $messages_config->{$property} = $value;
3853
-                    }
3854
-                }
3855
-                // only update if the form submission was valid!
3856
-                EE_Registry::instance()->NET_CFG->update_config(true, false);
3857
-                EE_Registry::instance()->CFG->update_espresso_config();
3858
-                EE_Error::overwrite_success();
3859
-                EE_Error::add_success(esc_html__('Global message settings were updated', 'event_espresso'));
3860
-            }
3861
-        }
3862
-        $this->_redirect_after_action(0, '', '', ['action' => 'settings'], true);
3863
-    }
3864
-
3865
-
3866
-    /**
3867
-     * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3868
-     *
3869
-     * @param array $tab_array This is an array of message type tab details used to generate the tabs
3870
-     * @return string html formatted tabs
3871
-     * @throws DomainException
3872
-     */
3873
-    protected function _get_mt_tabs($tab_array)
3874
-    {
3875
-        $tab_array = (array) $tab_array;
3876
-        $template  = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3877
-        $tabs      = '';
3878
-
3879
-        foreach ($tab_array as $tab) {
3880
-            $tabs .= EEH_Template::display_template($template, $tab, true);
3881
-        }
3882
-
3883
-        return $tabs;
3884
-    }
3885
-
3886
-
3887
-    /**
3888
-     * This prepares the content of the messenger meta box admin settings
3889
-     *
3890
-     * @param EE_messenger $messenger The messenger we're setting up content for
3891
-     * @return string html formatted content
3892
-     * @throws DomainException
3893
-     */
3894
-    protected function _get_messenger_box_content(EE_messenger $messenger)
3895
-    {
3896
-
3897
-        $fields                                         = $messenger->get_admin_settings_fields();
3898
-        $settings_template_args['template_form_fields'] = '';
3899
-
3900
-        // is $messenger active?
3901
-        $settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3902
-
3903
-
3904
-        if (! empty($fields)) {
3905
-            $existing_settings = $messenger->get_existing_admin_settings();
3906
-
3907
-            foreach ($fields as $fldname => $fldprops) {
3908
-                $field_id                         = $messenger->name . '-' . $fldname;
3909
-                $template_form_field[ $field_id ] = [
3910
-                    'name'       => 'messenger_settings[' . $field_id . ']',
3911
-                    'label'      => $fldprops['label'],
3912
-                    'input'      => $fldprops['field_type'],
3913
-                    'type'       => $fldprops['value_type'],
3914
-                    'required'   => $fldprops['required'],
3915
-                    'validation' => $fldprops['validation'],
3916
-                    'value'      => isset($existing_settings[ $field_id ])
3917
-                        ? $existing_settings[ $field_id ]
3918
-                        : $fldprops['default'],
3919
-                    'css_class'  => '',
3920
-                    'format'     => $fldprops['format'],
3921
-                ];
3922
-            }
3923
-
3924
-
3925
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3926
-                ? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3927
-                : '';
3928
-        }
3929
-
3930
-        // we also need some hidden fields
3931
-        $settings_template_args['hidden_fields'] = [
3932
-            'messenger_settings[messenger]' . $messenger->name => [
3933
-                'type'  => 'hidden',
3934
-                'value' => $messenger->name,
3935
-            ],
3936
-            'type' . $messenger->name                          => [
3937
-                'type'  => 'hidden',
3938
-                'value' => 'messenger',
3939
-            ],
3940
-        ];
3941
-
3942
-        // make sure any active message types that are existing are included in the hidden fields
3943
-        if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3944
-            foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3945
-                $settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = [
3946
-                    'type'  => 'hidden',
3947
-                    'value' => $mt,
3948
-                ];
3949
-            }
3950
-        }
3951
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3952
-            $settings_template_args['hidden_fields'],
3953
-            'array'
3954
-        );
3955
-        $active                                  =
3956
-            $this->_message_resource_manager->is_messenger_active($messenger->name);
3957
-
3958
-        $settings_template_args['messenger']           = $messenger->name;
3959
-        $settings_template_args['description']         = $messenger->description;
3960
-        $settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3961
-
3962
-
3963
-        $settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3964
-            $messenger->name
3965
-        )
3966
-            ? $settings_template_args['show_hide_edit_form']
3967
-            : ' hidden';
3968
-
3969
-        $settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3970
-            ? ' hidden'
3971
-            : $settings_template_args['show_hide_edit_form'];
3972
-
3973
-
3974
-        $settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3975
-        $settings_template_args['nonce']         = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3976
-        $settings_template_args['on_off_status'] = $active;
3977
-        $template                                = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3978
-        return EEH_Template::display_template(
3979
-            $template,
3980
-            $settings_template_args,
3981
-            true
3982
-        );
3983
-    }
3984
-
3985
-
3986
-    /**
3987
-     * used by ajax on the messages settings page to activate|deactivate the messenger
3988
-     *
3989
-     * @throws DomainException
3990
-     * @throws EE_Error
3991
-     * @throws InvalidDataTypeException
3992
-     * @throws InvalidInterfaceException
3993
-     * @throws InvalidArgumentException
3994
-     * @throws ReflectionException
3995
-     */
3996
-    public function activate_messenger_toggle()
3997
-    {
3998
-        $success = true;
3999
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
4000
-        // let's check that we have required data
4001
-
4002
-        if (! $this->_active_messenger_name) {
4003
-            EE_Error::add_error(
4004
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4005
-                __FILE__,
4006
-                __FUNCTION__,
4007
-                __LINE__
4008
-            );
4009
-            $success = false;
4010
-        }
4011
-
4012
-        // do a nonce check here since we're not arriving via a normal route
4013
-        $nonce     = $this->request->getRequestParam('activate_nonce', '');
4014
-        $nonce_ref = "activate_{$this->_active_messenger_name}_toggle_nonce";
4015
-
4016
-        $this->_verify_nonce($nonce, $nonce_ref);
4017
-
4018
-
4019
-        $status = $this->request->getRequestParam('status');
4020
-        if (! $status) {
4021
-            EE_Error::add_error(
4022
-                esc_html__(
4023
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4024
-                    'event_espresso'
4025
-                ),
4026
-                __FILE__,
4027
-                __FUNCTION__,
4028
-                __LINE__
4029
-            );
4030
-            $success = false;
4031
-        }
4032
-
4033
-        // do check to verify we have a valid status.
4034
-        if ($status !== 'off' && $status !== 'on') {
4035
-            EE_Error::add_error(
4036
-                sprintf(
4037
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
4038
-                    $status
4039
-                ),
4040
-                __FILE__,
4041
-                __FUNCTION__,
4042
-                __LINE__
4043
-            );
4044
-            $success = false;
4045
-        }
4046
-
4047
-        if ($success) {
4048
-            // made it here?  Stop dawdling then!!
4049
-            $success = $status === 'off'
4050
-                ? $this->_deactivate_messenger($this->_active_messenger_name)
4051
-                : $this->_activate_messenger($this->_active_messenger_name);
4052
-        }
4053
-
4054
-        $this->_template_args['success'] = $success;
4055
-
4056
-        // no special instructions so let's just do the json return (which should automatically do all the special stuff).
4057
-        $this->_return_json();
4058
-    }
4059
-
4060
-
4061
-    /**
4062
-     * used by ajax from the messages settings page to activate|deactivate a message type
4063
-     *
4064
-     * @throws DomainException
4065
-     * @throws EE_Error
4066
-     * @throws ReflectionException
4067
-     * @throws InvalidDataTypeException
4068
-     * @throws InvalidInterfaceException
4069
-     * @throws InvalidArgumentException
4070
-     */
4071
-    public function activate_mt_toggle()
4072
-    {
4073
-        $success = true;
4074
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
4075
-
4076
-        // let's make sure we have the necessary data
4077
-        if (! $this->_active_message_type_name) {
4078
-            EE_Error::add_error(
4079
-                esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
4080
-                __FILE__,
4081
-                __FUNCTION__,
4082
-                __LINE__
4083
-            );
4084
-            $success = false;
4085
-        }
4086
-
4087
-        if (! $this->_active_messenger_name) {
4088
-            EE_Error::add_error(
4089
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4090
-                __FILE__,
4091
-                __FUNCTION__,
4092
-                __LINE__
4093
-            );
4094
-            $success = false;
4095
-        }
4096
-
4097
-        $status = $this->request->getRequestParam('status');
4098
-        if (! $status) {
4099
-            EE_Error::add_error(
4100
-                esc_html__(
4101
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4102
-                    'event_espresso'
4103
-                ),
4104
-                __FILE__,
4105
-                __FUNCTION__,
4106
-                __LINE__
4107
-            );
4108
-            $success = false;
4109
-        }
4110
-
4111
-
4112
-        // do check to verify we have a valid status.
4113
-        if ($status !== 'activate' && $status !== 'deactivate') {
4114
-            EE_Error::add_error(
4115
-                sprintf(
4116
-                    esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
4117
-                    $status
4118
-                ),
4119
-                __FILE__,
4120
-                __FUNCTION__,
4121
-                __LINE__
4122
-            );
4123
-            $success = false;
4124
-        }
4125
-
4126
-
4127
-        // do a nonce check here since we're not arriving via a normal route
4128
-        $nonce = $this->request->getRequestParam('mt_nonce', '');
4129
-        $this->_verify_nonce($nonce, "{$this->_active_message_type_name}_nonce");
4130
-
4131
-        if ($success) {
4132
-            // made it here? um, what are you waiting for then?
4133
-            $success = $status === 'deactivate'
4134
-                ? $this->_deactivate_message_type_for_messenger(
4135
-                    $this->_active_messenger_name,
4136
-                    $this->_active_message_type_name
4137
-                )
4138
-                : $this->_activate_message_type_for_messenger(
4139
-                    $this->_active_messenger_name,
4140
-                    $this->_active_message_type_name
4141
-                );
4142
-        }
4143
-
4144
-        $this->_template_args['success'] = $success;
4145
-        $this->_return_json();
4146
-    }
4147
-
4148
-
4149
-    /**
4150
-     * Takes care of processing activating a messenger and preparing the appropriate response.
4151
-     *
4152
-     * @param string $messenger_name The name of the messenger being activated
4153
-     * @return bool
4154
-     * @throws DomainException
4155
-     * @throws EE_Error
4156
-     * @throws InvalidArgumentException
4157
-     * @throws ReflectionException
4158
-     * @throws InvalidDataTypeException
4159
-     * @throws InvalidInterfaceException
4160
-     */
4161
-    protected function _activate_messenger($messenger_name)
4162
-    {
4163
-        $active_messenger          = $this->_message_resource_manager->get_messenger($messenger_name);
4164
-        $message_types_to_activate = $active_messenger instanceof EE_Messenger
4165
-            ? $active_messenger->get_default_message_types()
4166
-            : [];
4167
-
4168
-        // ensure is active
4169
-        $this->_message_resource_manager->activate_messenger($active_messenger, $message_types_to_activate);
4170
-
4171
-        // set response_data for reload
4172
-        foreach ($message_types_to_activate as $message_type_name) {
4173
-            $message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4174
-            if (
4175
-                $this->_message_resource_manager->is_message_type_active_for_messenger(
4176
-                    $messenger_name,
4177
-                    $message_type_name
4178
-                )
4179
-                && $message_type instanceof EE_message_type
4180
-            ) {
4181
-                $this->_template_args['data']['active_mts'][] = $message_type_name;
4182
-                if ($message_type->get_admin_settings_fields()) {
4183
-                    $this->_template_args['data']['mt_reload'][] = $message_type_name;
4184
-                }
4185
-            }
4186
-        }
4187
-
4188
-        // add success message for activating messenger
4189
-        return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4190
-    }
4191
-
4192
-
4193
-    /**
4194
-     * Takes care of processing deactivating a messenger and preparing the appropriate response.
4195
-     *
4196
-     * @param string $messenger_name The name of the messenger being activated
4197
-     * @return bool
4198
-     * @throws DomainException
4199
-     * @throws EE_Error
4200
-     * @throws InvalidArgumentException
4201
-     * @throws ReflectionException
4202
-     * @throws InvalidDataTypeException
4203
-     * @throws InvalidInterfaceException
4204
-     */
4205
-    protected function _deactivate_messenger($messenger_name)
4206
-    {
4207
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4208
-        $this->_message_resource_manager->deactivate_messenger($messenger_name);
4209
-
4210
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4211
-    }
4212
-
4213
-
4214
-    /**
4215
-     * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4216
-     *
4217
-     * @param string $messenger_name    The name of the messenger the message type is being activated for.
4218
-     * @param string $message_type_name The name of the message type being activated for the messenger
4219
-     * @return bool
4220
-     * @throws DomainException
4221
-     * @throws EE_Error
4222
-     * @throws InvalidArgumentException
4223
-     * @throws ReflectionException
4224
-     * @throws InvalidDataTypeException
4225
-     * @throws InvalidInterfaceException
4226
-     */
4227
-    protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4228
-    {
4229
-        $active_messenger         = $this->_message_resource_manager->get_messenger($messenger_name);
4230
-        $message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4231
-
4232
-        // ensure is active
4233
-        $this->_message_resource_manager->activate_messenger($active_messenger, $message_type_name);
4234
-
4235
-        // set response for load
4236
-        if (
4237
-            $this->_message_resource_manager->is_message_type_active_for_messenger(
4238
-                $messenger_name,
4239
-                $message_type_name
4240
-            )
4241
-        ) {
4242
-            $this->_template_args['data']['active_mts'][] = $message_type_name;
4243
-            if ($message_type_to_activate->get_admin_settings_fields()) {
4244
-                $this->_template_args['data']['mt_reload'][] = $message_type_name;
4245
-            }
4246
-        }
4247
-
4248
-        return $this->_setup_response_message_for_activating_messenger_with_message_types(
4249
-            $active_messenger,
4250
-            $message_type_to_activate
4251
-        );
4252
-    }
4253
-
4254
-
4255
-    /**
4256
-     * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4257
-     *
4258
-     * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4259
-     * @param string $message_type_name The name of the message type being deactivated for the messenger
4260
-     * @return bool
4261
-     * @throws DomainException
4262
-     * @throws EE_Error
4263
-     * @throws InvalidArgumentException
4264
-     * @throws ReflectionException
4265
-     * @throws InvalidDataTypeException
4266
-     * @throws InvalidInterfaceException
4267
-     */
4268
-    protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4269
-    {
4270
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4271
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4272
-        $message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4273
-        $this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4274
-
4275
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4276
-            $active_messenger,
4277
-            $message_type_to_deactivate
4278
-        );
4279
-    }
4280
-
4281
-
4282
-    /**
4283
-     * This just initializes the defaults for activating messenger and message type responses.
4284
-     */
4285
-    protected function _prep_default_response_for_messenger_or_message_type_toggle()
4286
-    {
4287
-        $this->_template_args['data']['active_mts'] = [];
4288
-        $this->_template_args['data']['mt_reload']  = [];
4289
-    }
4290
-
4291
-
4292
-    /**
4293
-     * Setup appropriate response for activating a messenger and/or message types
4294
-     *
4295
-     * @param EE_messenger         $messenger
4296
-     * @param EE_message_type|null $message_type
4297
-     * @return bool
4298
-     * @throws DomainException
4299
-     * @throws EE_Error
4300
-     * @throws InvalidArgumentException
4301
-     * @throws ReflectionException
4302
-     * @throws InvalidDataTypeException
4303
-     * @throws InvalidInterfaceException
4304
-     */
4305
-    protected function _setup_response_message_for_activating_messenger_with_message_types(
4306
-        $messenger,
4307
-        EE_Message_Type $message_type = null
4308
-    ) {
4309
-        // if $messenger isn't a valid messenger object then get out.
4310
-        if (! $messenger instanceof EE_Messenger) {
4311
-            EE_Error::add_error(
4312
-                esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4313
-                __FILE__,
4314
-                __FUNCTION__,
4315
-                __LINE__
4316
-            );
4317
-            return false;
4318
-        }
4319
-        // activated
4320
-        if ($this->_template_args['data']['active_mts']) {
4321
-            EE_Error::overwrite_success();
4322
-            // activated a message type with the messenger
4323
-            if ($message_type instanceof EE_message_type) {
4324
-                EE_Error::add_success(
4325
-                    sprintf(
4326
-                        esc_html__(
4327
-                            '%s message type has been successfully activated with the %s messenger',
4328
-                            'event_espresso'
4329
-                        ),
4330
-                        ucwords($message_type->label['singular']),
4331
-                        ucwords($messenger->label['singular'])
4332
-                    )
4333
-                );
4334
-
4335
-                // if message type was invoice then let's make sure we activate the invoice payment method.
4336
-                if ($message_type->name === 'invoice') {
4337
-                    EE_Registry::instance()->load_lib('Payment_Method_Manager');
4338
-                    $pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4339
-                    if ($pm instanceof EE_Payment_Method) {
4340
-                        EE_Error::add_attention(
4341
-                            esc_html__(
4342
-                                'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4343
-                                'event_espresso'
4344
-                            )
4345
-                        );
4346
-                    }
4347
-                }
4348
-                // just toggles the entire messenger
4349
-            } else {
4350
-                EE_Error::add_success(
4351
-                    sprintf(
4352
-                        esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4353
-                        ucwords($messenger->label['singular'])
4354
-                    )
4355
-                );
4356
-            }
4357
-
4358
-            return true;
4359
-
4360
-            // possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4361
-            // message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4362
-            // in which case we just give a success message for the messenger being successfully activated.
4363
-        } else {
4364
-            if (! $messenger->get_default_message_types()) {
4365
-                // messenger doesn't have any default message types so still a success.
4366
-                EE_Error::add_success(
4367
-                    sprintf(
4368
-                        esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4369
-                        ucwords($messenger->label['singular'])
4370
-                    )
4371
-                );
4372
-
4373
-                return true;
4374
-            } else {
4375
-                EE_Error::add_error(
4376
-                    $message_type instanceof EE_message_type
4377
-                    ? sprintf(
4378
-                        esc_html__(
4379
-                            '%s message type was not successfully activated with the %s messenger',
4380
-                            'event_espresso'
4381
-                        ),
4382
-                        ucwords($message_type->label['singular']),
4383
-                        ucwords($messenger->label['singular'])
4384
-                    )
4385
-                    : sprintf(
4386
-                        esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4387
-                        ucwords($messenger->label['singular'])
4388
-                    ),
4389
-                    __FILE__,
4390
-                    __FUNCTION__,
4391
-                    __LINE__
4392
-                );
4393
-
4394
-                return false;
4395
-            }
4396
-        }
4397
-    }
4398
-
4399
-
4400
-    /**
4401
-     * This sets up the appropriate response for deactivating a messenger and/or message type.
4402
-     *
4403
-     * @param EE_messenger         $messenger
4404
-     * @param EE_message_type|null $message_type
4405
-     * @return bool
4406
-     * @throws DomainException
4407
-     * @throws EE_Error
4408
-     * @throws InvalidArgumentException
4409
-     * @throws ReflectionException
4410
-     * @throws InvalidDataTypeException
4411
-     * @throws InvalidInterfaceException
4412
-     */
4413
-    protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4414
-        $messenger,
4415
-        EE_message_type $message_type = null
4416
-    ) {
4417
-        EE_Error::overwrite_success();
4418
-
4419
-        // if $messenger isn't a valid messenger object then get out.
4420
-        if (! $messenger instanceof EE_Messenger) {
4421
-            EE_Error::add_error(
4422
-                esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4423
-                __FILE__,
4424
-                __FUNCTION__,
4425
-                __LINE__
4426
-            );
4427
-
4428
-            return false;
4429
-        }
4430
-
4431
-        if ($message_type instanceof EE_message_type) {
4432
-            $message_type_name = $message_type->name;
4433
-            EE_Error::add_success(
4434
-                sprintf(
4435
-                    esc_html__(
4436
-                        '%s message type has been successfully deactivated for the %s messenger.',
4437
-                        'event_espresso'
4438
-                    ),
4439
-                    ucwords($message_type->label['singular']),
4440
-                    ucwords($messenger->label['singular'])
4441
-                )
4442
-            );
4443
-        } else {
4444
-            $message_type_name = '';
4445
-            EE_Error::add_success(
4446
-                sprintf(
4447
-                    esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4448
-                    ucwords($messenger->label['singular'])
4449
-                )
4450
-            );
4451
-        }
4452
-
4453
-        // if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4454
-        if (
4455
-            $messenger->name === 'html'
4456
-            && (
4457
-                is_null($message_type)
4458
-                || $message_type_name === 'invoice'
4459
-            )
4460
-        ) {
4461
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
4462
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4463
-            if ($count_updated > 0) {
4464
-                $msg = $message_type_name === 'invoice'
4465
-                    ? esc_html__(
4466
-                        'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4467
-                        'event_espresso'
4468
-                    )
4469
-                    : esc_html__(
4470
-                        'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4471
-                        'event_espresso'
4472
-                    );
4473
-                EE_Error::add_attention($msg);
4474
-            }
4475
-        }
4476
-
4477
-        return true;
4478
-    }
4479
-
4480
-
4481
-    /**
4482
-     * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4483
-     *
4484
-     * @throws DomainException
4485
-     * @throws EE_Error
4486
-     * @throws EE_Error
4487
-     */
4488
-    public function update_mt_form()
4489
-    {
4490
-        if (! $this->_active_messenger_name || ! $this->_active_message_type_name) {
4491
-            EE_Error::add_error(
4492
-                esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4493
-                __FILE__,
4494
-                __FUNCTION__,
4495
-                __LINE__
4496
-            );
4497
-            $this->_return_json();
4498
-        }
4499
-
4500
-        $message_types = $this->get_installed_message_types();
4501
-        $message_type  = $message_types[ $this->_active_message_type_name ];
4502
-        $messenger     = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
4503
-        $content       = $this->_message_type_settings_content($message_type, $messenger, true);
4504
-
4505
-        $this->_template_args['success'] = true;
4506
-        $this->_template_args['content'] = $content;
4507
-        $this->_return_json();
4508
-    }
4509
-
4510
-
4511
-    /**
4512
-     * this handles saving the settings for a messenger or message type
4513
-     *
4514
-     * @throws EE_Error
4515
-     * @throws EE_Error
4516
-     */
4517
-    public function save_settings()
4518
-    {
4519
-        $type = $this->request->getRequestParam('type');
4520
-        if (! $type) {
4521
-            EE_Error::add_error(
4522
-                esc_html__(
4523
-                    'Cannot save settings because type is unknown (messenger settings or message type settings?)',
4524
-                    'event_espresso'
4525
-                ),
4526
-                __FILE__,
4527
-                __FUNCTION__,
4528
-                __LINE__
4529
-            );
4530
-            $this->_template_args['error'] = true;
4531
-            $this->_return_json();
4532
-        }
4533
-
4534
-
4535
-        if ($type === 'messenger') {
4536
-            // this should be an array.
4537
-            $settings  = $this->request->getRequestParam('messenger_settings', [], 'string', true);
4538
-            $messenger = $settings['messenger'];
4539
-            // remove messenger and message_types from settings array
4540
-            unset($settings['messenger'], $settings['message_types']);
4541
-            $this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4542
-        } elseif ($type === 'message_type') {
4543
-            $settings     = $this->request->getRequestParam('message_type_settings', [], 'string', true);
4544
-            $messenger    = $settings['messenger'];
4545
-            $message_type = $settings['message_type'];
4546
-            // remove messenger and message_types from settings array
4547
-            unset($settings['messenger'], $settings['message_types']);
4548
-            $this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4549
-        }
4550
-
4551
-        // okay we should have the data all setup.  Now we just update!
4552
-        $success = $this->_message_resource_manager->update_active_messengers_option();
4553
-
4554
-        if ($success) {
4555
-            EE_Error::add_success(esc_html__('Settings updated', 'event_espresso'));
4556
-        } else {
4557
-            EE_Error::add_error(
4558
-                esc_html__('Settings did not get updated', 'event_espresso'),
4559
-                __FILE__,
4560
-                __FUNCTION__,
4561
-                __LINE__
4562
-            );
4563
-        }
4564
-
4565
-        $this->_template_args['success'] = $success;
4566
-        $this->_return_json();
4567
-    }
4568
-
4569
-
4570
-
4571
-
4572
-    /**  EE MESSAGE PROCESSING ACTIONS **/
4573
-
4574
-
4575
-    /**
4576
-     * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4577
-     * However, this does not send immediately, it just queues for sending.
4578
-     *
4579
-     * @throws EE_Error
4580
-     * @throws InvalidDataTypeException
4581
-     * @throws InvalidInterfaceException
4582
-     * @throws InvalidArgumentException
4583
-     * @throws ReflectionException
4584
-     * @since 4.9.0
4585
-     */
4586
-    protected function _generate_now()
4587
-    {
4588
-        EED_Messages::generate_now($this->_get_msg_ids_from_request());
4589
-        $this->_redirect_after_action(false, '', '', [], true);
4590
-    }
4591
-
4592
-
4593
-    /**
4594
-     * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4595
-     * are EEM_Message::status_resend or EEM_Message::status_idle
4596
-     *
4597
-     * @throws EE_Error
4598
-     * @throws InvalidDataTypeException
4599
-     * @throws InvalidInterfaceException
4600
-     * @throws InvalidArgumentException
4601
-     * @throws ReflectionException
4602
-     * @since 4.9.0
4603
-     */
4604
-    protected function _generate_and_send_now()
4605
-    {
4606
-        EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4607
-        $this->_redirect_after_action(false, '', '', [], true);
4608
-    }
4609
-
4610
-
4611
-    /**
4612
-     * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4613
-     *
4614
-     * @throws EE_Error
4615
-     * @throws InvalidDataTypeException
4616
-     * @throws InvalidInterfaceException
4617
-     * @throws InvalidArgumentException
4618
-     * @throws ReflectionException
4619
-     * @since 4.9.0
4620
-     */
4621
-    protected function _queue_for_resending()
4622
-    {
4623
-        EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4624
-        $this->_redirect_after_action(false, '', '', [], true);
4625
-    }
4626
-
4627
-
4628
-    /**
4629
-     *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4630
-     *
4631
-     * @throws EE_Error
4632
-     * @throws InvalidDataTypeException
4633
-     * @throws InvalidInterfaceException
4634
-     * @throws InvalidArgumentException
4635
-     * @throws ReflectionException
4636
-     * @since 4.9.0
4637
-     */
4638
-    protected function _send_now()
4639
-    {
4640
-        EED_Messages::send_now($this->_get_msg_ids_from_request());
4641
-        $this->_redirect_after_action(false, '', '', [], true);
4642
-    }
4643
-
4644
-
4645
-    /**
4646
-     * Deletes EE_messages for IDs in the request.
4647
-     *
4648
-     * @throws EE_Error
4649
-     * @throws InvalidDataTypeException
4650
-     * @throws InvalidInterfaceException
4651
-     * @throws InvalidArgumentException
4652
-     * @since 4.9.0
4653
-     */
4654
-    protected function _delete_ee_messages()
4655
-    {
4656
-        $MSG_IDs       = $this->_get_msg_ids_from_request();
4657
-        $deleted_count = 0;
4658
-        foreach ($MSG_IDs as $MSG_ID) {
4659
-            if ($this->getMsgModel()->delete_by_ID($MSG_ID)) {
4660
-                $deleted_count++;
4661
-            }
4662
-        }
4663
-        if ($deleted_count) {
4664
-            EE_Error::add_success(
4665
-                esc_html(
4666
-                    _n(
4667
-                        'Message successfully deleted',
4668
-                        'Messages successfully deleted',
4669
-                        $deleted_count,
4670
-                        'event_espresso'
4671
-                    )
4672
-                )
4673
-            );
4674
-        } else {
4675
-            EE_Error::add_error(
4676
-                _n('The message was not deleted.', 'The messages were not deleted', count($MSG_IDs), 'event_espresso'),
4677
-                __FILE__,
4678
-                __FUNCTION__,
4679
-                __LINE__
4680
-            );
4681
-        }
4682
-        $this->_redirect_after_action(false, '', '', [], true);
4683
-    }
4684
-
4685
-
4686
-    /**
4687
-     *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4688
-     *
4689
-     * @return array
4690
-     * @since 4.9.0
4691
-     */
4692
-    protected function _get_msg_ids_from_request()
4693
-    {
4694
-        $MSG_IDs = $this->request->getRequestParam('MSG_ID', [], 'string', true);
4695
-        if (empty($MSG_IDs)) {
4696
-            return [];
4697
-        }
4698
-        // if 'MSG_ID' was just a single ID (not an array)
4699
-        // then $MSG_IDs will be something like [123] so $MSG_IDs[0] should be 123
4700
-        // otherwise, $MSG_IDs was already an array where message IDs were used as the keys
4701
-        return count($MSG_IDs) === 1 && isset($MSG_IDs[0])
4702
-            ? $MSG_IDs
4703
-            : array_keys($MSG_IDs);
4704
-    }
2713
+	}
2714
+
2715
+
2716
+	/**
2717
+	 * @param bool $new
2718
+	 * @throws EE_Error
2719
+	 * @throws ReflectionException
2720
+	 */
2721
+	protected function _insert_or_update_message_template($new = false)
2722
+	{
2723
+		$form_data    = $this->getMessageTemplateFormData();
2724
+		$GRP_ID       = $form_data['GRP_ID'];
2725
+		$messenger    = $form_data['MTP_messenger'];
2726
+		$message_type = $form_data['MTP_message_type'];
2727
+		$context      = $form_data['MTP_context'];
2728
+
2729
+		// if this is "new" then we need to generate the default contexts
2730
+		// for the selected messenger/message_type for user to edit.
2731
+		[$success, $query_args] = $new
2732
+			? $this->generateNewTemplates($GRP_ID, $messenger, $message_type)
2733
+			: $this->updateExistingTemplates($GRP_ID, $messenger, $message_type, $context, $form_data);
2734
+
2735
+		$success     = $success ? 1 : 0;
2736
+		$action_desc = $new ? 'created' : 'updated';
2737
+		$item_desc   = $this->generateUpdateDescription($messenger, $message_type, $context);
2738
+		$override    = $this->performTestSendAfterUpdate($messenger, $message_type, $context);
2739
+
2740
+		$this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
2741
+	}
2742
+
2743
+
2744
+	/**
2745
+	 * retrieve and sanitize form data
2746
+	 *
2747
+	 * @return array
2748
+	 * @since 4.10.29.p
2749
+	 */
2750
+	protected function getMessageTemplateFormData()
2751
+	{
2752
+		return [
2753
+			'GRP_ID'           => $this->request->getRequestParam('GRP_ID', 0, 'int'),
2754
+			'MTP_context'      => strtolower($this->request->getRequestParam('MTP_context', '')),
2755
+			'MTP_messenger'    => strtolower($this->request->getRequestParam('MTP_messenger', '')),
2756
+			'MTP_message_type' => strtolower($this->request->getRequestParam('MTP_message_type', '')),
2757
+			'MTP_user_id'      => $this->request->getRequestParam('MTP_user_id', 0, 'int'),
2758
+			'MTP_is_global'    => $this->request->getRequestParam('MTP_is_global', 0, 'int'),
2759
+			'MTP_is_override'  => $this->request->getRequestParam('MTP_is_override', 0, 'int'),
2760
+			'MTP_deleted'      => $this->request->getRequestParam('MTP_deleted', 0, 'int'),
2761
+			'MTP_is_active'    => $this->request->getRequestParam('MTP_is_active', 0, 'int'),
2762
+		];
2763
+	}
2764
+
2765
+
2766
+	/**
2767
+	 * @param int    $GRP_ID
2768
+	 * @param string $messenger
2769
+	 * @param string $message_type
2770
+	 * @return array no return on AJAX requests
2771
+	 * @throws EE_Error
2772
+	 * @throws ReflectionException
2773
+	 * @since 4.10.29.p
2774
+	 */
2775
+	private function generateNewTemplates($GRP_ID, $messenger, $message_type)
2776
+	{
2777
+		$new_templates = $this->_generate_new_templates($messenger, [$message_type], $GRP_ID);
2778
+		$success       = ! empty($new_templates);
2779
+
2780
+		// we return things differently if doing ajax
2781
+		if ($this->request->isAjax()) {
2782
+			$this->_template_args['success'] = $success;
2783
+			$this->_template_args['error']   = ! $success;
2784
+			$this->_template_args['content'] = '';
2785
+			$this->_template_args['data']    = [
2786
+				'grpID'        => $new_templates['GRP_ID'],
2787
+				'templateName' => $new_templates['template_name'],
2788
+			];
2789
+			if ($success) {
2790
+				EE_Error::overwrite_success();
2791
+				EE_Error::add_success(
2792
+					esc_html__(
2793
+						'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2794
+						'event_espresso'
2795
+					)
2796
+				);
2797
+			}
2798
+			$this->_return_json();
2799
+		}
2800
+		return [
2801
+			$success,
2802
+			// 'query_args'
2803
+			[
2804
+				'id'      => $new_templates['GRP_ID'],
2805
+				'context' => $new_templates['MTP_context'],
2806
+				'action'  => 'edit_message_template',
2807
+			],
2808
+		];
2809
+	}
2810
+
2811
+
2812
+	/**
2813
+	 * @param int    $GRP_ID
2814
+	 * @param string $messenger
2815
+	 * @param string $message_type
2816
+	 * @param string $context
2817
+	 * @param array  $form_data
2818
+	 * @return array
2819
+	 * @throws EE_Error
2820
+	 * @since 4.10.29.p
2821
+	 */
2822
+	private function updateExistingTemplates(
2823
+		$GRP_ID,
2824
+		$messenger,
2825
+		$message_type,
2826
+		$context,
2827
+		array $form_data
2828
+	) {
2829
+		$success         = false;
2830
+		$template_fields = $this->getTemplateFields();
2831
+		if ($template_fields) {
2832
+			// if field data is valid, then success will be true
2833
+			$success = $this->validateTemplateFields(
2834
+				$messenger,
2835
+				$message_type,
2836
+				$context,
2837
+				$template_fields
2838
+			);
2839
+			if ($success) {
2840
+				$field_data = [];
2841
+				foreach ($template_fields as $template_field => $content) {
2842
+					// combine top-level form data with content for this field
2843
+					$field_data = $this->getTemplateFieldFormData($content, $form_data);
2844
+					$success    = $this->updateMessageTemplates($template_field, $field_data) ? $success : false;
2845
+				}
2846
+				// we can use the last set_column_values for the MTPG update
2847
+				// (because its the same for all of these specific MTPs)
2848
+				$success = $this->updateMessageTemplateGroup($field_data) ? $success : false;
2849
+			}
2850
+		}
2851
+
2852
+		return [
2853
+			$success,
2854
+			// 'query_args'
2855
+			[
2856
+				'id'      => $GRP_ID,
2857
+				'context' => $context,
2858
+				'action'  => 'edit_message_template',
2859
+			],
2860
+		];
2861
+	}
2862
+
2863
+
2864
+	/**
2865
+	 * @return array
2866
+	 * @since 4.10.29.p
2867
+	 */
2868
+	private function getTemplateFields()
2869
+	{
2870
+		$template_fields = $this->request->getRequestParam('MTP_template_fields', null, 'html', true);
2871
+		if (empty($template_fields)) {
2872
+			EE_Error::add_error(
2873
+				esc_html__(
2874
+					'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2875
+					'event_espresso'
2876
+				),
2877
+				__FILE__,
2878
+				__FUNCTION__,
2879
+				__LINE__
2880
+			);
2881
+			return null;
2882
+		}
2883
+		// messages content is expected to be escaped
2884
+		return EEH_Array::addSlashesRecursively($template_fields);
2885
+	}
2886
+
2887
+
2888
+	/**
2889
+	 * @param string $messenger
2890
+	 * @param string $message_type
2891
+	 * @param string $context
2892
+	 * @param array  $template_fields
2893
+	 * @return bool
2894
+	 * @throws EE_Error
2895
+	 * @since   4.10.29.p
2896
+	 */
2897
+	private function validateTemplateFields(
2898
+		$messenger,
2899
+		$message_type,
2900
+		$context,
2901
+		array $template_fields
2902
+	) {
2903
+		// first validate all fields!
2904
+		// this filter allows client code to add its own validation to the template fields as well.
2905
+		// returning an empty array means everything passed validation.
2906
+		// errors in validation should be represented in an array with the following shape:
2907
+		// array(
2908
+		//   'fieldname' => array(
2909
+		//          'msg' => 'error message'
2910
+		//          'value' => 'value for field producing error'
2911
+		// )
2912
+		$custom_validation = (array) apply_filters(
2913
+			'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2914
+			[],
2915
+			$template_fields,
2916
+			$context,
2917
+			$messenger,
2918
+			$message_type
2919
+		);
2920
+
2921
+		$system_validation = $this->getMtgModel()->validate(
2922
+			$template_fields,
2923
+			$context,
2924
+			$messenger,
2925
+			$message_type
2926
+		);
2927
+
2928
+		$system_validation = ! is_array($system_validation) && $system_validation ? [] : $system_validation;
2929
+		$validates         = array_merge($custom_validation, $system_validation);
2930
+
2931
+		// if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2932
+		// appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2933
+		//  WE need to make sure there is no actual error messages in validates.
2934
+		if (empty($validates)) {
2935
+			return true;
2936
+		}
2937
+
2938
+		// add the transient so when the form loads we know which fields to highlight
2939
+		$this->_add_transient('edit_message_template', $validates);
2940
+		// setup notices
2941
+		foreach ($validates as $error) {
2942
+			if (isset($error['msg'])) {
2943
+				EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2944
+			}
2945
+		}
2946
+		return false;
2947
+	}
2948
+
2949
+
2950
+	/**
2951
+	 * @param array $field_data
2952
+	 * @param array $form_data
2953
+	 * @return array
2954
+	 * @since   4.10.29.p
2955
+	 */
2956
+	private function getTemplateFieldFormData(array $field_data, array $form_data)
2957
+	{
2958
+		return $form_data + [
2959
+				'MTP_ID'             => $field_data['MTP_ID'],
2960
+				'MTP_template_field' => $field_data['name'],
2961
+				// if they aren't allowed to use all JS, restrict them to standard allowed post tags
2962
+				'MTP_content'        => ! current_user_can('unfiltered_html')
2963
+					? $this->sanitizeMessageTemplateContent($field_data['content'])
2964
+					: $field_data['content'],
2965
+			];
2966
+	}
2967
+
2968
+
2969
+	/**
2970
+	 * @param string $template_field
2971
+	 * @param array  $form_data
2972
+	 * @return bool
2973
+	 * @throws EE_Error
2974
+	 * @since 4.10.29.p
2975
+	 */
2976
+	private function updateMessageTemplates($template_field, array $form_data)
2977
+	{
2978
+		$MTP_ID                  = $form_data['MTP_ID'];
2979
+		$message_template_fields = [
2980
+			'GRP_ID'             => $form_data['GRP_ID'],
2981
+			'MTP_template_field' => $form_data['MTP_template_field'],
2982
+			'MTP_context'        => $form_data['MTP_context'],
2983
+			'MTP_content'        => $form_data['MTP_content'],
2984
+		];
2985
+
2986
+		$hasMtpID = ! empty($MTP_ID);
2987
+		// if we have a MTP_ID for this field then update it, otherwise insert.
2988
+		// this has already been through the template field validator and sanitized, so it will be
2989
+		// safe to insert this field.  Why insert?  This typically happens when we introduce a new
2990
+		// message template field in a messenger/message type and existing users don't have the
2991
+		// default setup for it.
2992
+		// @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2993
+		$updated = $hasMtpID
2994
+			? $this->getMtpModel()->update($message_template_fields, [['MTP_ID' => $MTP_ID]])
2995
+			: $this->getMtpModel()->insert($message_template_fields);
2996
+
2997
+		$insert_failed = ! $hasMtpID && ! $updated;
2998
+		// updates will return 0 if the field was not changed (ie: no changes = nothing actually updated)
2999
+		// but we won't consider that a problem, but if it returns false, then something went BOOM!
3000
+		$update_failed = $hasMtpID && $updated === false;
3001
+
3002
+		if ($insert_failed || $update_failed) {
3003
+			EE_Error::add_error(
3004
+				sprintf(
3005
+					esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
3006
+					$template_field
3007
+				),
3008
+				__FILE__,
3009
+				__FUNCTION__,
3010
+				__LINE__
3011
+			);
3012
+			return false;
3013
+		}
3014
+		return true;
3015
+	}
3016
+
3017
+
3018
+	/**
3019
+	 * @param array $form_data
3020
+	 * @return bool
3021
+	 * @throws EE_Error
3022
+	 * @since 4.10.29.p
3023
+	 */
3024
+	private function updateMessageTemplateGroup(array $form_data)
3025
+	{
3026
+		$GRP_ID  = $form_data['GRP_ID'];
3027
+		$updated = $this->getMtgModel()->update(
3028
+		// fields and values
3029
+			[
3030
+				'MTP_user_id'      => $form_data['MTP_user_id'],
3031
+				'MTP_messenger'    => $form_data['MTP_messenger'],
3032
+				'MTP_message_type' => $form_data['MTP_message_type'],
3033
+				'MTP_is_global'    => $form_data['MTP_is_global'],
3034
+				'MTP_is_override'  => $form_data['MTP_is_override'],
3035
+				'MTP_deleted'      => $form_data['MTP_deleted'],
3036
+				'MTP_is_active'    => $form_data['MTP_is_active'],
3037
+				'MTP_name'         => $this->request->getRequestParam('ee_msg_non_global_fields[MTP_name]', ''),
3038
+				'MTP_description'  => $this->request->getRequestParam(
3039
+					'ee_msg_non_global_fields[MTP_description]',
3040
+					''
3041
+				),
3042
+			],
3043
+			// where
3044
+			[['GRP_ID' => $GRP_ID]]
3045
+		);
3046
+
3047
+		if ($updated === false) {
3048
+			EE_Error::add_error(
3049
+				sprintf(
3050
+					esc_html__(
3051
+						'The Message Template Group (%d) was NOT updated for some reason',
3052
+						'event_espresso'
3053
+					),
3054
+					$form_data['GRP_ID']
3055
+				),
3056
+				__FILE__,
3057
+				__FUNCTION__,
3058
+				__LINE__
3059
+			);
3060
+			return false;
3061
+		}
3062
+		// k now we need to ensure the template_pack and template_variation fields are set.
3063
+		$template_pack      = $this->request->getRequestParam('MTP_template_pack', 'default');
3064
+		$template_variation = $this->request->getRequestParam('MTP_template_variation', 'default');
3065
+
3066
+		$message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3067
+		if ($message_template_group instanceof EE_Message_Template_Group) {
3068
+			$message_template_group->set_template_pack_name($template_pack);
3069
+			$message_template_group->set_template_pack_variation($template_variation);
3070
+		}
3071
+		return true;
3072
+	}
3073
+
3074
+
3075
+	/**
3076
+	 * recursively runs wp_kses() on message template content in a model safe manner
3077
+	 *
3078
+	 * @param array|string $content
3079
+	 * @return array|string
3080
+	 * @since   4.10.29.p
3081
+	 */
3082
+	private function sanitizeMessageTemplateContent($content)
3083
+	{
3084
+		if (is_array($content)) {
3085
+			foreach ($content as $key => $value) {
3086
+				$content[ $key ] = $this->sanitizeMessageTemplateContent($value);
3087
+			}
3088
+			return $content;
3089
+		}
3090
+		// remove slashes so wp_kses() works properly
3091
+		// wp_kses_stripslashes() only removes slashes from double-quotes,
3092
+		// so attributes using single quotes always appear invalid.
3093
+		$content = stripslashes($content);
3094
+		$content = wp_kses($content, wp_kses_allowed_html('post'));
3095
+		// But currently the models expect slashed data, so after wp_kses()
3096
+		// runs we need to re-slash the data. Sheesh.
3097
+		// See https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
3098
+		return addslashes($content);
3099
+	}
3100
+
3101
+
3102
+	/**
3103
+	 * @param string $messenger
3104
+	 * @param string $message_type
3105
+	 * @param string $context
3106
+	 * @return string
3107
+	 * @since 4.10.29.p
3108
+	 */
3109
+	private function generateUpdateDescription($messenger, $message_type, $context)
3110
+	{
3111
+		// need the message type and messenger objects to be able to use the labels for the notices
3112
+		$messenger_object = $this->_message_resource_manager->get_messenger($messenger);
3113
+		$messenger_label  = $messenger_object instanceof EE_messenger
3114
+			? ucwords($messenger_object->label['singular'])
3115
+			: '';
3116
+
3117
+		$message_type_object = $this->_message_resource_manager->get_message_type($message_type);
3118
+		$message_type_label  = $message_type_object instanceof EE_message_type
3119
+			? ucwords($message_type_object->label['singular'])
3120
+			: '';
3121
+
3122
+		$context   = ucwords(str_replace('_', ' ', $context));
3123
+		$item_desc = $messenger_label && $message_type_label
3124
+			? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
3125
+			: '';
3126
+		$item_desc .= 'Message Template';
3127
+		return $item_desc;
3128
+	}
3129
+
3130
+
3131
+	/**
3132
+	 * @param string $messenger
3133
+	 * @param string $message_type
3134
+	 * @param string $context
3135
+	 * @return bool
3136
+	 * @throws EE_Error
3137
+	 * @throws ReflectionException
3138
+	 * @since 4.10.29.p
3139
+	 */
3140
+	private function performTestSendAfterUpdate($messenger, $message_type, $context)
3141
+	{
3142
+		// was a test send triggered?
3143
+		if ($this->request->requestParamIsSet('test_button')) {
3144
+			EE_Error::overwrite_success();
3145
+			$this->_do_test_send($context, $messenger, $message_type);
3146
+			return true;
3147
+		}
3148
+		return false;
3149
+	}
3150
+
3151
+
3152
+	/**
3153
+	 * processes a test send request to do an actual messenger delivery test for the given message template being tested
3154
+	 *
3155
+	 * @param string $context      what context being tested
3156
+	 * @param string $messenger    messenger being tested
3157
+	 * @param string $message_type message type being tested
3158
+	 * @throws EE_Error
3159
+	 * @throws InvalidArgumentException
3160
+	 * @throws InvalidDataTypeException
3161
+	 * @throws InvalidInterfaceException
3162
+	 * @throws ReflectionException
3163
+	 */
3164
+	protected function _do_test_send($context, $messenger, $message_type)
3165
+	{
3166
+		// set things up for preview
3167
+		$this->request->setRequestParam('messenger', $messenger);
3168
+		$this->request->setRequestParam('message_type', $message_type);
3169
+		$this->request->setRequestParam('context', $context);
3170
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
3171
+		$this->request->setRequestParam('GRP_ID', $GRP_ID);
3172
+
3173
+		$active_messenger  = $this->_message_resource_manager->get_active_messenger($messenger);
3174
+		$test_settings_fld = $this->request->getRequestParam('test_settings_fld', [], 'string', true);
3175
+
3176
+		// let's save any existing fields that might be required by the messenger
3177
+		if (
3178
+			! empty($test_settings_fld)
3179
+			&& $active_messenger instanceof EE_messenger
3180
+			&& apply_filters(
3181
+				'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3182
+				true,
3183
+				$test_settings_fld,
3184
+				$active_messenger
3185
+			)
3186
+		) {
3187
+			$active_messenger->set_existing_test_settings($test_settings_fld);
3188
+		}
3189
+
3190
+		/**
3191
+		 * Use filter to add additional controls on whether message can send or not
3192
+		 */
3193
+		if (
3194
+			apply_filters(
3195
+				'FHEE__Messages_Admin_Page__do_test_send__can_send',
3196
+				true,
3197
+				$context,
3198
+				$this->request->requestParams(),
3199
+				$messenger,
3200
+				$message_type
3201
+			)
3202
+		) {
3203
+			if (EEM_Event::instance()->count() > 0) {
3204
+				$success = $this->_preview_message(true);
3205
+				if ($success) {
3206
+					EE_Error::add_success(esc_html__('Test message sent', 'event_espresso'));
3207
+				} else {
3208
+					EE_Error::add_error(
3209
+						esc_html__('The test message was not sent', 'event_espresso'),
3210
+						__FILE__,
3211
+						__FUNCTION__,
3212
+						__LINE__
3213
+					);
3214
+				}
3215
+			} else {
3216
+				$this->noEventsErrorMessage(true);
3217
+			}
3218
+		}
3219
+	}
3220
+
3221
+
3222
+	/**
3223
+	 * _generate_new_templates
3224
+	 * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3225
+	 * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3226
+	 * for the event.
3227
+	 *
3228
+	 *
3229
+	 * @param string $messenger      the messenger we are generating templates for
3230
+	 * @param array  $message_types  array of message types that the templates are generated for.
3231
+	 * @param int    $GRP_ID         If this is a custom template being generated then a GRP_ID needs to be included to
3232
+	 *                               indicate the message_template_group being used as the base.
3233
+	 *
3234
+	 * @param bool   $global
3235
+	 *
3236
+	 * @return array|bool array of data required for the redirect to the correct edit page or bool if
3237
+	 *                               encountering problems.
3238
+	 * @throws EE_Error
3239
+	 * @throws ReflectionException
3240
+	 */
3241
+	protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3242
+	{
3243
+		// if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3244
+		// just don't generate any templates.
3245
+		if (empty($message_types)) {
3246
+			return [];
3247
+		}
3248
+
3249
+		$templates = EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3250
+		return $templates[0];
3251
+	}
3252
+
3253
+
3254
+	/**
3255
+	 * [_trash_or_restore_message_template]
3256
+	 *
3257
+	 * @param boolean $trash  whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3258
+	 * @param boolean $all    whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3259
+	 *                        an individual context (FALSE).
3260
+	 * @return void
3261
+	 * @throws EE_Error
3262
+	 * @throws InvalidArgumentException
3263
+	 * @throws InvalidDataTypeException
3264
+	 * @throws InvalidInterfaceException
3265
+	 */
3266
+	protected function _trash_or_restore_message_template($trash = true, $all = false)
3267
+	{
3268
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3269
+
3270
+		$success = 1;
3271
+
3272
+		// incoming GRP_IDs
3273
+		if ($all) {
3274
+			// Checkboxes
3275
+			$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3276
+			if (! empty($checkboxes)) {
3277
+				// if array has more than one element then success message should be plural.
3278
+				// todo: what about nonce?
3279
+				$success = count($checkboxes) > 1 ? 2 : 1;
3280
+
3281
+				// cycle through checkboxes
3282
+				while (list($GRP_ID, $value) = each($checkboxes)) {
3283
+					$trashed_or_restored = $trash
3284
+						? $this->getMtgModel()->delete_by_ID($GRP_ID)
3285
+						: $this->getMtgModel()->restore_by_ID($GRP_ID);
3286
+					if (! $trashed_or_restored) {
3287
+						$success = 0;
3288
+					}
3289
+				}
3290
+			} else {
3291
+				// grab single GRP_ID and handle
3292
+				$GRP_ID = $this->request->getRequestParam('id', 0, 'int');
3293
+				if (! empty($GRP_ID)) {
3294
+					$trashed_or_restored = $trash
3295
+						? $this->getMtgModel()->delete_by_ID($GRP_ID)
3296
+						: $this->getMtgModel()->restore_by_ID($GRP_ID);
3297
+					if (! $trashed_or_restored) {
3298
+						$success = 0;
3299
+					}
3300
+				} else {
3301
+					$success = 0;
3302
+				}
3303
+			}
3304
+		}
3305
+
3306
+		$action_desc = $trash
3307
+			? esc_html__('moved to the trash', 'event_espresso')
3308
+			: esc_html__('restored', 'event_espresso');
3309
+
3310
+		$template_switch = $this->request->getRequestParam('template_switch', false, 'bool');
3311
+		$action_desc     = $template_switch ? esc_html__('switched', 'event_espresso') : $action_desc;
3312
+
3313
+		$item_desc = $all ? _n(
3314
+			'Message Template Group',
3315
+			'Message Template Groups',
3316
+			$success,
3317
+			'event_espresso'
3318
+		) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3319
+
3320
+		$item_desc = $template_switch
3321
+			? _n('template', 'templates', $success, 'event_espresso')
3322
+			: $item_desc;
3323
+
3324
+		$this->_redirect_after_action($success, $item_desc, $action_desc, []);
3325
+	}
3326
+
3327
+
3328
+	/**
3329
+	 * [_delete_message_template]
3330
+	 * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3331
+	 *
3332
+	 * @return void
3333
+	 * @throws EE_Error
3334
+	 * @throws InvalidArgumentException
3335
+	 * @throws InvalidDataTypeException
3336
+	 * @throws InvalidInterfaceException
3337
+	 * @throws ReflectionException
3338
+	 */
3339
+	protected function _delete_message_template()
3340
+	{
3341
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3342
+
3343
+		// checkboxes
3344
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3345
+		if (! empty($checkboxes)) {
3346
+			// if array has more than one element then success message should be plural
3347
+			$success = count($checkboxes) > 1 ? 2 : 1;
3348
+
3349
+			// cycle through bulk action checkboxes
3350
+			while (list($GRP_ID, $value) = each($checkboxes)) {
3351
+				$success = $this->_delete_mtp_permanently($GRP_ID) ? $success : false;
3352
+			}
3353
+		} else {
3354
+			// grab single grp_id and delete
3355
+			$GRP_ID  = $this->request->getRequestParam('id', 0, 'int');
3356
+			$success = $this->_delete_mtp_permanently($GRP_ID);
3357
+		}
3358
+
3359
+		$this->_redirect_after_action($success, 'Message Templates', 'deleted', []);
3360
+	}
3361
+
3362
+
3363
+	/**
3364
+	 * helper for permanently deleting a mtP group and all related message_templates
3365
+	 *
3366
+	 * @param int  $GRP_ID        The group being deleted
3367
+	 * @param bool $include_group whether to delete the Message Template Group as well.
3368
+	 * @return bool boolean to indicate the success of the deletes or not.
3369
+	 * @throws EE_Error
3370
+	 * @throws InvalidArgumentException
3371
+	 * @throws InvalidDataTypeException
3372
+	 * @throws InvalidInterfaceException
3373
+	 * @throws ReflectionException
3374
+	 * @throws ReflectionException
3375
+	 */
3376
+	private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3377
+	{
3378
+		$success = true;
3379
+		// first let's GET this group
3380
+		$MTG = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3381
+		// then delete permanently all the related Message Templates
3382
+		$deleted = $MTG->delete_related_permanently('Message_Template');
3383
+
3384
+		if ($deleted === 0) {
3385
+			$success = false;
3386
+		}
3387
+
3388
+		// now delete permanently this particular group
3389
+
3390
+		if ($include_group && ! $MTG->delete_permanently()) {
3391
+			$success = false;
3392
+		}
3393
+
3394
+		return $success;
3395
+	}
3396
+
3397
+
3398
+	/**
3399
+	 *    _learn_more_about_message_templates_link
3400
+	 *
3401
+	 * @access protected
3402
+	 * @return string
3403
+	 */
3404
+	protected function _learn_more_about_message_templates_link()
3405
+	{
3406
+		return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3407
+			   . esc_html__('learn more about how message templates works', 'event_espresso')
3408
+			   . '</a>';
3409
+	}
3410
+
3411
+
3412
+	/**
3413
+	 * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3414
+	 * ajax and other routes.
3415
+	 *
3416
+	 * @return void
3417
+	 * @throws DomainException
3418
+	 * @throws EE_Error
3419
+	 */
3420
+	protected function _settings()
3421
+	{
3422
+		$this->_set_m_mt_settings();
3423
+
3424
+		// let's setup the messenger tabs
3425
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3426
+			$this->_m_mt_settings['messenger_tabs'],
3427
+			'messenger_links',
3428
+			'|',
3429
+			$this->request->getRequestParam('selected_messenger', 'email')
3430
+		);
3431
+
3432
+		$this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3433
+		$this->_template_args['after_admin_page_content']  = '</div><!-- end .ui-widget -->';
3434
+
3435
+		$this->display_admin_page_with_sidebar();
3436
+	}
3437
+
3438
+
3439
+	/**
3440
+	 * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3441
+	 *
3442
+	 * @access protected
3443
+	 * @return void
3444
+	 * @throws DomainException
3445
+	 */
3446
+	protected function _set_m_mt_settings()
3447
+	{
3448
+		// first if this is already set then lets get out no need to regenerate data.
3449
+		if (! empty($this->_m_mt_settings)) {
3450
+			return;
3451
+		}
3452
+
3453
+		// get all installed messengers and message_types
3454
+		$messengers    = $this->_message_resource_manager->installed_messengers();
3455
+		$message_types = $this->_message_resource_manager->installed_message_types();
3456
+
3457
+
3458
+		// assemble the array for the _tab_text_links helper
3459
+
3460
+		foreach ($messengers as $messenger) {
3461
+			$active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3462
+			$class = 'ee-messenger-' .  sanitize_key($messenger->label['singular']);
3463
+			$this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = [
3464
+				'label' => ucwords($messenger->label['singular']),
3465
+				'class' => $active ? "{$class} messenger-active" : $class,
3466
+				'href'  => $messenger->name,
3467
+				'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3468
+				'slug'  => $messenger->name,
3469
+				'obj'   => $messenger,
3470
+				'icon' => $active
3471
+					? '<span class="dashicons dashicons-yes-alt"></span>'
3472
+					: '<span class="dashicons dashicons-remove"></span>',
3473
+			];
3474
+
3475
+
3476
+			$message_types_for_messenger = $messenger->get_valid_message_types();
3477
+
3478
+			foreach ($message_types as $message_type) {
3479
+				// first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3480
+				// it shouldn't show in either the inactive OR active metabox.
3481
+				if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3482
+					continue;
3483
+				}
3484
+
3485
+				$a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3486
+					$messenger->name,
3487
+					$message_type->name
3488
+				)
3489
+					? 'active'
3490
+					: 'inactive';
3491
+
3492
+				$this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = [
3493
+					'label'    => ucwords($message_type->label['singular']),
3494
+					'class'    => 'message-type-' . $a_or_i,
3495
+					'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3496
+					'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3497
+					'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3498
+					'title'    => $a_or_i === 'active'
3499
+						? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3500
+						: esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3501
+					'content'  => $a_or_i === 'active'
3502
+						? $this->_message_type_settings_content($message_type, $messenger, true)
3503
+						: $this->_message_type_settings_content($message_type, $messenger),
3504
+					'slug'     => $message_type->name,
3505
+					'active'   => $a_or_i === 'active',
3506
+					'obj'      => $message_type,
3507
+				];
3508
+			}
3509
+		}
3510
+	}
3511
+
3512
+
3513
+	/**
3514
+	 * This just prepares the content for the message type settings
3515
+	 *
3516
+	 * @param EE_message_type $message_type The message type object
3517
+	 * @param EE_messenger    $messenger    The messenger object
3518
+	 * @param boolean         $active       Whether the message type is active or not
3519
+	 * @return string html output for the content
3520
+	 * @throws DomainException
3521
+	 */
3522
+	protected function _message_type_settings_content($message_type, $messenger, $active = false)
3523
+	{
3524
+		// get message type fields
3525
+		$fields                                         = $message_type->get_admin_settings_fields();
3526
+		$settings_template_args['template_form_fields'] = '';
3527
+
3528
+		if (! empty($fields) && $active) {
3529
+			$existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3530
+			foreach ($fields as $fldname => $fldprops) {
3531
+				$field_id                         = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3532
+				$template_form_field[ $field_id ] = [
3533
+					'name'       => 'message_type_settings[' . $fldname . ']',
3534
+					'label'      => $fldprops['label'],
3535
+					'input'      => $fldprops['field_type'],
3536
+					'type'       => $fldprops['value_type'],
3537
+					'required'   => $fldprops['required'],
3538
+					'validation' => $fldprops['validation'],
3539
+					'value'      => isset($existing_settings[ $fldname ])
3540
+						? $existing_settings[ $fldname ]
3541
+						: $fldprops['default'],
3542
+					'options'    => isset($fldprops['options'])
3543
+						? $fldprops['options']
3544
+						: [],
3545
+					'default'    => isset($existing_settings[ $fldname ])
3546
+						? $existing_settings[ $fldname ]
3547
+						: $fldprops['default'],
3548
+					'css_class'  => 'no-drag',
3549
+					'format'     => $fldprops['format'],
3550
+				];
3551
+			}
3552
+
3553
+
3554
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3555
+				? $this->_generate_admin_form_fields(
3556
+					$template_form_field,
3557
+					'string',
3558
+					'ee_mt_activate_form'
3559
+				)
3560
+				: '';
3561
+		}
3562
+
3563
+		$settings_template_args['description'] = $message_type->description;
3564
+		// we also need some hidden fields
3565
+		$hidden_fields = [
3566
+			'message_type_settings[messenger]' . $message_type->name    => [
3567
+				'type'  => 'hidden',
3568
+				'value' => $messenger->name,
3569
+			],
3570
+			'message_type_settings[message_type]' . $message_type->name => [
3571
+				'type'  => 'hidden',
3572
+				'value' => $message_type->name,
3573
+			],
3574
+			'type' . $message_type->name                                => [
3575
+				'type'  => 'hidden',
3576
+				'value' => 'message_type',
3577
+			],
3578
+		];
3579
+
3580
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3581
+			$hidden_fields,
3582
+			'array'
3583
+		);
3584
+		$settings_template_args['show_form']     = empty($settings_template_args['template_form_fields'])
3585
+			? ' hidden'
3586
+			: '';
3587
+
3588
+
3589
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3590
+		return EEH_Template::display_template($template, $settings_template_args, true);
3591
+	}
3592
+
3593
+
3594
+	/**
3595
+	 * Generate all the metaboxes for the message types and register them for the messages settings page.
3596
+	 *
3597
+	 * @access protected
3598
+	 * @return void
3599
+	 * @throws DomainException
3600
+	 */
3601
+	protected function _messages_settings_metaboxes()
3602
+	{
3603
+		$this->_set_m_mt_settings();
3604
+		$m_boxes         = $mt_boxes = [];
3605
+		$m_template_args = $mt_template_args = [];
3606
+
3607
+		$selected_messenger = $this->request->getRequestParam('selected_messenger', 'email');
3608
+
3609
+		if (isset($this->_m_mt_settings['messenger_tabs'])) {
3610
+			foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3611
+				$is_messenger_active = $this->_message_resource_manager->is_messenger_active($messenger);
3612
+				$hide_on_message     = $is_messenger_active ? '' : 'hidden';
3613
+				$hide_off_message    = $is_messenger_active ? 'hidden' : '';
3614
+
3615
+				// messenger meta boxes
3616
+				$active         = $selected_messenger === $messenger;
3617
+				$active_mt_tabs = isset($this->_m_mt_settings['message_type_tabs'][ $messenger ]['active'])
3618
+					? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3619
+					: '';
3620
+
3621
+				$m_boxes[ $messenger . '_a_box' ] = sprintf(
3622
+					esc_html__('%s Settings', 'event_espresso'),
3623
+					$tab_array['label']
3624
+				);
3625
+
3626
+				$m_template_args[ $messenger . '_a_box' ] = [
3627
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3628
+					'inactive_message_types' => isset(
3629
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3630
+					)
3631
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3632
+						: '',
3633
+					'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3634
+					'hidden'                 => $active ? '' : ' hidden',
3635
+					'hide_on_message'        => $hide_on_message,
3636
+					'messenger'              => $messenger,
3637
+					'active'                 => $active,
3638
+				];
3639
+
3640
+				// message type meta boxes
3641
+				// (which is really just the inactive container for each messenger
3642
+				// showing inactive message types for that messenger)
3643
+				$mt_boxes[ $messenger . '_i_box' ]         = esc_html__('Inactive Message Types', 'event_espresso');
3644
+				$mt_template_args[ $messenger . '_i_box' ] = [
3645
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3646
+					'inactive_message_types' => isset(
3647
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3648
+					)
3649
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3650
+						: '',
3651
+					'hidden'                 => $active ? '' : ' hidden',
3652
+					'hide_on_message'        => $hide_on_message,
3653
+					'hide_off_message'       => $hide_off_message,
3654
+					'messenger'              => $messenger,
3655
+					'active'                 => $active,
3656
+				];
3657
+			}
3658
+		}
3659
+
3660
+
3661
+		// register messenger metaboxes
3662
+		$m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3663
+		foreach ($m_boxes as $box => $label) {
3664
+			$callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]];
3665
+			$msgr          = str_replace('_a_box', '', $box);
3666
+			$this->addMetaBox(
3667
+				'espresso_' . $msgr . '_settings',
3668
+				$label,
3669
+				function ($post, $metabox) {
3670
+					EEH_Template::display_template(
3671
+						$metabox['args']['template_path'],
3672
+						$metabox['args']['template_args']
3673
+					);
3674
+				},
3675
+				$this->_current_screen->id,
3676
+				'normal',
3677
+				'high',
3678
+				$callback_args
3679
+			);
3680
+		}
3681
+
3682
+		// register message type metaboxes
3683
+		$mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3684
+		foreach ($mt_boxes as $box => $label) {
3685
+			$callback_args = [
3686
+				'template_path' => $mt_template_path,
3687
+				'template_args' => $mt_template_args[ $box ],
3688
+			];
3689
+			$mt            = str_replace('_i_box', '', $box);
3690
+			$this->addMetaBox(
3691
+				'espresso_' . $mt . '_inactive_mts',
3692
+				$label,
3693
+				function ($post, $metabox) {
3694
+					EEH_Template::display_template(
3695
+						$metabox['args']['template_path'],
3696
+						$metabox['args']['template_args']
3697
+					);
3698
+				},
3699
+				$this->_current_screen->id,
3700
+				'side',
3701
+				'high',
3702
+				$callback_args
3703
+			);
3704
+		}
3705
+
3706
+		// register metabox for global messages settings but only when on the main site.  On single site installs this
3707
+		// will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3708
+		if (is_main_site()) {
3709
+			$this->addMetaBox(
3710
+				'espresso_global_message_settings',
3711
+				esc_html__('Global Message Settings', 'event_espresso'),
3712
+				[$this, 'global_messages_settings_metabox_content'],
3713
+				$this->_current_screen->id,
3714
+				'normal',
3715
+				'low',
3716
+				[]
3717
+			);
3718
+		}
3719
+	}
3720
+
3721
+
3722
+	/**
3723
+	 *  This generates the content for the global messages settings metabox.
3724
+	 *
3725
+	 * @return void
3726
+	 * @throws EE_Error
3727
+	 * @throws InvalidArgumentException
3728
+	 * @throws ReflectionException
3729
+	 * @throws InvalidDataTypeException
3730
+	 * @throws InvalidInterfaceException
3731
+	 */
3732
+	public function global_messages_settings_metabox_content()
3733
+	{
3734
+		$form = $this->_generate_global_settings_form();
3735
+		echo wp_kses(
3736
+			$form->form_open(
3737
+				$this->add_query_args_and_nonce(['action' => 'update_global_settings'], EE_MSG_ADMIN_URL),
3738
+				'POST'
3739
+			),
3740
+			AllowedTags::getWithFormTags()
3741
+		);
3742
+		echo wp_kses($form->get_html(), AllowedTags::getWithFormTags());
3743
+		echo wp_kses($form->form_close(), AllowedTags::getWithFormTags());
3744
+	}
3745
+
3746
+
3747
+	/**
3748
+	 * This generates and returns the form object for the global messages settings.
3749
+	 *
3750
+	 * @return EE_Form_Section_Proper
3751
+	 * @throws EE_Error
3752
+	 * @throws InvalidArgumentException
3753
+	 * @throws ReflectionException
3754
+	 * @throws InvalidDataTypeException
3755
+	 * @throws InvalidInterfaceException
3756
+	 */
3757
+	protected function _generate_global_settings_form()
3758
+	{
3759
+		/** @var EE_Network_Core_Config $network_config */
3760
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3761
+
3762
+		return new EE_Form_Section_Proper(
3763
+			[
3764
+				'name'            => 'global_messages_settings',
3765
+				'html_id'         => 'global_messages_settings',
3766
+				'html_class'      => 'form-table',
3767
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3768
+				'subsections'     => apply_filters(
3769
+					'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3770
+					[
3771
+						'do_messages_on_same_request' => new EE_Select_Input(
3772
+							[
3773
+								true  => esc_html__('On the same request', 'event_espresso'),
3774
+								false => esc_html__('On a separate request', 'event_espresso'),
3775
+							],
3776
+							[
3777
+								'default'         => $network_config->do_messages_on_same_request,
3778
+								'html_label_text' => esc_html__(
3779
+									'Generate and send all messages:',
3780
+									'event_espresso'
3781
+								),
3782
+								'html_help_text'  => esc_html__(
3783
+									'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3784
+									'event_espresso'
3785
+								),
3786
+							]
3787
+						),
3788
+						'delete_threshold'            => new EE_Select_Input(
3789
+							[
3790
+								0  => esc_html__('Forever', 'event_espresso'),
3791
+								3  => esc_html__('3 Months', 'event_espresso'),
3792
+								6  => esc_html__('6 Months', 'event_espresso'),
3793
+								9  => esc_html__('9 Months', 'event_espresso'),
3794
+								12 => esc_html__('12 Months', 'event_espresso'),
3795
+								24 => esc_html__('24 Months', 'event_espresso'),
3796
+								36 => esc_html__('36 Months', 'event_espresso'),
3797
+							],
3798
+							[
3799
+								'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3800
+								'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3801
+								'html_help_text'  => esc_html__(
3802
+									'You can control how long a record of processed messages is kept via this option.',
3803
+									'event_espresso'
3804
+								),
3805
+							]
3806
+						),
3807
+						'update_settings'             => new EE_Submit_Input(
3808
+							[
3809
+								'default'         => esc_html__('Update', 'event_espresso'),
3810
+								'html_label_text' => '',
3811
+							]
3812
+						),
3813
+					]
3814
+				),
3815
+			]
3816
+		);
3817
+	}
3818
+
3819
+
3820
+	/**
3821
+	 * This handles updating the global settings set on the admin page.
3822
+	 *
3823
+	 * @throws EE_Error
3824
+	 * @throws InvalidDataTypeException
3825
+	 * @throws InvalidInterfaceException
3826
+	 * @throws InvalidArgumentException
3827
+	 * @throws ReflectionException
3828
+	 */
3829
+	protected function _update_global_settings()
3830
+	{
3831
+		/** @var EE_Network_Core_Config $network_config */
3832
+		$network_config  = EE_Registry::instance()->NET_CFG->core;
3833
+		$messages_config = EE_Registry::instance()->CFG->messages;
3834
+		$form            = $this->_generate_global_settings_form();
3835
+		if ($form->was_submitted()) {
3836
+			$form->receive_form_submission();
3837
+			if ($form->is_valid()) {
3838
+				$valid_data = $form->valid_data();
3839
+				foreach ($valid_data as $property => $value) {
3840
+					$setter = 'set_' . $property;
3841
+					if (method_exists($network_config, $setter)) {
3842
+						$network_config->{$setter}($value);
3843
+					} elseif (
3844
+						property_exists($network_config, $property)
3845
+						&& $network_config->{$property} !== $value
3846
+					) {
3847
+						$network_config->{$property} = $value;
3848
+					} elseif (
3849
+						property_exists($messages_config, $property)
3850
+						&& $messages_config->{$property} !== $value
3851
+					) {
3852
+						$messages_config->{$property} = $value;
3853
+					}
3854
+				}
3855
+				// only update if the form submission was valid!
3856
+				EE_Registry::instance()->NET_CFG->update_config(true, false);
3857
+				EE_Registry::instance()->CFG->update_espresso_config();
3858
+				EE_Error::overwrite_success();
3859
+				EE_Error::add_success(esc_html__('Global message settings were updated', 'event_espresso'));
3860
+			}
3861
+		}
3862
+		$this->_redirect_after_action(0, '', '', ['action' => 'settings'], true);
3863
+	}
3864
+
3865
+
3866
+	/**
3867
+	 * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3868
+	 *
3869
+	 * @param array $tab_array This is an array of message type tab details used to generate the tabs
3870
+	 * @return string html formatted tabs
3871
+	 * @throws DomainException
3872
+	 */
3873
+	protected function _get_mt_tabs($tab_array)
3874
+	{
3875
+		$tab_array = (array) $tab_array;
3876
+		$template  = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3877
+		$tabs      = '';
3878
+
3879
+		foreach ($tab_array as $tab) {
3880
+			$tabs .= EEH_Template::display_template($template, $tab, true);
3881
+		}
3882
+
3883
+		return $tabs;
3884
+	}
3885
+
3886
+
3887
+	/**
3888
+	 * This prepares the content of the messenger meta box admin settings
3889
+	 *
3890
+	 * @param EE_messenger $messenger The messenger we're setting up content for
3891
+	 * @return string html formatted content
3892
+	 * @throws DomainException
3893
+	 */
3894
+	protected function _get_messenger_box_content(EE_messenger $messenger)
3895
+	{
3896
+
3897
+		$fields                                         = $messenger->get_admin_settings_fields();
3898
+		$settings_template_args['template_form_fields'] = '';
3899
+
3900
+		// is $messenger active?
3901
+		$settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3902
+
3903
+
3904
+		if (! empty($fields)) {
3905
+			$existing_settings = $messenger->get_existing_admin_settings();
3906
+
3907
+			foreach ($fields as $fldname => $fldprops) {
3908
+				$field_id                         = $messenger->name . '-' . $fldname;
3909
+				$template_form_field[ $field_id ] = [
3910
+					'name'       => 'messenger_settings[' . $field_id . ']',
3911
+					'label'      => $fldprops['label'],
3912
+					'input'      => $fldprops['field_type'],
3913
+					'type'       => $fldprops['value_type'],
3914
+					'required'   => $fldprops['required'],
3915
+					'validation' => $fldprops['validation'],
3916
+					'value'      => isset($existing_settings[ $field_id ])
3917
+						? $existing_settings[ $field_id ]
3918
+						: $fldprops['default'],
3919
+					'css_class'  => '',
3920
+					'format'     => $fldprops['format'],
3921
+				];
3922
+			}
3923
+
3924
+
3925
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3926
+				? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3927
+				: '';
3928
+		}
3929
+
3930
+		// we also need some hidden fields
3931
+		$settings_template_args['hidden_fields'] = [
3932
+			'messenger_settings[messenger]' . $messenger->name => [
3933
+				'type'  => 'hidden',
3934
+				'value' => $messenger->name,
3935
+			],
3936
+			'type' . $messenger->name                          => [
3937
+				'type'  => 'hidden',
3938
+				'value' => 'messenger',
3939
+			],
3940
+		];
3941
+
3942
+		// make sure any active message types that are existing are included in the hidden fields
3943
+		if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3944
+			foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3945
+				$settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = [
3946
+					'type'  => 'hidden',
3947
+					'value' => $mt,
3948
+				];
3949
+			}
3950
+		}
3951
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3952
+			$settings_template_args['hidden_fields'],
3953
+			'array'
3954
+		);
3955
+		$active                                  =
3956
+			$this->_message_resource_manager->is_messenger_active($messenger->name);
3957
+
3958
+		$settings_template_args['messenger']           = $messenger->name;
3959
+		$settings_template_args['description']         = $messenger->description;
3960
+		$settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3961
+
3962
+
3963
+		$settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3964
+			$messenger->name
3965
+		)
3966
+			? $settings_template_args['show_hide_edit_form']
3967
+			: ' hidden';
3968
+
3969
+		$settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3970
+			? ' hidden'
3971
+			: $settings_template_args['show_hide_edit_form'];
3972
+
3973
+
3974
+		$settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3975
+		$settings_template_args['nonce']         = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3976
+		$settings_template_args['on_off_status'] = $active;
3977
+		$template                                = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3978
+		return EEH_Template::display_template(
3979
+			$template,
3980
+			$settings_template_args,
3981
+			true
3982
+		);
3983
+	}
3984
+
3985
+
3986
+	/**
3987
+	 * used by ajax on the messages settings page to activate|deactivate the messenger
3988
+	 *
3989
+	 * @throws DomainException
3990
+	 * @throws EE_Error
3991
+	 * @throws InvalidDataTypeException
3992
+	 * @throws InvalidInterfaceException
3993
+	 * @throws InvalidArgumentException
3994
+	 * @throws ReflectionException
3995
+	 */
3996
+	public function activate_messenger_toggle()
3997
+	{
3998
+		$success = true;
3999
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
4000
+		// let's check that we have required data
4001
+
4002
+		if (! $this->_active_messenger_name) {
4003
+			EE_Error::add_error(
4004
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4005
+				__FILE__,
4006
+				__FUNCTION__,
4007
+				__LINE__
4008
+			);
4009
+			$success = false;
4010
+		}
4011
+
4012
+		// do a nonce check here since we're not arriving via a normal route
4013
+		$nonce     = $this->request->getRequestParam('activate_nonce', '');
4014
+		$nonce_ref = "activate_{$this->_active_messenger_name}_toggle_nonce";
4015
+
4016
+		$this->_verify_nonce($nonce, $nonce_ref);
4017
+
4018
+
4019
+		$status = $this->request->getRequestParam('status');
4020
+		if (! $status) {
4021
+			EE_Error::add_error(
4022
+				esc_html__(
4023
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4024
+					'event_espresso'
4025
+				),
4026
+				__FILE__,
4027
+				__FUNCTION__,
4028
+				__LINE__
4029
+			);
4030
+			$success = false;
4031
+		}
4032
+
4033
+		// do check to verify we have a valid status.
4034
+		if ($status !== 'off' && $status !== 'on') {
4035
+			EE_Error::add_error(
4036
+				sprintf(
4037
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
4038
+					$status
4039
+				),
4040
+				__FILE__,
4041
+				__FUNCTION__,
4042
+				__LINE__
4043
+			);
4044
+			$success = false;
4045
+		}
4046
+
4047
+		if ($success) {
4048
+			// made it here?  Stop dawdling then!!
4049
+			$success = $status === 'off'
4050
+				? $this->_deactivate_messenger($this->_active_messenger_name)
4051
+				: $this->_activate_messenger($this->_active_messenger_name);
4052
+		}
4053
+
4054
+		$this->_template_args['success'] = $success;
4055
+
4056
+		// no special instructions so let's just do the json return (which should automatically do all the special stuff).
4057
+		$this->_return_json();
4058
+	}
4059
+
4060
+
4061
+	/**
4062
+	 * used by ajax from the messages settings page to activate|deactivate a message type
4063
+	 *
4064
+	 * @throws DomainException
4065
+	 * @throws EE_Error
4066
+	 * @throws ReflectionException
4067
+	 * @throws InvalidDataTypeException
4068
+	 * @throws InvalidInterfaceException
4069
+	 * @throws InvalidArgumentException
4070
+	 */
4071
+	public function activate_mt_toggle()
4072
+	{
4073
+		$success = true;
4074
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
4075
+
4076
+		// let's make sure we have the necessary data
4077
+		if (! $this->_active_message_type_name) {
4078
+			EE_Error::add_error(
4079
+				esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
4080
+				__FILE__,
4081
+				__FUNCTION__,
4082
+				__LINE__
4083
+			);
4084
+			$success = false;
4085
+		}
4086
+
4087
+		if (! $this->_active_messenger_name) {
4088
+			EE_Error::add_error(
4089
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4090
+				__FILE__,
4091
+				__FUNCTION__,
4092
+				__LINE__
4093
+			);
4094
+			$success = false;
4095
+		}
4096
+
4097
+		$status = $this->request->getRequestParam('status');
4098
+		if (! $status) {
4099
+			EE_Error::add_error(
4100
+				esc_html__(
4101
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4102
+					'event_espresso'
4103
+				),
4104
+				__FILE__,
4105
+				__FUNCTION__,
4106
+				__LINE__
4107
+			);
4108
+			$success = false;
4109
+		}
4110
+
4111
+
4112
+		// do check to verify we have a valid status.
4113
+		if ($status !== 'activate' && $status !== 'deactivate') {
4114
+			EE_Error::add_error(
4115
+				sprintf(
4116
+					esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
4117
+					$status
4118
+				),
4119
+				__FILE__,
4120
+				__FUNCTION__,
4121
+				__LINE__
4122
+			);
4123
+			$success = false;
4124
+		}
4125
+
4126
+
4127
+		// do a nonce check here since we're not arriving via a normal route
4128
+		$nonce = $this->request->getRequestParam('mt_nonce', '');
4129
+		$this->_verify_nonce($nonce, "{$this->_active_message_type_name}_nonce");
4130
+
4131
+		if ($success) {
4132
+			// made it here? um, what are you waiting for then?
4133
+			$success = $status === 'deactivate'
4134
+				? $this->_deactivate_message_type_for_messenger(
4135
+					$this->_active_messenger_name,
4136
+					$this->_active_message_type_name
4137
+				)
4138
+				: $this->_activate_message_type_for_messenger(
4139
+					$this->_active_messenger_name,
4140
+					$this->_active_message_type_name
4141
+				);
4142
+		}
4143
+
4144
+		$this->_template_args['success'] = $success;
4145
+		$this->_return_json();
4146
+	}
4147
+
4148
+
4149
+	/**
4150
+	 * Takes care of processing activating a messenger and preparing the appropriate response.
4151
+	 *
4152
+	 * @param string $messenger_name The name of the messenger being activated
4153
+	 * @return bool
4154
+	 * @throws DomainException
4155
+	 * @throws EE_Error
4156
+	 * @throws InvalidArgumentException
4157
+	 * @throws ReflectionException
4158
+	 * @throws InvalidDataTypeException
4159
+	 * @throws InvalidInterfaceException
4160
+	 */
4161
+	protected function _activate_messenger($messenger_name)
4162
+	{
4163
+		$active_messenger          = $this->_message_resource_manager->get_messenger($messenger_name);
4164
+		$message_types_to_activate = $active_messenger instanceof EE_Messenger
4165
+			? $active_messenger->get_default_message_types()
4166
+			: [];
4167
+
4168
+		// ensure is active
4169
+		$this->_message_resource_manager->activate_messenger($active_messenger, $message_types_to_activate);
4170
+
4171
+		// set response_data for reload
4172
+		foreach ($message_types_to_activate as $message_type_name) {
4173
+			$message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4174
+			if (
4175
+				$this->_message_resource_manager->is_message_type_active_for_messenger(
4176
+					$messenger_name,
4177
+					$message_type_name
4178
+				)
4179
+				&& $message_type instanceof EE_message_type
4180
+			) {
4181
+				$this->_template_args['data']['active_mts'][] = $message_type_name;
4182
+				if ($message_type->get_admin_settings_fields()) {
4183
+					$this->_template_args['data']['mt_reload'][] = $message_type_name;
4184
+				}
4185
+			}
4186
+		}
4187
+
4188
+		// add success message for activating messenger
4189
+		return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4190
+	}
4191
+
4192
+
4193
+	/**
4194
+	 * Takes care of processing deactivating a messenger and preparing the appropriate response.
4195
+	 *
4196
+	 * @param string $messenger_name The name of the messenger being activated
4197
+	 * @return bool
4198
+	 * @throws DomainException
4199
+	 * @throws EE_Error
4200
+	 * @throws InvalidArgumentException
4201
+	 * @throws ReflectionException
4202
+	 * @throws InvalidDataTypeException
4203
+	 * @throws InvalidInterfaceException
4204
+	 */
4205
+	protected function _deactivate_messenger($messenger_name)
4206
+	{
4207
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4208
+		$this->_message_resource_manager->deactivate_messenger($messenger_name);
4209
+
4210
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4211
+	}
4212
+
4213
+
4214
+	/**
4215
+	 * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4216
+	 *
4217
+	 * @param string $messenger_name    The name of the messenger the message type is being activated for.
4218
+	 * @param string $message_type_name The name of the message type being activated for the messenger
4219
+	 * @return bool
4220
+	 * @throws DomainException
4221
+	 * @throws EE_Error
4222
+	 * @throws InvalidArgumentException
4223
+	 * @throws ReflectionException
4224
+	 * @throws InvalidDataTypeException
4225
+	 * @throws InvalidInterfaceException
4226
+	 */
4227
+	protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4228
+	{
4229
+		$active_messenger         = $this->_message_resource_manager->get_messenger($messenger_name);
4230
+		$message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4231
+
4232
+		// ensure is active
4233
+		$this->_message_resource_manager->activate_messenger($active_messenger, $message_type_name);
4234
+
4235
+		// set response for load
4236
+		if (
4237
+			$this->_message_resource_manager->is_message_type_active_for_messenger(
4238
+				$messenger_name,
4239
+				$message_type_name
4240
+			)
4241
+		) {
4242
+			$this->_template_args['data']['active_mts'][] = $message_type_name;
4243
+			if ($message_type_to_activate->get_admin_settings_fields()) {
4244
+				$this->_template_args['data']['mt_reload'][] = $message_type_name;
4245
+			}
4246
+		}
4247
+
4248
+		return $this->_setup_response_message_for_activating_messenger_with_message_types(
4249
+			$active_messenger,
4250
+			$message_type_to_activate
4251
+		);
4252
+	}
4253
+
4254
+
4255
+	/**
4256
+	 * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4257
+	 *
4258
+	 * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4259
+	 * @param string $message_type_name The name of the message type being deactivated for the messenger
4260
+	 * @return bool
4261
+	 * @throws DomainException
4262
+	 * @throws EE_Error
4263
+	 * @throws InvalidArgumentException
4264
+	 * @throws ReflectionException
4265
+	 * @throws InvalidDataTypeException
4266
+	 * @throws InvalidInterfaceException
4267
+	 */
4268
+	protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4269
+	{
4270
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4271
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4272
+		$message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4273
+		$this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4274
+
4275
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4276
+			$active_messenger,
4277
+			$message_type_to_deactivate
4278
+		);
4279
+	}
4280
+
4281
+
4282
+	/**
4283
+	 * This just initializes the defaults for activating messenger and message type responses.
4284
+	 */
4285
+	protected function _prep_default_response_for_messenger_or_message_type_toggle()
4286
+	{
4287
+		$this->_template_args['data']['active_mts'] = [];
4288
+		$this->_template_args['data']['mt_reload']  = [];
4289
+	}
4290
+
4291
+
4292
+	/**
4293
+	 * Setup appropriate response for activating a messenger and/or message types
4294
+	 *
4295
+	 * @param EE_messenger         $messenger
4296
+	 * @param EE_message_type|null $message_type
4297
+	 * @return bool
4298
+	 * @throws DomainException
4299
+	 * @throws EE_Error
4300
+	 * @throws InvalidArgumentException
4301
+	 * @throws ReflectionException
4302
+	 * @throws InvalidDataTypeException
4303
+	 * @throws InvalidInterfaceException
4304
+	 */
4305
+	protected function _setup_response_message_for_activating_messenger_with_message_types(
4306
+		$messenger,
4307
+		EE_Message_Type $message_type = null
4308
+	) {
4309
+		// if $messenger isn't a valid messenger object then get out.
4310
+		if (! $messenger instanceof EE_Messenger) {
4311
+			EE_Error::add_error(
4312
+				esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4313
+				__FILE__,
4314
+				__FUNCTION__,
4315
+				__LINE__
4316
+			);
4317
+			return false;
4318
+		}
4319
+		// activated
4320
+		if ($this->_template_args['data']['active_mts']) {
4321
+			EE_Error::overwrite_success();
4322
+			// activated a message type with the messenger
4323
+			if ($message_type instanceof EE_message_type) {
4324
+				EE_Error::add_success(
4325
+					sprintf(
4326
+						esc_html__(
4327
+							'%s message type has been successfully activated with the %s messenger',
4328
+							'event_espresso'
4329
+						),
4330
+						ucwords($message_type->label['singular']),
4331
+						ucwords($messenger->label['singular'])
4332
+					)
4333
+				);
4334
+
4335
+				// if message type was invoice then let's make sure we activate the invoice payment method.
4336
+				if ($message_type->name === 'invoice') {
4337
+					EE_Registry::instance()->load_lib('Payment_Method_Manager');
4338
+					$pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4339
+					if ($pm instanceof EE_Payment_Method) {
4340
+						EE_Error::add_attention(
4341
+							esc_html__(
4342
+								'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4343
+								'event_espresso'
4344
+							)
4345
+						);
4346
+					}
4347
+				}
4348
+				// just toggles the entire messenger
4349
+			} else {
4350
+				EE_Error::add_success(
4351
+					sprintf(
4352
+						esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4353
+						ucwords($messenger->label['singular'])
4354
+					)
4355
+				);
4356
+			}
4357
+
4358
+			return true;
4359
+
4360
+			// possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4361
+			// message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4362
+			// in which case we just give a success message for the messenger being successfully activated.
4363
+		} else {
4364
+			if (! $messenger->get_default_message_types()) {
4365
+				// messenger doesn't have any default message types so still a success.
4366
+				EE_Error::add_success(
4367
+					sprintf(
4368
+						esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4369
+						ucwords($messenger->label['singular'])
4370
+					)
4371
+				);
4372
+
4373
+				return true;
4374
+			} else {
4375
+				EE_Error::add_error(
4376
+					$message_type instanceof EE_message_type
4377
+					? sprintf(
4378
+						esc_html__(
4379
+							'%s message type was not successfully activated with the %s messenger',
4380
+							'event_espresso'
4381
+						),
4382
+						ucwords($message_type->label['singular']),
4383
+						ucwords($messenger->label['singular'])
4384
+					)
4385
+					: sprintf(
4386
+						esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4387
+						ucwords($messenger->label['singular'])
4388
+					),
4389
+					__FILE__,
4390
+					__FUNCTION__,
4391
+					__LINE__
4392
+				);
4393
+
4394
+				return false;
4395
+			}
4396
+		}
4397
+	}
4398
+
4399
+
4400
+	/**
4401
+	 * This sets up the appropriate response for deactivating a messenger and/or message type.
4402
+	 *
4403
+	 * @param EE_messenger         $messenger
4404
+	 * @param EE_message_type|null $message_type
4405
+	 * @return bool
4406
+	 * @throws DomainException
4407
+	 * @throws EE_Error
4408
+	 * @throws InvalidArgumentException
4409
+	 * @throws ReflectionException
4410
+	 * @throws InvalidDataTypeException
4411
+	 * @throws InvalidInterfaceException
4412
+	 */
4413
+	protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4414
+		$messenger,
4415
+		EE_message_type $message_type = null
4416
+	) {
4417
+		EE_Error::overwrite_success();
4418
+
4419
+		// if $messenger isn't a valid messenger object then get out.
4420
+		if (! $messenger instanceof EE_Messenger) {
4421
+			EE_Error::add_error(
4422
+				esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4423
+				__FILE__,
4424
+				__FUNCTION__,
4425
+				__LINE__
4426
+			);
4427
+
4428
+			return false;
4429
+		}
4430
+
4431
+		if ($message_type instanceof EE_message_type) {
4432
+			$message_type_name = $message_type->name;
4433
+			EE_Error::add_success(
4434
+				sprintf(
4435
+					esc_html__(
4436
+						'%s message type has been successfully deactivated for the %s messenger.',
4437
+						'event_espresso'
4438
+					),
4439
+					ucwords($message_type->label['singular']),
4440
+					ucwords($messenger->label['singular'])
4441
+				)
4442
+			);
4443
+		} else {
4444
+			$message_type_name = '';
4445
+			EE_Error::add_success(
4446
+				sprintf(
4447
+					esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4448
+					ucwords($messenger->label['singular'])
4449
+				)
4450
+			);
4451
+		}
4452
+
4453
+		// if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4454
+		if (
4455
+			$messenger->name === 'html'
4456
+			&& (
4457
+				is_null($message_type)
4458
+				|| $message_type_name === 'invoice'
4459
+			)
4460
+		) {
4461
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
4462
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4463
+			if ($count_updated > 0) {
4464
+				$msg = $message_type_name === 'invoice'
4465
+					? esc_html__(
4466
+						'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4467
+						'event_espresso'
4468
+					)
4469
+					: esc_html__(
4470
+						'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4471
+						'event_espresso'
4472
+					);
4473
+				EE_Error::add_attention($msg);
4474
+			}
4475
+		}
4476
+
4477
+		return true;
4478
+	}
4479
+
4480
+
4481
+	/**
4482
+	 * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4483
+	 *
4484
+	 * @throws DomainException
4485
+	 * @throws EE_Error
4486
+	 * @throws EE_Error
4487
+	 */
4488
+	public function update_mt_form()
4489
+	{
4490
+		if (! $this->_active_messenger_name || ! $this->_active_message_type_name) {
4491
+			EE_Error::add_error(
4492
+				esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4493
+				__FILE__,
4494
+				__FUNCTION__,
4495
+				__LINE__
4496
+			);
4497
+			$this->_return_json();
4498
+		}
4499
+
4500
+		$message_types = $this->get_installed_message_types();
4501
+		$message_type  = $message_types[ $this->_active_message_type_name ];
4502
+		$messenger     = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
4503
+		$content       = $this->_message_type_settings_content($message_type, $messenger, true);
4504
+
4505
+		$this->_template_args['success'] = true;
4506
+		$this->_template_args['content'] = $content;
4507
+		$this->_return_json();
4508
+	}
4509
+
4510
+
4511
+	/**
4512
+	 * this handles saving the settings for a messenger or message type
4513
+	 *
4514
+	 * @throws EE_Error
4515
+	 * @throws EE_Error
4516
+	 */
4517
+	public function save_settings()
4518
+	{
4519
+		$type = $this->request->getRequestParam('type');
4520
+		if (! $type) {
4521
+			EE_Error::add_error(
4522
+				esc_html__(
4523
+					'Cannot save settings because type is unknown (messenger settings or message type settings?)',
4524
+					'event_espresso'
4525
+				),
4526
+				__FILE__,
4527
+				__FUNCTION__,
4528
+				__LINE__
4529
+			);
4530
+			$this->_template_args['error'] = true;
4531
+			$this->_return_json();
4532
+		}
4533
+
4534
+
4535
+		if ($type === 'messenger') {
4536
+			// this should be an array.
4537
+			$settings  = $this->request->getRequestParam('messenger_settings', [], 'string', true);
4538
+			$messenger = $settings['messenger'];
4539
+			// remove messenger and message_types from settings array
4540
+			unset($settings['messenger'], $settings['message_types']);
4541
+			$this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4542
+		} elseif ($type === 'message_type') {
4543
+			$settings     = $this->request->getRequestParam('message_type_settings', [], 'string', true);
4544
+			$messenger    = $settings['messenger'];
4545
+			$message_type = $settings['message_type'];
4546
+			// remove messenger and message_types from settings array
4547
+			unset($settings['messenger'], $settings['message_types']);
4548
+			$this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4549
+		}
4550
+
4551
+		// okay we should have the data all setup.  Now we just update!
4552
+		$success = $this->_message_resource_manager->update_active_messengers_option();
4553
+
4554
+		if ($success) {
4555
+			EE_Error::add_success(esc_html__('Settings updated', 'event_espresso'));
4556
+		} else {
4557
+			EE_Error::add_error(
4558
+				esc_html__('Settings did not get updated', 'event_espresso'),
4559
+				__FILE__,
4560
+				__FUNCTION__,
4561
+				__LINE__
4562
+			);
4563
+		}
4564
+
4565
+		$this->_template_args['success'] = $success;
4566
+		$this->_return_json();
4567
+	}
4568
+
4569
+
4570
+
4571
+
4572
+	/**  EE MESSAGE PROCESSING ACTIONS **/
4573
+
4574
+
4575
+	/**
4576
+	 * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4577
+	 * However, this does not send immediately, it just queues for sending.
4578
+	 *
4579
+	 * @throws EE_Error
4580
+	 * @throws InvalidDataTypeException
4581
+	 * @throws InvalidInterfaceException
4582
+	 * @throws InvalidArgumentException
4583
+	 * @throws ReflectionException
4584
+	 * @since 4.9.0
4585
+	 */
4586
+	protected function _generate_now()
4587
+	{
4588
+		EED_Messages::generate_now($this->_get_msg_ids_from_request());
4589
+		$this->_redirect_after_action(false, '', '', [], true);
4590
+	}
4591
+
4592
+
4593
+	/**
4594
+	 * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4595
+	 * are EEM_Message::status_resend or EEM_Message::status_idle
4596
+	 *
4597
+	 * @throws EE_Error
4598
+	 * @throws InvalidDataTypeException
4599
+	 * @throws InvalidInterfaceException
4600
+	 * @throws InvalidArgumentException
4601
+	 * @throws ReflectionException
4602
+	 * @since 4.9.0
4603
+	 */
4604
+	protected function _generate_and_send_now()
4605
+	{
4606
+		EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4607
+		$this->_redirect_after_action(false, '', '', [], true);
4608
+	}
4609
+
4610
+
4611
+	/**
4612
+	 * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4613
+	 *
4614
+	 * @throws EE_Error
4615
+	 * @throws InvalidDataTypeException
4616
+	 * @throws InvalidInterfaceException
4617
+	 * @throws InvalidArgumentException
4618
+	 * @throws ReflectionException
4619
+	 * @since 4.9.0
4620
+	 */
4621
+	protected function _queue_for_resending()
4622
+	{
4623
+		EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4624
+		$this->_redirect_after_action(false, '', '', [], true);
4625
+	}
4626
+
4627
+
4628
+	/**
4629
+	 *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4630
+	 *
4631
+	 * @throws EE_Error
4632
+	 * @throws InvalidDataTypeException
4633
+	 * @throws InvalidInterfaceException
4634
+	 * @throws InvalidArgumentException
4635
+	 * @throws ReflectionException
4636
+	 * @since 4.9.0
4637
+	 */
4638
+	protected function _send_now()
4639
+	{
4640
+		EED_Messages::send_now($this->_get_msg_ids_from_request());
4641
+		$this->_redirect_after_action(false, '', '', [], true);
4642
+	}
4643
+
4644
+
4645
+	/**
4646
+	 * Deletes EE_messages for IDs in the request.
4647
+	 *
4648
+	 * @throws EE_Error
4649
+	 * @throws InvalidDataTypeException
4650
+	 * @throws InvalidInterfaceException
4651
+	 * @throws InvalidArgumentException
4652
+	 * @since 4.9.0
4653
+	 */
4654
+	protected function _delete_ee_messages()
4655
+	{
4656
+		$MSG_IDs       = $this->_get_msg_ids_from_request();
4657
+		$deleted_count = 0;
4658
+		foreach ($MSG_IDs as $MSG_ID) {
4659
+			if ($this->getMsgModel()->delete_by_ID($MSG_ID)) {
4660
+				$deleted_count++;
4661
+			}
4662
+		}
4663
+		if ($deleted_count) {
4664
+			EE_Error::add_success(
4665
+				esc_html(
4666
+					_n(
4667
+						'Message successfully deleted',
4668
+						'Messages successfully deleted',
4669
+						$deleted_count,
4670
+						'event_espresso'
4671
+					)
4672
+				)
4673
+			);
4674
+		} else {
4675
+			EE_Error::add_error(
4676
+				_n('The message was not deleted.', 'The messages were not deleted', count($MSG_IDs), 'event_espresso'),
4677
+				__FILE__,
4678
+				__FUNCTION__,
4679
+				__LINE__
4680
+			);
4681
+		}
4682
+		$this->_redirect_after_action(false, '', '', [], true);
4683
+	}
4684
+
4685
+
4686
+	/**
4687
+	 *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4688
+	 *
4689
+	 * @return array
4690
+	 * @since 4.9.0
4691
+	 */
4692
+	protected function _get_msg_ids_from_request()
4693
+	{
4694
+		$MSG_IDs = $this->request->getRequestParam('MSG_ID', [], 'string', true);
4695
+		if (empty($MSG_IDs)) {
4696
+			return [];
4697
+		}
4698
+		// if 'MSG_ID' was just a single ID (not an array)
4699
+		// then $MSG_IDs will be something like [123] so $MSG_IDs[0] should be 123
4700
+		// otherwise, $MSG_IDs was already an array where message IDs were used as the keys
4701
+		return count($MSG_IDs) === 1 && isset($MSG_IDs[0])
4702
+			? $MSG_IDs
4703
+			: array_keys($MSG_IDs);
4704
+	}
4705 4705
 }
Please login to merge, or discard this patch.