Completed
Pull Request — master (#938)
by Darren
14:34
created
admin_pages/registrations/EE_Registrations_List_Table.class.php 2 patches
Indentation   +965 added lines, -965 removed lines patch added patch discarded remove patch
@@ -24,1046 +24,1046 @@
 block discarded – undo
24 24
 {
25 25
 
26 26
 
27
-    /**
28
-     * @var array
29
-     */
30
-    private $_status;
27
+	/**
28
+	 * @var array
29
+	 */
30
+	private $_status;
31 31
 
32 32
 
33
-    /**
34
-     * An array of transaction details for the related transaction to the registration being processed.
35
-     * This is set via the _set_related_details method.
36
-     *
37
-     * @var array
38
-     */
39
-    protected $_transaction_details = array();
33
+	/**
34
+	 * An array of transaction details for the related transaction to the registration being processed.
35
+	 * This is set via the _set_related_details method.
36
+	 *
37
+	 * @var array
38
+	 */
39
+	protected $_transaction_details = array();
40 40
 
41 41
 
42
-    /**
43
-     * An array of event details for the related event to the registration being processed.
44
-     * This is set via the _set_related_details method.
45
-     *
46
-     * @var array
47
-     */
48
-    protected $_event_details = array();
42
+	/**
43
+	 * An array of event details for the related event to the registration being processed.
44
+	 * This is set via the _set_related_details method.
45
+	 *
46
+	 * @var array
47
+	 */
48
+	protected $_event_details = array();
49 49
 
50 50
 
51
-    /**
52
-     * @param \Registrations_Admin_Page $admin_page
53
-     */
54
-    public function __construct(Registrations_Admin_Page $admin_page)
55
-    {
56
-        if (! empty($_GET['event_id'])) {
57
-            $extra_query_args = array();
58
-            foreach ($admin_page->get_views() as $key => $view_details) {
59
-                $extra_query_args[ $view_details['slug'] ] = array('event_id' => $_GET['event_id']);
60
-            }
61
-            $this->_views = $admin_page->get_list_table_view_RLs($extra_query_args);
62
-        }
63
-        parent::__construct($admin_page);
64
-        $this->_status = $this->_admin_page->get_registration_status_array();
65
-    }
51
+	/**
52
+	 * @param \Registrations_Admin_Page $admin_page
53
+	 */
54
+	public function __construct(Registrations_Admin_Page $admin_page)
55
+	{
56
+		if (! empty($_GET['event_id'])) {
57
+			$extra_query_args = array();
58
+			foreach ($admin_page->get_views() as $key => $view_details) {
59
+				$extra_query_args[ $view_details['slug'] ] = array('event_id' => $_GET['event_id']);
60
+			}
61
+			$this->_views = $admin_page->get_list_table_view_RLs($extra_query_args);
62
+		}
63
+		parent::__construct($admin_page);
64
+		$this->_status = $this->_admin_page->get_registration_status_array();
65
+	}
66 66
 
67 67
 
68
-    /**
69
-     *    _setup_data
70
-     *
71
-     * @access protected
72
-     * @return void
73
-     */
74
-    protected function _setup_data()
75
-    {
76
-        $this->_data = $this->_admin_page->get_registrations($this->_per_page);
77
-        $this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true, false, false);
78
-    }
68
+	/**
69
+	 *    _setup_data
70
+	 *
71
+	 * @access protected
72
+	 * @return void
73
+	 */
74
+	protected function _setup_data()
75
+	{
76
+		$this->_data = $this->_admin_page->get_registrations($this->_per_page);
77
+		$this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true, false, false);
78
+	}
79 79
 
80 80
 
81
-    /**
82
-     *    _set_properties
83
-     *
84
-     * @access protected
85
-     * @return void
86
-     */
87
-    protected function _set_properties()
88
-    {
89
-        $this->_wp_list_args = array(
90
-            'singular' => __('registration', 'event_espresso'),
91
-            'plural'   => __('registrations', 'event_espresso'),
92
-            'ajax'     => true,
93
-            'screen'   => $this->_admin_page->get_current_screen()->id,
94
-        );
95
-        $ID_column_name = __('ID', 'event_espresso');
96
-        $ID_column_name .= ' : <span class="show-on-mobile-view-only" style="float:none">';
97
-        $ID_column_name .= __('Registrant Name', 'event_espresso');
98
-        $ID_column_name .= '</span> ';
99
-        if (isset($_GET['event_id'])) {
100
-            $this->_columns = array(
101
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
102
-                '_REG_ID'          => $ID_column_name,
103
-                'ATT_fname'        => __('Name', 'event_espresso'),
104
-                'ATT_email'        => __('Email', 'event_espresso'),
105
-                '_REG_date'        => __('Reg Date', 'event_espresso'),
106
-                'PRC_amount'       => __('TKT Price', 'event_espresso'),
107
-                '_REG_final_price' => __('Final Price', 'event_espresso'),
108
-                'TXN_total'        => __('Total Txn', 'event_espresso'),
109
-                'TXN_paid'         => __('Paid', 'event_espresso'),
110
-                'actions'          => __('Actions', 'event_espresso'),
111
-            );
112
-            $this->_bottom_buttons = array(
113
-                'report' => array(
114
-                    'route'         => 'registrations_report',
115
-                    'extra_request' => array(
116
-                        'EVT_ID'     => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
117
-                        'return_url' => urlencode("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"),
118
-                    ),
119
-                ),
120
-            );
121
-        } else {
122
-            $this->_columns = array(
123
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
124
-                '_REG_ID'          => $ID_column_name,
125
-                'ATT_fname'        => __('Name', 'event_espresso'),
126
-                '_REG_date'        => __('TXN Date', 'event_espresso'),
127
-                'event_name'       => __('Event', 'event_espresso'),
128
-                'DTT_EVT_start'    => __('Event Date', 'event_espresso'),
129
-                '_REG_final_price' => __('Price', 'event_espresso'),
130
-                '_REG_paid'        => __('Paid', 'event_espresso'),
131
-                'actions'          => __('Actions', 'event_espresso'),
132
-            );
133
-            $this->_bottom_buttons = array(
134
-                'report_all' => array(
135
-                    'route'         => 'registrations_report',
136
-                    'extra_request' => array(
137
-                        'return_url' => urlencode("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"),
138
-                    ),
139
-                ),
140
-            );
141
-        }
142
-        $this->_bottom_buttons['report_filtered'] = array(
143
-            'route'         => 'registrations_report',
144
-            'extra_request' => array(
145
-                'use_filters' => true,
146
-                'return_url'  => urlencode("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"),
147
-            ),
148
-        );
149
-        $filters = array_diff_key(
150
-            $this->_req_data,
151
-            array_flip(
152
-                array(
153
-                    'page',
154
-                    'action',
155
-                    'default_nonce',
156
-                )
157
-            )
158
-        );
159
-        if (!empty($filters)) {
160
-            $this->_bottom_buttons['report_filtered']['extra_request']['filters'] = $filters;
161
-        }
162
-        $this->_primary_column = '_REG_ID';
163
-        $this->_sortable_columns = array(
164
-            '_REG_date'     => array('_REG_date' => true),   // true means its already sorted
165
-            /**
166
-             * Allows users to change the default sort if they wish.
167
-             * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
168
-             * name.
169
-             */
170
-            'ATT_fname'     => array(
171
-                'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
172
-                true,
173
-                $this,
174
-            )
175
-                ? array('ATT_lname' => false)
176
-                : array('ATT_fname' => false),
177
-            'event_name'    => array('event_name' => false),
178
-            'DTT_EVT_start' => array('DTT_EVT_start' => false),
179
-            '_REG_ID'       => array('_REG_ID' => false),
180
-        );
181
-        $this->_hidden_columns = array();
182
-    }
81
+	/**
82
+	 *    _set_properties
83
+	 *
84
+	 * @access protected
85
+	 * @return void
86
+	 */
87
+	protected function _set_properties()
88
+	{
89
+		$this->_wp_list_args = array(
90
+			'singular' => __('registration', 'event_espresso'),
91
+			'plural'   => __('registrations', 'event_espresso'),
92
+			'ajax'     => true,
93
+			'screen'   => $this->_admin_page->get_current_screen()->id,
94
+		);
95
+		$ID_column_name = __('ID', 'event_espresso');
96
+		$ID_column_name .= ' : <span class="show-on-mobile-view-only" style="float:none">';
97
+		$ID_column_name .= __('Registrant Name', 'event_espresso');
98
+		$ID_column_name .= '</span> ';
99
+		if (isset($_GET['event_id'])) {
100
+			$this->_columns = array(
101
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
102
+				'_REG_ID'          => $ID_column_name,
103
+				'ATT_fname'        => __('Name', 'event_espresso'),
104
+				'ATT_email'        => __('Email', 'event_espresso'),
105
+				'_REG_date'        => __('Reg Date', 'event_espresso'),
106
+				'PRC_amount'       => __('TKT Price', 'event_espresso'),
107
+				'_REG_final_price' => __('Final Price', 'event_espresso'),
108
+				'TXN_total'        => __('Total Txn', 'event_espresso'),
109
+				'TXN_paid'         => __('Paid', 'event_espresso'),
110
+				'actions'          => __('Actions', 'event_espresso'),
111
+			);
112
+			$this->_bottom_buttons = array(
113
+				'report' => array(
114
+					'route'         => 'registrations_report',
115
+					'extra_request' => array(
116
+						'EVT_ID'     => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
117
+						'return_url' => urlencode("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"),
118
+					),
119
+				),
120
+			);
121
+		} else {
122
+			$this->_columns = array(
123
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
124
+				'_REG_ID'          => $ID_column_name,
125
+				'ATT_fname'        => __('Name', 'event_espresso'),
126
+				'_REG_date'        => __('TXN Date', 'event_espresso'),
127
+				'event_name'       => __('Event', 'event_espresso'),
128
+				'DTT_EVT_start'    => __('Event Date', 'event_espresso'),
129
+				'_REG_final_price' => __('Price', 'event_espresso'),
130
+				'_REG_paid'        => __('Paid', 'event_espresso'),
131
+				'actions'          => __('Actions', 'event_espresso'),
132
+			);
133
+			$this->_bottom_buttons = array(
134
+				'report_all' => array(
135
+					'route'         => 'registrations_report',
136
+					'extra_request' => array(
137
+						'return_url' => urlencode("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"),
138
+					),
139
+				),
140
+			);
141
+		}
142
+		$this->_bottom_buttons['report_filtered'] = array(
143
+			'route'         => 'registrations_report',
144
+			'extra_request' => array(
145
+				'use_filters' => true,
146
+				'return_url'  => urlencode("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"),
147
+			),
148
+		);
149
+		$filters = array_diff_key(
150
+			$this->_req_data,
151
+			array_flip(
152
+				array(
153
+					'page',
154
+					'action',
155
+					'default_nonce',
156
+				)
157
+			)
158
+		);
159
+		if (!empty($filters)) {
160
+			$this->_bottom_buttons['report_filtered']['extra_request']['filters'] = $filters;
161
+		}
162
+		$this->_primary_column = '_REG_ID';
163
+		$this->_sortable_columns = array(
164
+			'_REG_date'     => array('_REG_date' => true),   // true means its already sorted
165
+			/**
166
+			 * Allows users to change the default sort if they wish.
167
+			 * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
168
+			 * name.
169
+			 */
170
+			'ATT_fname'     => array(
171
+				'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
172
+				true,
173
+				$this,
174
+			)
175
+				? array('ATT_lname' => false)
176
+				: array('ATT_fname' => false),
177
+			'event_name'    => array('event_name' => false),
178
+			'DTT_EVT_start' => array('DTT_EVT_start' => false),
179
+			'_REG_ID'       => array('_REG_ID' => false),
180
+		);
181
+		$this->_hidden_columns = array();
182
+	}
183 183
 
184 184
 
185
-    /**
186
-     * This simply sets up the row class for the table rows.
187
-     * Allows for easier overriding of child methods for setting up sorting.
188
-     *
189
-     * @param  EE_Registration $item the current item
190
-     * @return string
191
-     */
192
-    protected function _get_row_class($item)
193
-    {
194
-        $class = parent::_get_row_class($item);
195
-        // add status class
196
-        $class .= ' ee-status-strip reg-status-' . $item->status_ID();
197
-        if ($this->_has_checkbox_column) {
198
-            $class .= ' has-checkbox-column';
199
-        }
200
-        return $class;
201
-    }
185
+	/**
186
+	 * This simply sets up the row class for the table rows.
187
+	 * Allows for easier overriding of child methods for setting up sorting.
188
+	 *
189
+	 * @param  EE_Registration $item the current item
190
+	 * @return string
191
+	 */
192
+	protected function _get_row_class($item)
193
+	{
194
+		$class = parent::_get_row_class($item);
195
+		// add status class
196
+		$class .= ' ee-status-strip reg-status-' . $item->status_ID();
197
+		if ($this->_has_checkbox_column) {
198
+			$class .= ' has-checkbox-column';
199
+		}
200
+		return $class;
201
+	}
202 202
 
203 203
 
204
-    /**
205
-     * Set the $_transaction_details property if not set yet.
206
-     *
207
-     * @param EE_Registration $registration
208
-     * @throws EE_Error
209
-     * @throws InvalidArgumentException
210
-     * @throws ReflectionException
211
-     * @throws InvalidDataTypeException
212
-     * @throws InvalidInterfaceException
213
-     */
214
-    protected function _set_related_details(EE_Registration $registration)
215
-    {
216
-        $transaction = $registration->get_first_related('Transaction');
217
-        $status = $transaction instanceof EE_Transaction ? $transaction->status_ID()
218
-            : EEM_Transaction::failed_status_code;
219
-        $this->_transaction_details = array(
220
-            'transaction' => $transaction,
221
-            'status'      => $status,
222
-            'id'          => $transaction instanceof EE_Transaction ? $transaction->ID() : 0,
223
-            'title_attr'  => sprintf(
224
-                __('View Transaction Details (%s)', 'event_espresso'),
225
-                EEH_Template::pretty_status($status, false, 'sentence')
226
-            ),
227
-        );
228
-        try {
229
-            $event = $registration->event();
230
-        } catch (EntityNotFoundException $e) {
231
-            $event = null;
232
-        }
233
-        $status = $event instanceof EE_Event ? $event->get_active_status() : EE_Datetime::inactive;
234
-        $this->_event_details = array(
235
-            'event'      => $event,
236
-            'status'     => $status,
237
-            'id'         => $event instanceof EE_Event ? $event->ID() : 0,
238
-            'title_attr' => sprintf(
239
-                __('Edit Event (%s)', 'event_espresso'),
240
-                EEH_Template::pretty_status($status, false, 'sentence')
241
-            ),
242
-        );
243
-    }
204
+	/**
205
+	 * Set the $_transaction_details property if not set yet.
206
+	 *
207
+	 * @param EE_Registration $registration
208
+	 * @throws EE_Error
209
+	 * @throws InvalidArgumentException
210
+	 * @throws ReflectionException
211
+	 * @throws InvalidDataTypeException
212
+	 * @throws InvalidInterfaceException
213
+	 */
214
+	protected function _set_related_details(EE_Registration $registration)
215
+	{
216
+		$transaction = $registration->get_first_related('Transaction');
217
+		$status = $transaction instanceof EE_Transaction ? $transaction->status_ID()
218
+			: EEM_Transaction::failed_status_code;
219
+		$this->_transaction_details = array(
220
+			'transaction' => $transaction,
221
+			'status'      => $status,
222
+			'id'          => $transaction instanceof EE_Transaction ? $transaction->ID() : 0,
223
+			'title_attr'  => sprintf(
224
+				__('View Transaction Details (%s)', 'event_espresso'),
225
+				EEH_Template::pretty_status($status, false, 'sentence')
226
+			),
227
+		);
228
+		try {
229
+			$event = $registration->event();
230
+		} catch (EntityNotFoundException $e) {
231
+			$event = null;
232
+		}
233
+		$status = $event instanceof EE_Event ? $event->get_active_status() : EE_Datetime::inactive;
234
+		$this->_event_details = array(
235
+			'event'      => $event,
236
+			'status'     => $status,
237
+			'id'         => $event instanceof EE_Event ? $event->ID() : 0,
238
+			'title_attr' => sprintf(
239
+				__('Edit Event (%s)', 'event_espresso'),
240
+				EEH_Template::pretty_status($status, false, 'sentence')
241
+			),
242
+		);
243
+	}
244 244
 
245 245
 
246
-    /**
247
-     *    _get_table_filters
248
-     *
249
-     * @access protected
250
-     * @return array
251
-     */
252
-    protected function _get_table_filters()
253
-    {
254
-        $filters = array();
255
-        // todo we're currently using old functions here. We need to move things into the Events_Admin_Page() class as
256
-        // methods.
257
-        $cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
258
-        $cur_category = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
259
-        $reg_status = isset($this->_req_data['_reg_status']) ? $this->_req_data['_reg_status'] : '';
260
-        $filters[] = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
261
-        $filters[] = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
262
-        $status = array();
263
-        $status[] = array('id' => 0, 'text' => __('Select Status', 'event_espresso'));
264
-        foreach ($this->_status as $key => $value) {
265
-            $status[] = array('id' => $key, 'text' => $value);
266
-        }
267
-        if ($this->_view !== 'incomplete') {
268
-            $filters[] = EEH_Form_Fields::select_input(
269
-                '_reg_status',
270
-                $status,
271
-                isset($this->_req_data['_reg_status']) ? strtoupper(sanitize_key($this->_req_data['_reg_status']))
272
-                    : ''
273
-            );
274
-        }
275
-        if (isset($this->_req_data['event_id'])) {
276
-            $filters[] = EEH_Form_Fields::hidden_input('event_id', $this->_req_data['event_id'], 'reg_event_id');
277
-        }
278
-        return $filters;
279
-    }
246
+	/**
247
+	 *    _get_table_filters
248
+	 *
249
+	 * @access protected
250
+	 * @return array
251
+	 */
252
+	protected function _get_table_filters()
253
+	{
254
+		$filters = array();
255
+		// todo we're currently using old functions here. We need to move things into the Events_Admin_Page() class as
256
+		// methods.
257
+		$cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
258
+		$cur_category = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
259
+		$reg_status = isset($this->_req_data['_reg_status']) ? $this->_req_data['_reg_status'] : '';
260
+		$filters[] = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
261
+		$filters[] = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
262
+		$status = array();
263
+		$status[] = array('id' => 0, 'text' => __('Select Status', 'event_espresso'));
264
+		foreach ($this->_status as $key => $value) {
265
+			$status[] = array('id' => $key, 'text' => $value);
266
+		}
267
+		if ($this->_view !== 'incomplete') {
268
+			$filters[] = EEH_Form_Fields::select_input(
269
+				'_reg_status',
270
+				$status,
271
+				isset($this->_req_data['_reg_status']) ? strtoupper(sanitize_key($this->_req_data['_reg_status']))
272
+					: ''
273
+			);
274
+		}
275
+		if (isset($this->_req_data['event_id'])) {
276
+			$filters[] = EEH_Form_Fields::hidden_input('event_id', $this->_req_data['event_id'], 'reg_event_id');
277
+		}
278
+		return $filters;
279
+	}
280 280
 
281 281
 
282
-    /**
283
-     *    _add_view_counts
284
-     *
285
-     * @access protected
286
-     * @return void
287
-     * @throws EE_Error
288
-     * @throws InvalidArgumentException
289
-     * @throws InvalidDataTypeException
290
-     * @throws InvalidInterfaceException
291
-     */
292
-    protected function _add_view_counts()
293
-    {
294
-        $this->_views['all']['count'] = $this->_total_registrations();
295
-        $this->_views['month']['count'] = $this->_total_registrations_this_month();
296
-        $this->_views['today']['count'] = $this->_total_registrations_today();
297
-        if (EE_Registry::instance()->CAP->current_user_can(
298
-            'ee_delete_registrations',
299
-            'espresso_registrations_trash_registrations'
300
-        )) {
301
-            $this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
302
-            $this->_views['trash']['count'] = $this->_total_registrations('trash');
303
-        }
304
-    }
282
+	/**
283
+	 *    _add_view_counts
284
+	 *
285
+	 * @access protected
286
+	 * @return void
287
+	 * @throws EE_Error
288
+	 * @throws InvalidArgumentException
289
+	 * @throws InvalidDataTypeException
290
+	 * @throws InvalidInterfaceException
291
+	 */
292
+	protected function _add_view_counts()
293
+	{
294
+		$this->_views['all']['count'] = $this->_total_registrations();
295
+		$this->_views['month']['count'] = $this->_total_registrations_this_month();
296
+		$this->_views['today']['count'] = $this->_total_registrations_today();
297
+		if (EE_Registry::instance()->CAP->current_user_can(
298
+			'ee_delete_registrations',
299
+			'espresso_registrations_trash_registrations'
300
+		)) {
301
+			$this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
302
+			$this->_views['trash']['count'] = $this->_total_registrations('trash');
303
+		}
304
+	}
305 305
 
306 306
 
307
-    /**
308
-     * _total_registrations
309
-     *
310
-     * @access protected
311
-     * @param string $view
312
-     * @return int
313
-     * @throws EE_Error
314
-     * @throws InvalidArgumentException
315
-     * @throws InvalidDataTypeException
316
-     * @throws InvalidInterfaceException
317
-     */
318
-    protected function _total_registrations($view = '')
319
-    {
320
-        $_where = array();
321
-        $EVT_ID = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : false;
322
-        if ($EVT_ID) {
323
-            $_where['EVT_ID'] = $EVT_ID;
324
-        }
325
-        switch ($view) {
326
-            case 'trash':
327
-                return EEM_Registration::instance()->count_deleted(array($_where));
328
-                break;
329
-            case 'incomplete':
330
-                $_where['STS_ID'] = EEM_Registration::status_id_incomplete;
331
-                break;
332
-            default:
333
-                $_where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
334
-        }
335
-        return EEM_Registration::instance()->count(array($_where));
336
-    }
307
+	/**
308
+	 * _total_registrations
309
+	 *
310
+	 * @access protected
311
+	 * @param string $view
312
+	 * @return int
313
+	 * @throws EE_Error
314
+	 * @throws InvalidArgumentException
315
+	 * @throws InvalidDataTypeException
316
+	 * @throws InvalidInterfaceException
317
+	 */
318
+	protected function _total_registrations($view = '')
319
+	{
320
+		$_where = array();
321
+		$EVT_ID = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : false;
322
+		if ($EVT_ID) {
323
+			$_where['EVT_ID'] = $EVT_ID;
324
+		}
325
+		switch ($view) {
326
+			case 'trash':
327
+				return EEM_Registration::instance()->count_deleted(array($_where));
328
+				break;
329
+			case 'incomplete':
330
+				$_where['STS_ID'] = EEM_Registration::status_id_incomplete;
331
+				break;
332
+			default:
333
+				$_where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
334
+		}
335
+		return EEM_Registration::instance()->count(array($_where));
336
+	}
337 337
 
338 338
 
339
-    /**
340
-     * _total_registrations_this_month
341
-     *
342
-     * @access protected
343
-     * @return int
344
-     * @throws EE_Error
345
-     * @throws InvalidArgumentException
346
-     * @throws InvalidDataTypeException
347
-     * @throws InvalidInterfaceException
348
-     */
349
-    protected function _total_registrations_this_month()
350
-    {
351
-        $EVT_ID = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : false;
352
-        $_where = $EVT_ID ? array('EVT_ID' => $EVT_ID) : array();
353
-        $this_year_r = date('Y', current_time('timestamp'));
354
-        $time_start = ' 00:00:00';
355
-        $time_end = ' 23:59:59';
356
-        $this_month_r = date('m', current_time('timestamp'));
357
-        $days_this_month = date('t', current_time('timestamp'));
358
-        // setup date query.
359
-        $beginning_string = EEM_Registration::instance()->convert_datetime_for_query(
360
-            'REG_date',
361
-            $this_year_r . '-' . $this_month_r . '-01' . ' ' . $time_start,
362
-            'Y-m-d H:i:s'
363
-        );
364
-        $end_string = EEM_Registration::instance()->convert_datetime_for_query(
365
-            'REG_date',
366
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' ' . $time_end,
367
-            'Y-m-d H:i:s'
368
-        );
369
-        $_where['REG_date'] = array(
370
-            'BETWEEN',
371
-            array(
372
-                $beginning_string,
373
-                $end_string,
374
-            ),
375
-        );
376
-        $_where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
377
-        return EEM_Registration::instance()->count(array($_where));
378
-    }
339
+	/**
340
+	 * _total_registrations_this_month
341
+	 *
342
+	 * @access protected
343
+	 * @return int
344
+	 * @throws EE_Error
345
+	 * @throws InvalidArgumentException
346
+	 * @throws InvalidDataTypeException
347
+	 * @throws InvalidInterfaceException
348
+	 */
349
+	protected function _total_registrations_this_month()
350
+	{
351
+		$EVT_ID = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : false;
352
+		$_where = $EVT_ID ? array('EVT_ID' => $EVT_ID) : array();
353
+		$this_year_r = date('Y', current_time('timestamp'));
354
+		$time_start = ' 00:00:00';
355
+		$time_end = ' 23:59:59';
356
+		$this_month_r = date('m', current_time('timestamp'));
357
+		$days_this_month = date('t', current_time('timestamp'));
358
+		// setup date query.
359
+		$beginning_string = EEM_Registration::instance()->convert_datetime_for_query(
360
+			'REG_date',
361
+			$this_year_r . '-' . $this_month_r . '-01' . ' ' . $time_start,
362
+			'Y-m-d H:i:s'
363
+		);
364
+		$end_string = EEM_Registration::instance()->convert_datetime_for_query(
365
+			'REG_date',
366
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' ' . $time_end,
367
+			'Y-m-d H:i:s'
368
+		);
369
+		$_where['REG_date'] = array(
370
+			'BETWEEN',
371
+			array(
372
+				$beginning_string,
373
+				$end_string,
374
+			),
375
+		);
376
+		$_where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
377
+		return EEM_Registration::instance()->count(array($_where));
378
+	}
379 379
 
380 380
 
381
-    /**
382
-     * _total_registrations_today
383
-     *
384
-     * @access protected
385
-     * @return int
386
-     * @throws EE_Error
387
-     * @throws InvalidArgumentException
388
-     * @throws InvalidDataTypeException
389
-     * @throws InvalidInterfaceException
390
-     */
391
-    protected function _total_registrations_today()
392
-    {
393
-        $EVT_ID = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : false;
394
-        $_where = $EVT_ID ? array('EVT_ID' => $EVT_ID) : array();
395
-        $current_date = date('Y-m-d', current_time('timestamp'));
396
-        $time_start = ' 00:00:00';
397
-        $time_end = ' 23:59:59';
398
-        $_where['REG_date'] = array(
399
-            'BETWEEN',
400
-            array(
401
-                EEM_Registration::instance()->convert_datetime_for_query(
402
-                    'REG_date',
403
-                    $current_date . $time_start,
404
-                    'Y-m-d H:i:s'
405
-                ),
406
-                EEM_Registration::instance()->convert_datetime_for_query(
407
-                    'REG_date',
408
-                    $current_date . $time_end,
409
-                    'Y-m-d H:i:s'
410
-                ),
411
-            ),
412
-        );
413
-        $_where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
414
-        return EEM_Registration::instance()->count(array($_where));
415
-    }
381
+	/**
382
+	 * _total_registrations_today
383
+	 *
384
+	 * @access protected
385
+	 * @return int
386
+	 * @throws EE_Error
387
+	 * @throws InvalidArgumentException
388
+	 * @throws InvalidDataTypeException
389
+	 * @throws InvalidInterfaceException
390
+	 */
391
+	protected function _total_registrations_today()
392
+	{
393
+		$EVT_ID = isset($this->_req_data['event_id']) ? absint($this->_req_data['event_id']) : false;
394
+		$_where = $EVT_ID ? array('EVT_ID' => $EVT_ID) : array();
395
+		$current_date = date('Y-m-d', current_time('timestamp'));
396
+		$time_start = ' 00:00:00';
397
+		$time_end = ' 23:59:59';
398
+		$_where['REG_date'] = array(
399
+			'BETWEEN',
400
+			array(
401
+				EEM_Registration::instance()->convert_datetime_for_query(
402
+					'REG_date',
403
+					$current_date . $time_start,
404
+					'Y-m-d H:i:s'
405
+				),
406
+				EEM_Registration::instance()->convert_datetime_for_query(
407
+					'REG_date',
408
+					$current_date . $time_end,
409
+					'Y-m-d H:i:s'
410
+				),
411
+			),
412
+		);
413
+		$_where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
414
+		return EEM_Registration::instance()->count(array($_where));
415
+	}
416 416
 
417 417
 
418
-    /**
419
-     * column_cb
420
-     *
421
-     * @access public
422
-     * @param \EE_Registration $item
423
-     * @return string
424
-     * @throws EE_Error
425
-     * @throws InvalidArgumentException
426
-     * @throws InvalidDataTypeException
427
-     * @throws InvalidInterfaceException
428
-     * @throws ReflectionException
429
-     */
430
-    public function column_cb($item)
431
-    {
432
-        /** checkbox/lock **/
433
-        $transaction = $item->get_first_related('Transaction');
434
-        $payment_count = $transaction instanceof EE_Transaction
435
-            ? $transaction->count_related('Payment')
436
-            : 0;
437
-        return $payment_count > 0
438
-               || ! EE_Registry::instance()->CAP->current_user_can(
439
-                   'ee_edit_registration',
440
-                   'registration_list_table_checkbox_input',
441
-                   $item->ID()
442
-               )
443
-            ? sprintf('<input type="checkbox" name="_REG_ID[]" value="%1$d" />', $item->ID())
444
-              . '<span class="ee-lock-icon"></span>'
445
-            : sprintf('<input type="checkbox" name="_REG_ID[]" value="%1$d" />', $item->ID());
446
-    }
418
+	/**
419
+	 * column_cb
420
+	 *
421
+	 * @access public
422
+	 * @param \EE_Registration $item
423
+	 * @return string
424
+	 * @throws EE_Error
425
+	 * @throws InvalidArgumentException
426
+	 * @throws InvalidDataTypeException
427
+	 * @throws InvalidInterfaceException
428
+	 * @throws ReflectionException
429
+	 */
430
+	public function column_cb($item)
431
+	{
432
+		/** checkbox/lock **/
433
+		$transaction = $item->get_first_related('Transaction');
434
+		$payment_count = $transaction instanceof EE_Transaction
435
+			? $transaction->count_related('Payment')
436
+			: 0;
437
+		return $payment_count > 0
438
+			   || ! EE_Registry::instance()->CAP->current_user_can(
439
+				   'ee_edit_registration',
440
+				   'registration_list_table_checkbox_input',
441
+				   $item->ID()
442
+			   )
443
+			? sprintf('<input type="checkbox" name="_REG_ID[]" value="%1$d" />', $item->ID())
444
+			  . '<span class="ee-lock-icon"></span>'
445
+			: sprintf('<input type="checkbox" name="_REG_ID[]" value="%1$d" />', $item->ID());
446
+	}
447 447
 
448 448
 
449
-    /**
450
-     * column__REG_ID
451
-     *
452
-     * @access public
453
-     * @param \EE_Registration $item
454
-     * @return string
455
-     * @throws EE_Error
456
-     * @throws InvalidArgumentException
457
-     * @throws InvalidDataTypeException
458
-     * @throws InvalidInterfaceException
459
-     * @throws ReflectionException
460
-     */
461
-    public function column__REG_ID(EE_Registration $item)
462
-    {
463
-        $attendee = $item->attendee();
464
-        $content = $item->ID();
465
-        $content .= '<div class="show-on-mobile-view-only">';
466
-        $content .= '<br>';
467
-        $content .= $attendee instanceof EE_Attendee ? $attendee->full_name() : '';
468
-        $content .= '&nbsp;' . sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
469
-        $content .= '<br>' . sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
470
-        $content .= '</div>';
471
-        return $content;
472
-    }
449
+	/**
450
+	 * column__REG_ID
451
+	 *
452
+	 * @access public
453
+	 * @param \EE_Registration $item
454
+	 * @return string
455
+	 * @throws EE_Error
456
+	 * @throws InvalidArgumentException
457
+	 * @throws InvalidDataTypeException
458
+	 * @throws InvalidInterfaceException
459
+	 * @throws ReflectionException
460
+	 */
461
+	public function column__REG_ID(EE_Registration $item)
462
+	{
463
+		$attendee = $item->attendee();
464
+		$content = $item->ID();
465
+		$content .= '<div class="show-on-mobile-view-only">';
466
+		$content .= '<br>';
467
+		$content .= $attendee instanceof EE_Attendee ? $attendee->full_name() : '';
468
+		$content .= '&nbsp;' . sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
469
+		$content .= '<br>' . sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
470
+		$content .= '</div>';
471
+		return $content;
472
+	}
473 473
 
474 474
 
475
-    /**
476
-     * column__REG_date
477
-     *
478
-     * @access public
479
-     * @param \EE_Registration $item
480
-     * @return string
481
-     * @throws EE_Error
482
-     * @throws InvalidArgumentException
483
-     * @throws InvalidDataTypeException
484
-     * @throws InvalidInterfaceException
485
-     * @throws ReflectionException
486
-     */
487
-    public function column__REG_date(EE_Registration $item)
488
-    {
489
-        $this->_set_related_details($item);
490
-        // Build row actions
491
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
492
-            array(
493
-                'action' => 'view_transaction',
494
-                'TXN_ID' => $this->_transaction_details['id'],
495
-            ),
496
-            TXN_ADMIN_URL
497
-        );
498
-        $view_link = EE_Registry::instance()->CAP->current_user_can(
499
-            'ee_read_transaction',
500
-            'espresso_transactions_view_transaction'
501
-        )
502
-            ? '<a class="ee-status-color-'
503
-              . $this->_transaction_details['status']
504
-              . '" href="'
505
-              . $view_lnk_url
506
-              . '" title="'
507
-              . esc_attr($this->_transaction_details['title_attr'])
508
-              . '">'
509
-              . $item->get_i18n_datetime('REG_date')
510
-              . '</a>' : $item->get_i18n_datetime('REG_date');
511
-        $view_link .= '<br><span class="ee-status-text-small">'
512
-                      . EEH_Template::pretty_status($this->_transaction_details['status'], false, 'sentence')
513
-                      . '</span>';
514
-        return $view_link;
515
-    }
475
+	/**
476
+	 * column__REG_date
477
+	 *
478
+	 * @access public
479
+	 * @param \EE_Registration $item
480
+	 * @return string
481
+	 * @throws EE_Error
482
+	 * @throws InvalidArgumentException
483
+	 * @throws InvalidDataTypeException
484
+	 * @throws InvalidInterfaceException
485
+	 * @throws ReflectionException
486
+	 */
487
+	public function column__REG_date(EE_Registration $item)
488
+	{
489
+		$this->_set_related_details($item);
490
+		// Build row actions
491
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
492
+			array(
493
+				'action' => 'view_transaction',
494
+				'TXN_ID' => $this->_transaction_details['id'],
495
+			),
496
+			TXN_ADMIN_URL
497
+		);
498
+		$view_link = EE_Registry::instance()->CAP->current_user_can(
499
+			'ee_read_transaction',
500
+			'espresso_transactions_view_transaction'
501
+		)
502
+			? '<a class="ee-status-color-'
503
+			  . $this->_transaction_details['status']
504
+			  . '" href="'
505
+			  . $view_lnk_url
506
+			  . '" title="'
507
+			  . esc_attr($this->_transaction_details['title_attr'])
508
+			  . '">'
509
+			  . $item->get_i18n_datetime('REG_date')
510
+			  . '</a>' : $item->get_i18n_datetime('REG_date');
511
+		$view_link .= '<br><span class="ee-status-text-small">'
512
+					  . EEH_Template::pretty_status($this->_transaction_details['status'], false, 'sentence')
513
+					  . '</span>';
514
+		return $view_link;
515
+	}
516 516
 
517 517
 
518
-    /**
519
-     * column_event_name
520
-     *
521
-     * @access public
522
-     * @param \EE_Registration $item
523
-     * @return string
524
-     * @throws EE_Error
525
-     * @throws InvalidArgumentException
526
-     * @throws InvalidDataTypeException
527
-     * @throws InvalidInterfaceException
528
-     * @throws ReflectionException
529
-     */
530
-    public function column_event_name(EE_Registration $item)
531
-    {
532
-        $this->_set_related_details($item);
533
-        // page=espresso_events&action=edit_event&EVT_ID=2&edit_event_nonce=cf3a7e5b62
534
-        $EVT_ID = $item->event_ID();
535
-        $event_name = $item->event_name();
536
-        $event_name = $event_name ? $event_name : __("No Associated Event", 'event_espresso');
537
-        $event_name = wp_trim_words($event_name, 30, '...');
538
-        if ($EVT_ID) {
539
-            $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
540
-                array('action' => 'edit', 'post' => $EVT_ID),
541
-                EVENTS_ADMIN_URL
542
-            );
543
-            $edit_event = EE_Registry::instance()->CAP->current_user_can('ee_edit_event', 'edit_event', $EVT_ID)
544
-                ? '<a class="ee-status-color-'
545
-                  . $this->_event_details['status']
546
-                  . '" href="'
547
-                  . $edit_event_url
548
-                  . '" title="'
549
-                  . esc_attr($this->_event_details['title_attr'])
550
-                  . '">'
551
-                  . $event_name
552
-                  . '</a>' : $event_name;
553
-            $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(array('event_id' => $EVT_ID), REG_ADMIN_URL);
554
-            $actions['event_filter'] = '<a href="' . $edit_event_url . '" title="';
555
-            $actions['event_filter'] .= sprintf(
556
-                esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
557
-                $event_name
558
-            );
559
-            $actions['event_filter'] .= '">' . __('View Registrations', 'event_espresso') . '</a>';
560
-        } else {
561
-            $edit_event = $event_name;
562
-            $actions['event_filter'] = '';
563
-        }
564
-        return sprintf('%1$s %2$s', $edit_event, $this->row_actions($actions));
565
-    }
518
+	/**
519
+	 * column_event_name
520
+	 *
521
+	 * @access public
522
+	 * @param \EE_Registration $item
523
+	 * @return string
524
+	 * @throws EE_Error
525
+	 * @throws InvalidArgumentException
526
+	 * @throws InvalidDataTypeException
527
+	 * @throws InvalidInterfaceException
528
+	 * @throws ReflectionException
529
+	 */
530
+	public function column_event_name(EE_Registration $item)
531
+	{
532
+		$this->_set_related_details($item);
533
+		// page=espresso_events&action=edit_event&EVT_ID=2&edit_event_nonce=cf3a7e5b62
534
+		$EVT_ID = $item->event_ID();
535
+		$event_name = $item->event_name();
536
+		$event_name = $event_name ? $event_name : __("No Associated Event", 'event_espresso');
537
+		$event_name = wp_trim_words($event_name, 30, '...');
538
+		if ($EVT_ID) {
539
+			$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
540
+				array('action' => 'edit', 'post' => $EVT_ID),
541
+				EVENTS_ADMIN_URL
542
+			);
543
+			$edit_event = EE_Registry::instance()->CAP->current_user_can('ee_edit_event', 'edit_event', $EVT_ID)
544
+				? '<a class="ee-status-color-'
545
+				  . $this->_event_details['status']
546
+				  . '" href="'
547
+				  . $edit_event_url
548
+				  . '" title="'
549
+				  . esc_attr($this->_event_details['title_attr'])
550
+				  . '">'
551
+				  . $event_name
552
+				  . '</a>' : $event_name;
553
+			$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(array('event_id' => $EVT_ID), REG_ADMIN_URL);
554
+			$actions['event_filter'] = '<a href="' . $edit_event_url . '" title="';
555
+			$actions['event_filter'] .= sprintf(
556
+				esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
557
+				$event_name
558
+			);
559
+			$actions['event_filter'] .= '">' . __('View Registrations', 'event_espresso') . '</a>';
560
+		} else {
561
+			$edit_event = $event_name;
562
+			$actions['event_filter'] = '';
563
+		}
564
+		return sprintf('%1$s %2$s', $edit_event, $this->row_actions($actions));
565
+	}
566 566
 
567 567
 
568
-    /**
569
-     * column_DTT_EVT_start
570
-     *
571
-     * @access public
572
-     * @param \EE_Registration $item
573
-     * @return string
574
-     * @throws EE_Error
575
-     * @throws InvalidArgumentException
576
-     * @throws InvalidDataTypeException
577
-     * @throws InvalidInterfaceException
578
-     * @throws ReflectionException
579
-     */
580
-    public function column_DTT_EVT_start(EE_Registration $item)
581
-    {
582
-        $datetime_strings = array();
583
-        $ticket = $item->ticket(true);
584
-        if ($ticket instanceof EE_Ticket) {
585
-            $remove_defaults = array('default_where_conditions' => 'none');
586
-            $datetimes = $ticket->datetimes($remove_defaults);
587
-            foreach ($datetimes as $datetime) {
588
-                $datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start');
589
-            }
590
-            return $this->generateDisplayForDatetimes($datetime_strings);
591
-        }
592
-        return __('There is no ticket on this registration', 'event_espresso');
593
-    }
568
+	/**
569
+	 * column_DTT_EVT_start
570
+	 *
571
+	 * @access public
572
+	 * @param \EE_Registration $item
573
+	 * @return string
574
+	 * @throws EE_Error
575
+	 * @throws InvalidArgumentException
576
+	 * @throws InvalidDataTypeException
577
+	 * @throws InvalidInterfaceException
578
+	 * @throws ReflectionException
579
+	 */
580
+	public function column_DTT_EVT_start(EE_Registration $item)
581
+	{
582
+		$datetime_strings = array();
583
+		$ticket = $item->ticket(true);
584
+		if ($ticket instanceof EE_Ticket) {
585
+			$remove_defaults = array('default_where_conditions' => 'none');
586
+			$datetimes = $ticket->datetimes($remove_defaults);
587
+			foreach ($datetimes as $datetime) {
588
+				$datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start');
589
+			}
590
+			return $this->generateDisplayForDatetimes($datetime_strings);
591
+		}
592
+		return __('There is no ticket on this registration', 'event_espresso');
593
+	}
594 594
 
595 595
 
596
-    /**
597
-     * Receives an array of datetime strings to display and converts them to the html container for the column.
598
-     *
599
-     * @param array $datetime_strings
600
-     * @return string
601
-     */
602
-    public function generateDisplayForDateTimes(array $datetime_strings)
603
-    {
604
-        $content = '<div class="ee-registration-event-datetimes-container">';
605
-        $expand_toggle = count($datetime_strings) > 1
606
-            ? ' <span title="' . esc_attr__('Click to view all dates', 'event_espresso')
607
-              . '" class="ee-js ee-more-datetimes-toggle dashicons dashicons-plus"></span>'
608
-            : '';
609
-        // get first item for initial visibility
610
-        $content .= '<div class="left">' . array_shift($datetime_strings) . '</div>';
611
-        $content .= $expand_toggle;
612
-        if ($datetime_strings) {
613
-            $content .= '<div style="clear:both"></div>';
614
-            $content .= '<div class="ee-registration-event-datetimes-container more-items hidden">';
615
-            $content .= implode("<br />", $datetime_strings);
616
-            $content .= '</div>';
617
-        }
618
-        $content .= '</div>';
619
-        return $content;
620
-    }
596
+	/**
597
+	 * Receives an array of datetime strings to display and converts them to the html container for the column.
598
+	 *
599
+	 * @param array $datetime_strings
600
+	 * @return string
601
+	 */
602
+	public function generateDisplayForDateTimes(array $datetime_strings)
603
+	{
604
+		$content = '<div class="ee-registration-event-datetimes-container">';
605
+		$expand_toggle = count($datetime_strings) > 1
606
+			? ' <span title="' . esc_attr__('Click to view all dates', 'event_espresso')
607
+			  . '" class="ee-js ee-more-datetimes-toggle dashicons dashicons-plus"></span>'
608
+			: '';
609
+		// get first item for initial visibility
610
+		$content .= '<div class="left">' . array_shift($datetime_strings) . '</div>';
611
+		$content .= $expand_toggle;
612
+		if ($datetime_strings) {
613
+			$content .= '<div style="clear:both"></div>';
614
+			$content .= '<div class="ee-registration-event-datetimes-container more-items hidden">';
615
+			$content .= implode("<br />", $datetime_strings);
616
+			$content .= '</div>';
617
+		}
618
+		$content .= '</div>';
619
+		return $content;
620
+	}
621 621
 
622 622
 
623
-    /**
624
-     * column_ATT_fname
625
-     *
626
-     * @access public
627
-     * @param \EE_Registration $item
628
-     * @return string
629
-     * @throws EE_Error
630
-     * @throws InvalidArgumentException
631
-     * @throws InvalidDataTypeException
632
-     * @throws InvalidInterfaceException
633
-     * @throws ReflectionException
634
-     */
635
-    public function column_ATT_fname(EE_Registration $item)
636
-    {
637
-        $attendee = $item->attendee();
638
-        $edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
639
-            array(
640
-                'action'  => 'view_registration',
641
-                '_REG_ID' => $item->ID(),
642
-            ),
643
-            REG_ADMIN_URL
644
-        );
645
-        $attendee_name = $attendee instanceof EE_Attendee ? $attendee->full_name() : '';
646
-        $link = EE_Registry::instance()->CAP->current_user_can(
647
-            'ee_read_registration',
648
-            'espresso_registrations_view_registration',
649
-            $item->ID()
650
-        )
651
-            ? '<a href="'
652
-              . $edit_lnk_url
653
-              . '" title="'
654
-              . esc_attr__('View Registration Details', 'event_espresso')
655
-              . '">'
656
-              . $attendee_name
657
-              . '</a>' : $attendee_name;
658
-        $link .= $item->count() === 1
659
-            ? '&nbsp;<sup><div class="dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8"></div></sup>' : '';
660
-        $t = $item->get_first_related('Transaction');
661
-        $payment_count = $t instanceof EE_Transaction ? $t->count_related('Payment') : 0;
662
-        // append group count to name
663
-        $link .= '&nbsp;' . sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
664
-        // append reg_code
665
-        $link .= '<br>' . sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
666
-        // reg status text for accessibility
667
-        $link .= '<br><span class="ee-status-text-small">'
668
-                 . EEH_Template::pretty_status($item->status_ID(), false, 'sentence')
669
-                 . '</span>';
670
-        $action = [ '_REG_ID' => $item->ID() ];
671
-        if (isset($this->_req_data['event_id'])) {
672
-            $action['event_id'] = $item->event_ID();
673
-        }
674
-        // trash/restore/delete actions
675
-        $actions = array();
676
-        if ($this->_view !== 'trash'
677
-            && $payment_count === 0
678
-            && EE_Registry::instance()->CAP->current_user_can(
679
-                'ee_delete_registration',
680
-                'espresso_registrations_trash_registrations',
681
-                $item->ID()
682
-            )) {
683
-            $action['action'] = 'trash_registrations';
684
-            $trash_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
685
-                $action,
686
-                REG_ADMIN_URL
687
-            );
688
-            $actions['trash'] = '<a href="'
689
-                                . $trash_lnk_url
690
-                                . '" title="'
691
-                                . esc_attr__('Trash Registration', 'event_espresso')
692
-                                . '">' . __('Trash', 'event_espresso') . '</a>';
693
-        } elseif ($this->_view === 'trash') {
694
-            // restore registration link
695
-            if (EE_Registry::instance()->CAP->current_user_can(
696
-                'ee_delete_registration',
697
-                'espresso_registrations_restore_registrations',
698
-                $item->ID()
699
-            )) {
700
-                $action['action'] = 'restore_registrations';
701
-                $restore_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
702
-                    $action,
703
-                    REG_ADMIN_URL
704
-                );
705
-                $actions['restore'] = '<a href="'
706
-                                      . $restore_lnk_url
707
-                                      . '" title="'
708
-                                      . esc_attr__('Restore Registration', 'event_espresso') . '">'
709
-                                      . __('Restore', 'event_espresso') . '</a>';
710
-            }
711
-            if (EE_Registry::instance()->CAP->current_user_can(
712
-                'ee_delete_registration',
713
-                'espresso_registrations_ee_delete_registrations',
714
-                $item->ID()
715
-            )) {
716
-                $action['action'] = 'delete_registrations';
717
-                $delete_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
718
-                    $action,
719
-                    REG_ADMIN_URL
720
-                );
721
-                $actions['delete'] = '<a href="'
722
-                                     . $delete_lnk_url
723
-                                     . '" title="'
724
-                                     . esc_attr__('Delete Registration Permanently', 'event_espresso')
725
-                                     . '">'
726
-                                     . __('Delete', 'event_espresso')
727
-                                     . '</a>';
728
-            }
729
-        }
730
-        return sprintf('%1$s %2$s', $link, $this->row_actions($actions));
731
-    }
623
+	/**
624
+	 * column_ATT_fname
625
+	 *
626
+	 * @access public
627
+	 * @param \EE_Registration $item
628
+	 * @return string
629
+	 * @throws EE_Error
630
+	 * @throws InvalidArgumentException
631
+	 * @throws InvalidDataTypeException
632
+	 * @throws InvalidInterfaceException
633
+	 * @throws ReflectionException
634
+	 */
635
+	public function column_ATT_fname(EE_Registration $item)
636
+	{
637
+		$attendee = $item->attendee();
638
+		$edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
639
+			array(
640
+				'action'  => 'view_registration',
641
+				'_REG_ID' => $item->ID(),
642
+			),
643
+			REG_ADMIN_URL
644
+		);
645
+		$attendee_name = $attendee instanceof EE_Attendee ? $attendee->full_name() : '';
646
+		$link = EE_Registry::instance()->CAP->current_user_can(
647
+			'ee_read_registration',
648
+			'espresso_registrations_view_registration',
649
+			$item->ID()
650
+		)
651
+			? '<a href="'
652
+			  . $edit_lnk_url
653
+			  . '" title="'
654
+			  . esc_attr__('View Registration Details', 'event_espresso')
655
+			  . '">'
656
+			  . $attendee_name
657
+			  . '</a>' : $attendee_name;
658
+		$link .= $item->count() === 1
659
+			? '&nbsp;<sup><div class="dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8"></div></sup>' : '';
660
+		$t = $item->get_first_related('Transaction');
661
+		$payment_count = $t instanceof EE_Transaction ? $t->count_related('Payment') : 0;
662
+		// append group count to name
663
+		$link .= '&nbsp;' . sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
664
+		// append reg_code
665
+		$link .= '<br>' . sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
666
+		// reg status text for accessibility
667
+		$link .= '<br><span class="ee-status-text-small">'
668
+				 . EEH_Template::pretty_status($item->status_ID(), false, 'sentence')
669
+				 . '</span>';
670
+		$action = [ '_REG_ID' => $item->ID() ];
671
+		if (isset($this->_req_data['event_id'])) {
672
+			$action['event_id'] = $item->event_ID();
673
+		}
674
+		// trash/restore/delete actions
675
+		$actions = array();
676
+		if ($this->_view !== 'trash'
677
+			&& $payment_count === 0
678
+			&& EE_Registry::instance()->CAP->current_user_can(
679
+				'ee_delete_registration',
680
+				'espresso_registrations_trash_registrations',
681
+				$item->ID()
682
+			)) {
683
+			$action['action'] = 'trash_registrations';
684
+			$trash_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
685
+				$action,
686
+				REG_ADMIN_URL
687
+			);
688
+			$actions['trash'] = '<a href="'
689
+								. $trash_lnk_url
690
+								. '" title="'
691
+								. esc_attr__('Trash Registration', 'event_espresso')
692
+								. '">' . __('Trash', 'event_espresso') . '</a>';
693
+		} elseif ($this->_view === 'trash') {
694
+			// restore registration link
695
+			if (EE_Registry::instance()->CAP->current_user_can(
696
+				'ee_delete_registration',
697
+				'espresso_registrations_restore_registrations',
698
+				$item->ID()
699
+			)) {
700
+				$action['action'] = 'restore_registrations';
701
+				$restore_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
702
+					$action,
703
+					REG_ADMIN_URL
704
+				);
705
+				$actions['restore'] = '<a href="'
706
+									  . $restore_lnk_url
707
+									  . '" title="'
708
+									  . esc_attr__('Restore Registration', 'event_espresso') . '">'
709
+									  . __('Restore', 'event_espresso') . '</a>';
710
+			}
711
+			if (EE_Registry::instance()->CAP->current_user_can(
712
+				'ee_delete_registration',
713
+				'espresso_registrations_ee_delete_registrations',
714
+				$item->ID()
715
+			)) {
716
+				$action['action'] = 'delete_registrations';
717
+				$delete_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
718
+					$action,
719
+					REG_ADMIN_URL
720
+				);
721
+				$actions['delete'] = '<a href="'
722
+									 . $delete_lnk_url
723
+									 . '" title="'
724
+									 . esc_attr__('Delete Registration Permanently', 'event_espresso')
725
+									 . '">'
726
+									 . __('Delete', 'event_espresso')
727
+									 . '</a>';
728
+			}
729
+		}
730
+		return sprintf('%1$s %2$s', $link, $this->row_actions($actions));
731
+	}
732 732
 
733 733
 
734
-    /**
735
-     * column_ATT_email
736
-     *
737
-     * @access public
738
-     * @param \EE_Registration $item
739
-     * @return string
740
-     * @throws EE_Error
741
-     * @throws InvalidArgumentException
742
-     * @throws InvalidDataTypeException
743
-     * @throws InvalidInterfaceException
744
-     * @throws ReflectionException
745
-     */
746
-    public function column_ATT_email(EE_Registration $item)
747
-    {
748
-        $attendee = $item->get_first_related('Attendee');
749
-        return ! $attendee instanceof EE_Attendee ? __('No attached contact record.', 'event_espresso')
750
-            : $attendee->email();
751
-    }
734
+	/**
735
+	 * column_ATT_email
736
+	 *
737
+	 * @access public
738
+	 * @param \EE_Registration $item
739
+	 * @return string
740
+	 * @throws EE_Error
741
+	 * @throws InvalidArgumentException
742
+	 * @throws InvalidDataTypeException
743
+	 * @throws InvalidInterfaceException
744
+	 * @throws ReflectionException
745
+	 */
746
+	public function column_ATT_email(EE_Registration $item)
747
+	{
748
+		$attendee = $item->get_first_related('Attendee');
749
+		return ! $attendee instanceof EE_Attendee ? __('No attached contact record.', 'event_espresso')
750
+			: $attendee->email();
751
+	}
752 752
 
753 753
 
754
-    /**
755
-     * column__REG_count
756
-     *
757
-     * @access public
758
-     * @param \EE_Registration $item
759
-     * @return string
760
-     */
761
-    public function column__REG_count(EE_Registration $item)
762
-    {
763
-        return sprintf(__('%1$s / %2$s', 'event_espresso'), $item->count(), $item->group_size());
764
-    }
754
+	/**
755
+	 * column__REG_count
756
+	 *
757
+	 * @access public
758
+	 * @param \EE_Registration $item
759
+	 * @return string
760
+	 */
761
+	public function column__REG_count(EE_Registration $item)
762
+	{
763
+		return sprintf(__('%1$s / %2$s', 'event_espresso'), $item->count(), $item->group_size());
764
+	}
765 765
 
766 766
 
767
-    /**
768
-     * column_PRC_amount
769
-     *
770
-     * @access public
771
-     * @param \EE_Registration $item
772
-     * @return string
773
-     * @throws EE_Error
774
-     */
775
-    public function column_PRC_amount(EE_Registration $item)
776
-    {
777
-        $ticket = $item->ticket();
778
-        $content = isset($_GET['event_id']) && $ticket instanceof EE_Ticket ? '<span class="TKT_name">'
779
-                                                                              . $ticket->name()
780
-                                                                              . '</span><br />' : '';
781
-        if ($item->final_price() > 0) {
782
-            $content .= '<span class="reg-pad-rght">' . $item->pretty_final_price() . '</span>';
783
-        } else {
784
-            // free event
785
-            $content .= '<span class="reg-overview-free-event-spn reg-pad-rght">'
786
-                        . __('free', 'event_espresso')
787
-                        . '</span>';
788
-        }
789
-        return $content;
790
-    }
767
+	/**
768
+	 * column_PRC_amount
769
+	 *
770
+	 * @access public
771
+	 * @param \EE_Registration $item
772
+	 * @return string
773
+	 * @throws EE_Error
774
+	 */
775
+	public function column_PRC_amount(EE_Registration $item)
776
+	{
777
+		$ticket = $item->ticket();
778
+		$content = isset($_GET['event_id']) && $ticket instanceof EE_Ticket ? '<span class="TKT_name">'
779
+																			  . $ticket->name()
780
+																			  . '</span><br />' : '';
781
+		if ($item->final_price() > 0) {
782
+			$content .= '<span class="reg-pad-rght">' . $item->pretty_final_price() . '</span>';
783
+		} else {
784
+			// free event
785
+			$content .= '<span class="reg-overview-free-event-spn reg-pad-rght">'
786
+						. __('free', 'event_espresso')
787
+						. '</span>';
788
+		}
789
+		return $content;
790
+	}
791 791
 
792 792
 
793
-    /**
794
-     * column__REG_final_price
795
-     *
796
-     * @access public
797
-     * @param \EE_Registration $item
798
-     * @return string
799
-     * @throws EE_Error
800
-     */
801
-    public function column__REG_final_price(EE_Registration $item)
802
-    {
803
-        $ticket = $item->ticket();
804
-        $content = isset($_GET['event_id']) || ! $ticket instanceof EE_Ticket
805
-            ? ''
806
-            : '<span class="TKT_name">'
807
-              . $ticket->name()
808
-              . '</span><br />';
809
-        $content .= '<span class="reg-pad-rght">' . $item->pretty_final_price() . '</span>';
810
-        return $content;
811
-    }
793
+	/**
794
+	 * column__REG_final_price
795
+	 *
796
+	 * @access public
797
+	 * @param \EE_Registration $item
798
+	 * @return string
799
+	 * @throws EE_Error
800
+	 */
801
+	public function column__REG_final_price(EE_Registration $item)
802
+	{
803
+		$ticket = $item->ticket();
804
+		$content = isset($_GET['event_id']) || ! $ticket instanceof EE_Ticket
805
+			? ''
806
+			: '<span class="TKT_name">'
807
+			  . $ticket->name()
808
+			  . '</span><br />';
809
+		$content .= '<span class="reg-pad-rght">' . $item->pretty_final_price() . '</span>';
810
+		return $content;
811
+	}
812 812
 
813 813
 
814
-    /**
815
-     * column__REG_paid
816
-     *
817
-     * @access public
818
-     * @param \EE_Registration $item
819
-     * @return string
820
-     * @throws EE_Error
821
-     */
822
-    public function column__REG_paid(EE_Registration $item)
823
-    {
824
-        $payment_method = $item->payment_method();
825
-        $payment_method_name = $payment_method instanceof EE_Payment_Method ? $payment_method->admin_name()
826
-            : __('Unknown', 'event_espresso');
827
-        $content = '<span class="reg-pad-rght">' . $item->pretty_paid() . '</span>';
828
-        if ($item->paid() > 0) {
829
-            $content .= '<br><span class="ee-status-text-small">'
830
-                        . sprintf(
831
-                            __('...via %s', 'event_espresso'),
832
-                            $payment_method_name
833
-                        )
834
-                        . '</span>';
835
-        }
836
-        return $content;
837
-    }
814
+	/**
815
+	 * column__REG_paid
816
+	 *
817
+	 * @access public
818
+	 * @param \EE_Registration $item
819
+	 * @return string
820
+	 * @throws EE_Error
821
+	 */
822
+	public function column__REG_paid(EE_Registration $item)
823
+	{
824
+		$payment_method = $item->payment_method();
825
+		$payment_method_name = $payment_method instanceof EE_Payment_Method ? $payment_method->admin_name()
826
+			: __('Unknown', 'event_espresso');
827
+		$content = '<span class="reg-pad-rght">' . $item->pretty_paid() . '</span>';
828
+		if ($item->paid() > 0) {
829
+			$content .= '<br><span class="ee-status-text-small">'
830
+						. sprintf(
831
+							__('...via %s', 'event_espresso'),
832
+							$payment_method_name
833
+						)
834
+						. '</span>';
835
+		}
836
+		return $content;
837
+	}
838 838
 
839 839
 
840
-    /**
841
-     * column_TXN_total
842
-     *
843
-     * @access public
844
-     * @param \EE_Registration $item
845
-     * @return string
846
-     * @throws EE_Error
847
-     * @throws EntityNotFoundException
848
-     * @throws InvalidArgumentException
849
-     * @throws InvalidDataTypeException
850
-     * @throws InvalidInterfaceException
851
-     */
852
-    public function column_TXN_total(EE_Registration $item)
853
-    {
854
-        if ($item->transaction()) {
855
-            $view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
856
-                array(
857
-                    'action' => 'view_transaction',
858
-                    'TXN_ID' => $item->transaction_ID(),
859
-                ),
860
-                TXN_ADMIN_URL
861
-            );
862
-            return EE_Registry::instance()->CAP->current_user_can(
863
-                'ee_read_transaction',
864
-                'espresso_transactions_view_transaction',
865
-                $item->transaction_ID()
866
-            )
867
-                ? '<span class="reg-pad-rght"><a class="status-'
868
-                  . $item->transaction()->status_ID()
869
-                  . '" href="'
870
-                  . $view_txn_lnk_url
871
-                  . '"  title="'
872
-                  . esc_attr__('View Transaction', 'event_espresso')
873
-                  . '">'
874
-                  . $item->transaction()->pretty_total()
875
-                  . '</a></span>' : '<span class="reg-pad-rght">' . $item->transaction()->pretty_total() . '</span>';
876
-        } else {
877
-            return __("None", "event_espresso");
878
-        }
879
-    }
840
+	/**
841
+	 * column_TXN_total
842
+	 *
843
+	 * @access public
844
+	 * @param \EE_Registration $item
845
+	 * @return string
846
+	 * @throws EE_Error
847
+	 * @throws EntityNotFoundException
848
+	 * @throws InvalidArgumentException
849
+	 * @throws InvalidDataTypeException
850
+	 * @throws InvalidInterfaceException
851
+	 */
852
+	public function column_TXN_total(EE_Registration $item)
853
+	{
854
+		if ($item->transaction()) {
855
+			$view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
856
+				array(
857
+					'action' => 'view_transaction',
858
+					'TXN_ID' => $item->transaction_ID(),
859
+				),
860
+				TXN_ADMIN_URL
861
+			);
862
+			return EE_Registry::instance()->CAP->current_user_can(
863
+				'ee_read_transaction',
864
+				'espresso_transactions_view_transaction',
865
+				$item->transaction_ID()
866
+			)
867
+				? '<span class="reg-pad-rght"><a class="status-'
868
+				  . $item->transaction()->status_ID()
869
+				  . '" href="'
870
+				  . $view_txn_lnk_url
871
+				  . '"  title="'
872
+				  . esc_attr__('View Transaction', 'event_espresso')
873
+				  . '">'
874
+				  . $item->transaction()->pretty_total()
875
+				  . '</a></span>' : '<span class="reg-pad-rght">' . $item->transaction()->pretty_total() . '</span>';
876
+		} else {
877
+			return __("None", "event_espresso");
878
+		}
879
+	}
880 880
 
881 881
 
882
-    /**
883
-     * column_TXN_paid
884
-     *
885
-     * @access public
886
-     * @param \EE_Registration $item
887
-     * @return string
888
-     * @throws EE_Error
889
-     * @throws EntityNotFoundException
890
-     * @throws InvalidArgumentException
891
-     * @throws InvalidDataTypeException
892
-     * @throws InvalidInterfaceException
893
-     */
894
-    public function column_TXN_paid(EE_Registration $item)
895
-    {
896
-        if ($item->count() === 1) {
897
-            $transaction = $item->transaction() ? $item->transaction() : EE_Transaction::new_instance();
898
-            if ($transaction->paid() >= $transaction->total()) {
899
-                return '<span class="reg-pad-rght"><div class="dashicons dashicons-yes green-icon"></div></span>';
900
-            } else {
901
-                $view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
902
-                    array(
903
-                        'action' => 'view_transaction',
904
-                        'TXN_ID' => $item->transaction_ID(),
905
-                    ),
906
-                    TXN_ADMIN_URL
907
-                );
908
-                return EE_Registry::instance()->CAP->current_user_can(
909
-                    'ee_read_transaction',
910
-                    'espresso_transactions_view_transaction',
911
-                    $item->transaction_ID()
912
-                )
913
-                    ? '<span class="reg-pad-rght"><a class="status-'
914
-                      . $transaction->status_ID()
915
-                      . '" href="'
916
-                      . $view_txn_lnk_url
917
-                      . '"  title="'
918
-                      . esc_attr__('View Transaction', 'event_espresso')
919
-                      . '">'
920
-                      . $item->transaction()->pretty_paid()
921
-                      . '</a><span>' : '<span class="reg-pad-rght">' . $item->transaction()->pretty_paid() . '</span>';
922
-            }
923
-        }
924
-        return '&nbsp;';
925
-    }
882
+	/**
883
+	 * column_TXN_paid
884
+	 *
885
+	 * @access public
886
+	 * @param \EE_Registration $item
887
+	 * @return string
888
+	 * @throws EE_Error
889
+	 * @throws EntityNotFoundException
890
+	 * @throws InvalidArgumentException
891
+	 * @throws InvalidDataTypeException
892
+	 * @throws InvalidInterfaceException
893
+	 */
894
+	public function column_TXN_paid(EE_Registration $item)
895
+	{
896
+		if ($item->count() === 1) {
897
+			$transaction = $item->transaction() ? $item->transaction() : EE_Transaction::new_instance();
898
+			if ($transaction->paid() >= $transaction->total()) {
899
+				return '<span class="reg-pad-rght"><div class="dashicons dashicons-yes green-icon"></div></span>';
900
+			} else {
901
+				$view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
902
+					array(
903
+						'action' => 'view_transaction',
904
+						'TXN_ID' => $item->transaction_ID(),
905
+					),
906
+					TXN_ADMIN_URL
907
+				);
908
+				return EE_Registry::instance()->CAP->current_user_can(
909
+					'ee_read_transaction',
910
+					'espresso_transactions_view_transaction',
911
+					$item->transaction_ID()
912
+				)
913
+					? '<span class="reg-pad-rght"><a class="status-'
914
+					  . $transaction->status_ID()
915
+					  . '" href="'
916
+					  . $view_txn_lnk_url
917
+					  . '"  title="'
918
+					  . esc_attr__('View Transaction', 'event_espresso')
919
+					  . '">'
920
+					  . $item->transaction()->pretty_paid()
921
+					  . '</a><span>' : '<span class="reg-pad-rght">' . $item->transaction()->pretty_paid() . '</span>';
922
+			}
923
+		}
924
+		return '&nbsp;';
925
+	}
926 926
 
927 927
 
928
-    /**
929
-     * column_actions
930
-     *
931
-     * @access public
932
-     * @param \EE_Registration $item
933
-     * @return string
934
-     * @throws EE_Error
935
-     * @throws InvalidArgumentException
936
-     * @throws InvalidDataTypeException
937
-     * @throws InvalidInterfaceException
938
-     * @throws ReflectionException
939
-     */
940
-    public function column_actions(EE_Registration $item)
941
-    {
942
-        $actions = array();
943
-        $attendee = $item->attendee();
944
-        $this->_set_related_details($item);
945
-        // Build row actions
946
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
947
-            array(
948
-                'action'  => 'view_registration',
949
-                '_REG_ID' => $item->ID(),
950
-            ),
951
-            REG_ADMIN_URL
952
-        );
953
-        $edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
954
-            array(
955
-                'action' => 'edit_attendee',
956
-                'post'   => $item->attendee_ID(),
957
-            ),
958
-            REG_ADMIN_URL
959
-        );
960
-        // page=attendees&event_admin_reports=resend_email&registration_id=43653465634&event_id=2&form_action=resend_email
961
-        // $resend_reg_lnk_url_params = array( 'action'=>'resend_registration', '_REG_ID'=>$item->REG_ID );
962
-        $resend_reg_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
963
-            array(
964
-                'action'  => 'resend_registration',
965
-                '_REG_ID' => $item->ID(),
966
-            ),
967
-            REG_ADMIN_URL,
968
-            true
969
-        );
970
-        // Build row actions
971
-        $actions['view_lnk'] = EE_Registry::instance()->CAP->current_user_can(
972
-            'ee_read_registration',
973
-            'espresso_registrations_view_registration',
974
-            $item->ID()
975
-        ) ? '<li><a href="'
976
-            . $view_lnk_url
977
-            . '" title="'
978
-            . esc_attr__('View Registration Details', 'event_espresso')
979
-            . '" class="tiny-text">
928
+	/**
929
+	 * column_actions
930
+	 *
931
+	 * @access public
932
+	 * @param \EE_Registration $item
933
+	 * @return string
934
+	 * @throws EE_Error
935
+	 * @throws InvalidArgumentException
936
+	 * @throws InvalidDataTypeException
937
+	 * @throws InvalidInterfaceException
938
+	 * @throws ReflectionException
939
+	 */
940
+	public function column_actions(EE_Registration $item)
941
+	{
942
+		$actions = array();
943
+		$attendee = $item->attendee();
944
+		$this->_set_related_details($item);
945
+		// Build row actions
946
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
947
+			array(
948
+				'action'  => 'view_registration',
949
+				'_REG_ID' => $item->ID(),
950
+			),
951
+			REG_ADMIN_URL
952
+		);
953
+		$edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
954
+			array(
955
+				'action' => 'edit_attendee',
956
+				'post'   => $item->attendee_ID(),
957
+			),
958
+			REG_ADMIN_URL
959
+		);
960
+		// page=attendees&event_admin_reports=resend_email&registration_id=43653465634&event_id=2&form_action=resend_email
961
+		// $resend_reg_lnk_url_params = array( 'action'=>'resend_registration', '_REG_ID'=>$item->REG_ID );
962
+		$resend_reg_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
963
+			array(
964
+				'action'  => 'resend_registration',
965
+				'_REG_ID' => $item->ID(),
966
+			),
967
+			REG_ADMIN_URL,
968
+			true
969
+		);
970
+		// Build row actions
971
+		$actions['view_lnk'] = EE_Registry::instance()->CAP->current_user_can(
972
+			'ee_read_registration',
973
+			'espresso_registrations_view_registration',
974
+			$item->ID()
975
+		) ? '<li><a href="'
976
+			. $view_lnk_url
977
+			. '" title="'
978
+			. esc_attr__('View Registration Details', 'event_espresso')
979
+			. '" class="tiny-text">
980 980
 				<div class="dashicons dashicons-clipboard"></div>
981 981
 			</a>
982 982
 			</li>'
983
-            : '';
984
-        $actions['edit_lnk'] = EE_Registry::instance()->CAP->current_user_can(
985
-            'ee_edit_contacts',
986
-            'espresso_registrations_edit_attendee'
987
-        )
988
-                               && $attendee instanceof EE_Attendee
989
-            ? '
983
+			: '';
984
+		$actions['edit_lnk'] = EE_Registry::instance()->CAP->current_user_can(
985
+			'ee_edit_contacts',
986
+			'espresso_registrations_edit_attendee'
987
+		)
988
+							   && $attendee instanceof EE_Attendee
989
+			? '
990 990
 			<li>
991 991
 			<a href="' . $edit_lnk_url . '" title="'
992
-              . esc_attr__('Edit Contact Details', 'event_espresso') . '" class="tiny-text">
992
+			  . esc_attr__('Edit Contact Details', 'event_espresso') . '" class="tiny-text">
993 993
 				<div class="ee-icon ee-icon-user-edit ee-icon-size-16"></div>
994 994
 			</a>
995 995
 			</li>' : '';
996
-        $actions['resend_reg_lnk'] = $attendee instanceof EE_Attendee
997
-                                     && EE_Registry::instance()->CAP->current_user_can(
998
-                                         'ee_send_message',
999
-                                         'espresso_registrations_resend_registration',
1000
-                                         $item->ID()
1001
-                                     )
1002
-            ? '
996
+		$actions['resend_reg_lnk'] = $attendee instanceof EE_Attendee
997
+									 && EE_Registry::instance()->CAP->current_user_can(
998
+										 'ee_send_message',
999
+										 'espresso_registrations_resend_registration',
1000
+										 $item->ID()
1001
+									 )
1002
+			? '
1003 1003
 			<li>
1004 1004
 			<a href="'
1005
-              . $resend_reg_lnk_url
1006
-              . '" title="'
1007
-              . esc_attr__('Resend Registration Details', 'event_espresso')
1008
-              . '" class="tiny-text">
1005
+			  . $resend_reg_lnk_url
1006
+			  . '" title="'
1007
+			  . esc_attr__('Resend Registration Details', 'event_espresso')
1008
+			  . '" class="tiny-text">
1009 1009
 				<div class="dashicons dashicons-email-alt"></div>
1010 1010
 			</a>
1011 1011
 			</li>' : '';
1012
-        // page=transactions&action=view_transaction&txn=256&_wpnonce=6414da4dbb
1013
-        $view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
1014
-            array(
1015
-                'action' => 'view_transaction',
1016
-                'TXN_ID' => $this->_transaction_details['id'],
1017
-            ),
1018
-            TXN_ADMIN_URL
1019
-        );
1020
-        $actions['view_txn_lnk'] = EE_Registry::instance()->CAP->current_user_can(
1021
-            'ee_read_transaction',
1022
-            'espresso_transactions_view_transaction',
1023
-            $this->_transaction_details['id']
1024
-        )
1025
-            ? '
1012
+		// page=transactions&action=view_transaction&txn=256&_wpnonce=6414da4dbb
1013
+		$view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
1014
+			array(
1015
+				'action' => 'view_transaction',
1016
+				'TXN_ID' => $this->_transaction_details['id'],
1017
+			),
1018
+			TXN_ADMIN_URL
1019
+		);
1020
+		$actions['view_txn_lnk'] = EE_Registry::instance()->CAP->current_user_can(
1021
+			'ee_read_transaction',
1022
+			'espresso_transactions_view_transaction',
1023
+			$this->_transaction_details['id']
1024
+		)
1025
+			? '
1026 1026
 			<li>
1027 1027
 			<a class="ee-status-color-'
1028
-              . $this->_transaction_details['status']
1029
-              . ' tiny-text" href="'
1030
-              . $view_txn_lnk_url
1031
-              . '"  title="'
1032
-              . $this->_transaction_details['title_attr']
1033
-              . '">
1028
+			  . $this->_transaction_details['status']
1029
+			  . ' tiny-text" href="'
1030
+			  . $view_txn_lnk_url
1031
+			  . '"  title="'
1032
+			  . $this->_transaction_details['title_attr']
1033
+			  . '">
1034 1034
 				<div class="dashicons dashicons-cart"></div>
1035 1035
 			</a>
1036 1036
 			</li>' : '';
1037
-        // invoice link
1038
-        $actions['dl_invoice_lnk'] = '';
1039
-        $dl_invoice_lnk_url = $item->invoice_url();
1040
-        // only show invoice link if message type is active.
1041
-        if ($attendee instanceof EE_Attendee
1042
-            && $item->is_primary_registrant()
1043
-            && EEH_MSG_Template::is_mt_active('invoice')
1044
-        ) {
1045
-            $actions['dl_invoice_lnk'] = '
1037
+		// invoice link
1038
+		$actions['dl_invoice_lnk'] = '';
1039
+		$dl_invoice_lnk_url = $item->invoice_url();
1040
+		// only show invoice link if message type is active.
1041
+		if ($attendee instanceof EE_Attendee
1042
+			&& $item->is_primary_registrant()
1043
+			&& EEH_MSG_Template::is_mt_active('invoice')
1044
+		) {
1045
+			$actions['dl_invoice_lnk'] = '
1046 1046
 		<li>
1047 1047
 			<a title="'
1048
-                                         . esc_attr__('View Transaction Invoice', 'event_espresso')
1049
-                                         . '" target="_blank" href="'
1050
-                                         . $dl_invoice_lnk_url
1051
-                                         . '" class="tiny-text">
1048
+										 . esc_attr__('View Transaction Invoice', 'event_espresso')
1049
+										 . '" target="_blank" href="'
1050
+										 . $dl_invoice_lnk_url
1051
+										 . '" class="tiny-text">
1052 1052
 				<span class="dashicons dashicons-media-spreadsheet ee-icon-size-18"></span>
1053 1053
 			</a>
1054 1054
 		</li>';
1055
-        }
1056
-        $actions['filtered_messages_link'] = '';
1057
-        // message list table link (filtered by REG_ID
1058
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
1059
-            $actions['filtered_messages_link'] = '<li>'
1060
-                                                 . EEH_MSG_Template::get_message_action_link(
1061
-                                                     'see_notifications_for',
1062
-                                                     null,
1063
-                                                     array('_REG_ID' => $item->ID())
1064
-                                                 ) . '</li>';
1065
-        }
1066
-        $actions = apply_filters('FHEE__EE_Registrations_List_Table__column_actions__actions', $actions, $item, $this);
1067
-        return $this->_action_string(implode('', $actions), $item, 'ul', 'reg-overview-actions-ul');
1068
-    }
1055
+		}
1056
+		$actions['filtered_messages_link'] = '';
1057
+		// message list table link (filtered by REG_ID
1058
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
1059
+			$actions['filtered_messages_link'] = '<li>'
1060
+												 . EEH_MSG_Template::get_message_action_link(
1061
+													 'see_notifications_for',
1062
+													 null,
1063
+													 array('_REG_ID' => $item->ID())
1064
+												 ) . '</li>';
1065
+		}
1066
+		$actions = apply_filters('FHEE__EE_Registrations_List_Table__column_actions__actions', $actions, $item, $this);
1067
+		return $this->_action_string(implode('', $actions), $item, 'ul', 'reg-overview-actions-ul');
1068
+	}
1069 1069
 }
Please login to merge, or discard this patch.
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -53,10 +53,10 @@  discard block
 block discarded – undo
53 53
      */
54 54
     public function __construct(Registrations_Admin_Page $admin_page)
55 55
     {
56
-        if (! empty($_GET['event_id'])) {
56
+        if ( ! empty($_GET['event_id'])) {
57 57
             $extra_query_args = array();
58 58
             foreach ($admin_page->get_views() as $key => $view_details) {
59
-                $extra_query_args[ $view_details['slug'] ] = array('event_id' => $_GET['event_id']);
59
+                $extra_query_args[$view_details['slug']] = array('event_id' => $_GET['event_id']);
60 60
             }
61 61
             $this->_views = $admin_page->get_list_table_view_RLs($extra_query_args);
62 62
         }
@@ -156,12 +156,12 @@  discard block
 block discarded – undo
156 156
                 )
157 157
             )
158 158
         );
159
-        if (!empty($filters)) {
159
+        if ( ! empty($filters)) {
160 160
             $this->_bottom_buttons['report_filtered']['extra_request']['filters'] = $filters;
161 161
         }
162 162
         $this->_primary_column = '_REG_ID';
163 163
         $this->_sortable_columns = array(
164
-            '_REG_date'     => array('_REG_date' => true),   // true means its already sorted
164
+            '_REG_date'     => array('_REG_date' => true), // true means its already sorted
165 165
             /**
166 166
              * Allows users to change the default sort if they wish.
167 167
              * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
@@ -193,7 +193,7 @@  discard block
 block discarded – undo
193 193
     {
194 194
         $class = parent::_get_row_class($item);
195 195
         // add status class
196
-        $class .= ' ee-status-strip reg-status-' . $item->status_ID();
196
+        $class .= ' ee-status-strip reg-status-'.$item->status_ID();
197 197
         if ($this->_has_checkbox_column) {
198 198
             $class .= ' has-checkbox-column';
199 199
         }
@@ -358,12 +358,12 @@  discard block
 block discarded – undo
358 358
         // setup date query.
359 359
         $beginning_string = EEM_Registration::instance()->convert_datetime_for_query(
360 360
             'REG_date',
361
-            $this_year_r . '-' . $this_month_r . '-01' . ' ' . $time_start,
361
+            $this_year_r.'-'.$this_month_r.'-01'.' '.$time_start,
362 362
             'Y-m-d H:i:s'
363 363
         );
364 364
         $end_string = EEM_Registration::instance()->convert_datetime_for_query(
365 365
             'REG_date',
366
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' ' . $time_end,
366
+            $this_year_r.'-'.$this_month_r.'-'.$days_this_month.' '.$time_end,
367 367
             'Y-m-d H:i:s'
368 368
         );
369 369
         $_where['REG_date'] = array(
@@ -400,12 +400,12 @@  discard block
 block discarded – undo
400 400
             array(
401 401
                 EEM_Registration::instance()->convert_datetime_for_query(
402 402
                     'REG_date',
403
-                    $current_date . $time_start,
403
+                    $current_date.$time_start,
404 404
                     'Y-m-d H:i:s'
405 405
                 ),
406 406
                 EEM_Registration::instance()->convert_datetime_for_query(
407 407
                     'REG_date',
408
-                    $current_date . $time_end,
408
+                    $current_date.$time_end,
409 409
                     'Y-m-d H:i:s'
410 410
                 ),
411 411
             ),
@@ -465,8 +465,8 @@  discard block
 block discarded – undo
465 465
         $content .= '<div class="show-on-mobile-view-only">';
466 466
         $content .= '<br>';
467 467
         $content .= $attendee instanceof EE_Attendee ? $attendee->full_name() : '';
468
-        $content .= '&nbsp;' . sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
469
-        $content .= '<br>' . sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
468
+        $content .= '&nbsp;'.sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
469
+        $content .= '<br>'.sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
470 470
         $content .= '</div>';
471 471
         return $content;
472 472
     }
@@ -551,12 +551,12 @@  discard block
 block discarded – undo
551 551
                   . $event_name
552 552
                   . '</a>' : $event_name;
553 553
             $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(array('event_id' => $EVT_ID), REG_ADMIN_URL);
554
-            $actions['event_filter'] = '<a href="' . $edit_event_url . '" title="';
554
+            $actions['event_filter'] = '<a href="'.$edit_event_url.'" title="';
555 555
             $actions['event_filter'] .= sprintf(
556 556
                 esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
557 557
                 $event_name
558 558
             );
559
-            $actions['event_filter'] .= '">' . __('View Registrations', 'event_espresso') . '</a>';
559
+            $actions['event_filter'] .= '">'.__('View Registrations', 'event_espresso').'</a>';
560 560
         } else {
561 561
             $edit_event = $event_name;
562 562
             $actions['event_filter'] = '';
@@ -603,11 +603,11 @@  discard block
 block discarded – undo
603 603
     {
604 604
         $content = '<div class="ee-registration-event-datetimes-container">';
605 605
         $expand_toggle = count($datetime_strings) > 1
606
-            ? ' <span title="' . esc_attr__('Click to view all dates', 'event_espresso')
606
+            ? ' <span title="'.esc_attr__('Click to view all dates', 'event_espresso')
607 607
               . '" class="ee-js ee-more-datetimes-toggle dashicons dashicons-plus"></span>'
608 608
             : '';
609 609
         // get first item for initial visibility
610
-        $content .= '<div class="left">' . array_shift($datetime_strings) . '</div>';
610
+        $content .= '<div class="left">'.array_shift($datetime_strings).'</div>';
611 611
         $content .= $expand_toggle;
612 612
         if ($datetime_strings) {
613 613
             $content .= '<div style="clear:both"></div>';
@@ -660,14 +660,14 @@  discard block
 block discarded – undo
660 660
         $t = $item->get_first_related('Transaction');
661 661
         $payment_count = $t instanceof EE_Transaction ? $t->count_related('Payment') : 0;
662 662
         // append group count to name
663
-        $link .= '&nbsp;' . sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
663
+        $link .= '&nbsp;'.sprintf(__('(%1$s / %2$s)', 'event_espresso'), $item->count(), $item->group_size());
664 664
         // append reg_code
665
-        $link .= '<br>' . sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
665
+        $link .= '<br>'.sprintf(__('Reg Code: %s', 'event_espresso'), $item->get('REG_code'));
666 666
         // reg status text for accessibility
667 667
         $link .= '<br><span class="ee-status-text-small">'
668 668
                  . EEH_Template::pretty_status($item->status_ID(), false, 'sentence')
669 669
                  . '</span>';
670
-        $action = [ '_REG_ID' => $item->ID() ];
670
+        $action = ['_REG_ID' => $item->ID()];
671 671
         if (isset($this->_req_data['event_id'])) {
672 672
             $action['event_id'] = $item->event_ID();
673 673
         }
@@ -689,7 +689,7 @@  discard block
 block discarded – undo
689 689
                                 . $trash_lnk_url
690 690
                                 . '" title="'
691 691
                                 . esc_attr__('Trash Registration', 'event_espresso')
692
-                                . '">' . __('Trash', 'event_espresso') . '</a>';
692
+                                . '">'.__('Trash', 'event_espresso').'</a>';
693 693
         } elseif ($this->_view === 'trash') {
694 694
             // restore registration link
695 695
             if (EE_Registry::instance()->CAP->current_user_can(
@@ -705,8 +705,8 @@  discard block
 block discarded – undo
705 705
                 $actions['restore'] = '<a href="'
706 706
                                       . $restore_lnk_url
707 707
                                       . '" title="'
708
-                                      . esc_attr__('Restore Registration', 'event_espresso') . '">'
709
-                                      . __('Restore', 'event_espresso') . '</a>';
708
+                                      . esc_attr__('Restore Registration', 'event_espresso').'">'
709
+                                      . __('Restore', 'event_espresso').'</a>';
710 710
             }
711 711
             if (EE_Registry::instance()->CAP->current_user_can(
712 712
                 'ee_delete_registration',
@@ -779,7 +779,7 @@  discard block
 block discarded – undo
779 779
                                                                               . $ticket->name()
780 780
                                                                               . '</span><br />' : '';
781 781
         if ($item->final_price() > 0) {
782
-            $content .= '<span class="reg-pad-rght">' . $item->pretty_final_price() . '</span>';
782
+            $content .= '<span class="reg-pad-rght">'.$item->pretty_final_price().'</span>';
783 783
         } else {
784 784
             // free event
785 785
             $content .= '<span class="reg-overview-free-event-spn reg-pad-rght">'
@@ -806,7 +806,7 @@  discard block
 block discarded – undo
806 806
             : '<span class="TKT_name">'
807 807
               . $ticket->name()
808 808
               . '</span><br />';
809
-        $content .= '<span class="reg-pad-rght">' . $item->pretty_final_price() . '</span>';
809
+        $content .= '<span class="reg-pad-rght">'.$item->pretty_final_price().'</span>';
810 810
         return $content;
811 811
     }
812 812
 
@@ -824,7 +824,7 @@  discard block
 block discarded – undo
824 824
         $payment_method = $item->payment_method();
825 825
         $payment_method_name = $payment_method instanceof EE_Payment_Method ? $payment_method->admin_name()
826 826
             : __('Unknown', 'event_espresso');
827
-        $content = '<span class="reg-pad-rght">' . $item->pretty_paid() . '</span>';
827
+        $content = '<span class="reg-pad-rght">'.$item->pretty_paid().'</span>';
828 828
         if ($item->paid() > 0) {
829 829
             $content .= '<br><span class="ee-status-text-small">'
830 830
                         . sprintf(
@@ -872,7 +872,7 @@  discard block
 block discarded – undo
872 872
                   . esc_attr__('View Transaction', 'event_espresso')
873 873
                   . '">'
874 874
                   . $item->transaction()->pretty_total()
875
-                  . '</a></span>' : '<span class="reg-pad-rght">' . $item->transaction()->pretty_total() . '</span>';
875
+                  . '</a></span>' : '<span class="reg-pad-rght">'.$item->transaction()->pretty_total().'</span>';
876 876
         } else {
877 877
             return __("None", "event_espresso");
878 878
         }
@@ -918,7 +918,7 @@  discard block
 block discarded – undo
918 918
                       . esc_attr__('View Transaction', 'event_espresso')
919 919
                       . '">'
920 920
                       . $item->transaction()->pretty_paid()
921
-                      . '</a><span>' : '<span class="reg-pad-rght">' . $item->transaction()->pretty_paid() . '</span>';
921
+                      . '</a><span>' : '<span class="reg-pad-rght">'.$item->transaction()->pretty_paid().'</span>';
922 922
             }
923 923
         }
924 924
         return '&nbsp;';
@@ -988,8 +988,8 @@  discard block
 block discarded – undo
988 988
                                && $attendee instanceof EE_Attendee
989 989
             ? '
990 990
 			<li>
991
-			<a href="' . $edit_lnk_url . '" title="'
992
-              . esc_attr__('Edit Contact Details', 'event_espresso') . '" class="tiny-text">
991
+			<a href="' . $edit_lnk_url.'" title="'
992
+              . esc_attr__('Edit Contact Details', 'event_espresso').'" class="tiny-text">
993 993
 				<div class="ee-icon ee-icon-user-edit ee-icon-size-16"></div>
994 994
 			</a>
995 995
 			</li>' : '';
@@ -1061,7 +1061,7 @@  discard block
 block discarded – undo
1061 1061
                                                      'see_notifications_for',
1062 1062
                                                      null,
1063 1063
                                                      array('_REG_ID' => $item->ID())
1064
-                                                 ) . '</li>';
1064
+                                                 ).'</li>';
1065 1065
         }
1066 1066
         $actions = apply_filters('FHEE__EE_Registrations_List_Table__column_actions__actions', $actions, $item, $this);
1067 1067
         return $this->_action_string(implode('', $actions), $item, 'ul', 'reg-overview-actions-ul');
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 2 patches
Spacing   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -65,7 +65,7 @@  discard block
 block discarded – undo
65 65
         // when adding a new registration...
66 66
         if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67 67
             EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
68
+            if ( ! isset($this->_req_data['processing_registration'])
69 69
                 || absint($this->_req_data['processing_registration']) !== 1
70 70
             ) {
71 71
                 // and it's NOT the attendee information reg step
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
         // style
659 659
         wp_register_style(
660 660
             'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
661
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
662 662
             array('ee-admin-css'),
663 663
             EVENT_ESPRESSO_VERSION
664 664
         );
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
         // script
667 667
         wp_register_script(
668 668
             'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
669
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
670 670
             array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671 671
             EVENT_ESPRESSO_VERSION,
672 672
             true
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
         wp_dequeue_style('espresso_reg');
705 705
         wp_register_style(
706 706
             'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
707
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
708 708
             array('ee-admin-css'),
709 709
             EVENT_ESPRESSO_VERSION
710 710
         );
@@ -716,7 +716,7 @@  discard block
 block discarded – undo
716 716
     {
717 717
         wp_register_script(
718 718
             'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
719
+            REG_ASSETS_URL.'spco_for_admin.js',
720 720
             array('underscore', 'jquery'),
721 721
             EVENT_ESPRESSO_VERSION,
722 722
             true
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
         }
951 951
         $sc_items = array(
952 952
             'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
953
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
954 954
                 'desc'  => EEH_Template::pretty_status(
955 955
                     EEM_Registration::status_id_approved,
956 956
                     false,
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
                 ),
959 959
             ),
960 960
             'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
961
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
962 962
                 'desc'  => EEH_Template::pretty_status(
963 963
                     EEM_Registration::status_id_pending_payment,
964 964
                     false,
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
                 ),
967 967
             ),
968 968
             'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
969
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
970 970
                 'desc'  => EEH_Template::pretty_status(
971 971
                     EEM_Registration::status_id_wait_list,
972 972
                     false,
@@ -974,7 +974,7 @@  discard block
 block discarded – undo
974 974
                 ),
975 975
             ),
976 976
             'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
977
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_incomplete,
978 978
                 'desc'  => EEH_Template::pretty_status(
979 979
                     EEM_Registration::status_id_incomplete,
980 980
                     false,
@@ -982,7 +982,7 @@  discard block
 block discarded – undo
982 982
                 ),
983 983
             ),
984 984
             'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
985
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
986 986
                 'desc'  => EEH_Template::pretty_status(
987 987
                     EEM_Registration::status_id_not_approved,
988 988
                     false,
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
                 ),
991 991
             ),
992 992
             'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
993
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
994 994
                 'desc'  => EEH_Template::pretty_status(
995 995
                     EEM_Registration::status_id_declined,
996 996
                     false,
@@ -998,7 +998,7 @@  discard block
 block discarded – undo
998 998
                 ),
999 999
             ),
1000 1000
             'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1001
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1002 1002
                 'desc'  => EEH_Template::pretty_status(
1003 1003
                     EEM_Registration::status_id_cancelled,
1004 1004
                     false,
@@ -1033,13 +1033,13 @@  discard block
 block discarded – undo
1033 1033
                         'event_espresso'
1034 1034
                     ),
1035 1035
                     '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1036
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
1037 1037
                         array(
1038 1038
                             'action' => 'edit_attendee',
1039 1039
                             'post'   => $ATT_ID,
1040 1040
                         ),
1041 1041
                         REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1042
+                    ).'">'.$attendee->full_name().'</a>',
1043 1043
                     '</h3>'
1044 1044
                 );
1045 1045
             }
@@ -1050,7 +1050,7 @@  discard block
 block discarded – undo
1050 1050
                 'espresso_registrations_new_registration',
1051 1051
                 $EVT_ID
1052 1052
             )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1053
+                $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1054 1054
                     'new_registration',
1055 1055
                     'add-registrant',
1056 1056
                     array('event_id' => $EVT_ID),
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
                 $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091 1091
                 $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092 1092
                 $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1093
+                $this->_template_args['admin_page_header'] .= ' ( '.$datetime->start_date().' )';
1094 1094
                 $this->_template_args['admin_page_header'] .= '</span></h3>';
1095 1095
             }
1096 1096
         }
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
             return true;
1117 1117
         }
1118 1118
         $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1119
+        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120 1120
         if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121 1121
             return true;
1122 1122
         } else {
@@ -1200,7 +1200,7 @@  discard block
 block discarded – undo
1200 1200
             'caps'                     => EEM_Registration::caps_read_admin,
1201 1201
             'default_where_conditions' => 'this_model_only',
1202 1202
         );
1203
-        if (! $count) {
1203
+        if ( ! $count) {
1204 1204
             $query_params = array_merge(
1205 1205
                 $query_params,
1206 1206
                 $this->_get_orderby_for_registrations_query(),
@@ -1221,7 +1221,7 @@  discard block
 block discarded – undo
1221 1221
     protected function addAttendeeIdToWhereConditions(array $request)
1222 1222
     {
1223 1223
         $where = array();
1224
-        if (! empty($request['ATT_ID'])) {
1224
+        if ( ! empty($request['ATT_ID'])) {
1225 1225
             $where['ATT_ID'] = absint($request['ATT_ID']);
1226 1226
         }
1227 1227
         return $where;
@@ -1237,7 +1237,7 @@  discard block
 block discarded – undo
1237 1237
     protected function _add_event_id_to_where_conditions(array $request)
1238 1238
     {
1239 1239
         $where = array();
1240
-        if (! empty($request['event_id'])) {
1240
+        if ( ! empty($request['event_id'])) {
1241 1241
             $where['EVT_ID'] = absint($request['event_id']);
1242 1242
         }
1243 1243
         return $where;
@@ -1253,7 +1253,7 @@  discard block
 block discarded – undo
1253 1253
     protected function _add_category_id_to_where_conditions(array $request)
1254 1254
     {
1255 1255
         $where = array();
1256
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1256
+        if ( ! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257 1257
             $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258 1258
         }
1259 1259
         return $where;
@@ -1269,10 +1269,10 @@  discard block
 block discarded – undo
1269 1269
     protected function _add_datetime_id_to_where_conditions(array $request)
1270 1270
     {
1271 1271
         $where = array();
1272
-        if (! empty($request['datetime_id'])) {
1272
+        if ( ! empty($request['datetime_id'])) {
1273 1273
             $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274 1274
         }
1275
-        if (! empty($request['DTT_ID'])) {
1275
+        if ( ! empty($request['DTT_ID'])) {
1276 1276
             $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277 1277
         }
1278 1278
         return $where;
@@ -1298,7 +1298,7 @@  discard block
 block discarded – undo
1298 1298
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1299 1299
          * UNLESS viewing trashed registrations.
1300 1300
          */
1301
-        if (! empty($registration_status)) {
1301
+        if ( ! empty($registration_status)) {
1302 1302
             $where['STS_ID'] = $registration_status;
1303 1303
         } else {
1304 1304
             // make sure we exclude incomplete registrations, but only if not trashed.
@@ -1341,12 +1341,12 @@  discard block
 block discarded – undo
1341 1341
                 array(
1342 1342
                     EEM_Registration::instance()->convert_datetime_for_query(
1343 1343
                         'REG_date',
1344
-                        $now . ' 00:00:00',
1344
+                        $now.' 00:00:00',
1345 1345
                         'Y-m-d H:i:s'
1346 1346
                     ),
1347 1347
                     EEM_Registration::instance()->convert_datetime_for_query(
1348 1348
                         'REG_date',
1349
-                        $now . ' 23:59:59',
1349
+                        $now.' 23:59:59',
1350 1350
                         'Y-m-d H:i:s'
1351 1351
                     ),
1352 1352
                 ),
@@ -1359,12 +1359,12 @@  discard block
 block discarded – undo
1359 1359
                 array(
1360 1360
                     EEM_Registration::instance()->convert_datetime_for_query(
1361 1361
                         'REG_date',
1362
-                        $current_year_and_month . '-01 00:00:00',
1362
+                        $current_year_and_month.'-01 00:00:00',
1363 1363
                         'Y-m-d H:i:s'
1364 1364
                     ),
1365 1365
                     EEM_Registration::instance()->convert_datetime_for_query(
1366 1366
                         'REG_date',
1367
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1367
+                        $current_year_and_month.'-'.$days_this_month.' 23:59:59',
1368 1368
                         'Y-m-d H:i:s'
1369 1369
                     ),
1370 1370
                 ),
@@ -1379,18 +1379,18 @@  discard block
 block discarded – undo
1379 1379
                 : '';
1380 1380
             // if there is not a month or year then we can't go further
1381 1381
             if ($month_requested && $year_requested) {
1382
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1382
+                $days_in_month = date('t', strtotime($year_requested.'-'.$month_requested.'-'.'01'));
1383 1383
                 $where['REG_date'] = array(
1384 1384
                     'BETWEEN',
1385 1385
                     array(
1386 1386
                         EEM_Registration::instance()->convert_datetime_for_query(
1387 1387
                             'REG_date',
1388
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1388
+                            $year_requested.'-'.$month_requested.'-01 00:00:00',
1389 1389
                             'Y-m-d H:i:s'
1390 1390
                         ),
1391 1391
                         EEM_Registration::instance()->convert_datetime_for_query(
1392 1392
                             'REG_date',
1393
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1393
+                            $year_requested.'-'.$month_requested.'-'.$days_in_month.' 23:59:59',
1394 1394
                             'Y-m-d H:i:s'
1395 1395
                         ),
1396 1396
                     ),
@@ -1410,8 +1410,8 @@  discard block
 block discarded – undo
1410 1410
     protected function _add_search_to_where_conditions(array $request)
1411 1411
     {
1412 1412
         $where = array();
1413
-        if (! empty($request['s'])) {
1414
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1413
+        if ( ! empty($request['s'])) {
1414
+            $search_string = '%'.sanitize_text_field($request['s']).'%';
1415 1415
             $where['OR*search_conditions'] = array(
1416 1416
                 'Event.EVT_name'                          => array('LIKE', $search_string),
1417 1417
                 'Event.EVT_desc'                          => array('LIKE', $search_string),
@@ -1647,7 +1647,7 @@  discard block
 block discarded – undo
1647 1647
                 )
1648 1648
                 : '';
1649 1649
             // grab header
1650
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1650
+            $template_path = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1651 1651
             $this->_template_args['REG_ID'] = $this->_registration->ID();
1652 1652
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653 1653
                 $template_path,
@@ -1784,7 +1784,7 @@  discard block
 block discarded – undo
1784 1784
                             EEH_HTML::strong(
1785 1785
                                 $this->_registration->pretty_status(),
1786 1786
                                 '',
1787
-                                'status-' . $this->_registration->status_ID(),
1787
+                                'status-'.$this->_registration->status_ID(),
1788 1788
                                 'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789 1789
                             )
1790 1790
                         )
@@ -1839,14 +1839,14 @@  discard block
 block discarded – undo
1839 1839
     protected function _get_reg_statuses()
1840 1840
     {
1841 1841
         $reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1842
+        unset($reg_status_array[EEM_Registration::status_id_incomplete]);
1843 1843
         // get current reg status
1844 1844
         $current_status = $this->_registration->status_ID();
1845 1845
         // is registration for free event? This will determine whether to display the pending payment option
1846 1846
         if ($current_status !== EEM_Registration::status_id_pending_payment
1847 1847
             && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848 1848
         ) {
1849
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1849
+            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1850 1850
         }
1851 1851
         return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852 1852
     }
@@ -1938,7 +1938,7 @@  discard block
 block discarded – undo
1938 1938
         $success = false;
1939 1939
         // typecast $REG_IDs
1940 1940
         $REG_IDs = (array) $REG_IDs;
1941
-        if (! empty($REG_IDs)) {
1941
+        if ( ! empty($REG_IDs)) {
1942 1942
             $success = true;
1943 1943
             // set default status if none is passed
1944 1944
             $status = $status ? $status : EEM_Registration::status_id_pending_payment;
@@ -2086,7 +2086,7 @@  discard block
 block discarded – undo
2086 2086
             $action,
2087 2087
             $notify
2088 2088
         );
2089
-        $method = $action . '_registration';
2089
+        $method = $action.'_registration';
2090 2090
         if (method_exists($this, $method)) {
2091 2091
             $this->$method($notify);
2092 2092
         }
@@ -2317,7 +2317,7 @@  discard block
 block discarded – undo
2317 2317
         $this->_template_args['REG_ID'] = $this->_registration->ID();
2318 2318
         $this->_template_args['event_id'] = $this->_registration->event_ID();
2319 2319
         $template_path =
2320
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2320
+            REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2321 2321
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2322 2322
     }
2323 2323
 
@@ -2350,7 +2350,7 @@  discard block
 block discarded – undo
2350 2350
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2351 2351
             $this->_template_args['REG_ID'] = $this->_registration->ID();
2352 2352
             $template_path =
2353
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2353
+                REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2354 2354
             echo EEH_Template::display_template($template_path, $this->_template_args, true);
2355 2355
         }
2356 2356
     }
@@ -2367,7 +2367,7 @@  discard block
 block discarded – undo
2367 2367
     public function form_before_question_group($output)
2368 2368
     {
2369 2369
         EE_Error::doing_it_wrong(
2370
-            __CLASS__ . '::' . __FUNCTION__,
2370
+            __CLASS__.'::'.__FUNCTION__,
2371 2371
             esc_html__(
2372 2372
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2373 2373
                 'event_espresso'
@@ -2392,7 +2392,7 @@  discard block
 block discarded – undo
2392 2392
     public function form_after_question_group($output)
2393 2393
     {
2394 2394
         EE_Error::doing_it_wrong(
2395
-            __CLASS__ . '::' . __FUNCTION__,
2395
+            __CLASS__.'::'.__FUNCTION__,
2396 2396
             esc_html__(
2397 2397
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2398 2398
                 'event_espresso'
@@ -2430,7 +2430,7 @@  discard block
 block discarded – undo
2430 2430
     public function form_form_field_label_wrap($label)
2431 2431
     {
2432 2432
         EE_Error::doing_it_wrong(
2433
-            __CLASS__ . '::' . __FUNCTION__,
2433
+            __CLASS__.'::'.__FUNCTION__,
2434 2434
             esc_html__(
2435 2435
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2436 2436
                 'event_espresso'
@@ -2440,7 +2440,7 @@  discard block
 block discarded – undo
2440 2440
         return '
2441 2441
 			<tr>
2442 2442
 				<th>
2443
-					' . $label . '
2443
+					' . $label.'
2444 2444
 				</th>';
2445 2445
     }
2446 2446
 
@@ -2456,7 +2456,7 @@  discard block
 block discarded – undo
2456 2456
     public function form_form_field_input__wrap($input)
2457 2457
     {
2458 2458
         EE_Error::doing_it_wrong(
2459
-            __CLASS__ . '::' . __FUNCTION__,
2459
+            __CLASS__.'::'.__FUNCTION__,
2460 2460
             esc_html__(
2461 2461
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2462 2462
                 'event_espresso'
@@ -2465,7 +2465,7 @@  discard block
 block discarded – undo
2465 2465
         );
2466 2466
         return '
2467 2467
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2468
-					' . $input . '
2468
+					' . $input.'
2469 2469
 				</td>
2470 2470
 			</tr>';
2471 2471
     }
@@ -2509,8 +2509,8 @@  discard block
 block discarded – undo
2509 2509
      */
2510 2510
     protected function _get_reg_custom_questions_form($REG_ID)
2511 2511
     {
2512
-        if (! $this->_reg_custom_questions_form) {
2513
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2512
+        if ( ! $this->_reg_custom_questions_form) {
2513
+            require_once(REG_ADMIN.'form_sections'.DS.'EE_Registration_Custom_Questions_Form.form.php');
2514 2514
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2515 2515
                 EEM_Registration::instance()->get_one_by_ID($REG_ID)
2516 2516
             );
@@ -2533,7 +2533,7 @@  discard block
 block discarded – undo
2533 2533
      */
2534 2534
     private function _save_reg_custom_questions_form($REG_ID = false)
2535 2535
     {
2536
-        if (! $REG_ID) {
2536
+        if ( ! $REG_ID) {
2537 2537
             EE_Error::add_error(
2538 2538
                 esc_html__(
2539 2539
                     'An error occurred. No registration ID was received.',
@@ -2624,28 +2624,28 @@  discard block
 block discarded – undo
2624 2624
                     ? $registration->attendee()
2625 2625
                     : EEM_Attendee::instance()
2626 2626
                                   ->create_default_object();
2627
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2628
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2629
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2630
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2631
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2632
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2627
+                $this->_template_args['attendees'][$att_nmbr]['STS_ID'] = $registration->status_ID();
2628
+                $this->_template_args['attendees'][$att_nmbr]['fname'] = $attendee->fname();
2629
+                $this->_template_args['attendees'][$att_nmbr]['lname'] = $attendee->lname();
2630
+                $this->_template_args['attendees'][$att_nmbr]['email'] = $attendee->email();
2631
+                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2632
+                $this->_template_args['attendees'][$att_nmbr]['address'] = implode(
2633 2633
                     ', ',
2634 2634
                     $attendee->full_address_as_array()
2635 2635
                 );
2636
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2636
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2637 2637
                     array(
2638 2638
                         'action' => 'edit_attendee',
2639 2639
                         'post'   => $attendee->ID(),
2640 2640
                     ),
2641 2641
                     REG_ADMIN_URL
2642 2642
                 );
2643
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2643
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] = $registration->event_obj()->name();
2644 2644
                 $att_nmbr++;
2645 2645
             }
2646 2646
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2647 2647
         }
2648
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2648
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2649 2649
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2650 2650
     }
2651 2651
 
@@ -2669,11 +2669,11 @@  discard block
 block discarded – undo
2669 2669
         // now let's determine if this is not the primary registration.  If it isn't then we set the
2670 2670
         // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2671 2671
         // primary registration object (that way we know if we need to show create button or not)
2672
-        if (! $this->_registration->is_primary_registrant()) {
2672
+        if ( ! $this->_registration->is_primary_registrant()) {
2673 2673
             $primary_registration = $this->_registration->get_primary_registration();
2674 2674
             $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2675 2675
                 : null;
2676
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2676
+            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2677 2677
                 // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2678 2678
                 // custom attendee object so let's not worry about the primary reg.
2679 2679
                 $primary_registration = null;
@@ -2707,7 +2707,7 @@  discard block
 block discarded – undo
2707 2707
             ) : '';
2708 2708
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2709 2709
         $this->_template_args['att_check'] = $att_check;
2710
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2710
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2711 2711
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2712 2712
     }
2713 2713
 
@@ -2745,7 +2745,7 @@  discard block
 block discarded – undo
2745 2745
         $success = 0;
2746 2746
         $overwrite_msgs = false;
2747 2747
         // Checkboxes
2748
-        if (! is_array($this->_req_data['_REG_ID'])) {
2748
+        if ( ! is_array($this->_req_data['_REG_ID'])) {
2749 2749
             $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2750 2750
         }
2751 2751
         $reg_count = count($this->_req_data['_REG_ID']);
@@ -2754,7 +2754,7 @@  discard block
 block discarded – undo
2754 2754
             /** @var EE_Registration $REG */
2755 2755
             $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2756 2756
             $payments = $REG->registration_payments();
2757
-            if (! empty($payments)) {
2757
+            if ( ! empty($payments)) {
2758 2758
                 $name = $REG->attendee() instanceof EE_Attendee
2759 2759
                     ? $REG->attendee()->full_name()
2760 2760
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2815,17 +2815,17 @@  discard block
 block discarded – undo
2815 2815
         $REG_MDL = EEM_Registration::instance();
2816 2816
         $success = 1;
2817 2817
         // Checkboxes
2818
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2818
+        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2819 2819
             // if array has more than one element than success message should be plural
2820 2820
             $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2821 2821
             // cycle thru checkboxes
2822 2822
             while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2823 2823
                 $REG = $REG_MDL->get_one_by_ID($REG_ID);
2824
-                if (! $REG instanceof EE_Registration) {
2824
+                if ( ! $REG instanceof EE_Registration) {
2825 2825
                     continue;
2826 2826
                 }
2827 2827
                 $deleted = $this->_delete_registration($REG);
2828
-                if (! $deleted) {
2828
+                if ( ! $deleted) {
2829 2829
                     $success = 0;
2830 2830
                 }
2831 2831
             }
@@ -2834,7 +2834,7 @@  discard block
 block discarded – undo
2834 2834
             $REG_ID = $this->_req_data['_REG_ID'];
2835 2835
             $REG = $REG_MDL->get_one_by_ID($REG_ID);
2836 2836
             $deleted = $this->_delete_registration($REG);
2837
-            if (! $deleted) {
2837
+            if ( ! $deleted) {
2838 2838
                 $success = 0;
2839 2839
             }
2840 2840
         }
@@ -2868,11 +2868,11 @@  discard block
 block discarded – undo
2868 2868
         $REGS = $TXN->get_many_related('Registration');
2869 2869
         $all_trashed = true;
2870 2870
         foreach ($REGS as $registration) {
2871
-            if (! $registration->get('REG_deleted')) {
2871
+            if ( ! $registration->get('REG_deleted')) {
2872 2872
                 $all_trashed = false;
2873 2873
             }
2874 2874
         }
2875
-        if (! $all_trashed) {
2875
+        if ( ! $all_trashed) {
2876 2876
             EE_Error::add_error(
2877 2877
                 esc_html__(
2878 2878
                     'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
@@ -2931,7 +2931,7 @@  discard block
 block discarded – undo
2931 2931
      */
2932 2932
     public function new_registration()
2933 2933
     {
2934
-        if (! $this->_set_reg_event()) {
2934
+        if ( ! $this->_set_reg_event()) {
2935 2935
             throw new EE_Error(
2936 2936
                 esc_html__(
2937 2937
                     'Unable to continue with registering because there is no Event ID in the request',
@@ -2941,8 +2941,8 @@  discard block
 block discarded – undo
2941 2941
         }
2942 2942
         EE_Registry::instance()->REQ->set_espresso_page(true);
2943 2943
         // gotta start with a clean slate if we're not coming here via ajax
2944
-        if (! defined('DOING_AJAX')
2945
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2944
+        if ( ! defined('DOING_AJAX')
2945
+            && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2946 2946
         ) {
2947 2947
             EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2948 2948
         }
@@ -2975,7 +2975,7 @@  discard block
 block discarded – undo
2975 2975
         }
2976 2976
         // grab header
2977 2977
         $template_path =
2978
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2978
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2979 2979
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2980 2980
             $template_path,
2981 2981
             $this->_template_args,
@@ -3016,7 +3016,7 @@  discard block
 block discarded – undo
3016 3016
                 '</b>'
3017 3017
             );
3018 3018
             return '
3019
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3019
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
3020 3020
 	<script >
3021 3021
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
3022 3022
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -3084,7 +3084,7 @@  discard block
 block discarded – undo
3084 3084
         // we come back to the process_registration_step route.
3085 3085
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3086 3086
         return EEH_Template::display_template(
3087
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3087
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
3088 3088
             $template_args,
3089 3089
             true
3090 3090
         );
@@ -3106,8 +3106,8 @@  discard block
 block discarded – undo
3106 3106
         if (is_object($this->_reg_event)) {
3107 3107
             return true;
3108 3108
         }
3109
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3110
-        if (! $EVT_ID) {
3109
+        $EVT_ID = ( ! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3110
+        if ( ! $EVT_ID) {
3111 3111
             return false;
3112 3112
         }
3113 3113
         $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
@@ -3139,8 +3139,8 @@  discard block
 block discarded – undo
3139 3139
         $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3140 3140
         // if doing ajax then we need to verify the nonce
3141 3141
         if (defined('DOING_AJAX')) {
3142
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3143
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3142
+            $nonce = isset($this->_req_data[$this->_req_nonce])
3143
+                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3144 3144
             $this->_verify_nonce($nonce, $this->_req_nonce);
3145 3145
         }
3146 3146
         switch ($step) {
@@ -3176,7 +3176,7 @@  discard block
 block discarded – undo
3176 3176
                 }
3177 3177
                 break;
3178 3178
             case 'questions':
3179
-                if (! isset(
3179
+                if ( ! isset(
3180 3180
                     $this->_req_data['txn_reg_status_change'],
3181 3181
                     $this->_req_data['txn_reg_status_change']['send_notifications']
3182 3182
                 )
@@ -3191,7 +3191,7 @@  discard block
 block discarded – undo
3191 3191
                         $grand_total->save_this_and_descendants_to_txn();
3192 3192
                     }
3193 3193
                 }
3194
-                if (! $transaction instanceof EE_Transaction) {
3194
+                if ( ! $transaction instanceof EE_Transaction) {
3195 3195
                     $query_args = array(
3196 3196
                         'action'                  => 'new_registration',
3197 3197
                         'processing_registration' => 2,
@@ -3214,7 +3214,7 @@  discard block
 block discarded – undo
3214 3214
                     }
3215 3215
                 }
3216 3216
                 // maybe update status, and make sure to save transaction if not done already
3217
-                if (! $transaction->update_status_based_on_total_paid()) {
3217
+                if ( ! $transaction->update_status_based_on_total_paid()) {
3218 3218
                     $transaction->save();
3219 3219
                 }
3220 3220
                 EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
@@ -3297,7 +3297,7 @@  discard block
 block discarded – undo
3297 3297
     public function get_attendees($per_page, $count = false, $trash = false)
3298 3298
     {
3299 3299
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3300
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3300
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3301 3301
         $ATT_MDL = EEM_Attendee::instance();
3302 3302
         $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3303 3303
         switch ($this->_req_data['orderby']) {
@@ -3336,8 +3336,8 @@  discard block
 block discarded – undo
3336 3336
             ? $this->_req_data['perpage']
3337 3337
             : $per_page;
3338 3338
         $_where = array();
3339
-        if (! empty($this->_req_data['s'])) {
3340
-            $sstr = '%' . $this->_req_data['s'] . '%';
3339
+        if ( ! empty($this->_req_data['s'])) {
3340
+            $sstr = '%'.$this->_req_data['s'].'%';
3341 3341
             $_where['OR'] = array(
3342 3342
                 'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3343 3343
                 'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
@@ -3364,7 +3364,7 @@  discard block
 block discarded – undo
3364 3364
             'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3365 3365
             'limit'         => $limit,
3366 3366
         );
3367
-        if (! $count) {
3367
+        if ( ! $count) {
3368 3368
             $query_args['order_by'] = array($orderby => $sort);
3369 3369
         }
3370 3370
         if ($trash) {
@@ -3407,7 +3407,7 @@  discard block
 block discarded – undo
3407 3407
      */
3408 3408
     public function _registrations_report_base($method_name_for_getting_query_params)
3409 3409
     {
3410
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3410
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3411 3411
             wp_redirect(
3412 3412
                 EE_Admin_Page::add_query_args_and_nonce(
3413 3413
                     array(
@@ -3439,8 +3439,8 @@  discard block
 block discarded – undo
3439 3439
                 'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3440 3440
             );
3441 3441
             $this->_req_data = array_merge($this->_req_data, $new_request_args);
3442
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3443
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3442
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3443
+                require_once(EE_CLASSES.'EE_Export.class.php');
3444 3444
                 $EE_Export = EE_Export::instance($this->_req_data);
3445 3445
                 $EE_Export->export();
3446 3446
             }
@@ -3461,8 +3461,8 @@  discard block
 block discarded – undo
3461 3461
 
3462 3462
     public function _contact_list_export()
3463 3463
     {
3464
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3465
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3464
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3465
+            require_once(EE_CLASSES.'EE_Export.class.php');
3466 3466
             $EE_Export = EE_Export::instance($this->_req_data);
3467 3467
             $EE_Export->export_attendees();
3468 3468
         }
@@ -3471,7 +3471,7 @@  discard block
 block discarded – undo
3471 3471
 
3472 3472
     public function _contact_list_report()
3473 3473
     {
3474
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3474
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3475 3475
             wp_redirect(
3476 3476
                 EE_Admin_Page::add_query_args_and_nonce(
3477 3477
                     array(
@@ -3483,8 +3483,8 @@  discard block
 block discarded – undo
3483 3483
                 )
3484 3484
             );
3485 3485
         } else {
3486
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3487
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3486
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3487
+                require_once(EE_CLASSES.'EE_Export.class.php');
3488 3488
                 $EE_Export = EE_Export::instance($this->_req_data);
3489 3489
                 $EE_Export->report_attendees();
3490 3490
             }
@@ -3570,7 +3570,7 @@  discard block
 block discarded – undo
3570 3570
             $updated_fields = array(
3571 3571
                 'ATT_fname'     => $this->_req_data['ATT_fname'],
3572 3572
                 'ATT_lname'     => $this->_req_data['ATT_lname'],
3573
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3573
+                'ATT_full_name' => $this->_req_data['ATT_fname'].' '.$this->_req_data['ATT_lname'],
3574 3574
                 'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3575 3575
                 'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3576 3576
                 'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
@@ -3646,17 +3646,17 @@  discard block
 block discarded – undo
3646 3646
             'postexcerpt',
3647 3647
             esc_html__('Excerpt', 'event_espresso'),
3648 3648
             'post_excerpt_meta_box',
3649
-            $this->_cpt_routes[ $this->_req_action ],
3649
+            $this->_cpt_routes[$this->_req_action],
3650 3650
             'normal',
3651 3651
             'core'
3652 3652
         );
3653
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3653
+        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3654 3654
         if (post_type_supports('espresso_attendees', 'excerpt')) {
3655 3655
             add_meta_box(
3656 3656
                 'postexcerpt',
3657 3657
                 esc_html__('Short Biography', 'event_espresso'),
3658 3658
                 'post_excerpt_meta_box',
3659
-                $this->_cpt_routes[ $this->_req_action ],
3659
+                $this->_cpt_routes[$this->_req_action],
3660 3660
                 'normal'
3661 3661
             );
3662 3662
         }
@@ -3665,7 +3665,7 @@  discard block
 block discarded – undo
3665 3665
                 'commentsdiv',
3666 3666
                 esc_html__('Notes on the Contact', 'event_espresso'),
3667 3667
                 'post_comment_meta_box',
3668
-                $this->_cpt_routes[ $this->_req_action ],
3668
+                $this->_cpt_routes[$this->_req_action],
3669 3669
                 'normal',
3670 3670
                 'core'
3671 3671
             );
@@ -3674,7 +3674,7 @@  discard block
 block discarded – undo
3674 3674
             'attendee_contact_info',
3675 3675
             esc_html__('Contact Info', 'event_espresso'),
3676 3676
             array($this, 'attendee_contact_info'),
3677
-            $this->_cpt_routes[ $this->_req_action ],
3677
+            $this->_cpt_routes[$this->_req_action],
3678 3678
             'side',
3679 3679
             'core'
3680 3680
         );
@@ -3682,7 +3682,7 @@  discard block
 block discarded – undo
3682 3682
             'attendee_details_address',
3683 3683
             esc_html__('Address Details', 'event_espresso'),
3684 3684
             array($this, 'attendee_address_details'),
3685
-            $this->_cpt_routes[ $this->_req_action ],
3685
+            $this->_cpt_routes[$this->_req_action],
3686 3686
             'normal',
3687 3687
             'core'
3688 3688
         );
@@ -3690,7 +3690,7 @@  discard block
 block discarded – undo
3690 3690
             'attendee_registrations',
3691 3691
             esc_html__('Registrations for this Contact', 'event_espresso'),
3692 3692
             array($this, 'attendee_registrations_meta_box'),
3693
-            $this->_cpt_routes[ $this->_req_action ],
3693
+            $this->_cpt_routes[$this->_req_action],
3694 3694
             'normal',
3695 3695
             'high'
3696 3696
         );
@@ -3791,7 +3791,7 @@  discard block
 block discarded – undo
3791 3791
             )
3792 3792
         );
3793 3793
         $template =
3794
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3794
+            REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3795 3795
         EEH_Template::display_template($template, $this->_template_args);
3796 3796
     }
3797 3797
 
@@ -3810,7 +3810,7 @@  discard block
 block discarded – undo
3810 3810
         $this->_template_args['attendee'] = $this->_cpt_model_obj;
3811 3811
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3812 3812
         $template =
3813
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3813
+            REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3814 3814
         EEH_Template::display_template($template, $this->_template_args);
3815 3815
     }
3816 3816
 
@@ -3825,7 +3825,7 @@  discard block
 block discarded – undo
3825 3825
     public function after_title_form_fields($post)
3826 3826
     {
3827 3827
         if ($post->post_type == 'espresso_attendees') {
3828
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3828
+            $template = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3829 3829
             $template_args['attendee'] = $this->_cpt_model_obj;
3830 3830
             EEH_Template::display_template($template, $template_args);
3831 3831
         }
@@ -3849,14 +3849,14 @@  discard block
 block discarded – undo
3849 3849
         $ATT_MDL = EEM_Attendee::instance();
3850 3850
         $success = 1;
3851 3851
         // Checkboxes
3852
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3852
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3853 3853
             // if array has more than one element than success message should be plural
3854 3854
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3855 3855
             // cycle thru checkboxes
3856 3856
             while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3857 3857
                 $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3858 3858
                     : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3859
-                if (! $updated) {
3859
+                if ( ! $updated) {
3860 3860
                     $success = 0;
3861 3861
                 }
3862 3862
             }
@@ -3867,7 +3867,7 @@  discard block
 block discarded – undo
3867 3867
             $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3868 3868
             $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3869 3869
             $updated = $att->save();
3870
-            if (! $updated) {
3870
+            if ( ! $updated) {
3871 3871
                 $success = 0;
3872 3872
             }
3873 3873
         }
Please login to merge, or discard this patch.
Indentation   +3821 added lines, -3821 removed lines patch added patch discarded remove patch
@@ -19,2396 +19,2396 @@  discard block
 block discarded – undo
19 19
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
20 20
 {
21 21
 
22
-    /**
23
-     * @var EE_Registration
24
-     */
25
-    private $_registration;
26
-
27
-    /**
28
-     * @var EE_Event
29
-     */
30
-    private $_reg_event;
31
-
32
-    /**
33
-     * @var EE_Session
34
-     */
35
-    private $_session;
36
-
37
-    private static $_reg_status;
38
-
39
-    /**
40
-     * Form for displaying the custom questions for this registration.
41
-     * This gets used a few times throughout the request so its best to cache it
42
-     *
43
-     * @var EE_Registration_Custom_Questions_Form
44
-     */
45
-    protected $_reg_custom_questions_form = null;
46
-
47
-
48
-    /**
49
-     *        constructor
50
-     *
51
-     * @Constructor
52
-     * @access public
53
-     * @param bool $routing
54
-     * @return Registrations_Admin_Page
55
-     */
56
-    public function __construct($routing = true)
57
-    {
58
-        parent::__construct($routing);
59
-        add_action('wp_loaded', array($this, 'wp_loaded'));
60
-    }
61
-
62
-
63
-    public function wp_loaded()
64
-    {
65
-        // when adding a new registration...
66
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
-            EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
69
-                || absint($this->_req_data['processing_registration']) !== 1
70
-            ) {
71
-                // and it's NOT the attendee information reg step
72
-                // force cookie expiration by setting time to last week
73
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
-                // and update the global
75
-                $_COOKIE['ee_registration_added'] = 0;
76
-            }
77
-        }
78
-    }
79
-
80
-
81
-    protected function _init_page_props()
82
-    {
83
-        $this->page_slug = REG_PG_SLUG;
84
-        $this->_admin_base_url = REG_ADMIN_URL;
85
-        $this->_admin_base_path = REG_ADMIN;
86
-        $this->page_label = esc_html__('Registrations', 'event_espresso');
87
-        $this->_cpt_routes = array(
88
-            'add_new_attendee' => 'espresso_attendees',
89
-            'edit_attendee'    => 'espresso_attendees',
90
-            'insert_attendee'  => 'espresso_attendees',
91
-            'update_attendee'  => 'espresso_attendees',
92
-        );
93
-        $this->_cpt_model_names = array(
94
-            'add_new_attendee' => 'EEM_Attendee',
95
-            'edit_attendee'    => 'EEM_Attendee',
96
-        );
97
-        $this->_cpt_edit_routes = array(
98
-            'espresso_attendees' => 'edit_attendee',
99
-        );
100
-        $this->_pagenow_map = array(
101
-            'add_new_attendee' => 'post-new.php',
102
-            'edit_attendee'    => 'post.php',
103
-            'trash'            => 'post.php',
104
-        );
105
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
-        // add filters so that the comment urls don't take users to a confusing 404 page
107
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
-    }
109
-
110
-
111
-    public function clear_comment_link($link, $comment, $args)
112
-    {
113
-        // gotta make sure this only happens on this route
114
-        $post_type = get_post_type($comment->comment_post_ID);
115
-        if ($post_type === 'espresso_attendees') {
116
-            return '#commentsdiv';
117
-        }
118
-        return $link;
119
-    }
120
-
121
-
122
-    protected function _ajax_hooks()
123
-    {
124
-        // todo: all hooks for registrations ajax goes in here
125
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
-    }
127
-
128
-
129
-    protected function _define_page_props()
130
-    {
131
-        $this->_admin_page_title = $this->page_label;
132
-        $this->_labels = array(
133
-            'buttons'                      => array(
134
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
-                'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
-                'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
-            ),
143
-            'publishbox'                   => array(
144
-                'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
-                'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
-            ),
147
-            'hide_add_button_on_cpt_route' => array(
148
-                'edit_attendee' => true,
149
-            ),
150
-        );
151
-    }
152
-
153
-
154
-    /**
155
-     *        grab url requests and route them
156
-     *
157
-     * @access private
158
-     * @return void
159
-     */
160
-    public function _set_page_routes()
161
-    {
162
-        $this->_get_registration_status_array();
163
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
-            ? $this->_req_data['_REG_ID'] : 0;
165
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
167
-            : $reg_id;
168
-        $att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
-            ? $this->_req_data['ATT_ID'] : 0;
170
-        $att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
-            ? $this->_req_data['post']
172
-            : $att_id;
173
-        $this->_page_routes = array(
174
-            'default'                             => array(
175
-                'func'       => '_registrations_overview_list_table',
176
-                'capability' => 'ee_read_registrations',
177
-            ),
178
-            'view_registration'                   => array(
179
-                'func'       => '_registration_details',
180
-                'capability' => 'ee_read_registration',
181
-                'obj_id'     => $reg_id,
182
-            ),
183
-            'edit_registration'                   => array(
184
-                'func'               => '_update_attendee_registration_form',
185
-                'noheader'           => true,
186
-                'headers_sent_route' => 'view_registration',
187
-                'capability'         => 'ee_edit_registration',
188
-                'obj_id'             => $reg_id,
189
-                '_REG_ID'            => $reg_id,
190
-            ),
191
-            'trash_registrations'                 => array(
192
-                'func'       => '_trash_or_restore_registrations',
193
-                'args'       => array('trash' => true),
194
-                'noheader'   => true,
195
-                'capability' => 'ee_delete_registrations',
196
-            ),
197
-            'restore_registrations'               => array(
198
-                'func'       => '_trash_or_restore_registrations',
199
-                'args'       => array('trash' => false),
200
-                'noheader'   => true,
201
-                'capability' => 'ee_delete_registrations',
202
-            ),
203
-            'delete_registrations'                => array(
204
-                'func'       => '_delete_registrations',
205
-                'noheader'   => true,
206
-                'capability' => 'ee_delete_registrations',
207
-            ),
208
-            'new_registration'                    => array(
209
-                'func'       => 'new_registration',
210
-                'capability' => 'ee_edit_registrations',
211
-            ),
212
-            'process_reg_step'                    => array(
213
-                'func'       => 'process_reg_step',
214
-                'noheader'   => true,
215
-                'capability' => 'ee_edit_registrations',
216
-            ),
217
-            'redirect_to_txn'                     => array(
218
-                'func'       => 'redirect_to_txn',
219
-                'noheader'   => true,
220
-                'capability' => 'ee_edit_registrations',
221
-            ),
222
-            'change_reg_status'                   => array(
223
-                'func'       => '_change_reg_status',
224
-                'noheader'   => true,
225
-                'capability' => 'ee_edit_registration',
226
-                'obj_id'     => $reg_id,
227
-            ),
228
-            'approve_registration'                => array(
229
-                'func'       => 'approve_registration',
230
-                'noheader'   => true,
231
-                'capability' => 'ee_edit_registration',
232
-                'obj_id'     => $reg_id,
233
-            ),
234
-            'approve_and_notify_registration'     => array(
235
-                'func'       => 'approve_registration',
236
-                'noheader'   => true,
237
-                'args'       => array(true),
238
-                'capability' => 'ee_edit_registration',
239
-                'obj_id'     => $reg_id,
240
-            ),
241
-            'approve_registrations'               => array(
242
-                'func'       => 'bulk_action_on_registrations',
243
-                'noheader'   => true,
244
-                'capability' => 'ee_edit_registrations',
245
-                'args'       => array('approve'),
246
-            ),
247
-            'approve_and_notify_registrations'    => array(
248
-                'func'       => 'bulk_action_on_registrations',
249
-                'noheader'   => true,
250
-                'capability' => 'ee_edit_registrations',
251
-                'args'       => array('approve', true),
252
-            ),
253
-            'decline_registration'                => array(
254
-                'func'       => 'decline_registration',
255
-                'noheader'   => true,
256
-                'capability' => 'ee_edit_registration',
257
-                'obj_id'     => $reg_id,
258
-            ),
259
-            'decline_and_notify_registration'     => array(
260
-                'func'       => 'decline_registration',
261
-                'noheader'   => true,
262
-                'args'       => array(true),
263
-                'capability' => 'ee_edit_registration',
264
-                'obj_id'     => $reg_id,
265
-            ),
266
-            'decline_registrations'               => array(
267
-                'func'       => 'bulk_action_on_registrations',
268
-                'noheader'   => true,
269
-                'capability' => 'ee_edit_registrations',
270
-                'args'       => array('decline'),
271
-            ),
272
-            'decline_and_notify_registrations'    => array(
273
-                'func'       => 'bulk_action_on_registrations',
274
-                'noheader'   => true,
275
-                'capability' => 'ee_edit_registrations',
276
-                'args'       => array('decline', true),
277
-            ),
278
-            'pending_registration'                => array(
279
-                'func'       => 'pending_registration',
280
-                'noheader'   => true,
281
-                'capability' => 'ee_edit_registration',
282
-                'obj_id'     => $reg_id,
283
-            ),
284
-            'pending_and_notify_registration'     => array(
285
-                'func'       => 'pending_registration',
286
-                'noheader'   => true,
287
-                'args'       => array(true),
288
-                'capability' => 'ee_edit_registration',
289
-                'obj_id'     => $reg_id,
290
-            ),
291
-            'pending_registrations'               => array(
292
-                'func'       => 'bulk_action_on_registrations',
293
-                'noheader'   => true,
294
-                'capability' => 'ee_edit_registrations',
295
-                'args'       => array('pending'),
296
-            ),
297
-            'pending_and_notify_registrations'    => array(
298
-                'func'       => 'bulk_action_on_registrations',
299
-                'noheader'   => true,
300
-                'capability' => 'ee_edit_registrations',
301
-                'args'       => array('pending', true),
302
-            ),
303
-            'no_approve_registration'             => array(
304
-                'func'       => 'not_approve_registration',
305
-                'noheader'   => true,
306
-                'capability' => 'ee_edit_registration',
307
-                'obj_id'     => $reg_id,
308
-            ),
309
-            'no_approve_and_notify_registration'  => array(
310
-                'func'       => 'not_approve_registration',
311
-                'noheader'   => true,
312
-                'args'       => array(true),
313
-                'capability' => 'ee_edit_registration',
314
-                'obj_id'     => $reg_id,
315
-            ),
316
-            'no_approve_registrations'            => array(
317
-                'func'       => 'bulk_action_on_registrations',
318
-                'noheader'   => true,
319
-                'capability' => 'ee_edit_registrations',
320
-                'args'       => array('not_approve'),
321
-            ),
322
-            'no_approve_and_notify_registrations' => array(
323
-                'func'       => 'bulk_action_on_registrations',
324
-                'noheader'   => true,
325
-                'capability' => 'ee_edit_registrations',
326
-                'args'       => array('not_approve', true),
327
-            ),
328
-            'cancel_registration'                 => array(
329
-                'func'       => 'cancel_registration',
330
-                'noheader'   => true,
331
-                'capability' => 'ee_edit_registration',
332
-                'obj_id'     => $reg_id,
333
-            ),
334
-            'cancel_and_notify_registration'      => array(
335
-                'func'       => 'cancel_registration',
336
-                'noheader'   => true,
337
-                'args'       => array(true),
338
-                'capability' => 'ee_edit_registration',
339
-                'obj_id'     => $reg_id,
340
-            ),
341
-            'cancel_registrations'                => array(
342
-                'func'       => 'bulk_action_on_registrations',
343
-                'noheader'   => true,
344
-                'capability' => 'ee_edit_registrations',
345
-                'args'       => array('cancel'),
346
-            ),
347
-            'cancel_and_notify_registrations'     => array(
348
-                'func'       => 'bulk_action_on_registrations',
349
-                'noheader'   => true,
350
-                'capability' => 'ee_edit_registrations',
351
-                'args'       => array('cancel', true),
352
-            ),
353
-            'wait_list_registration'              => array(
354
-                'func'       => 'wait_list_registration',
355
-                'noheader'   => true,
356
-                'capability' => 'ee_edit_registration',
357
-                'obj_id'     => $reg_id,
358
-            ),
359
-            'wait_list_and_notify_registration'   => array(
360
-                'func'       => 'wait_list_registration',
361
-                'noheader'   => true,
362
-                'args'       => array(true),
363
-                'capability' => 'ee_edit_registration',
364
-                'obj_id'     => $reg_id,
365
-            ),
366
-            'contact_list'                        => array(
367
-                'func'       => '_attendee_contact_list_table',
368
-                'capability' => 'ee_read_contacts',
369
-            ),
370
-            'add_new_attendee'                    => array(
371
-                'func' => '_create_new_cpt_item',
372
-                'args' => array(
373
-                    'new_attendee' => true,
374
-                    'capability'   => 'ee_edit_contacts',
375
-                ),
376
-            ),
377
-            'edit_attendee'                       => array(
378
-                'func'       => '_edit_cpt_item',
379
-                'capability' => 'ee_edit_contacts',
380
-                'obj_id'     => $att_id,
381
-            ),
382
-            'duplicate_attendee'                  => array(
383
-                'func'       => '_duplicate_attendee',
384
-                'noheader'   => true,
385
-                'capability' => 'ee_edit_contacts',
386
-                'obj_id'     => $att_id,
387
-            ),
388
-            'insert_attendee'                     => array(
389
-                'func'       => '_insert_or_update_attendee',
390
-                'args'       => array(
391
-                    'new_attendee' => true,
392
-                ),
393
-                'noheader'   => true,
394
-                'capability' => 'ee_edit_contacts',
395
-            ),
396
-            'update_attendee'                     => array(
397
-                'func'       => '_insert_or_update_attendee',
398
-                'args'       => array(
399
-                    'new_attendee' => false,
400
-                ),
401
-                'noheader'   => true,
402
-                'capability' => 'ee_edit_contacts',
403
-                'obj_id'     => $att_id,
404
-            ),
405
-            'trash_attendees'                     => array(
406
-                'func'       => '_trash_or_restore_attendees',
407
-                'args'       => array(
408
-                    'trash' => 'true',
409
-                ),
410
-                'noheader'   => true,
411
-                'capability' => 'ee_delete_contacts',
412
-            ),
413
-            'trash_attendee'                      => array(
414
-                'func'       => '_trash_or_restore_attendees',
415
-                'args'       => array(
416
-                    'trash' => true,
417
-                ),
418
-                'noheader'   => true,
419
-                'capability' => 'ee_delete_contacts',
420
-                'obj_id'     => $att_id,
421
-            ),
422
-            'restore_attendees'                   => array(
423
-                'func'       => '_trash_or_restore_attendees',
424
-                'args'       => array(
425
-                    'trash' => false,
426
-                ),
427
-                'noheader'   => true,
428
-                'capability' => 'ee_delete_contacts',
429
-                'obj_id'     => $att_id,
430
-            ),
431
-            'resend_registration'                 => array(
432
-                'func'       => '_resend_registration',
433
-                'noheader'   => true,
434
-                'capability' => 'ee_send_message',
435
-            ),
436
-            'registrations_report'                => array(
437
-                'func'       => '_registrations_report',
438
-                'noheader'   => true,
439
-                'capability' => 'ee_read_registrations',
440
-            ),
441
-            'contact_list_export'                 => array(
442
-                'func'       => '_contact_list_export',
443
-                'noheader'   => true,
444
-                'capability' => 'export',
445
-            ),
446
-            'contact_list_report'                 => array(
447
-                'func'       => '_contact_list_report',
448
-                'noheader'   => true,
449
-                'capability' => 'ee_read_contacts',
450
-            ),
451
-        );
452
-    }
453
-
454
-
455
-    protected function _set_page_config()
456
-    {
457
-        $this->_page_config = array(
458
-            'default'           => array(
459
-                'nav'           => array(
460
-                    'label' => esc_html__('Overview', 'event_espresso'),
461
-                    'order' => 5,
462
-                ),
463
-                'help_tabs'     => array(
464
-                    'registrations_overview_help_tab'                       => array(
465
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
-                        'filename' => 'registrations_overview',
467
-                    ),
468
-                    'registrations_overview_table_column_headings_help_tab' => array(
469
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
-                        'filename' => 'registrations_overview_table_column_headings',
471
-                    ),
472
-                    'registrations_overview_filters_help_tab'               => array(
473
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
-                        'filename' => 'registrations_overview_filters',
475
-                    ),
476
-                    'registrations_overview_views_help_tab'                 => array(
477
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
478
-                        'filename' => 'registrations_overview_views',
479
-                    ),
480
-                    'registrations_regoverview_other_help_tab'              => array(
481
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
-                        'filename' => 'registrations_overview_other',
483
-                    ),
484
-                ),
485
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
486
-                'qtips'         => array('Registration_List_Table_Tips'),
487
-                'list_table'    => 'EE_Registrations_List_Table',
488
-                'require_nonce' => false,
489
-            ),
490
-            'view_registration' => array(
491
-                'nav'           => array(
492
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
493
-                    'order'      => 15,
494
-                    'url'        => isset($this->_req_data['_REG_ID'])
495
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
-                        : $this->_admin_base_url,
497
-                    'persistent' => false,
498
-                ),
499
-                'help_tabs'     => array(
500
-                    'registrations_details_help_tab'                    => array(
501
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
502
-                        'filename' => 'registrations_details',
503
-                    ),
504
-                    'registrations_details_table_help_tab'              => array(
505
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
-                        'filename' => 'registrations_details_table',
507
-                    ),
508
-                    'registrations_details_form_answers_help_tab'       => array(
509
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
-                        'filename' => 'registrations_details_form_answers',
511
-                    ),
512
-                    'registrations_details_registrant_details_help_tab' => array(
513
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
514
-                        'filename' => 'registrations_details_registrant_details',
515
-                    ),
516
-                ),
517
-                'help_tour'     => array('Registration_Details_Help_Tour'),
518
-                'metaboxes'     => array_merge(
519
-                    $this->_default_espresso_metaboxes,
520
-                    array('_registration_details_metaboxes')
521
-                ),
522
-                'require_nonce' => false,
523
-            ),
524
-            'new_registration'  => array(
525
-                'nav'           => array(
526
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
-                    'url'        => '#',
528
-                    'order'      => 15,
529
-                    'persistent' => false,
530
-                ),
531
-                'metaboxes'     => $this->_default_espresso_metaboxes,
532
-                'labels'        => array(
533
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
-                ),
535
-                'require_nonce' => false,
536
-            ),
537
-            'add_new_attendee'  => array(
538
-                'nav'           => array(
539
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
540
-                    'order'      => 15,
541
-                    'persistent' => false,
542
-                ),
543
-                'metaboxes'     => array_merge(
544
-                    $this->_default_espresso_metaboxes,
545
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
546
-                ),
547
-                'require_nonce' => false,
548
-            ),
549
-            'edit_attendee'     => array(
550
-                'nav'           => array(
551
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
-                    'order'      => 15,
553
-                    'persistent' => false,
554
-                    'url'        => isset($this->_req_data['ATT_ID'])
555
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
-                        : $this->_admin_base_url,
557
-                ),
558
-                'metaboxes'     => array('attendee_editor_metaboxes'),
559
-                'require_nonce' => false,
560
-            ),
561
-            'contact_list'      => array(
562
-                'nav'           => array(
563
-                    'label' => esc_html__('Contact List', 'event_espresso'),
564
-                    'order' => 20,
565
-                ),
566
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
567
-                'help_tabs'     => array(
568
-                    'registrations_contact_list_help_tab'                       => array(
569
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
-                        'filename' => 'registrations_contact_list',
571
-                    ),
572
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
573
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
-                        'filename' => 'registrations_contact_list_table_column_headings',
575
-                    ),
576
-                    'registrations_contact_list_views_help_tab'                 => array(
577
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
-                        'filename' => 'registrations_contact_list_views',
579
-                    ),
580
-                    'registrations_contact_list_other_help_tab'                 => array(
581
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
-                        'filename' => 'registrations_contact_list_other',
583
-                    ),
584
-                ),
585
-                'help_tour'     => array('Contact_List_Help_Tour'),
586
-                'metaboxes'     => array(),
587
-                'require_nonce' => false,
588
-            ),
589
-            // override default cpt routes
590
-            'create_new'        => '',
591
-            'edit'              => '',
592
-        );
593
-    }
594
-
595
-
596
-    /**
597
-     * The below methods aren't used by this class currently
598
-     */
599
-    protected function _add_screen_options()
600
-    {
601
-    }
602
-
603
-
604
-    protected function _add_feature_pointers()
605
-    {
606
-    }
607
-
608
-
609
-    public function admin_init()
610
-    {
611
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
-            'click "Update Registration Questions" to save your changes',
613
-            'event_espresso'
614
-        );
615
-    }
616
-
617
-
618
-    public function admin_notices()
619
-    {
620
-    }
621
-
622
-
623
-    public function admin_footer_scripts()
624
-    {
625
-    }
626
-
627
-
628
-    /**
629
-     *        get list of registration statuses
630
-     *
631
-     * @access private
632
-     * @return void
633
-     * @throws EE_Error
634
-     */
635
-    private function _get_registration_status_array()
636
-    {
637
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
-    }
639
-
640
-
641
-    protected function _add_screen_options_default()
642
-    {
643
-        $this->_per_page_screen_option();
644
-    }
645
-
646
-
647
-    protected function _add_screen_options_contact_list()
648
-    {
649
-        $page_title = $this->_admin_page_title;
650
-        $this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
-        $this->_per_page_screen_option();
652
-        $this->_admin_page_title = $page_title;
653
-    }
654
-
655
-
656
-    public function load_scripts_styles()
657
-    {
658
-        // style
659
-        wp_register_style(
660
-            'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
-            array('ee-admin-css'),
663
-            EVENT_ESPRESSO_VERSION
664
-        );
665
-        wp_enqueue_style('espresso_reg');
666
-        // script
667
-        wp_register_script(
668
-            'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
-            EVENT_ESPRESSO_VERSION,
672
-            true
673
-        );
674
-        wp_enqueue_script('espresso_reg');
675
-    }
676
-
677
-
678
-    public function load_scripts_styles_edit_attendee()
679
-    {
680
-        // stuff to only show up on our attendee edit details page.
681
-        $attendee_details_translations = array(
682
-            'att_publish_text' => sprintf(
683
-                esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
-                $this->_cpt_model_obj->get_datetime('ATT_created')
685
-            ),
686
-        );
687
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
-        wp_enqueue_script('jquery-validate');
689
-    }
690
-
691
-
692
-    public function load_scripts_styles_view_registration()
693
-    {
694
-        // styles
695
-        wp_enqueue_style('espresso-ui-theme');
696
-        // scripts
697
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
698
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
-    }
700
-
701
-
702
-    public function load_scripts_styles_contact_list()
703
-    {
704
-        wp_dequeue_style('espresso_reg');
705
-        wp_register_style(
706
-            'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
-            array('ee-admin-css'),
709
-            EVENT_ESPRESSO_VERSION
710
-        );
711
-        wp_enqueue_style('espresso_att');
712
-    }
713
-
714
-
715
-    public function load_scripts_styles_new_registration()
716
-    {
717
-        wp_register_script(
718
-            'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
720
-            array('underscore', 'jquery'),
721
-            EVENT_ESPRESSO_VERSION,
722
-            true
723
-        );
724
-        wp_enqueue_script('ee-spco-for-admin');
725
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
-        EE_Form_Section_Proper::wp_enqueue_scripts();
727
-        EED_Ticket_Selector::load_tckt_slctr_assets();
728
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
729
-    }
730
-
731
-
732
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
-    {
734
-        add_filter('FHEE_load_EE_messages', '__return_true');
735
-    }
736
-
737
-
738
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
-    {
740
-        add_filter('FHEE_load_EE_messages', '__return_true');
741
-    }
742
-
743
-
744
-    protected function _set_list_table_views_default()
745
-    {
746
-        // for notification related bulk actions we need to make sure only active messengers have an option.
747
-        EED_Messages::set_autoloaders();
748
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
749
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
-        $active_mts = $message_resource_manager->list_of_active_message_types();
751
-        // key= bulk_action_slug, value= message type.
752
-        $match_array = array(
753
-            'approve_registrations'    => 'registration',
754
-            'decline_registrations'    => 'declined_registration',
755
-            'pending_registrations'    => 'pending_approval',
756
-            'no_approve_registrations' => 'not_approved_registration',
757
-            'cancel_registrations'     => 'cancelled_registration',
758
-        );
759
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
760
-            'ee_send_message',
761
-            'batch_send_messages'
762
-        );
763
-        /** setup reg status bulk actions **/
764
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
-                'Approve and Notify Registrations',
768
-                'event_espresso'
769
-            );
770
-        }
771
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
-                'Decline and Notify Registrations',
775
-                'event_espresso'
776
-            );
777
-        }
778
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
779
-            'Set Registrations to Pending Payment',
780
-            'event_espresso'
781
-        );
782
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
-                'Set Registrations to Pending Payment and Notify',
785
-                'event_espresso'
786
-            );
787
-        }
788
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
-            'Set Registrations to Not Approved',
790
-            'event_espresso'
791
-        );
792
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
-                'Set Registrations to Not Approved and Notify',
795
-                'event_espresso'
796
-            );
797
-        }
798
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
-                'Cancel Registrations and Notify',
802
-                'event_espresso'
803
-            );
804
-        }
805
-        $def_reg_status_actions = apply_filters(
806
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
-            $def_reg_status_actions,
808
-            $active_mts,
809
-            $can_send
810
-        );
811
-
812
-        $this->_views = array(
813
-            'all'   => array(
814
-                'slug'        => 'all',
815
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
-                'count'       => 0,
817
-                'bulk_action' => array_merge(
818
-                    $def_reg_status_actions,
819
-                    array(
820
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
-                    )
822
-                ),
823
-            ),
824
-            'month' => array(
825
-                'slug'        => 'month',
826
-                'label'       => esc_html__('This Month', 'event_espresso'),
827
-                'count'       => 0,
828
-                'bulk_action' => array_merge(
829
-                    $def_reg_status_actions,
830
-                    array(
831
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
-                    )
833
-                ),
834
-            ),
835
-            'today' => array(
836
-                'slug'        => 'today',
837
-                'label'       => sprintf(
838
-                    esc_html__('Today - %s', 'event_espresso'),
839
-                    date('M d, Y', current_time('timestamp'))
840
-                ),
841
-                'count'       => 0,
842
-                'bulk_action' => array_merge(
843
-                    $def_reg_status_actions,
844
-                    array(
845
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
-                    )
847
-                ),
848
-            ),
849
-        );
850
-        if (EE_Registry::instance()->CAP->current_user_can(
851
-            'ee_delete_registrations',
852
-            'espresso_registrations_delete_registration'
853
-        )) {
854
-            $this->_views['incomplete'] = array(
855
-                'slug'        => 'incomplete',
856
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
857
-                'count'       => 0,
858
-                'bulk_action' => array(
859
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
-                ),
861
-            );
862
-            $this->_views['trash'] = array(
863
-                'slug'        => 'trash',
864
-                'label'       => esc_html__('Trash', 'event_espresso'),
865
-                'count'       => 0,
866
-                'bulk_action' => array(
867
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
-                ),
870
-            );
871
-        }
872
-    }
873
-
874
-
875
-    protected function _set_list_table_views_contact_list()
876
-    {
877
-        $this->_views = array(
878
-            'in_use' => array(
879
-                'slug'        => 'in_use',
880
-                'label'       => esc_html__('In Use', 'event_espresso'),
881
-                'count'       => 0,
882
-                'bulk_action' => array(
883
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
-                ),
885
-            ),
886
-        );
887
-        if (EE_Registry::instance()->CAP->current_user_can(
888
-            'ee_delete_contacts',
889
-            'espresso_registrations_trash_attendees'
890
-        )
891
-        ) {
892
-            $this->_views['trash'] = array(
893
-                'slug'        => 'trash',
894
-                'label'       => esc_html__('Trash', 'event_espresso'),
895
-                'count'       => 0,
896
-                'bulk_action' => array(
897
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
-                ),
899
-            );
900
-        }
901
-    }
902
-
903
-
904
-    protected function _registration_legend_items()
905
-    {
906
-        $fc_items = array(
907
-            'star-icon'        => array(
908
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
-            ),
911
-            'view_details'     => array(
912
-                'class' => 'dashicons dashicons-clipboard',
913
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
-            ),
915
-            'edit_attendee'    => array(
916
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
-            ),
919
-            'view_transaction' => array(
920
-                'class' => 'dashicons dashicons-cart',
921
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
-            ),
923
-            'view_invoice'     => array(
924
-                'class' => 'dashicons dashicons-media-spreadsheet',
925
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
-            ),
927
-        );
928
-        if (EE_Registry::instance()->CAP->current_user_can(
929
-            'ee_send_message',
930
-            'espresso_registrations_resend_registration'
931
-        )) {
932
-            $fc_items['resend_registration'] = array(
933
-                'class' => 'dashicons dashicons-email-alt',
934
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
-            );
936
-        } else {
937
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
-        }
939
-        if (EE_Registry::instance()->CAP->current_user_can(
940
-            'ee_read_global_messages',
941
-            'view_filtered_messages'
942
-        )) {
943
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
-                $fc_items['view_related_messages'] = array(
946
-                    'class' => $related_for_icon['css_class'],
947
-                    'desc'  => $related_for_icon['label'],
948
-                );
949
-            }
950
-        }
951
-        $sc_items = array(
952
-            'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
-                'desc'  => EEH_Template::pretty_status(
955
-                    EEM_Registration::status_id_approved,
956
-                    false,
957
-                    'sentence'
958
-                ),
959
-            ),
960
-            'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
-                'desc'  => EEH_Template::pretty_status(
963
-                    EEM_Registration::status_id_pending_payment,
964
-                    false,
965
-                    'sentence'
966
-                ),
967
-            ),
968
-            'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
-                'desc'  => EEH_Template::pretty_status(
971
-                    EEM_Registration::status_id_wait_list,
972
-                    false,
973
-                    'sentence'
974
-                ),
975
-            ),
976
-            'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
-                'desc'  => EEH_Template::pretty_status(
979
-                    EEM_Registration::status_id_incomplete,
980
-                    false,
981
-                    'sentence'
982
-                ),
983
-            ),
984
-            'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
-                'desc'  => EEH_Template::pretty_status(
987
-                    EEM_Registration::status_id_not_approved,
988
-                    false,
989
-                    'sentence'
990
-                ),
991
-            ),
992
-            'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
-                'desc'  => EEH_Template::pretty_status(
995
-                    EEM_Registration::status_id_declined,
996
-                    false,
997
-                    'sentence'
998
-                ),
999
-            ),
1000
-            'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
-                'desc'  => EEH_Template::pretty_status(
1003
-                    EEM_Registration::status_id_cancelled,
1004
-                    false,
1005
-                    'sentence'
1006
-                ),
1007
-            ),
1008
-        );
1009
-        return array_merge($fc_items, $sc_items);
1010
-    }
1011
-
1012
-
1013
-
1014
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1015
-    /**
1016
-     * @throws \EE_Error
1017
-     */
1018
-    protected function _registrations_overview_list_table()
1019
-    {
1020
-        $this->_template_args['admin_page_header'] = '';
1021
-        $EVT_ID = ! empty($this->_req_data['event_id'])
1022
-            ? absint($this->_req_data['event_id'])
1023
-            : 0;
1024
-        $ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
-            ? absint($this->_req_data['ATT_ID'])
1026
-            : 0;
1027
-        if ($ATT_ID) {
1028
-            $attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
-            if ($attendee instanceof EE_Attendee) {
1030
-                $this->_template_args['admin_page_header'] = sprintf(
1031
-                    esc_html__(
1032
-                        '%1$s Viewing registrations for %2$s%3$s',
1033
-                        'event_espresso'
1034
-                    ),
1035
-                    '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
-                        array(
1038
-                            'action' => 'edit_attendee',
1039
-                            'post'   => $ATT_ID,
1040
-                        ),
1041
-                        REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1043
-                    '</h3>'
1044
-                );
1045
-            }
1046
-        }
1047
-        if ($EVT_ID) {
1048
-            if (EE_Registry::instance()->CAP->current_user_can(
1049
-                'ee_edit_registrations',
1050
-                'espresso_registrations_new_registration',
1051
-                $EVT_ID
1052
-            )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
-                    'new_registration',
1055
-                    'add-registrant',
1056
-                    array('event_id' => $EVT_ID),
1057
-                    'add-new-h2'
1058
-                );
1059
-            }
1060
-            $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
-            if ($event instanceof EE_Event) {
1062
-                $this->_template_args['admin_page_header'] = sprintf(
1063
-                    esc_html__(
1064
-                        '%s Viewing registrations for the event: %s%s',
1065
-                        'event_espresso'
1066
-                    ),
1067
-                    '<h3 style="line-height:1.5em;">',
1068
-                    '<br /><a href="'
1069
-                    . EE_Admin_Page::add_query_args_and_nonce(
1070
-                        array(
1071
-                            'action' => 'edit',
1072
-                            'post'   => $event->ID(),
1073
-                        ),
1074
-                        EVENTS_ADMIN_URL
1075
-                    )
1076
-                    . '">&nbsp;'
1077
-                    . $event->get('EVT_name')
1078
-                    . '&nbsp;</a>&nbsp;',
1079
-                    '</h3>'
1080
-                );
1081
-            }
1082
-            $DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
-            if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
-                $this->_template_args['admin_page_header'] = substr(
1086
-                    $this->_template_args['admin_page_header'],
1087
-                    0,
1088
-                    -5
1089
-                );
1090
-                $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
-                $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
-                $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
-                $this->_template_args['admin_page_header'] .= '</span></h3>';
1095
-            }
1096
-        }
1097
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
-        $this->display_admin_list_table_page_with_no_sidebar();
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * This sets the _registration property for the registration details screen
1104
-     *
1105
-     * @access private
1106
-     * @return bool
1107
-     * @throws EE_Error
1108
-     * @throws InvalidArgumentException
1109
-     * @throws InvalidDataTypeException
1110
-     * @throws InvalidInterfaceException
1111
-     */
1112
-    private function _set_registration_object()
1113
-    {
1114
-        // get out if we've already set the object
1115
-        if ($this->_registration instanceof EE_Registration) {
1116
-            return true;
1117
-        }
1118
-        $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
-        if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
-            return true;
1122
-        } else {
1123
-            $error_msg = sprintf(
1124
-                esc_html__(
1125
-                    'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
-                    'event_espresso'
1127
-                ),
1128
-                $REG_ID
1129
-            );
1130
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            $this->_registration = null;
1132
-            return false;
1133
-        }
1134
-    }
1135
-
1136
-
1137
-    /**
1138
-     * Used to retrieve registrations for the list table.
1139
-     *
1140
-     * @param int  $per_page
1141
-     * @param bool $count
1142
-     * @param bool $this_month
1143
-     * @param bool $today
1144
-     * @return EE_Registration[]|int
1145
-     * @throws EE_Error
1146
-     * @throws InvalidArgumentException
1147
-     * @throws InvalidDataTypeException
1148
-     * @throws InvalidInterfaceException
1149
-     */
1150
-    public function get_registrations(
1151
-        $per_page = 10,
1152
-        $count = false,
1153
-        $this_month = false,
1154
-        $today = false
1155
-    ) {
1156
-        if ($this_month) {
1157
-            $this->_req_data['status'] = 'month';
1158
-        }
1159
-        if ($today) {
1160
-            $this->_req_data['status'] = 'today';
1161
-        }
1162
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
-        /**
1164
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
-         *
1166
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
-         *                             or if you have the development copy of EE you can view this at the path:
1169
-         *                             /docs/G--Model-System/model-query-params.md
1170
-         */
1171
-        $query_params['group_by'] = '';
1172
-
1173
-        return $count
1174
-            ? EEM_Registration::instance()->count($query_params)
1175
-            /** @type EE_Registration[] */
1176
-            : EEM_Registration::instance()->get_all($query_params);
1177
-    }
1178
-
1179
-
1180
-    /**
1181
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
-     * Note: this listens to values on the request for some of the query parameters.
1183
-     *
1184
-     * @param array $request
1185
-     * @param int   $per_page
1186
-     * @param bool  $count
1187
-     * @return array
1188
-     * @throws EE_Error
1189
-     */
1190
-    protected function _get_registration_query_parameters(
1191
-        $request = array(),
1192
-        $per_page = 10,
1193
-        $count = false
1194
-    ) {
1195
-
1196
-        $query_params = array(
1197
-            0                          => $this->_get_where_conditions_for_registrations_query(
1198
-                $request
1199
-            ),
1200
-            'caps'                     => EEM_Registration::caps_read_admin,
1201
-            'default_where_conditions' => 'this_model_only',
1202
-        );
1203
-        if (! $count) {
1204
-            $query_params = array_merge(
1205
-                $query_params,
1206
-                $this->_get_orderby_for_registrations_query(),
1207
-                $this->_get_limit($per_page)
1208
-            );
1209
-        }
1210
-
1211
-        return $query_params;
1212
-    }
1213
-
1214
-
1215
-    /**
1216
-     * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
-     *
1218
-     * @param array $request usually the same as $this->_req_data but not necessarily
1219
-     * @return array
1220
-     */
1221
-    protected function addAttendeeIdToWhereConditions(array $request)
1222
-    {
1223
-        $where = array();
1224
-        if (! empty($request['ATT_ID'])) {
1225
-            $where['ATT_ID'] = absint($request['ATT_ID']);
1226
-        }
1227
-        return $where;
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
-     *
1234
-     * @param array $request usually the same as $this->_req_data but not necessarily
1235
-     * @return array
1236
-     */
1237
-    protected function _add_event_id_to_where_conditions(array $request)
1238
-    {
1239
-        $where = array();
1240
-        if (! empty($request['event_id'])) {
1241
-            $where['EVT_ID'] = absint($request['event_id']);
1242
-        }
1243
-        return $where;
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
-     *
1250
-     * @param array $request usually the same as $this->_req_data but not necessarily
1251
-     * @return array
1252
-     */
1253
-    protected function _add_category_id_to_where_conditions(array $request)
1254
-    {
1255
-        $where = array();
1256
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
-        }
1259
-        return $where;
1260
-    }
1261
-
1262
-
1263
-    /**
1264
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
-     *
1266
-     * @param array $request usually the same as $this->_req_data but not necessarily
1267
-     * @return array
1268
-     */
1269
-    protected function _add_datetime_id_to_where_conditions(array $request)
1270
-    {
1271
-        $where = array();
1272
-        if (! empty($request['datetime_id'])) {
1273
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
-        }
1275
-        if (! empty($request['DTT_ID'])) {
1276
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
-        }
1278
-        return $where;
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * Adds the correct registration status to the where conditions for the registrations query.
1284
-     *
1285
-     * @param array $request usually the same as $this->_req_data but not necessarily
1286
-     * @return array
1287
-     */
1288
-    protected function _add_registration_status_to_where_conditions(array $request)
1289
-    {
1290
-        $where = array();
1291
-        $view = EEH_Array::is_set($request, 'status', '');
1292
-        $registration_status = ! empty($request['_reg_status'])
1293
-            ? sanitize_text_field($request['_reg_status'])
1294
-            : '';
1295
-
1296
-        /*
22
+	/**
23
+	 * @var EE_Registration
24
+	 */
25
+	private $_registration;
26
+
27
+	/**
28
+	 * @var EE_Event
29
+	 */
30
+	private $_reg_event;
31
+
32
+	/**
33
+	 * @var EE_Session
34
+	 */
35
+	private $_session;
36
+
37
+	private static $_reg_status;
38
+
39
+	/**
40
+	 * Form for displaying the custom questions for this registration.
41
+	 * This gets used a few times throughout the request so its best to cache it
42
+	 *
43
+	 * @var EE_Registration_Custom_Questions_Form
44
+	 */
45
+	protected $_reg_custom_questions_form = null;
46
+
47
+
48
+	/**
49
+	 *        constructor
50
+	 *
51
+	 * @Constructor
52
+	 * @access public
53
+	 * @param bool $routing
54
+	 * @return Registrations_Admin_Page
55
+	 */
56
+	public function __construct($routing = true)
57
+	{
58
+		parent::__construct($routing);
59
+		add_action('wp_loaded', array($this, 'wp_loaded'));
60
+	}
61
+
62
+
63
+	public function wp_loaded()
64
+	{
65
+		// when adding a new registration...
66
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
+			EE_System::do_not_cache();
68
+			if (! isset($this->_req_data['processing_registration'])
69
+				|| absint($this->_req_data['processing_registration']) !== 1
70
+			) {
71
+				// and it's NOT the attendee information reg step
72
+				// force cookie expiration by setting time to last week
73
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
+				// and update the global
75
+				$_COOKIE['ee_registration_added'] = 0;
76
+			}
77
+		}
78
+	}
79
+
80
+
81
+	protected function _init_page_props()
82
+	{
83
+		$this->page_slug = REG_PG_SLUG;
84
+		$this->_admin_base_url = REG_ADMIN_URL;
85
+		$this->_admin_base_path = REG_ADMIN;
86
+		$this->page_label = esc_html__('Registrations', 'event_espresso');
87
+		$this->_cpt_routes = array(
88
+			'add_new_attendee' => 'espresso_attendees',
89
+			'edit_attendee'    => 'espresso_attendees',
90
+			'insert_attendee'  => 'espresso_attendees',
91
+			'update_attendee'  => 'espresso_attendees',
92
+		);
93
+		$this->_cpt_model_names = array(
94
+			'add_new_attendee' => 'EEM_Attendee',
95
+			'edit_attendee'    => 'EEM_Attendee',
96
+		);
97
+		$this->_cpt_edit_routes = array(
98
+			'espresso_attendees' => 'edit_attendee',
99
+		);
100
+		$this->_pagenow_map = array(
101
+			'add_new_attendee' => 'post-new.php',
102
+			'edit_attendee'    => 'post.php',
103
+			'trash'            => 'post.php',
104
+		);
105
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
+		// add filters so that the comment urls don't take users to a confusing 404 page
107
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
+	}
109
+
110
+
111
+	public function clear_comment_link($link, $comment, $args)
112
+	{
113
+		// gotta make sure this only happens on this route
114
+		$post_type = get_post_type($comment->comment_post_ID);
115
+		if ($post_type === 'espresso_attendees') {
116
+			return '#commentsdiv';
117
+		}
118
+		return $link;
119
+	}
120
+
121
+
122
+	protected function _ajax_hooks()
123
+	{
124
+		// todo: all hooks for registrations ajax goes in here
125
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
+	}
127
+
128
+
129
+	protected function _define_page_props()
130
+	{
131
+		$this->_admin_page_title = $this->page_label;
132
+		$this->_labels = array(
133
+			'buttons'                      => array(
134
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
+				'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
+				'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
+			),
143
+			'publishbox'                   => array(
144
+				'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
+				'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
+			),
147
+			'hide_add_button_on_cpt_route' => array(
148
+				'edit_attendee' => true,
149
+			),
150
+		);
151
+	}
152
+
153
+
154
+	/**
155
+	 *        grab url requests and route them
156
+	 *
157
+	 * @access private
158
+	 * @return void
159
+	 */
160
+	public function _set_page_routes()
161
+	{
162
+		$this->_get_registration_status_array();
163
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
+			? $this->_req_data['_REG_ID'] : 0;
165
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
+			? $this->_req_data['reg_status_change_form']['REG_ID']
167
+			: $reg_id;
168
+		$att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
+			? $this->_req_data['ATT_ID'] : 0;
170
+		$att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
+			? $this->_req_data['post']
172
+			: $att_id;
173
+		$this->_page_routes = array(
174
+			'default'                             => array(
175
+				'func'       => '_registrations_overview_list_table',
176
+				'capability' => 'ee_read_registrations',
177
+			),
178
+			'view_registration'                   => array(
179
+				'func'       => '_registration_details',
180
+				'capability' => 'ee_read_registration',
181
+				'obj_id'     => $reg_id,
182
+			),
183
+			'edit_registration'                   => array(
184
+				'func'               => '_update_attendee_registration_form',
185
+				'noheader'           => true,
186
+				'headers_sent_route' => 'view_registration',
187
+				'capability'         => 'ee_edit_registration',
188
+				'obj_id'             => $reg_id,
189
+				'_REG_ID'            => $reg_id,
190
+			),
191
+			'trash_registrations'                 => array(
192
+				'func'       => '_trash_or_restore_registrations',
193
+				'args'       => array('trash' => true),
194
+				'noheader'   => true,
195
+				'capability' => 'ee_delete_registrations',
196
+			),
197
+			'restore_registrations'               => array(
198
+				'func'       => '_trash_or_restore_registrations',
199
+				'args'       => array('trash' => false),
200
+				'noheader'   => true,
201
+				'capability' => 'ee_delete_registrations',
202
+			),
203
+			'delete_registrations'                => array(
204
+				'func'       => '_delete_registrations',
205
+				'noheader'   => true,
206
+				'capability' => 'ee_delete_registrations',
207
+			),
208
+			'new_registration'                    => array(
209
+				'func'       => 'new_registration',
210
+				'capability' => 'ee_edit_registrations',
211
+			),
212
+			'process_reg_step'                    => array(
213
+				'func'       => 'process_reg_step',
214
+				'noheader'   => true,
215
+				'capability' => 'ee_edit_registrations',
216
+			),
217
+			'redirect_to_txn'                     => array(
218
+				'func'       => 'redirect_to_txn',
219
+				'noheader'   => true,
220
+				'capability' => 'ee_edit_registrations',
221
+			),
222
+			'change_reg_status'                   => array(
223
+				'func'       => '_change_reg_status',
224
+				'noheader'   => true,
225
+				'capability' => 'ee_edit_registration',
226
+				'obj_id'     => $reg_id,
227
+			),
228
+			'approve_registration'                => array(
229
+				'func'       => 'approve_registration',
230
+				'noheader'   => true,
231
+				'capability' => 'ee_edit_registration',
232
+				'obj_id'     => $reg_id,
233
+			),
234
+			'approve_and_notify_registration'     => array(
235
+				'func'       => 'approve_registration',
236
+				'noheader'   => true,
237
+				'args'       => array(true),
238
+				'capability' => 'ee_edit_registration',
239
+				'obj_id'     => $reg_id,
240
+			),
241
+			'approve_registrations'               => array(
242
+				'func'       => 'bulk_action_on_registrations',
243
+				'noheader'   => true,
244
+				'capability' => 'ee_edit_registrations',
245
+				'args'       => array('approve'),
246
+			),
247
+			'approve_and_notify_registrations'    => array(
248
+				'func'       => 'bulk_action_on_registrations',
249
+				'noheader'   => true,
250
+				'capability' => 'ee_edit_registrations',
251
+				'args'       => array('approve', true),
252
+			),
253
+			'decline_registration'                => array(
254
+				'func'       => 'decline_registration',
255
+				'noheader'   => true,
256
+				'capability' => 'ee_edit_registration',
257
+				'obj_id'     => $reg_id,
258
+			),
259
+			'decline_and_notify_registration'     => array(
260
+				'func'       => 'decline_registration',
261
+				'noheader'   => true,
262
+				'args'       => array(true),
263
+				'capability' => 'ee_edit_registration',
264
+				'obj_id'     => $reg_id,
265
+			),
266
+			'decline_registrations'               => array(
267
+				'func'       => 'bulk_action_on_registrations',
268
+				'noheader'   => true,
269
+				'capability' => 'ee_edit_registrations',
270
+				'args'       => array('decline'),
271
+			),
272
+			'decline_and_notify_registrations'    => array(
273
+				'func'       => 'bulk_action_on_registrations',
274
+				'noheader'   => true,
275
+				'capability' => 'ee_edit_registrations',
276
+				'args'       => array('decline', true),
277
+			),
278
+			'pending_registration'                => array(
279
+				'func'       => 'pending_registration',
280
+				'noheader'   => true,
281
+				'capability' => 'ee_edit_registration',
282
+				'obj_id'     => $reg_id,
283
+			),
284
+			'pending_and_notify_registration'     => array(
285
+				'func'       => 'pending_registration',
286
+				'noheader'   => true,
287
+				'args'       => array(true),
288
+				'capability' => 'ee_edit_registration',
289
+				'obj_id'     => $reg_id,
290
+			),
291
+			'pending_registrations'               => array(
292
+				'func'       => 'bulk_action_on_registrations',
293
+				'noheader'   => true,
294
+				'capability' => 'ee_edit_registrations',
295
+				'args'       => array('pending'),
296
+			),
297
+			'pending_and_notify_registrations'    => array(
298
+				'func'       => 'bulk_action_on_registrations',
299
+				'noheader'   => true,
300
+				'capability' => 'ee_edit_registrations',
301
+				'args'       => array('pending', true),
302
+			),
303
+			'no_approve_registration'             => array(
304
+				'func'       => 'not_approve_registration',
305
+				'noheader'   => true,
306
+				'capability' => 'ee_edit_registration',
307
+				'obj_id'     => $reg_id,
308
+			),
309
+			'no_approve_and_notify_registration'  => array(
310
+				'func'       => 'not_approve_registration',
311
+				'noheader'   => true,
312
+				'args'       => array(true),
313
+				'capability' => 'ee_edit_registration',
314
+				'obj_id'     => $reg_id,
315
+			),
316
+			'no_approve_registrations'            => array(
317
+				'func'       => 'bulk_action_on_registrations',
318
+				'noheader'   => true,
319
+				'capability' => 'ee_edit_registrations',
320
+				'args'       => array('not_approve'),
321
+			),
322
+			'no_approve_and_notify_registrations' => array(
323
+				'func'       => 'bulk_action_on_registrations',
324
+				'noheader'   => true,
325
+				'capability' => 'ee_edit_registrations',
326
+				'args'       => array('not_approve', true),
327
+			),
328
+			'cancel_registration'                 => array(
329
+				'func'       => 'cancel_registration',
330
+				'noheader'   => true,
331
+				'capability' => 'ee_edit_registration',
332
+				'obj_id'     => $reg_id,
333
+			),
334
+			'cancel_and_notify_registration'      => array(
335
+				'func'       => 'cancel_registration',
336
+				'noheader'   => true,
337
+				'args'       => array(true),
338
+				'capability' => 'ee_edit_registration',
339
+				'obj_id'     => $reg_id,
340
+			),
341
+			'cancel_registrations'                => array(
342
+				'func'       => 'bulk_action_on_registrations',
343
+				'noheader'   => true,
344
+				'capability' => 'ee_edit_registrations',
345
+				'args'       => array('cancel'),
346
+			),
347
+			'cancel_and_notify_registrations'     => array(
348
+				'func'       => 'bulk_action_on_registrations',
349
+				'noheader'   => true,
350
+				'capability' => 'ee_edit_registrations',
351
+				'args'       => array('cancel', true),
352
+			),
353
+			'wait_list_registration'              => array(
354
+				'func'       => 'wait_list_registration',
355
+				'noheader'   => true,
356
+				'capability' => 'ee_edit_registration',
357
+				'obj_id'     => $reg_id,
358
+			),
359
+			'wait_list_and_notify_registration'   => array(
360
+				'func'       => 'wait_list_registration',
361
+				'noheader'   => true,
362
+				'args'       => array(true),
363
+				'capability' => 'ee_edit_registration',
364
+				'obj_id'     => $reg_id,
365
+			),
366
+			'contact_list'                        => array(
367
+				'func'       => '_attendee_contact_list_table',
368
+				'capability' => 'ee_read_contacts',
369
+			),
370
+			'add_new_attendee'                    => array(
371
+				'func' => '_create_new_cpt_item',
372
+				'args' => array(
373
+					'new_attendee' => true,
374
+					'capability'   => 'ee_edit_contacts',
375
+				),
376
+			),
377
+			'edit_attendee'                       => array(
378
+				'func'       => '_edit_cpt_item',
379
+				'capability' => 'ee_edit_contacts',
380
+				'obj_id'     => $att_id,
381
+			),
382
+			'duplicate_attendee'                  => array(
383
+				'func'       => '_duplicate_attendee',
384
+				'noheader'   => true,
385
+				'capability' => 'ee_edit_contacts',
386
+				'obj_id'     => $att_id,
387
+			),
388
+			'insert_attendee'                     => array(
389
+				'func'       => '_insert_or_update_attendee',
390
+				'args'       => array(
391
+					'new_attendee' => true,
392
+				),
393
+				'noheader'   => true,
394
+				'capability' => 'ee_edit_contacts',
395
+			),
396
+			'update_attendee'                     => array(
397
+				'func'       => '_insert_or_update_attendee',
398
+				'args'       => array(
399
+					'new_attendee' => false,
400
+				),
401
+				'noheader'   => true,
402
+				'capability' => 'ee_edit_contacts',
403
+				'obj_id'     => $att_id,
404
+			),
405
+			'trash_attendees'                     => array(
406
+				'func'       => '_trash_or_restore_attendees',
407
+				'args'       => array(
408
+					'trash' => 'true',
409
+				),
410
+				'noheader'   => true,
411
+				'capability' => 'ee_delete_contacts',
412
+			),
413
+			'trash_attendee'                      => array(
414
+				'func'       => '_trash_or_restore_attendees',
415
+				'args'       => array(
416
+					'trash' => true,
417
+				),
418
+				'noheader'   => true,
419
+				'capability' => 'ee_delete_contacts',
420
+				'obj_id'     => $att_id,
421
+			),
422
+			'restore_attendees'                   => array(
423
+				'func'       => '_trash_or_restore_attendees',
424
+				'args'       => array(
425
+					'trash' => false,
426
+				),
427
+				'noheader'   => true,
428
+				'capability' => 'ee_delete_contacts',
429
+				'obj_id'     => $att_id,
430
+			),
431
+			'resend_registration'                 => array(
432
+				'func'       => '_resend_registration',
433
+				'noheader'   => true,
434
+				'capability' => 'ee_send_message',
435
+			),
436
+			'registrations_report'                => array(
437
+				'func'       => '_registrations_report',
438
+				'noheader'   => true,
439
+				'capability' => 'ee_read_registrations',
440
+			),
441
+			'contact_list_export'                 => array(
442
+				'func'       => '_contact_list_export',
443
+				'noheader'   => true,
444
+				'capability' => 'export',
445
+			),
446
+			'contact_list_report'                 => array(
447
+				'func'       => '_contact_list_report',
448
+				'noheader'   => true,
449
+				'capability' => 'ee_read_contacts',
450
+			),
451
+		);
452
+	}
453
+
454
+
455
+	protected function _set_page_config()
456
+	{
457
+		$this->_page_config = array(
458
+			'default'           => array(
459
+				'nav'           => array(
460
+					'label' => esc_html__('Overview', 'event_espresso'),
461
+					'order' => 5,
462
+				),
463
+				'help_tabs'     => array(
464
+					'registrations_overview_help_tab'                       => array(
465
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
+						'filename' => 'registrations_overview',
467
+					),
468
+					'registrations_overview_table_column_headings_help_tab' => array(
469
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
+						'filename' => 'registrations_overview_table_column_headings',
471
+					),
472
+					'registrations_overview_filters_help_tab'               => array(
473
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
+						'filename' => 'registrations_overview_filters',
475
+					),
476
+					'registrations_overview_views_help_tab'                 => array(
477
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
478
+						'filename' => 'registrations_overview_views',
479
+					),
480
+					'registrations_regoverview_other_help_tab'              => array(
481
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
+						'filename' => 'registrations_overview_other',
483
+					),
484
+				),
485
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
486
+				'qtips'         => array('Registration_List_Table_Tips'),
487
+				'list_table'    => 'EE_Registrations_List_Table',
488
+				'require_nonce' => false,
489
+			),
490
+			'view_registration' => array(
491
+				'nav'           => array(
492
+					'label'      => esc_html__('REG Details', 'event_espresso'),
493
+					'order'      => 15,
494
+					'url'        => isset($this->_req_data['_REG_ID'])
495
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
+						: $this->_admin_base_url,
497
+					'persistent' => false,
498
+				),
499
+				'help_tabs'     => array(
500
+					'registrations_details_help_tab'                    => array(
501
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
502
+						'filename' => 'registrations_details',
503
+					),
504
+					'registrations_details_table_help_tab'              => array(
505
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
+						'filename' => 'registrations_details_table',
507
+					),
508
+					'registrations_details_form_answers_help_tab'       => array(
509
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
+						'filename' => 'registrations_details_form_answers',
511
+					),
512
+					'registrations_details_registrant_details_help_tab' => array(
513
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
514
+						'filename' => 'registrations_details_registrant_details',
515
+					),
516
+				),
517
+				'help_tour'     => array('Registration_Details_Help_Tour'),
518
+				'metaboxes'     => array_merge(
519
+					$this->_default_espresso_metaboxes,
520
+					array('_registration_details_metaboxes')
521
+				),
522
+				'require_nonce' => false,
523
+			),
524
+			'new_registration'  => array(
525
+				'nav'           => array(
526
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
+					'url'        => '#',
528
+					'order'      => 15,
529
+					'persistent' => false,
530
+				),
531
+				'metaboxes'     => $this->_default_espresso_metaboxes,
532
+				'labels'        => array(
533
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
+				),
535
+				'require_nonce' => false,
536
+			),
537
+			'add_new_attendee'  => array(
538
+				'nav'           => array(
539
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
540
+					'order'      => 15,
541
+					'persistent' => false,
542
+				),
543
+				'metaboxes'     => array_merge(
544
+					$this->_default_espresso_metaboxes,
545
+					array('_publish_post_box', 'attendee_editor_metaboxes')
546
+				),
547
+				'require_nonce' => false,
548
+			),
549
+			'edit_attendee'     => array(
550
+				'nav'           => array(
551
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
+					'order'      => 15,
553
+					'persistent' => false,
554
+					'url'        => isset($this->_req_data['ATT_ID'])
555
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
+						: $this->_admin_base_url,
557
+				),
558
+				'metaboxes'     => array('attendee_editor_metaboxes'),
559
+				'require_nonce' => false,
560
+			),
561
+			'contact_list'      => array(
562
+				'nav'           => array(
563
+					'label' => esc_html__('Contact List', 'event_espresso'),
564
+					'order' => 20,
565
+				),
566
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
567
+				'help_tabs'     => array(
568
+					'registrations_contact_list_help_tab'                       => array(
569
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
+						'filename' => 'registrations_contact_list',
571
+					),
572
+					'registrations_contact-list_table_column_headings_help_tab' => array(
573
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
+						'filename' => 'registrations_contact_list_table_column_headings',
575
+					),
576
+					'registrations_contact_list_views_help_tab'                 => array(
577
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
+						'filename' => 'registrations_contact_list_views',
579
+					),
580
+					'registrations_contact_list_other_help_tab'                 => array(
581
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
+						'filename' => 'registrations_contact_list_other',
583
+					),
584
+				),
585
+				'help_tour'     => array('Contact_List_Help_Tour'),
586
+				'metaboxes'     => array(),
587
+				'require_nonce' => false,
588
+			),
589
+			// override default cpt routes
590
+			'create_new'        => '',
591
+			'edit'              => '',
592
+		);
593
+	}
594
+
595
+
596
+	/**
597
+	 * The below methods aren't used by this class currently
598
+	 */
599
+	protected function _add_screen_options()
600
+	{
601
+	}
602
+
603
+
604
+	protected function _add_feature_pointers()
605
+	{
606
+	}
607
+
608
+
609
+	public function admin_init()
610
+	{
611
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
+			'click "Update Registration Questions" to save your changes',
613
+			'event_espresso'
614
+		);
615
+	}
616
+
617
+
618
+	public function admin_notices()
619
+	{
620
+	}
621
+
622
+
623
+	public function admin_footer_scripts()
624
+	{
625
+	}
626
+
627
+
628
+	/**
629
+	 *        get list of registration statuses
630
+	 *
631
+	 * @access private
632
+	 * @return void
633
+	 * @throws EE_Error
634
+	 */
635
+	private function _get_registration_status_array()
636
+	{
637
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
+	}
639
+
640
+
641
+	protected function _add_screen_options_default()
642
+	{
643
+		$this->_per_page_screen_option();
644
+	}
645
+
646
+
647
+	protected function _add_screen_options_contact_list()
648
+	{
649
+		$page_title = $this->_admin_page_title;
650
+		$this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
+		$this->_per_page_screen_option();
652
+		$this->_admin_page_title = $page_title;
653
+	}
654
+
655
+
656
+	public function load_scripts_styles()
657
+	{
658
+		// style
659
+		wp_register_style(
660
+			'espresso_reg',
661
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
+			array('ee-admin-css'),
663
+			EVENT_ESPRESSO_VERSION
664
+		);
665
+		wp_enqueue_style('espresso_reg');
666
+		// script
667
+		wp_register_script(
668
+			'espresso_reg',
669
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
+			EVENT_ESPRESSO_VERSION,
672
+			true
673
+		);
674
+		wp_enqueue_script('espresso_reg');
675
+	}
676
+
677
+
678
+	public function load_scripts_styles_edit_attendee()
679
+	{
680
+		// stuff to only show up on our attendee edit details page.
681
+		$attendee_details_translations = array(
682
+			'att_publish_text' => sprintf(
683
+				esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
+				$this->_cpt_model_obj->get_datetime('ATT_created')
685
+			),
686
+		);
687
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
+		wp_enqueue_script('jquery-validate');
689
+	}
690
+
691
+
692
+	public function load_scripts_styles_view_registration()
693
+	{
694
+		// styles
695
+		wp_enqueue_style('espresso-ui-theme');
696
+		// scripts
697
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
698
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
+	}
700
+
701
+
702
+	public function load_scripts_styles_contact_list()
703
+	{
704
+		wp_dequeue_style('espresso_reg');
705
+		wp_register_style(
706
+			'espresso_att',
707
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
+			array('ee-admin-css'),
709
+			EVENT_ESPRESSO_VERSION
710
+		);
711
+		wp_enqueue_style('espresso_att');
712
+	}
713
+
714
+
715
+	public function load_scripts_styles_new_registration()
716
+	{
717
+		wp_register_script(
718
+			'ee-spco-for-admin',
719
+			REG_ASSETS_URL . 'spco_for_admin.js',
720
+			array('underscore', 'jquery'),
721
+			EVENT_ESPRESSO_VERSION,
722
+			true
723
+		);
724
+		wp_enqueue_script('ee-spco-for-admin');
725
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
+		EE_Form_Section_Proper::wp_enqueue_scripts();
727
+		EED_Ticket_Selector::load_tckt_slctr_assets();
728
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
729
+	}
730
+
731
+
732
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
+	{
734
+		add_filter('FHEE_load_EE_messages', '__return_true');
735
+	}
736
+
737
+
738
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
+	{
740
+		add_filter('FHEE_load_EE_messages', '__return_true');
741
+	}
742
+
743
+
744
+	protected function _set_list_table_views_default()
745
+	{
746
+		// for notification related bulk actions we need to make sure only active messengers have an option.
747
+		EED_Messages::set_autoloaders();
748
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
749
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
+		$active_mts = $message_resource_manager->list_of_active_message_types();
751
+		// key= bulk_action_slug, value= message type.
752
+		$match_array = array(
753
+			'approve_registrations'    => 'registration',
754
+			'decline_registrations'    => 'declined_registration',
755
+			'pending_registrations'    => 'pending_approval',
756
+			'no_approve_registrations' => 'not_approved_registration',
757
+			'cancel_registrations'     => 'cancelled_registration',
758
+		);
759
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
760
+			'ee_send_message',
761
+			'batch_send_messages'
762
+		);
763
+		/** setup reg status bulk actions **/
764
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
+				'Approve and Notify Registrations',
768
+				'event_espresso'
769
+			);
770
+		}
771
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
+				'Decline and Notify Registrations',
775
+				'event_espresso'
776
+			);
777
+		}
778
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
779
+			'Set Registrations to Pending Payment',
780
+			'event_espresso'
781
+		);
782
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
+				'Set Registrations to Pending Payment and Notify',
785
+				'event_espresso'
786
+			);
787
+		}
788
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
+			'Set Registrations to Not Approved',
790
+			'event_espresso'
791
+		);
792
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
+				'Set Registrations to Not Approved and Notify',
795
+				'event_espresso'
796
+			);
797
+		}
798
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
+				'Cancel Registrations and Notify',
802
+				'event_espresso'
803
+			);
804
+		}
805
+		$def_reg_status_actions = apply_filters(
806
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
+			$def_reg_status_actions,
808
+			$active_mts,
809
+			$can_send
810
+		);
811
+
812
+		$this->_views = array(
813
+			'all'   => array(
814
+				'slug'        => 'all',
815
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
+				'count'       => 0,
817
+				'bulk_action' => array_merge(
818
+					$def_reg_status_actions,
819
+					array(
820
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
+					)
822
+				),
823
+			),
824
+			'month' => array(
825
+				'slug'        => 'month',
826
+				'label'       => esc_html__('This Month', 'event_espresso'),
827
+				'count'       => 0,
828
+				'bulk_action' => array_merge(
829
+					$def_reg_status_actions,
830
+					array(
831
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
+					)
833
+				),
834
+			),
835
+			'today' => array(
836
+				'slug'        => 'today',
837
+				'label'       => sprintf(
838
+					esc_html__('Today - %s', 'event_espresso'),
839
+					date('M d, Y', current_time('timestamp'))
840
+				),
841
+				'count'       => 0,
842
+				'bulk_action' => array_merge(
843
+					$def_reg_status_actions,
844
+					array(
845
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
+					)
847
+				),
848
+			),
849
+		);
850
+		if (EE_Registry::instance()->CAP->current_user_can(
851
+			'ee_delete_registrations',
852
+			'espresso_registrations_delete_registration'
853
+		)) {
854
+			$this->_views['incomplete'] = array(
855
+				'slug'        => 'incomplete',
856
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
857
+				'count'       => 0,
858
+				'bulk_action' => array(
859
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
+				),
861
+			);
862
+			$this->_views['trash'] = array(
863
+				'slug'        => 'trash',
864
+				'label'       => esc_html__('Trash', 'event_espresso'),
865
+				'count'       => 0,
866
+				'bulk_action' => array(
867
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
+				),
870
+			);
871
+		}
872
+	}
873
+
874
+
875
+	protected function _set_list_table_views_contact_list()
876
+	{
877
+		$this->_views = array(
878
+			'in_use' => array(
879
+				'slug'        => 'in_use',
880
+				'label'       => esc_html__('In Use', 'event_espresso'),
881
+				'count'       => 0,
882
+				'bulk_action' => array(
883
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
+				),
885
+			),
886
+		);
887
+		if (EE_Registry::instance()->CAP->current_user_can(
888
+			'ee_delete_contacts',
889
+			'espresso_registrations_trash_attendees'
890
+		)
891
+		) {
892
+			$this->_views['trash'] = array(
893
+				'slug'        => 'trash',
894
+				'label'       => esc_html__('Trash', 'event_espresso'),
895
+				'count'       => 0,
896
+				'bulk_action' => array(
897
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
+				),
899
+			);
900
+		}
901
+	}
902
+
903
+
904
+	protected function _registration_legend_items()
905
+	{
906
+		$fc_items = array(
907
+			'star-icon'        => array(
908
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
+			),
911
+			'view_details'     => array(
912
+				'class' => 'dashicons dashicons-clipboard',
913
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
+			),
915
+			'edit_attendee'    => array(
916
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
+			),
919
+			'view_transaction' => array(
920
+				'class' => 'dashicons dashicons-cart',
921
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
+			),
923
+			'view_invoice'     => array(
924
+				'class' => 'dashicons dashicons-media-spreadsheet',
925
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
+			),
927
+		);
928
+		if (EE_Registry::instance()->CAP->current_user_can(
929
+			'ee_send_message',
930
+			'espresso_registrations_resend_registration'
931
+		)) {
932
+			$fc_items['resend_registration'] = array(
933
+				'class' => 'dashicons dashicons-email-alt',
934
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
+			);
936
+		} else {
937
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
+		}
939
+		if (EE_Registry::instance()->CAP->current_user_can(
940
+			'ee_read_global_messages',
941
+			'view_filtered_messages'
942
+		)) {
943
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
+				$fc_items['view_related_messages'] = array(
946
+					'class' => $related_for_icon['css_class'],
947
+					'desc'  => $related_for_icon['label'],
948
+				);
949
+			}
950
+		}
951
+		$sc_items = array(
952
+			'approved_status'   => array(
953
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
+				'desc'  => EEH_Template::pretty_status(
955
+					EEM_Registration::status_id_approved,
956
+					false,
957
+					'sentence'
958
+				),
959
+			),
960
+			'pending_status'    => array(
961
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
+				'desc'  => EEH_Template::pretty_status(
963
+					EEM_Registration::status_id_pending_payment,
964
+					false,
965
+					'sentence'
966
+				),
967
+			),
968
+			'wait_list'         => array(
969
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
+				'desc'  => EEH_Template::pretty_status(
971
+					EEM_Registration::status_id_wait_list,
972
+					false,
973
+					'sentence'
974
+				),
975
+			),
976
+			'incomplete_status' => array(
977
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
+				'desc'  => EEH_Template::pretty_status(
979
+					EEM_Registration::status_id_incomplete,
980
+					false,
981
+					'sentence'
982
+				),
983
+			),
984
+			'not_approved'      => array(
985
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
+				'desc'  => EEH_Template::pretty_status(
987
+					EEM_Registration::status_id_not_approved,
988
+					false,
989
+					'sentence'
990
+				),
991
+			),
992
+			'declined_status'   => array(
993
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
+				'desc'  => EEH_Template::pretty_status(
995
+					EEM_Registration::status_id_declined,
996
+					false,
997
+					'sentence'
998
+				),
999
+			),
1000
+			'cancelled_status'  => array(
1001
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
+				'desc'  => EEH_Template::pretty_status(
1003
+					EEM_Registration::status_id_cancelled,
1004
+					false,
1005
+					'sentence'
1006
+				),
1007
+			),
1008
+		);
1009
+		return array_merge($fc_items, $sc_items);
1010
+	}
1011
+
1012
+
1013
+
1014
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1015
+	/**
1016
+	 * @throws \EE_Error
1017
+	 */
1018
+	protected function _registrations_overview_list_table()
1019
+	{
1020
+		$this->_template_args['admin_page_header'] = '';
1021
+		$EVT_ID = ! empty($this->_req_data['event_id'])
1022
+			? absint($this->_req_data['event_id'])
1023
+			: 0;
1024
+		$ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
+			? absint($this->_req_data['ATT_ID'])
1026
+			: 0;
1027
+		if ($ATT_ID) {
1028
+			$attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
+			if ($attendee instanceof EE_Attendee) {
1030
+				$this->_template_args['admin_page_header'] = sprintf(
1031
+					esc_html__(
1032
+						'%1$s Viewing registrations for %2$s%3$s',
1033
+						'event_espresso'
1034
+					),
1035
+					'<h3 style="line-height:1.5em;">',
1036
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
+						array(
1038
+							'action' => 'edit_attendee',
1039
+							'post'   => $ATT_ID,
1040
+						),
1041
+						REG_ADMIN_URL
1042
+					) . '">' . $attendee->full_name() . '</a>',
1043
+					'</h3>'
1044
+				);
1045
+			}
1046
+		}
1047
+		if ($EVT_ID) {
1048
+			if (EE_Registry::instance()->CAP->current_user_can(
1049
+				'ee_edit_registrations',
1050
+				'espresso_registrations_new_registration',
1051
+				$EVT_ID
1052
+			)) {
1053
+				$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
+					'new_registration',
1055
+					'add-registrant',
1056
+					array('event_id' => $EVT_ID),
1057
+					'add-new-h2'
1058
+				);
1059
+			}
1060
+			$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
+			if ($event instanceof EE_Event) {
1062
+				$this->_template_args['admin_page_header'] = sprintf(
1063
+					esc_html__(
1064
+						'%s Viewing registrations for the event: %s%s',
1065
+						'event_espresso'
1066
+					),
1067
+					'<h3 style="line-height:1.5em;">',
1068
+					'<br /><a href="'
1069
+					. EE_Admin_Page::add_query_args_and_nonce(
1070
+						array(
1071
+							'action' => 'edit',
1072
+							'post'   => $event->ID(),
1073
+						),
1074
+						EVENTS_ADMIN_URL
1075
+					)
1076
+					. '">&nbsp;'
1077
+					. $event->get('EVT_name')
1078
+					. '&nbsp;</a>&nbsp;',
1079
+					'</h3>'
1080
+				);
1081
+			}
1082
+			$DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
+			if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
+				$this->_template_args['admin_page_header'] = substr(
1086
+					$this->_template_args['admin_page_header'],
1087
+					0,
1088
+					-5
1089
+				);
1090
+				$this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
+				$this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
+				$this->_template_args['admin_page_header'] .= $datetime->name();
1093
+				$this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
+				$this->_template_args['admin_page_header'] .= '</span></h3>';
1095
+			}
1096
+		}
1097
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
+		$this->display_admin_list_table_page_with_no_sidebar();
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * This sets the _registration property for the registration details screen
1104
+	 *
1105
+	 * @access private
1106
+	 * @return bool
1107
+	 * @throws EE_Error
1108
+	 * @throws InvalidArgumentException
1109
+	 * @throws InvalidDataTypeException
1110
+	 * @throws InvalidInterfaceException
1111
+	 */
1112
+	private function _set_registration_object()
1113
+	{
1114
+		// get out if we've already set the object
1115
+		if ($this->_registration instanceof EE_Registration) {
1116
+			return true;
1117
+		}
1118
+		$REG = EEM_Registration::instance();
1119
+		$REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
+		if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
+			return true;
1122
+		} else {
1123
+			$error_msg = sprintf(
1124
+				esc_html__(
1125
+					'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
+					'event_espresso'
1127
+				),
1128
+				$REG_ID
1129
+			);
1130
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			$this->_registration = null;
1132
+			return false;
1133
+		}
1134
+	}
1135
+
1136
+
1137
+	/**
1138
+	 * Used to retrieve registrations for the list table.
1139
+	 *
1140
+	 * @param int  $per_page
1141
+	 * @param bool $count
1142
+	 * @param bool $this_month
1143
+	 * @param bool $today
1144
+	 * @return EE_Registration[]|int
1145
+	 * @throws EE_Error
1146
+	 * @throws InvalidArgumentException
1147
+	 * @throws InvalidDataTypeException
1148
+	 * @throws InvalidInterfaceException
1149
+	 */
1150
+	public function get_registrations(
1151
+		$per_page = 10,
1152
+		$count = false,
1153
+		$this_month = false,
1154
+		$today = false
1155
+	) {
1156
+		if ($this_month) {
1157
+			$this->_req_data['status'] = 'month';
1158
+		}
1159
+		if ($today) {
1160
+			$this->_req_data['status'] = 'today';
1161
+		}
1162
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
+		/**
1164
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
+		 *
1166
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
+		 *                             or if you have the development copy of EE you can view this at the path:
1169
+		 *                             /docs/G--Model-System/model-query-params.md
1170
+		 */
1171
+		$query_params['group_by'] = '';
1172
+
1173
+		return $count
1174
+			? EEM_Registration::instance()->count($query_params)
1175
+			/** @type EE_Registration[] */
1176
+			: EEM_Registration::instance()->get_all($query_params);
1177
+	}
1178
+
1179
+
1180
+	/**
1181
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
+	 * Note: this listens to values on the request for some of the query parameters.
1183
+	 *
1184
+	 * @param array $request
1185
+	 * @param int   $per_page
1186
+	 * @param bool  $count
1187
+	 * @return array
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	protected function _get_registration_query_parameters(
1191
+		$request = array(),
1192
+		$per_page = 10,
1193
+		$count = false
1194
+	) {
1195
+
1196
+		$query_params = array(
1197
+			0                          => $this->_get_where_conditions_for_registrations_query(
1198
+				$request
1199
+			),
1200
+			'caps'                     => EEM_Registration::caps_read_admin,
1201
+			'default_where_conditions' => 'this_model_only',
1202
+		);
1203
+		if (! $count) {
1204
+			$query_params = array_merge(
1205
+				$query_params,
1206
+				$this->_get_orderby_for_registrations_query(),
1207
+				$this->_get_limit($per_page)
1208
+			);
1209
+		}
1210
+
1211
+		return $query_params;
1212
+	}
1213
+
1214
+
1215
+	/**
1216
+	 * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
+	 *
1218
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1219
+	 * @return array
1220
+	 */
1221
+	protected function addAttendeeIdToWhereConditions(array $request)
1222
+	{
1223
+		$where = array();
1224
+		if (! empty($request['ATT_ID'])) {
1225
+			$where['ATT_ID'] = absint($request['ATT_ID']);
1226
+		}
1227
+		return $where;
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
+	 *
1234
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1235
+	 * @return array
1236
+	 */
1237
+	protected function _add_event_id_to_where_conditions(array $request)
1238
+	{
1239
+		$where = array();
1240
+		if (! empty($request['event_id'])) {
1241
+			$where['EVT_ID'] = absint($request['event_id']);
1242
+		}
1243
+		return $where;
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
+	 *
1250
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1251
+	 * @return array
1252
+	 */
1253
+	protected function _add_category_id_to_where_conditions(array $request)
1254
+	{
1255
+		$where = array();
1256
+		if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
+		}
1259
+		return $where;
1260
+	}
1261
+
1262
+
1263
+	/**
1264
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
+	 *
1266
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1267
+	 * @return array
1268
+	 */
1269
+	protected function _add_datetime_id_to_where_conditions(array $request)
1270
+	{
1271
+		$where = array();
1272
+		if (! empty($request['datetime_id'])) {
1273
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
+		}
1275
+		if (! empty($request['DTT_ID'])) {
1276
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
+		}
1278
+		return $where;
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * Adds the correct registration status to the where conditions for the registrations query.
1284
+	 *
1285
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1286
+	 * @return array
1287
+	 */
1288
+	protected function _add_registration_status_to_where_conditions(array $request)
1289
+	{
1290
+		$where = array();
1291
+		$view = EEH_Array::is_set($request, 'status', '');
1292
+		$registration_status = ! empty($request['_reg_status'])
1293
+			? sanitize_text_field($request['_reg_status'])
1294
+			: '';
1295
+
1296
+		/*
1297 1297
          * If filtering by registration status, then we show registrations matching that status.
1298 1298
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1299 1299
          * UNLESS viewing trashed registrations.
1300 1300
          */
1301
-        if (! empty($registration_status)) {
1302
-            $where['STS_ID'] = $registration_status;
1303
-        } else {
1304
-            // make sure we exclude incomplete registrations, but only if not trashed.
1305
-            if ($view === 'trash') {
1306
-                $where['REG_deleted'] = true;
1307
-            } elseif ($view === 'incomplete') {
1308
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
-            } else {
1310
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
-            }
1312
-        }
1313
-        return $where;
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     * Adds any provided date restraints to the where conditions for the registrations query.
1319
-     *
1320
-     * @param array $request usually the same as $this->_req_data but not necessarily
1321
-     * @return array
1322
-     * @throws EE_Error
1323
-     * @throws InvalidArgumentException
1324
-     * @throws InvalidDataTypeException
1325
-     * @throws InvalidInterfaceException
1326
-     */
1327
-    protected function _add_date_to_where_conditions(array $request)
1328
-    {
1329
-        $where = array();
1330
-        $view = EEH_Array::is_set($request, 'status', '');
1331
-        $month_range = ! empty($request['month_range'])
1332
-            ? sanitize_text_field($request['month_range'])
1333
-            : '';
1334
-        $retrieve_for_today = $view === 'today';
1335
-        $retrieve_for_this_month = $view === 'month';
1336
-
1337
-        if ($retrieve_for_today) {
1338
-            $now = date('Y-m-d', current_time('timestamp'));
1339
-            $where['REG_date'] = array(
1340
-                'BETWEEN',
1341
-                array(
1342
-                    EEM_Registration::instance()->convert_datetime_for_query(
1343
-                        'REG_date',
1344
-                        $now . ' 00:00:00',
1345
-                        'Y-m-d H:i:s'
1346
-                    ),
1347
-                    EEM_Registration::instance()->convert_datetime_for_query(
1348
-                        'REG_date',
1349
-                        $now . ' 23:59:59',
1350
-                        'Y-m-d H:i:s'
1351
-                    ),
1352
-                ),
1353
-            );
1354
-        } elseif ($retrieve_for_this_month) {
1355
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1356
-            $days_this_month = date('t', current_time('timestamp'));
1357
-            $where['REG_date'] = array(
1358
-                'BETWEEN',
1359
-                array(
1360
-                    EEM_Registration::instance()->convert_datetime_for_query(
1361
-                        'REG_date',
1362
-                        $current_year_and_month . '-01 00:00:00',
1363
-                        'Y-m-d H:i:s'
1364
-                    ),
1365
-                    EEM_Registration::instance()->convert_datetime_for_query(
1366
-                        'REG_date',
1367
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
-                        'Y-m-d H:i:s'
1369
-                    ),
1370
-                ),
1371
-            );
1372
-        } elseif ($month_range) {
1373
-            $pieces = explode(' ', $month_range, 3);
1374
-            $month_requested = ! empty($pieces[0])
1375
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
-                : '';
1377
-            $year_requested = ! empty($pieces[1])
1378
-                ? $pieces[1]
1379
-                : '';
1380
-            // if there is not a month or year then we can't go further
1381
-            if ($month_requested && $year_requested) {
1382
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
-                $where['REG_date'] = array(
1384
-                    'BETWEEN',
1385
-                    array(
1386
-                        EEM_Registration::instance()->convert_datetime_for_query(
1387
-                            'REG_date',
1388
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1389
-                            'Y-m-d H:i:s'
1390
-                        ),
1391
-                        EEM_Registration::instance()->convert_datetime_for_query(
1392
-                            'REG_date',
1393
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
-                            'Y-m-d H:i:s'
1395
-                        ),
1396
-                    ),
1397
-                );
1398
-            }
1399
-        }
1400
-        return $where;
1401
-    }
1402
-
1403
-
1404
-    /**
1405
-     * Adds any provided search restraints to the where conditions for the registrations query
1406
-     *
1407
-     * @param array $request usually the same as $this->_req_data but not necessarily
1408
-     * @return array
1409
-     */
1410
-    protected function _add_search_to_where_conditions(array $request)
1411
-    {
1412
-        $where = array();
1413
-        if (! empty($request['s'])) {
1414
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
-            $where['OR*search_conditions'] = array(
1416
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1417
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
-                'REG_final_price'                         => array('LIKE', $search_string),
1428
-                'REG_code'                                => array('LIKE', $search_string),
1429
-                'REG_count'                               => array('LIKE', $search_string),
1430
-                'REG_group_size'                          => array('LIKE', $search_string),
1431
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
-            );
1435
-        }
1436
-        return $where;
1437
-    }
1438
-
1439
-
1440
-    /**
1441
-     * Sets up the where conditions for the registrations query.
1442
-     *
1443
-     * @param array $request
1444
-     * @return array
1445
-     * @throws EE_Error
1446
-     */
1447
-    protected function _get_where_conditions_for_registrations_query($request)
1448
-    {
1449
-        return apply_filters(
1450
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
-            array_merge(
1452
-                $this->addAttendeeIdToWhereConditions($request),
1453
-                $this->_add_event_id_to_where_conditions($request),
1454
-                $this->_add_category_id_to_where_conditions($request),
1455
-                $this->_add_datetime_id_to_where_conditions($request),
1456
-                $this->_add_registration_status_to_where_conditions($request),
1457
-                $this->_add_date_to_where_conditions($request),
1458
-                $this->_add_search_to_where_conditions($request)
1459
-            ),
1460
-            $request
1461
-        );
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * Sets up the orderby for the registrations query.
1467
-     *
1468
-     * @return array
1469
-     */
1470
-    protected function _get_orderby_for_registrations_query()
1471
-    {
1472
-        $orderby_field = ! empty($this->_req_data['orderby'])
1473
-            ? sanitize_text_field($this->_req_data['orderby'])
1474
-            : '_REG_date';
1475
-        switch ($orderby_field) {
1476
-            case '_REG_ID':
1477
-                $orderby = array('REG_ID');
1478
-                break;
1479
-            case '_Reg_status':
1480
-                $orderby = array('STS_ID');
1481
-                break;
1482
-            case 'ATT_fname':
1483
-                $orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
-                break;
1485
-            case 'ATT_lname':
1486
-                $orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
-                break;
1488
-            case 'event_name':
1489
-                $orderby = array('Event.EVT_name');
1490
-                break;
1491
-            case 'DTT_EVT_start':
1492
-                $orderby = array('Event.Datetime.DTT_EVT_start');
1493
-                break;
1494
-            case '_REG_date':
1495
-                $orderby = array('REG_date');
1496
-                break;
1497
-            default:
1498
-                $orderby = array($orderby_field);
1499
-                break;
1500
-        }
1501
-
1502
-        // order
1503
-        $order = ! empty($this->_req_data['order'])
1504
-            ? sanitize_text_field($this->_req_data['order'])
1505
-            : 'DESC';
1506
-        $orderby = array_combine(
1507
-            $orderby,
1508
-            array_fill(0, count($orderby), $order)
1509
-        );
1510
-        // because there are many registrations with the same date, define
1511
-        // a secondary way to order them, otherwise MySQL seems to be a bit random
1512
-        if (empty($orderby['REG_ID'])) {
1513
-            $orderby['REG_ID'] = $order;
1514
-        }
1515
-
1516
-        $orderby = apply_filters(
1517
-            'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
-            $orderby,
1519
-            $this->_req_data
1520
-        );
1521
-
1522
-        return array('order_by' => $orderby);
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * Sets up the limit for the registrations query.
1528
-     *
1529
-     * @param $per_page
1530
-     * @return array
1531
-     */
1532
-    protected function _get_limit($per_page)
1533
-    {
1534
-        $current_page = ! empty($this->_req_data['paged'])
1535
-            ? absint($this->_req_data['paged'])
1536
-            : 1;
1537
-        $per_page = ! empty($this->_req_data['perpage'])
1538
-            ? $this->_req_data['perpage']
1539
-            : $per_page;
1540
-
1541
-        // -1 means return all results so get out if that's set.
1542
-        if ((int) $per_page === -1) {
1543
-            return array();
1544
-        }
1545
-        $per_page = absint($per_page);
1546
-        $offset = ($current_page - 1) * $per_page;
1547
-        return array('limit' => array($offset, $per_page));
1548
-    }
1549
-
1550
-
1551
-    public function get_registration_status_array()
1552
-    {
1553
-        return self::$_reg_status;
1554
-    }
1555
-
1556
-
1557
-
1558
-
1559
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1560
-    /**
1561
-     *        generates HTML for the View Registration Details Admin page
1562
-     *
1563
-     * @access protected
1564
-     * @return void
1565
-     * @throws DomainException
1566
-     * @throws EE_Error
1567
-     * @throws InvalidArgumentException
1568
-     * @throws InvalidDataTypeException
1569
-     * @throws InvalidInterfaceException
1570
-     * @throws EntityNotFoundException
1571
-     */
1572
-    protected function _registration_details()
1573
-    {
1574
-        $this->_template_args = array();
1575
-        $this->_set_registration_object();
1576
-        if (is_object($this->_registration)) {
1577
-            $transaction = $this->_registration->transaction()
1578
-                ? $this->_registration->transaction()
1579
-                : EE_Transaction::new_instance();
1580
-            $this->_session = $transaction->session_data();
1581
-            $event_id = $this->_registration->event_ID();
1582
-            $this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
-            $this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
-            $this->_template_args['grand_total'] = $transaction->total();
1587
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
-            // link back to overview
1589
-            $this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
-            $this->_template_args['registration'] = $this->_registration;
1591
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
-                array(
1593
-                    'action'   => 'default',
1594
-                    'event_id' => $event_id,
1595
-                ),
1596
-                REG_ADMIN_URL
1597
-            );
1598
-            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
-                array(
1600
-                    'action' => 'default',
1601
-                    'EVT_ID' => $event_id,
1602
-                    'page'   => 'espresso_transactions',
1603
-                ),
1604
-                admin_url('admin.php')
1605
-            );
1606
-            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
-                array(
1608
-                    'page'   => 'espresso_events',
1609
-                    'action' => 'edit',
1610
-                    'post'   => $event_id,
1611
-                ),
1612
-                admin_url('admin.php')
1613
-            );
1614
-            // next and previous links
1615
-            $next_reg = $this->_registration->next(
1616
-                null,
1617
-                array(),
1618
-                'REG_ID'
1619
-            );
1620
-            $this->_template_args['next_registration'] = $next_reg
1621
-                ? $this->_next_link(
1622
-                    EE_Admin_Page::add_query_args_and_nonce(
1623
-                        array(
1624
-                            'action'  => 'view_registration',
1625
-                            '_REG_ID' => $next_reg['REG_ID'],
1626
-                        ),
1627
-                        REG_ADMIN_URL
1628
-                    ),
1629
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1630
-                )
1631
-                : '';
1632
-            $previous_reg = $this->_registration->previous(
1633
-                null,
1634
-                array(),
1635
-                'REG_ID'
1636
-            );
1637
-            $this->_template_args['previous_registration'] = $previous_reg
1638
-                ? $this->_previous_link(
1639
-                    EE_Admin_Page::add_query_args_and_nonce(
1640
-                        array(
1641
-                            'action'  => 'view_registration',
1642
-                            '_REG_ID' => $previous_reg['REG_ID'],
1643
-                        ),
1644
-                        REG_ADMIN_URL
1645
-                    ),
1646
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1647
-                )
1648
-                : '';
1649
-            // grab header
1650
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
1652
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
-                $template_path,
1654
-                $this->_template_args,
1655
-                true
1656
-            );
1657
-        } else {
1658
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
-        }
1660
-        // the details template wrapper
1661
-        $this->display_admin_page_with_sidebar();
1662
-    }
1663
-
1664
-
1665
-    protected function _registration_details_metaboxes()
1666
-    {
1667
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
-        $this->_set_registration_object();
1669
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
-        add_meta_box(
1671
-            'edit-reg-status-mbox',
1672
-            esc_html__('Registration Status', 'event_espresso'),
1673
-            array($this, 'set_reg_status_buttons_metabox'),
1674
-            $this->wp_page_slug,
1675
-            'normal',
1676
-            'high'
1677
-        );
1678
-        add_meta_box(
1679
-            'edit-reg-details-mbox',
1680
-            esc_html__('Registration Details', 'event_espresso'),
1681
-            array($this, '_reg_details_meta_box'),
1682
-            $this->wp_page_slug,
1683
-            'normal',
1684
-            'high'
1685
-        );
1686
-        if ($attendee instanceof EE_Attendee
1687
-            && EE_Registry::instance()->CAP->current_user_can(
1688
-                'ee_read_registration',
1689
-                'edit-reg-questions-mbox',
1690
-                $this->_registration->ID()
1691
-            )
1692
-        ) {
1693
-            add_meta_box(
1694
-                'edit-reg-questions-mbox',
1695
-                esc_html__('Registration Form Answers', 'event_espresso'),
1696
-                array($this, '_reg_questions_meta_box'),
1697
-                $this->wp_page_slug,
1698
-                'normal',
1699
-                'high'
1700
-            );
1701
-        }
1702
-        add_meta_box(
1703
-            'edit-reg-registrant-mbox',
1704
-            esc_html__('Contact Details', 'event_espresso'),
1705
-            array($this, '_reg_registrant_side_meta_box'),
1706
-            $this->wp_page_slug,
1707
-            'side',
1708
-            'high'
1709
-        );
1710
-        if ($this->_registration->group_size() > 1) {
1711
-            add_meta_box(
1712
-                'edit-reg-attendees-mbox',
1713
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
-                array($this, '_reg_attendees_meta_box'),
1715
-                $this->wp_page_slug,
1716
-                'normal',
1717
-                'high'
1718
-            );
1719
-        }
1720
-    }
1721
-
1722
-
1723
-    /**
1724
-     * set_reg_status_buttons_metabox
1725
-     *
1726
-     * @access protected
1727
-     * @return string
1728
-     * @throws \EE_Error
1729
-     */
1730
-    public function set_reg_status_buttons_metabox()
1731
-    {
1732
-        $this->_set_registration_object();
1733
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1734
-        echo $change_reg_status_form->form_open(
1735
-            self::add_query_args_and_nonce(
1736
-                array(
1737
-                    'action' => 'change_reg_status',
1738
-                ),
1739
-                REG_ADMIN_URL
1740
-            )
1741
-        );
1742
-        echo $change_reg_status_form->get_html();
1743
-        echo $change_reg_status_form->form_close();
1744
-    }
1745
-
1746
-
1747
-    /**
1748
-     * @return EE_Form_Section_Proper
1749
-     * @throws EE_Error
1750
-     * @throws InvalidArgumentException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws InvalidInterfaceException
1753
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
-     */
1755
-    protected function _generate_reg_status_change_form()
1756
-    {
1757
-        $reg_status_change_form_array = array(
1758
-            'name'            => 'reg_status_change_form',
1759
-            'html_id'         => 'reg-status-change-form',
1760
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
-            'subsections'     => array(
1762
-                'return'             => new EE_Hidden_Input(
1763
-                    array(
1764
-                        'name'    => 'return',
1765
-                        'default' => 'view_registration',
1766
-                    )
1767
-                ),
1768
-                'REG_ID'             => new EE_Hidden_Input(
1769
-                    array(
1770
-                        'name'    => 'REG_ID',
1771
-                        'default' => $this->_registration->ID(),
1772
-                    )
1773
-                ),
1774
-                'current_status'     => new EE_Form_Section_HTML(
1775
-                    EEH_HTML::tr(
1776
-                        EEH_HTML::th(
1777
-                            EEH_HTML::label(
1778
-                                EEH_HTML::strong(
1779
-                                    esc_html__('Current Registration Status', 'event_espresso')
1780
-                                )
1781
-                            )
1782
-                        )
1783
-                        . EEH_HTML::td(
1784
-                            EEH_HTML::strong(
1785
-                                $this->_registration->pretty_status(),
1786
-                                '',
1787
-                                'status-' . $this->_registration->status_ID(),
1788
-                                'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789
-                            )
1790
-                        )
1791
-                    )
1792
-                )
1793
-            )
1794
-        );
1795
-        if (EE_Registry::instance()->CAP->current_user_can(
1796
-            'ee_edit_registration',
1797
-            'toggle_registration_status',
1798
-            $this->_registration->ID()
1799
-        )) {
1800
-            $reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1801
-                $this->_get_reg_statuses(),
1802
-                array(
1803
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1804
-                    'default'         => $this->_registration->status_ID(),
1805
-                )
1806
-            );
1807
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1808
-                array(
1809
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1810
-                    'default'         => false,
1811
-                    'html_help_text'  => esc_html__(
1812
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1813
-                        'event_espresso'
1814
-                    )
1815
-                )
1816
-            );
1817
-            $reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1818
-                array(
1819
-                    'html_class'      => 'button-primary',
1820
-                    'html_label_text' => '&nbsp;',
1821
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1822
-                )
1823
-            );
1824
-        }
1825
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1826
-    }
1827
-
1828
-
1829
-    /**
1830
-     * Returns an array of all the buttons for the various statuses and switch status actions
1831
-     *
1832
-     * @return array
1833
-     * @throws EE_Error
1834
-     * @throws InvalidArgumentException
1835
-     * @throws InvalidDataTypeException
1836
-     * @throws InvalidInterfaceException
1837
-     * @throws EntityNotFoundException
1838
-     */
1839
-    protected function _get_reg_statuses()
1840
-    {
1841
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1843
-        // get current reg status
1844
-        $current_status = $this->_registration->status_ID();
1845
-        // is registration for free event? This will determine whether to display the pending payment option
1846
-        if ($current_status !== EEM_Registration::status_id_pending_payment
1847
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848
-        ) {
1849
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1850
-        }
1851
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1857
-     *
1858
-     * @param bool $status REG status given for changing registrations to.
1859
-     * @param bool $notify Whether to send messages notifications or not.
1860
-     * @return array (array with reg_id(s) updated and whether update was successful.
1861
-     * @throws EE_Error
1862
-     * @throws InvalidArgumentException
1863
-     * @throws InvalidDataTypeException
1864
-     * @throws InvalidInterfaceException
1865
-     * @throws ReflectionException
1866
-     * @throws RuntimeException
1867
-     * @throws EntityNotFoundException
1868
-     */
1869
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1870
-    {
1871
-        if (isset($this->_req_data['reg_status_change_form'])) {
1872
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1873
-                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1874
-                : array();
1875
-        } else {
1876
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1877
-                ? (array) $this->_req_data['_REG_ID']
1878
-                : array();
1879
-        }
1880
-        // sanitize $REG_IDs
1881
-        $REG_IDs = array_map('absint', $REG_IDs);
1882
-        // and remove empty entries
1883
-        $REG_IDs = array_filter($REG_IDs);
1884
-
1885
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1886
-
1887
-        /**
1888
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1889
-         * Currently this value is used downstream by the _process_resend_registration method.
1890
-         *
1891
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1892
-         * @param bool                     $status           The status registrations were changed to.
1893
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1894
-         * @param Registrations_Admin_Page $admin_page_object
1895
-         */
1896
-        $this->_req_data['_REG_ID'] = apply_filters(
1897
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1898
-            $result['REG_ID'],
1899
-            $status,
1900
-            $result['success'],
1901
-            $this
1902
-        );
1903
-
1904
-        // notify?
1905
-        if ($notify
1906
-            && $result['success']
1907
-            && ! empty($this->_req_data['_REG_ID'])
1908
-            && EE_Registry::instance()->CAP->current_user_can(
1909
-                'ee_send_message',
1910
-                'espresso_registrations_resend_registration'
1911
-            )
1912
-        ) {
1913
-            $this->_process_resend_registration();
1914
-        }
1915
-        return $result;
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1921
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1922
-     *
1923
-     * @param array  $REG_IDs
1924
-     * @param string $status
1925
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1926
-     *                        slug sent with setting the registration status.
1927
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1928
-     * @throws EE_Error
1929
-     * @throws InvalidArgumentException
1930
-     * @throws InvalidDataTypeException
1931
-     * @throws InvalidInterfaceException
1932
-     * @throws ReflectionException
1933
-     * @throws RuntimeException
1934
-     * @throws EntityNotFoundException
1935
-     */
1936
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1937
-    {
1938
-        $success = false;
1939
-        // typecast $REG_IDs
1940
-        $REG_IDs = (array) $REG_IDs;
1941
-        if (! empty($REG_IDs)) {
1942
-            $success = true;
1943
-            // set default status if none is passed
1944
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1945
-            $status_context = $notify
1946
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1947
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1948
-            // loop through REG_ID's and change status
1949
-            foreach ($REG_IDs as $REG_ID) {
1950
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1951
-                if ($registration instanceof EE_Registration) {
1952
-                    $registration->set_status(
1953
-                        $status,
1954
-                        false,
1955
-                        new Context(
1956
-                            $status_context,
1957
-                            esc_html__(
1958
-                                'Manually triggered status change on a Registration Admin Page route.',
1959
-                                'event_espresso'
1960
-                            )
1961
-                        )
1962
-                    );
1963
-                    $result = $registration->save();
1964
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1965
-                    $success = $result !== false ? $success : false;
1966
-                }
1967
-            }
1968
-        }
1969
-
1970
-        // return $success and processed registrations
1971
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1972
-    }
1973
-
1974
-
1975
-    /**
1976
-     * Common logic for setting up success message and redirecting to appropriate route
1977
-     *
1978
-     * @param  string $STS_ID status id for the registration changed to
1979
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1980
-     * @return void
1981
-     * @throws EE_Error
1982
-     */
1983
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1984
-    {
1985
-        $result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1986
-            : array('success' => false);
1987
-        $success = isset($result['success']) && $result['success'];
1988
-        // setup success message
1989
-        if ($success) {
1990
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1991
-                $msg = sprintf(
1992
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1993
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1994
-                );
1995
-            } else {
1996
-                $msg = sprintf(
1997
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1998
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1999
-                );
2000
-            }
2001
-            EE_Error::add_success($msg);
2002
-        } else {
2003
-            EE_Error::add_error(
2004
-                esc_html__(
2005
-                    'Something went wrong, and the status was not changed',
2006
-                    'event_espresso'
2007
-                ),
2008
-                __FILE__,
2009
-                __LINE__,
2010
-                __FUNCTION__
2011
-            );
2012
-        }
2013
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2014
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2015
-        } else {
2016
-            $route = array('action' => 'default');
2017
-        }
2018
-        $route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
2019
-        $this->_redirect_after_action($success, '', '', $route, true);
2020
-    }
2021
-
2022
-
2023
-    /**
2024
-     * incoming reg status change from reg details page.
2025
-     *
2026
-     * @return void
2027
-     */
2028
-    protected function _change_reg_status()
2029
-    {
2030
-        $this->_req_data['return'] = 'view_registration';
2031
-        // set notify based on whether the send notifications toggle is set or not
2032
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2033
-        // $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2034
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2035
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2036
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2037
-            case EEM_Registration::status_id_approved:
2038
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2039
-                $this->approve_registration($notify);
2040
-                break;
2041
-            case EEM_Registration::status_id_pending_payment:
2042
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2043
-                $this->pending_registration($notify);
2044
-                break;
2045
-            case EEM_Registration::status_id_not_approved:
2046
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2047
-                $this->not_approve_registration($notify);
2048
-                break;
2049
-            case EEM_Registration::status_id_declined:
2050
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2051
-                $this->decline_registration($notify);
2052
-                break;
2053
-            case EEM_Registration::status_id_cancelled:
2054
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2055
-                $this->cancel_registration($notify);
2056
-                break;
2057
-            case EEM_Registration::status_id_wait_list:
2058
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2059
-                $this->wait_list_registration($notify);
2060
-                break;
2061
-            case EEM_Registration::status_id_incomplete:
2062
-            default:
2063
-                $result['success'] = false;
2064
-                unset($this->_req_data['return']);
2065
-                $this->_reg_status_change_return('', false);
2066
-                break;
2067
-        }
2068
-    }
2069
-
2070
-
2071
-    /**
2072
-     * Callback for bulk action routes.
2073
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2074
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
2075
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2076
-     * when an action is happening on just a single registration).
2077
-     *
2078
-     * @param      $action
2079
-     * @param bool $notify
2080
-     */
2081
-    protected function bulk_action_on_registrations($action, $notify = false)
2082
-    {
2083
-        do_action(
2084
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2085
-            $this,
2086
-            $action,
2087
-            $notify
2088
-        );
2089
-        $method = $action . '_registration';
2090
-        if (method_exists($this, $method)) {
2091
-            $this->$method($notify);
2092
-        }
2093
-    }
2094
-
2095
-
2096
-    /**
2097
-     * approve_registration
2098
-     *
2099
-     * @access protected
2100
-     * @param bool $notify whether or not to notify the registrant about their approval.
2101
-     * @return void
2102
-     */
2103
-    protected function approve_registration($notify = false)
2104
-    {
2105
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2106
-    }
2107
-
2108
-
2109
-    /**
2110
-     *        decline_registration
2111
-     *
2112
-     * @access protected
2113
-     * @param bool $notify whether or not to notify the registrant about their status change.
2114
-     * @return void
2115
-     */
2116
-    protected function decline_registration($notify = false)
2117
-    {
2118
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2119
-    }
2120
-
2121
-
2122
-    /**
2123
-     *        cancel_registration
2124
-     *
2125
-     * @access protected
2126
-     * @param bool $notify whether or not to notify the registrant about their status change.
2127
-     * @return void
2128
-     */
2129
-    protected function cancel_registration($notify = false)
2130
-    {
2131
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2132
-    }
2133
-
2134
-
2135
-    /**
2136
-     *        not_approve_registration
2137
-     *
2138
-     * @access protected
2139
-     * @param bool $notify whether or not to notify the registrant about their status change.
2140
-     * @return void
2141
-     */
2142
-    protected function not_approve_registration($notify = false)
2143
-    {
2144
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2145
-    }
2146
-
2147
-
2148
-    /**
2149
-     *        decline_registration
2150
-     *
2151
-     * @access protected
2152
-     * @param bool $notify whether or not to notify the registrant about their status change.
2153
-     * @return void
2154
-     */
2155
-    protected function pending_registration($notify = false)
2156
-    {
2157
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2158
-    }
2159
-
2160
-
2161
-    /**
2162
-     * waitlist_registration
2163
-     *
2164
-     * @access protected
2165
-     * @param bool $notify whether or not to notify the registrant about their status change.
2166
-     * @return void
2167
-     */
2168
-    protected function wait_list_registration($notify = false)
2169
-    {
2170
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2171
-    }
2172
-
2173
-
2174
-    /**
2175
-     *        generates HTML for the Registration main meta box
2176
-     *
2177
-     * @access public
2178
-     * @return void
2179
-     * @throws DomainException
2180
-     * @throws EE_Error
2181
-     * @throws InvalidArgumentException
2182
-     * @throws InvalidDataTypeException
2183
-     * @throws InvalidInterfaceException
2184
-     * @throws ReflectionException
2185
-     * @throws EntityNotFoundException
2186
-     */
2187
-    public function _reg_details_meta_box()
2188
-    {
2189
-        EEH_Autoloader::register_line_item_display_autoloaders();
2190
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2191
-        EE_Registry::instance()->load_helper('Line_Item');
2192
-        $transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2193
-            : EE_Transaction::new_instance();
2194
-        $this->_session = $transaction->session_data();
2195
-        $filters = new EE_Line_Item_Filter_Collection();
2196
-        // $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2197
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2198
-        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2199
-            $filters,
2200
-            $transaction->total_line_item()
2201
-        );
2202
-        $filtered_line_item_tree = $line_item_filter_processor->process();
2203
-        $line_item_display = new EE_Line_Item_Display(
2204
-            'reg_admin_table',
2205
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2206
-        );
2207
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2208
-            $filtered_line_item_tree,
2209
-            array('EE_Registration' => $this->_registration)
2210
-        );
2211
-        $attendee = $this->_registration->attendee();
2212
-        if (EE_Registry::instance()->CAP->current_user_can(
2213
-            'ee_read_transaction',
2214
-            'espresso_transactions_view_transaction'
2215
-        )) {
2216
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2217
-                EE_Admin_Page::add_query_args_and_nonce(
2218
-                    array(
2219
-                        'action' => 'view_transaction',
2220
-                        'TXN_ID' => $transaction->ID(),
2221
-                    ),
2222
-                    TXN_ADMIN_URL
2223
-                ),
2224
-                esc_html__(' View Transaction', 'event_espresso'),
2225
-                'button secondary-button right',
2226
-                'dashicons dashicons-cart'
2227
-            );
2228
-        } else {
2229
-            $this->_template_args['view_transaction_button'] = '';
2230
-        }
2231
-        if ($attendee instanceof EE_Attendee
2232
-            && EE_Registry::instance()->CAP->current_user_can(
2233
-                'ee_send_message',
2234
-                'espresso_registrations_resend_registration'
2235
-            )
2236
-        ) {
2237
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2238
-                EE_Admin_Page::add_query_args_and_nonce(
2239
-                    array(
2240
-                        'action'      => 'resend_registration',
2241
-                        '_REG_ID'     => $this->_registration->ID(),
2242
-                        'redirect_to' => 'view_registration',
2243
-                    ),
2244
-                    REG_ADMIN_URL
2245
-                ),
2246
-                esc_html__(' Resend Registration', 'event_espresso'),
2247
-                'button secondary-button right',
2248
-                'dashicons dashicons-email-alt'
2249
-            );
2250
-        } else {
2251
-            $this->_template_args['resend_registration_button'] = '';
2252
-        }
2253
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2254
-        $payment = $transaction->get_first_related('Payment');
2255
-        $payment = ! $payment instanceof EE_Payment
2256
-            ? EE_Payment::new_instance()
2257
-            : $payment;
2258
-        $payment_method = $payment->get_first_related('Payment_Method');
2259
-        $payment_method = ! $payment_method instanceof EE_Payment_Method
2260
-            ? EE_Payment_Method::new_instance()
2261
-            : $payment_method;
2262
-        $reg_details = array(
2263
-            'payment_method'       => $payment_method->name(),
2264
-            'response_msg'         => $payment->gateway_response(),
2265
-            'registration_id'      => $this->_registration->get('REG_code'),
2266
-            'registration_session' => $this->_registration->session_ID(),
2267
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2268
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2269
-        );
2270
-        if (isset($reg_details['registration_id'])) {
2271
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2272
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2273
-                'Registration ID',
2274
-                'event_espresso'
2275
-            );
2276
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2277
-        }
2278
-        if (isset($reg_details['payment_method'])) {
2279
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2280
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2281
-                'Most Recent Payment Method',
2282
-                'event_espresso'
2283
-            );
2284
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2285
-            $this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2286
-            $this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2287
-                'Payment method response',
2288
-                'event_espresso'
2289
-            );
2290
-            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2291
-        }
2292
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2293
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2294
-            'Registration Session',
2295
-            'event_espresso'
2296
-        );
2297
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2298
-        $this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2299
-        $this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2300
-            'Registration placed from IP',
2301
-            'event_espresso'
2302
-        );
2303
-        $this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2304
-        $this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2305
-        $this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2306
-            'Registrant User Agent',
2307
-            'event_espresso'
2308
-        );
2309
-        $this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2310
-        $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2311
-            array(
2312
-                'action'   => 'default',
2313
-                'event_id' => $this->_registration->event_ID(),
2314
-            ),
2315
-            REG_ADMIN_URL
2316
-        );
2317
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2318
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2319
-        $template_path =
2320
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2321
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2322
-    }
2323
-
2324
-
2325
-    /**
2326
-     * generates HTML for the Registration Questions meta box.
2327
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2328
-     * otherwise uses new forms system
2329
-     *
2330
-     * @access public
2331
-     * @return void
2332
-     * @throws DomainException
2333
-     * @throws EE_Error
2334
-     */
2335
-    public function _reg_questions_meta_box()
2336
-    {
2337
-        // allow someone to override this method entirely
2338
-        if (apply_filters(
2339
-            'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2340
-            true,
2341
-            $this,
2342
-            $this->_registration
2343
-        )) {
2344
-            $form = $this->_get_reg_custom_questions_form(
2345
-                $this->_registration->ID()
2346
-            );
2347
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2348
-                ? $form->get_html_and_js()
2349
-                : '';
2350
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2351
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2352
-            $template_path =
2353
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2354
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2355
-        }
2356
-    }
2357
-
2358
-
2359
-    /**
2360
-     * form_before_question_group
2361
-     *
2362
-     * @deprecated    as of 4.8.32.rc.000
2363
-     * @access        public
2364
-     * @param        string $output
2365
-     * @return        string
2366
-     */
2367
-    public function form_before_question_group($output)
2368
-    {
2369
-        EE_Error::doing_it_wrong(
2370
-            __CLASS__ . '::' . __FUNCTION__,
2371
-            esc_html__(
2372
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2373
-                'event_espresso'
2374
-            ),
2375
-            '4.8.32.rc.000'
2376
-        );
2377
-        return '
1301
+		if (! empty($registration_status)) {
1302
+			$where['STS_ID'] = $registration_status;
1303
+		} else {
1304
+			// make sure we exclude incomplete registrations, but only if not trashed.
1305
+			if ($view === 'trash') {
1306
+				$where['REG_deleted'] = true;
1307
+			} elseif ($view === 'incomplete') {
1308
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
+			} else {
1310
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
+			}
1312
+		}
1313
+		return $where;
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1319
+	 *
1320
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1321
+	 * @return array
1322
+	 * @throws EE_Error
1323
+	 * @throws InvalidArgumentException
1324
+	 * @throws InvalidDataTypeException
1325
+	 * @throws InvalidInterfaceException
1326
+	 */
1327
+	protected function _add_date_to_where_conditions(array $request)
1328
+	{
1329
+		$where = array();
1330
+		$view = EEH_Array::is_set($request, 'status', '');
1331
+		$month_range = ! empty($request['month_range'])
1332
+			? sanitize_text_field($request['month_range'])
1333
+			: '';
1334
+		$retrieve_for_today = $view === 'today';
1335
+		$retrieve_for_this_month = $view === 'month';
1336
+
1337
+		if ($retrieve_for_today) {
1338
+			$now = date('Y-m-d', current_time('timestamp'));
1339
+			$where['REG_date'] = array(
1340
+				'BETWEEN',
1341
+				array(
1342
+					EEM_Registration::instance()->convert_datetime_for_query(
1343
+						'REG_date',
1344
+						$now . ' 00:00:00',
1345
+						'Y-m-d H:i:s'
1346
+					),
1347
+					EEM_Registration::instance()->convert_datetime_for_query(
1348
+						'REG_date',
1349
+						$now . ' 23:59:59',
1350
+						'Y-m-d H:i:s'
1351
+					),
1352
+				),
1353
+			);
1354
+		} elseif ($retrieve_for_this_month) {
1355
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1356
+			$days_this_month = date('t', current_time('timestamp'));
1357
+			$where['REG_date'] = array(
1358
+				'BETWEEN',
1359
+				array(
1360
+					EEM_Registration::instance()->convert_datetime_for_query(
1361
+						'REG_date',
1362
+						$current_year_and_month . '-01 00:00:00',
1363
+						'Y-m-d H:i:s'
1364
+					),
1365
+					EEM_Registration::instance()->convert_datetime_for_query(
1366
+						'REG_date',
1367
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
+						'Y-m-d H:i:s'
1369
+					),
1370
+				),
1371
+			);
1372
+		} elseif ($month_range) {
1373
+			$pieces = explode(' ', $month_range, 3);
1374
+			$month_requested = ! empty($pieces[0])
1375
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
+				: '';
1377
+			$year_requested = ! empty($pieces[1])
1378
+				? $pieces[1]
1379
+				: '';
1380
+			// if there is not a month or year then we can't go further
1381
+			if ($month_requested && $year_requested) {
1382
+				$days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
+				$where['REG_date'] = array(
1384
+					'BETWEEN',
1385
+					array(
1386
+						EEM_Registration::instance()->convert_datetime_for_query(
1387
+							'REG_date',
1388
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1389
+							'Y-m-d H:i:s'
1390
+						),
1391
+						EEM_Registration::instance()->convert_datetime_for_query(
1392
+							'REG_date',
1393
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
+							'Y-m-d H:i:s'
1395
+						),
1396
+					),
1397
+				);
1398
+			}
1399
+		}
1400
+		return $where;
1401
+	}
1402
+
1403
+
1404
+	/**
1405
+	 * Adds any provided search restraints to the where conditions for the registrations query
1406
+	 *
1407
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1408
+	 * @return array
1409
+	 */
1410
+	protected function _add_search_to_where_conditions(array $request)
1411
+	{
1412
+		$where = array();
1413
+		if (! empty($request['s'])) {
1414
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
+			$where['OR*search_conditions'] = array(
1416
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1417
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
+				'REG_final_price'                         => array('LIKE', $search_string),
1428
+				'REG_code'                                => array('LIKE', $search_string),
1429
+				'REG_count'                               => array('LIKE', $search_string),
1430
+				'REG_group_size'                          => array('LIKE', $search_string),
1431
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
+			);
1435
+		}
1436
+		return $where;
1437
+	}
1438
+
1439
+
1440
+	/**
1441
+	 * Sets up the where conditions for the registrations query.
1442
+	 *
1443
+	 * @param array $request
1444
+	 * @return array
1445
+	 * @throws EE_Error
1446
+	 */
1447
+	protected function _get_where_conditions_for_registrations_query($request)
1448
+	{
1449
+		return apply_filters(
1450
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
+			array_merge(
1452
+				$this->addAttendeeIdToWhereConditions($request),
1453
+				$this->_add_event_id_to_where_conditions($request),
1454
+				$this->_add_category_id_to_where_conditions($request),
1455
+				$this->_add_datetime_id_to_where_conditions($request),
1456
+				$this->_add_registration_status_to_where_conditions($request),
1457
+				$this->_add_date_to_where_conditions($request),
1458
+				$this->_add_search_to_where_conditions($request)
1459
+			),
1460
+			$request
1461
+		);
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * Sets up the orderby for the registrations query.
1467
+	 *
1468
+	 * @return array
1469
+	 */
1470
+	protected function _get_orderby_for_registrations_query()
1471
+	{
1472
+		$orderby_field = ! empty($this->_req_data['orderby'])
1473
+			? sanitize_text_field($this->_req_data['orderby'])
1474
+			: '_REG_date';
1475
+		switch ($orderby_field) {
1476
+			case '_REG_ID':
1477
+				$orderby = array('REG_ID');
1478
+				break;
1479
+			case '_Reg_status':
1480
+				$orderby = array('STS_ID');
1481
+				break;
1482
+			case 'ATT_fname':
1483
+				$orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
+				break;
1485
+			case 'ATT_lname':
1486
+				$orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
+				break;
1488
+			case 'event_name':
1489
+				$orderby = array('Event.EVT_name');
1490
+				break;
1491
+			case 'DTT_EVT_start':
1492
+				$orderby = array('Event.Datetime.DTT_EVT_start');
1493
+				break;
1494
+			case '_REG_date':
1495
+				$orderby = array('REG_date');
1496
+				break;
1497
+			default:
1498
+				$orderby = array($orderby_field);
1499
+				break;
1500
+		}
1501
+
1502
+		// order
1503
+		$order = ! empty($this->_req_data['order'])
1504
+			? sanitize_text_field($this->_req_data['order'])
1505
+			: 'DESC';
1506
+		$orderby = array_combine(
1507
+			$orderby,
1508
+			array_fill(0, count($orderby), $order)
1509
+		);
1510
+		// because there are many registrations with the same date, define
1511
+		// a secondary way to order them, otherwise MySQL seems to be a bit random
1512
+		if (empty($orderby['REG_ID'])) {
1513
+			$orderby['REG_ID'] = $order;
1514
+		}
1515
+
1516
+		$orderby = apply_filters(
1517
+			'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
+			$orderby,
1519
+			$this->_req_data
1520
+		);
1521
+
1522
+		return array('order_by' => $orderby);
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * Sets up the limit for the registrations query.
1528
+	 *
1529
+	 * @param $per_page
1530
+	 * @return array
1531
+	 */
1532
+	protected function _get_limit($per_page)
1533
+	{
1534
+		$current_page = ! empty($this->_req_data['paged'])
1535
+			? absint($this->_req_data['paged'])
1536
+			: 1;
1537
+		$per_page = ! empty($this->_req_data['perpage'])
1538
+			? $this->_req_data['perpage']
1539
+			: $per_page;
1540
+
1541
+		// -1 means return all results so get out if that's set.
1542
+		if ((int) $per_page === -1) {
1543
+			return array();
1544
+		}
1545
+		$per_page = absint($per_page);
1546
+		$offset = ($current_page - 1) * $per_page;
1547
+		return array('limit' => array($offset, $per_page));
1548
+	}
1549
+
1550
+
1551
+	public function get_registration_status_array()
1552
+	{
1553
+		return self::$_reg_status;
1554
+	}
1555
+
1556
+
1557
+
1558
+
1559
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1560
+	/**
1561
+	 *        generates HTML for the View Registration Details Admin page
1562
+	 *
1563
+	 * @access protected
1564
+	 * @return void
1565
+	 * @throws DomainException
1566
+	 * @throws EE_Error
1567
+	 * @throws InvalidArgumentException
1568
+	 * @throws InvalidDataTypeException
1569
+	 * @throws InvalidInterfaceException
1570
+	 * @throws EntityNotFoundException
1571
+	 */
1572
+	protected function _registration_details()
1573
+	{
1574
+		$this->_template_args = array();
1575
+		$this->_set_registration_object();
1576
+		if (is_object($this->_registration)) {
1577
+			$transaction = $this->_registration->transaction()
1578
+				? $this->_registration->transaction()
1579
+				: EE_Transaction::new_instance();
1580
+			$this->_session = $transaction->session_data();
1581
+			$event_id = $this->_registration->event_ID();
1582
+			$this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
+			$this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
+			$this->_template_args['grand_total'] = $transaction->total();
1587
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
+			// link back to overview
1589
+			$this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
+			$this->_template_args['registration'] = $this->_registration;
1591
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
+				array(
1593
+					'action'   => 'default',
1594
+					'event_id' => $event_id,
1595
+				),
1596
+				REG_ADMIN_URL
1597
+			);
1598
+			$this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
+				array(
1600
+					'action' => 'default',
1601
+					'EVT_ID' => $event_id,
1602
+					'page'   => 'espresso_transactions',
1603
+				),
1604
+				admin_url('admin.php')
1605
+			);
1606
+			$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
+				array(
1608
+					'page'   => 'espresso_events',
1609
+					'action' => 'edit',
1610
+					'post'   => $event_id,
1611
+				),
1612
+				admin_url('admin.php')
1613
+			);
1614
+			// next and previous links
1615
+			$next_reg = $this->_registration->next(
1616
+				null,
1617
+				array(),
1618
+				'REG_ID'
1619
+			);
1620
+			$this->_template_args['next_registration'] = $next_reg
1621
+				? $this->_next_link(
1622
+					EE_Admin_Page::add_query_args_and_nonce(
1623
+						array(
1624
+							'action'  => 'view_registration',
1625
+							'_REG_ID' => $next_reg['REG_ID'],
1626
+						),
1627
+						REG_ADMIN_URL
1628
+					),
1629
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1630
+				)
1631
+				: '';
1632
+			$previous_reg = $this->_registration->previous(
1633
+				null,
1634
+				array(),
1635
+				'REG_ID'
1636
+			);
1637
+			$this->_template_args['previous_registration'] = $previous_reg
1638
+				? $this->_previous_link(
1639
+					EE_Admin_Page::add_query_args_and_nonce(
1640
+						array(
1641
+							'action'  => 'view_registration',
1642
+							'_REG_ID' => $previous_reg['REG_ID'],
1643
+						),
1644
+						REG_ADMIN_URL
1645
+					),
1646
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1647
+				)
1648
+				: '';
1649
+			// grab header
1650
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
1652
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
+				$template_path,
1654
+				$this->_template_args,
1655
+				true
1656
+			);
1657
+		} else {
1658
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
+		}
1660
+		// the details template wrapper
1661
+		$this->display_admin_page_with_sidebar();
1662
+	}
1663
+
1664
+
1665
+	protected function _registration_details_metaboxes()
1666
+	{
1667
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
+		$this->_set_registration_object();
1669
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
+		add_meta_box(
1671
+			'edit-reg-status-mbox',
1672
+			esc_html__('Registration Status', 'event_espresso'),
1673
+			array($this, 'set_reg_status_buttons_metabox'),
1674
+			$this->wp_page_slug,
1675
+			'normal',
1676
+			'high'
1677
+		);
1678
+		add_meta_box(
1679
+			'edit-reg-details-mbox',
1680
+			esc_html__('Registration Details', 'event_espresso'),
1681
+			array($this, '_reg_details_meta_box'),
1682
+			$this->wp_page_slug,
1683
+			'normal',
1684
+			'high'
1685
+		);
1686
+		if ($attendee instanceof EE_Attendee
1687
+			&& EE_Registry::instance()->CAP->current_user_can(
1688
+				'ee_read_registration',
1689
+				'edit-reg-questions-mbox',
1690
+				$this->_registration->ID()
1691
+			)
1692
+		) {
1693
+			add_meta_box(
1694
+				'edit-reg-questions-mbox',
1695
+				esc_html__('Registration Form Answers', 'event_espresso'),
1696
+				array($this, '_reg_questions_meta_box'),
1697
+				$this->wp_page_slug,
1698
+				'normal',
1699
+				'high'
1700
+			);
1701
+		}
1702
+		add_meta_box(
1703
+			'edit-reg-registrant-mbox',
1704
+			esc_html__('Contact Details', 'event_espresso'),
1705
+			array($this, '_reg_registrant_side_meta_box'),
1706
+			$this->wp_page_slug,
1707
+			'side',
1708
+			'high'
1709
+		);
1710
+		if ($this->_registration->group_size() > 1) {
1711
+			add_meta_box(
1712
+				'edit-reg-attendees-mbox',
1713
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
+				array($this, '_reg_attendees_meta_box'),
1715
+				$this->wp_page_slug,
1716
+				'normal',
1717
+				'high'
1718
+			);
1719
+		}
1720
+	}
1721
+
1722
+
1723
+	/**
1724
+	 * set_reg_status_buttons_metabox
1725
+	 *
1726
+	 * @access protected
1727
+	 * @return string
1728
+	 * @throws \EE_Error
1729
+	 */
1730
+	public function set_reg_status_buttons_metabox()
1731
+	{
1732
+		$this->_set_registration_object();
1733
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1734
+		echo $change_reg_status_form->form_open(
1735
+			self::add_query_args_and_nonce(
1736
+				array(
1737
+					'action' => 'change_reg_status',
1738
+				),
1739
+				REG_ADMIN_URL
1740
+			)
1741
+		);
1742
+		echo $change_reg_status_form->get_html();
1743
+		echo $change_reg_status_form->form_close();
1744
+	}
1745
+
1746
+
1747
+	/**
1748
+	 * @return EE_Form_Section_Proper
1749
+	 * @throws EE_Error
1750
+	 * @throws InvalidArgumentException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws InvalidInterfaceException
1753
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
+	 */
1755
+	protected function _generate_reg_status_change_form()
1756
+	{
1757
+		$reg_status_change_form_array = array(
1758
+			'name'            => 'reg_status_change_form',
1759
+			'html_id'         => 'reg-status-change-form',
1760
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
+			'subsections'     => array(
1762
+				'return'             => new EE_Hidden_Input(
1763
+					array(
1764
+						'name'    => 'return',
1765
+						'default' => 'view_registration',
1766
+					)
1767
+				),
1768
+				'REG_ID'             => new EE_Hidden_Input(
1769
+					array(
1770
+						'name'    => 'REG_ID',
1771
+						'default' => $this->_registration->ID(),
1772
+					)
1773
+				),
1774
+				'current_status'     => new EE_Form_Section_HTML(
1775
+					EEH_HTML::tr(
1776
+						EEH_HTML::th(
1777
+							EEH_HTML::label(
1778
+								EEH_HTML::strong(
1779
+									esc_html__('Current Registration Status', 'event_espresso')
1780
+								)
1781
+							)
1782
+						)
1783
+						. EEH_HTML::td(
1784
+							EEH_HTML::strong(
1785
+								$this->_registration->pretty_status(),
1786
+								'',
1787
+								'status-' . $this->_registration->status_ID(),
1788
+								'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789
+							)
1790
+						)
1791
+					)
1792
+				)
1793
+			)
1794
+		);
1795
+		if (EE_Registry::instance()->CAP->current_user_can(
1796
+			'ee_edit_registration',
1797
+			'toggle_registration_status',
1798
+			$this->_registration->ID()
1799
+		)) {
1800
+			$reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1801
+				$this->_get_reg_statuses(),
1802
+				array(
1803
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1804
+					'default'         => $this->_registration->status_ID(),
1805
+				)
1806
+			);
1807
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1808
+				array(
1809
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1810
+					'default'         => false,
1811
+					'html_help_text'  => esc_html__(
1812
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1813
+						'event_espresso'
1814
+					)
1815
+				)
1816
+			);
1817
+			$reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1818
+				array(
1819
+					'html_class'      => 'button-primary',
1820
+					'html_label_text' => '&nbsp;',
1821
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1822
+				)
1823
+			);
1824
+		}
1825
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1826
+	}
1827
+
1828
+
1829
+	/**
1830
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1831
+	 *
1832
+	 * @return array
1833
+	 * @throws EE_Error
1834
+	 * @throws InvalidArgumentException
1835
+	 * @throws InvalidDataTypeException
1836
+	 * @throws InvalidInterfaceException
1837
+	 * @throws EntityNotFoundException
1838
+	 */
1839
+	protected function _get_reg_statuses()
1840
+	{
1841
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1843
+		// get current reg status
1844
+		$current_status = $this->_registration->status_ID();
1845
+		// is registration for free event? This will determine whether to display the pending payment option
1846
+		if ($current_status !== EEM_Registration::status_id_pending_payment
1847
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848
+		) {
1849
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1850
+		}
1851
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1857
+	 *
1858
+	 * @param bool $status REG status given for changing registrations to.
1859
+	 * @param bool $notify Whether to send messages notifications or not.
1860
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1861
+	 * @throws EE_Error
1862
+	 * @throws InvalidArgumentException
1863
+	 * @throws InvalidDataTypeException
1864
+	 * @throws InvalidInterfaceException
1865
+	 * @throws ReflectionException
1866
+	 * @throws RuntimeException
1867
+	 * @throws EntityNotFoundException
1868
+	 */
1869
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1870
+	{
1871
+		if (isset($this->_req_data['reg_status_change_form'])) {
1872
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1873
+				? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1874
+				: array();
1875
+		} else {
1876
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1877
+				? (array) $this->_req_data['_REG_ID']
1878
+				: array();
1879
+		}
1880
+		// sanitize $REG_IDs
1881
+		$REG_IDs = array_map('absint', $REG_IDs);
1882
+		// and remove empty entries
1883
+		$REG_IDs = array_filter($REG_IDs);
1884
+
1885
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1886
+
1887
+		/**
1888
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1889
+		 * Currently this value is used downstream by the _process_resend_registration method.
1890
+		 *
1891
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1892
+		 * @param bool                     $status           The status registrations were changed to.
1893
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1894
+		 * @param Registrations_Admin_Page $admin_page_object
1895
+		 */
1896
+		$this->_req_data['_REG_ID'] = apply_filters(
1897
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1898
+			$result['REG_ID'],
1899
+			$status,
1900
+			$result['success'],
1901
+			$this
1902
+		);
1903
+
1904
+		// notify?
1905
+		if ($notify
1906
+			&& $result['success']
1907
+			&& ! empty($this->_req_data['_REG_ID'])
1908
+			&& EE_Registry::instance()->CAP->current_user_can(
1909
+				'ee_send_message',
1910
+				'espresso_registrations_resend_registration'
1911
+			)
1912
+		) {
1913
+			$this->_process_resend_registration();
1914
+		}
1915
+		return $result;
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1921
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1922
+	 *
1923
+	 * @param array  $REG_IDs
1924
+	 * @param string $status
1925
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1926
+	 *                        slug sent with setting the registration status.
1927
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1928
+	 * @throws EE_Error
1929
+	 * @throws InvalidArgumentException
1930
+	 * @throws InvalidDataTypeException
1931
+	 * @throws InvalidInterfaceException
1932
+	 * @throws ReflectionException
1933
+	 * @throws RuntimeException
1934
+	 * @throws EntityNotFoundException
1935
+	 */
1936
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1937
+	{
1938
+		$success = false;
1939
+		// typecast $REG_IDs
1940
+		$REG_IDs = (array) $REG_IDs;
1941
+		if (! empty($REG_IDs)) {
1942
+			$success = true;
1943
+			// set default status if none is passed
1944
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1945
+			$status_context = $notify
1946
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1947
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1948
+			// loop through REG_ID's and change status
1949
+			foreach ($REG_IDs as $REG_ID) {
1950
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1951
+				if ($registration instanceof EE_Registration) {
1952
+					$registration->set_status(
1953
+						$status,
1954
+						false,
1955
+						new Context(
1956
+							$status_context,
1957
+							esc_html__(
1958
+								'Manually triggered status change on a Registration Admin Page route.',
1959
+								'event_espresso'
1960
+							)
1961
+						)
1962
+					);
1963
+					$result = $registration->save();
1964
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1965
+					$success = $result !== false ? $success : false;
1966
+				}
1967
+			}
1968
+		}
1969
+
1970
+		// return $success and processed registrations
1971
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1972
+	}
1973
+
1974
+
1975
+	/**
1976
+	 * Common logic for setting up success message and redirecting to appropriate route
1977
+	 *
1978
+	 * @param  string $STS_ID status id for the registration changed to
1979
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1980
+	 * @return void
1981
+	 * @throws EE_Error
1982
+	 */
1983
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1984
+	{
1985
+		$result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1986
+			: array('success' => false);
1987
+		$success = isset($result['success']) && $result['success'];
1988
+		// setup success message
1989
+		if ($success) {
1990
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1991
+				$msg = sprintf(
1992
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1993
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1994
+				);
1995
+			} else {
1996
+				$msg = sprintf(
1997
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1998
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1999
+				);
2000
+			}
2001
+			EE_Error::add_success($msg);
2002
+		} else {
2003
+			EE_Error::add_error(
2004
+				esc_html__(
2005
+					'Something went wrong, and the status was not changed',
2006
+					'event_espresso'
2007
+				),
2008
+				__FILE__,
2009
+				__LINE__,
2010
+				__FUNCTION__
2011
+			);
2012
+		}
2013
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2014
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2015
+		} else {
2016
+			$route = array('action' => 'default');
2017
+		}
2018
+		$route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
2019
+		$this->_redirect_after_action($success, '', '', $route, true);
2020
+	}
2021
+
2022
+
2023
+	/**
2024
+	 * incoming reg status change from reg details page.
2025
+	 *
2026
+	 * @return void
2027
+	 */
2028
+	protected function _change_reg_status()
2029
+	{
2030
+		$this->_req_data['return'] = 'view_registration';
2031
+		// set notify based on whether the send notifications toggle is set or not
2032
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2033
+		// $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2034
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2035
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2036
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2037
+			case EEM_Registration::status_id_approved:
2038
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2039
+				$this->approve_registration($notify);
2040
+				break;
2041
+			case EEM_Registration::status_id_pending_payment:
2042
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2043
+				$this->pending_registration($notify);
2044
+				break;
2045
+			case EEM_Registration::status_id_not_approved:
2046
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2047
+				$this->not_approve_registration($notify);
2048
+				break;
2049
+			case EEM_Registration::status_id_declined:
2050
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2051
+				$this->decline_registration($notify);
2052
+				break;
2053
+			case EEM_Registration::status_id_cancelled:
2054
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2055
+				$this->cancel_registration($notify);
2056
+				break;
2057
+			case EEM_Registration::status_id_wait_list:
2058
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2059
+				$this->wait_list_registration($notify);
2060
+				break;
2061
+			case EEM_Registration::status_id_incomplete:
2062
+			default:
2063
+				$result['success'] = false;
2064
+				unset($this->_req_data['return']);
2065
+				$this->_reg_status_change_return('', false);
2066
+				break;
2067
+		}
2068
+	}
2069
+
2070
+
2071
+	/**
2072
+	 * Callback for bulk action routes.
2073
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2074
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
2075
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2076
+	 * when an action is happening on just a single registration).
2077
+	 *
2078
+	 * @param      $action
2079
+	 * @param bool $notify
2080
+	 */
2081
+	protected function bulk_action_on_registrations($action, $notify = false)
2082
+	{
2083
+		do_action(
2084
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2085
+			$this,
2086
+			$action,
2087
+			$notify
2088
+		);
2089
+		$method = $action . '_registration';
2090
+		if (method_exists($this, $method)) {
2091
+			$this->$method($notify);
2092
+		}
2093
+	}
2094
+
2095
+
2096
+	/**
2097
+	 * approve_registration
2098
+	 *
2099
+	 * @access protected
2100
+	 * @param bool $notify whether or not to notify the registrant about their approval.
2101
+	 * @return void
2102
+	 */
2103
+	protected function approve_registration($notify = false)
2104
+	{
2105
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2106
+	}
2107
+
2108
+
2109
+	/**
2110
+	 *        decline_registration
2111
+	 *
2112
+	 * @access protected
2113
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2114
+	 * @return void
2115
+	 */
2116
+	protected function decline_registration($notify = false)
2117
+	{
2118
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2119
+	}
2120
+
2121
+
2122
+	/**
2123
+	 *        cancel_registration
2124
+	 *
2125
+	 * @access protected
2126
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2127
+	 * @return void
2128
+	 */
2129
+	protected function cancel_registration($notify = false)
2130
+	{
2131
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2132
+	}
2133
+
2134
+
2135
+	/**
2136
+	 *        not_approve_registration
2137
+	 *
2138
+	 * @access protected
2139
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2140
+	 * @return void
2141
+	 */
2142
+	protected function not_approve_registration($notify = false)
2143
+	{
2144
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2145
+	}
2146
+
2147
+
2148
+	/**
2149
+	 *        decline_registration
2150
+	 *
2151
+	 * @access protected
2152
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2153
+	 * @return void
2154
+	 */
2155
+	protected function pending_registration($notify = false)
2156
+	{
2157
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2158
+	}
2159
+
2160
+
2161
+	/**
2162
+	 * waitlist_registration
2163
+	 *
2164
+	 * @access protected
2165
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2166
+	 * @return void
2167
+	 */
2168
+	protected function wait_list_registration($notify = false)
2169
+	{
2170
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2171
+	}
2172
+
2173
+
2174
+	/**
2175
+	 *        generates HTML for the Registration main meta box
2176
+	 *
2177
+	 * @access public
2178
+	 * @return void
2179
+	 * @throws DomainException
2180
+	 * @throws EE_Error
2181
+	 * @throws InvalidArgumentException
2182
+	 * @throws InvalidDataTypeException
2183
+	 * @throws InvalidInterfaceException
2184
+	 * @throws ReflectionException
2185
+	 * @throws EntityNotFoundException
2186
+	 */
2187
+	public function _reg_details_meta_box()
2188
+	{
2189
+		EEH_Autoloader::register_line_item_display_autoloaders();
2190
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2191
+		EE_Registry::instance()->load_helper('Line_Item');
2192
+		$transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2193
+			: EE_Transaction::new_instance();
2194
+		$this->_session = $transaction->session_data();
2195
+		$filters = new EE_Line_Item_Filter_Collection();
2196
+		// $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2197
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2198
+		$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2199
+			$filters,
2200
+			$transaction->total_line_item()
2201
+		);
2202
+		$filtered_line_item_tree = $line_item_filter_processor->process();
2203
+		$line_item_display = new EE_Line_Item_Display(
2204
+			'reg_admin_table',
2205
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2206
+		);
2207
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2208
+			$filtered_line_item_tree,
2209
+			array('EE_Registration' => $this->_registration)
2210
+		);
2211
+		$attendee = $this->_registration->attendee();
2212
+		if (EE_Registry::instance()->CAP->current_user_can(
2213
+			'ee_read_transaction',
2214
+			'espresso_transactions_view_transaction'
2215
+		)) {
2216
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2217
+				EE_Admin_Page::add_query_args_and_nonce(
2218
+					array(
2219
+						'action' => 'view_transaction',
2220
+						'TXN_ID' => $transaction->ID(),
2221
+					),
2222
+					TXN_ADMIN_URL
2223
+				),
2224
+				esc_html__(' View Transaction', 'event_espresso'),
2225
+				'button secondary-button right',
2226
+				'dashicons dashicons-cart'
2227
+			);
2228
+		} else {
2229
+			$this->_template_args['view_transaction_button'] = '';
2230
+		}
2231
+		if ($attendee instanceof EE_Attendee
2232
+			&& EE_Registry::instance()->CAP->current_user_can(
2233
+				'ee_send_message',
2234
+				'espresso_registrations_resend_registration'
2235
+			)
2236
+		) {
2237
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2238
+				EE_Admin_Page::add_query_args_and_nonce(
2239
+					array(
2240
+						'action'      => 'resend_registration',
2241
+						'_REG_ID'     => $this->_registration->ID(),
2242
+						'redirect_to' => 'view_registration',
2243
+					),
2244
+					REG_ADMIN_URL
2245
+				),
2246
+				esc_html__(' Resend Registration', 'event_espresso'),
2247
+				'button secondary-button right',
2248
+				'dashicons dashicons-email-alt'
2249
+			);
2250
+		} else {
2251
+			$this->_template_args['resend_registration_button'] = '';
2252
+		}
2253
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2254
+		$payment = $transaction->get_first_related('Payment');
2255
+		$payment = ! $payment instanceof EE_Payment
2256
+			? EE_Payment::new_instance()
2257
+			: $payment;
2258
+		$payment_method = $payment->get_first_related('Payment_Method');
2259
+		$payment_method = ! $payment_method instanceof EE_Payment_Method
2260
+			? EE_Payment_Method::new_instance()
2261
+			: $payment_method;
2262
+		$reg_details = array(
2263
+			'payment_method'       => $payment_method->name(),
2264
+			'response_msg'         => $payment->gateway_response(),
2265
+			'registration_id'      => $this->_registration->get('REG_code'),
2266
+			'registration_session' => $this->_registration->session_ID(),
2267
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2268
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2269
+		);
2270
+		if (isset($reg_details['registration_id'])) {
2271
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2272
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2273
+				'Registration ID',
2274
+				'event_espresso'
2275
+			);
2276
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2277
+		}
2278
+		if (isset($reg_details['payment_method'])) {
2279
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2280
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2281
+				'Most Recent Payment Method',
2282
+				'event_espresso'
2283
+			);
2284
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2285
+			$this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2286
+			$this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2287
+				'Payment method response',
2288
+				'event_espresso'
2289
+			);
2290
+			$this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2291
+		}
2292
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2293
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2294
+			'Registration Session',
2295
+			'event_espresso'
2296
+		);
2297
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2298
+		$this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2299
+		$this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2300
+			'Registration placed from IP',
2301
+			'event_espresso'
2302
+		);
2303
+		$this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2304
+		$this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2305
+		$this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2306
+			'Registrant User Agent',
2307
+			'event_espresso'
2308
+		);
2309
+		$this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2310
+		$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2311
+			array(
2312
+				'action'   => 'default',
2313
+				'event_id' => $this->_registration->event_ID(),
2314
+			),
2315
+			REG_ADMIN_URL
2316
+		);
2317
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2318
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2319
+		$template_path =
2320
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2321
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2322
+	}
2323
+
2324
+
2325
+	/**
2326
+	 * generates HTML for the Registration Questions meta box.
2327
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2328
+	 * otherwise uses new forms system
2329
+	 *
2330
+	 * @access public
2331
+	 * @return void
2332
+	 * @throws DomainException
2333
+	 * @throws EE_Error
2334
+	 */
2335
+	public function _reg_questions_meta_box()
2336
+	{
2337
+		// allow someone to override this method entirely
2338
+		if (apply_filters(
2339
+			'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2340
+			true,
2341
+			$this,
2342
+			$this->_registration
2343
+		)) {
2344
+			$form = $this->_get_reg_custom_questions_form(
2345
+				$this->_registration->ID()
2346
+			);
2347
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2348
+				? $form->get_html_and_js()
2349
+				: '';
2350
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2351
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2352
+			$template_path =
2353
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2354
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2355
+		}
2356
+	}
2357
+
2358
+
2359
+	/**
2360
+	 * form_before_question_group
2361
+	 *
2362
+	 * @deprecated    as of 4.8.32.rc.000
2363
+	 * @access        public
2364
+	 * @param        string $output
2365
+	 * @return        string
2366
+	 */
2367
+	public function form_before_question_group($output)
2368
+	{
2369
+		EE_Error::doing_it_wrong(
2370
+			__CLASS__ . '::' . __FUNCTION__,
2371
+			esc_html__(
2372
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2373
+				'event_espresso'
2374
+			),
2375
+			'4.8.32.rc.000'
2376
+		);
2377
+		return '
2378 2378
 	<table class="form-table ee-width-100">
2379 2379
 		<tbody>
2380 2380
 			';
2381
-    }
2382
-
2383
-
2384
-    /**
2385
-     * form_after_question_group
2386
-     *
2387
-     * @deprecated    as of 4.8.32.rc.000
2388
-     * @access        public
2389
-     * @param        string $output
2390
-     * @return        string
2391
-     */
2392
-    public function form_after_question_group($output)
2393
-    {
2394
-        EE_Error::doing_it_wrong(
2395
-            __CLASS__ . '::' . __FUNCTION__,
2396
-            esc_html__(
2397
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2398
-                'event_espresso'
2399
-            ),
2400
-            '4.8.32.rc.000'
2401
-        );
2402
-        return '
2381
+	}
2382
+
2383
+
2384
+	/**
2385
+	 * form_after_question_group
2386
+	 *
2387
+	 * @deprecated    as of 4.8.32.rc.000
2388
+	 * @access        public
2389
+	 * @param        string $output
2390
+	 * @return        string
2391
+	 */
2392
+	public function form_after_question_group($output)
2393
+	{
2394
+		EE_Error::doing_it_wrong(
2395
+			__CLASS__ . '::' . __FUNCTION__,
2396
+			esc_html__(
2397
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2398
+				'event_espresso'
2399
+			),
2400
+			'4.8.32.rc.000'
2401
+		);
2402
+		return '
2403 2403
 			<tr class="hide-if-no-js">
2404 2404
 				<th> </th>
2405 2405
 				<td class="reg-admin-edit-attendee-question-td">
2406 2406
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2407
-               . esc_attr__('click to edit question', 'event_espresso')
2408
-               . '">
2407
+			   . esc_attr__('click to edit question', 'event_espresso')
2408
+			   . '">
2409 2409
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2410
-               . esc_html__('edit the above question group', 'event_espresso')
2411
-               . '</span>
2410
+			   . esc_html__('edit the above question group', 'event_espresso')
2411
+			   . '</span>
2412 2412
 						<div class="dashicons dashicons-edit"></div>
2413 2413
 					</a>
2414 2414
 				</td>
@@ -2416,606 +2416,606 @@  discard block
 block discarded – undo
2416 2416
 		</tbody>
2417 2417
 	</table>
2418 2418
 ';
2419
-    }
2420
-
2421
-
2422
-    /**
2423
-     * form_form_field_label_wrap
2424
-     *
2425
-     * @deprecated    as of 4.8.32.rc.000
2426
-     * @access        public
2427
-     * @param        string $label
2428
-     * @return        string
2429
-     */
2430
-    public function form_form_field_label_wrap($label)
2431
-    {
2432
-        EE_Error::doing_it_wrong(
2433
-            __CLASS__ . '::' . __FUNCTION__,
2434
-            esc_html__(
2435
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2436
-                'event_espresso'
2437
-            ),
2438
-            '4.8.32.rc.000'
2439
-        );
2440
-        return '
2419
+	}
2420
+
2421
+
2422
+	/**
2423
+	 * form_form_field_label_wrap
2424
+	 *
2425
+	 * @deprecated    as of 4.8.32.rc.000
2426
+	 * @access        public
2427
+	 * @param        string $label
2428
+	 * @return        string
2429
+	 */
2430
+	public function form_form_field_label_wrap($label)
2431
+	{
2432
+		EE_Error::doing_it_wrong(
2433
+			__CLASS__ . '::' . __FUNCTION__,
2434
+			esc_html__(
2435
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2436
+				'event_espresso'
2437
+			),
2438
+			'4.8.32.rc.000'
2439
+		);
2440
+		return '
2441 2441
 			<tr>
2442 2442
 				<th>
2443 2443
 					' . $label . '
2444 2444
 				</th>';
2445
-    }
2446
-
2447
-
2448
-    /**
2449
-     * form_form_field_input__wrap
2450
-     *
2451
-     * @deprecated    as of 4.8.32.rc.000
2452
-     * @access        public
2453
-     * @param        string $input
2454
-     * @return        string
2455
-     */
2456
-    public function form_form_field_input__wrap($input)
2457
-    {
2458
-        EE_Error::doing_it_wrong(
2459
-            __CLASS__ . '::' . __FUNCTION__,
2460
-            esc_html__(
2461
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2462
-                'event_espresso'
2463
-            ),
2464
-            '4.8.32.rc.000'
2465
-        );
2466
-        return '
2445
+	}
2446
+
2447
+
2448
+	/**
2449
+	 * form_form_field_input__wrap
2450
+	 *
2451
+	 * @deprecated    as of 4.8.32.rc.000
2452
+	 * @access        public
2453
+	 * @param        string $input
2454
+	 * @return        string
2455
+	 */
2456
+	public function form_form_field_input__wrap($input)
2457
+	{
2458
+		EE_Error::doing_it_wrong(
2459
+			__CLASS__ . '::' . __FUNCTION__,
2460
+			esc_html__(
2461
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2462
+				'event_espresso'
2463
+			),
2464
+			'4.8.32.rc.000'
2465
+		);
2466
+		return '
2467 2467
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2468 2468
 					' . $input . '
2469 2469
 				</td>
2470 2470
 			</tr>';
2471
-    }
2472
-
2473
-
2474
-    /**
2475
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2476
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2477
-     * to display the page
2478
-     *
2479
-     * @access protected
2480
-     * @return void
2481
-     * @throws EE_Error
2482
-     */
2483
-    protected function _update_attendee_registration_form()
2484
-    {
2485
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2486
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2487
-            $REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2488
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2489
-            if ($success) {
2490
-                $what = esc_html__('Registration Form', 'event_espresso');
2491
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2492
-                    : array('action' => 'default');
2493
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2494
-            }
2495
-        }
2496
-    }
2497
-
2498
-
2499
-    /**
2500
-     * Gets the form for saving registrations custom questions (if done
2501
-     * previously retrieves the cached form object, which may have validation errors in it)
2502
-     *
2503
-     * @param int $REG_ID
2504
-     * @return EE_Registration_Custom_Questions_Form
2505
-     * @throws EE_Error
2506
-     * @throws InvalidArgumentException
2507
-     * @throws InvalidDataTypeException
2508
-     * @throws InvalidInterfaceException
2509
-     */
2510
-    protected function _get_reg_custom_questions_form($REG_ID)
2511
-    {
2512
-        if (! $this->_reg_custom_questions_form) {
2513
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2514
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2515
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2516
-            );
2517
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2518
-        }
2519
-        return $this->_reg_custom_questions_form;
2520
-    }
2521
-
2522
-
2523
-    /**
2524
-     * Saves
2525
-     *
2526
-     * @access private
2527
-     * @param bool $REG_ID
2528
-     * @return bool
2529
-     * @throws EE_Error
2530
-     * @throws InvalidArgumentException
2531
-     * @throws InvalidDataTypeException
2532
-     * @throws InvalidInterfaceException
2533
-     */
2534
-    private function _save_reg_custom_questions_form($REG_ID = false)
2535
-    {
2536
-        if (! $REG_ID) {
2537
-            EE_Error::add_error(
2538
-                esc_html__(
2539
-                    'An error occurred. No registration ID was received.',
2540
-                    'event_espresso'
2541
-                ),
2542
-                __FILE__,
2543
-                __FUNCTION__,
2544
-                __LINE__
2545
-            );
2546
-        }
2547
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2548
-        $form->receive_form_submission($this->_req_data);
2549
-        $success = false;
2550
-        if ($form->is_valid()) {
2551
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2552
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2553
-                    $where_conditions = array(
2554
-                        'QST_ID' => $question_id,
2555
-                        'REG_ID' => $REG_ID,
2556
-                    );
2557
-                    $possibly_new_values = array(
2558
-                        'ANS_value' => $input->normalized_value(),
2559
-                    );
2560
-                    $answer = EEM_Answer::instance()->get_one(array($where_conditions));
2561
-                    if ($answer instanceof EE_Answer) {
2562
-                        $success = $answer->save($possibly_new_values);
2563
-                    } else {
2564
-                        // insert it then
2565
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2566
-                        $answer = EE_Answer::new_instance($cols_n_vals);
2567
-                        $success = $answer->save();
2568
-                    }
2569
-                }
2570
-            }
2571
-        } else {
2572
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2573
-        }
2574
-        return $success;
2575
-    }
2576
-
2577
-
2578
-    /**
2579
-     *        generates HTML for the Registration main meta box
2580
-     *
2581
-     * @access public
2582
-     * @return void
2583
-     * @throws DomainException
2584
-     * @throws EE_Error
2585
-     * @throws InvalidArgumentException
2586
-     * @throws InvalidDataTypeException
2587
-     * @throws InvalidInterfaceException
2588
-     */
2589
-    public function _reg_attendees_meta_box()
2590
-    {
2591
-        $REG = EEM_Registration::instance();
2592
-        // get all other registrations on this transaction, and cache
2593
-        // the attendees for them so we don't have to run another query using force_join
2594
-        $registrations = $REG->get_all(
2595
-            array(
2596
-                array(
2597
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2598
-                    'REG_ID' => array('!=', $this->_registration->ID()),
2599
-                ),
2600
-                'force_join' => array('Attendee'),
2601
-            )
2602
-        );
2603
-        $this->_template_args['attendees'] = array();
2604
-        $this->_template_args['attendee_notice'] = '';
2605
-        if (empty($registrations)
2606
-            || (is_array($registrations)
2607
-                && ! EEH_Array::get_one_item_from_array($registrations))
2608
-        ) {
2609
-            EE_Error::add_error(
2610
-                esc_html__(
2611
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2612
-                    'event_espresso'
2613
-                ),
2614
-                __FILE__,
2615
-                __FUNCTION__,
2616
-                __LINE__
2617
-            );
2618
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2619
-        } else {
2620
-            $att_nmbr = 1;
2621
-            foreach ($registrations as $registration) {
2622
-                /* @var $registration EE_Registration */
2623
-                $attendee = $registration->attendee()
2624
-                    ? $registration->attendee()
2625
-                    : EEM_Attendee::instance()
2626
-                                  ->create_default_object();
2627
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2628
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2629
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2630
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2631
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2632
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2633
-                    ', ',
2634
-                    $attendee->full_address_as_array()
2635
-                );
2636
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2637
-                    array(
2638
-                        'action' => 'edit_attendee',
2639
-                        'post'   => $attendee->ID(),
2640
-                    ),
2641
-                    REG_ADMIN_URL
2642
-                );
2643
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2644
-                $att_nmbr++;
2645
-            }
2646
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2647
-        }
2648
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2649
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2650
-    }
2651
-
2652
-
2653
-    /**
2654
-     *        generates HTML for the Edit Registration side meta box
2655
-     *
2656
-     * @access public
2657
-     * @return void
2658
-     * @throws DomainException
2659
-     * @throws EE_Error
2660
-     * @throws InvalidArgumentException
2661
-     * @throws InvalidDataTypeException
2662
-     * @throws InvalidInterfaceException
2663
-     */
2664
-    public function _reg_registrant_side_meta_box()
2665
-    {
2666
-        /*@var $attendee EE_Attendee */
2667
-        $att_check = $this->_registration->attendee();
2668
-        $attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2669
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2670
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2671
-        // primary registration object (that way we know if we need to show create button or not)
2672
-        if (! $this->_registration->is_primary_registrant()) {
2673
-            $primary_registration = $this->_registration->get_primary_registration();
2674
-            $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2675
-                : null;
2676
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2677
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2678
-                // custom attendee object so let's not worry about the primary reg.
2679
-                $primary_registration = null;
2680
-            }
2681
-        } else {
2682
-            $primary_registration = null;
2683
-        }
2684
-        $this->_template_args['ATT_ID'] = $attendee->ID();
2685
-        $this->_template_args['fname'] = $attendee->fname();
2686
-        $this->_template_args['lname'] = $attendee->lname();
2687
-        $this->_template_args['email'] = $attendee->email();
2688
-        $this->_template_args['phone'] = $attendee->phone();
2689
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2690
-        // edit link
2691
-        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2692
-            array(
2693
-                'action' => 'edit_attendee',
2694
-                'post'   => $attendee->ID(),
2695
-            ),
2696
-            REG_ADMIN_URL
2697
-        );
2698
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2699
-        // create link
2700
-        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2701
-            ? EE_Admin_Page::add_query_args_and_nonce(
2702
-                array(
2703
-                    'action'  => 'duplicate_attendee',
2704
-                    '_REG_ID' => $this->_registration->ID(),
2705
-                ),
2706
-                REG_ADMIN_URL
2707
-            ) : '';
2708
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2709
-        $this->_template_args['att_check'] = $att_check;
2710
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2711
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2712
-    }
2713
-
2714
-
2715
-    /**
2716
-     * trash or restore registrations
2717
-     *
2718
-     * @param  boolean $trash whether to archive or restore
2719
-     * @return void
2720
-     * @throws EE_Error
2721
-     * @throws InvalidArgumentException
2722
-     * @throws InvalidDataTypeException
2723
-     * @throws InvalidInterfaceException
2724
-     * @throws RuntimeException
2725
-     * @access protected
2726
-     */
2727
-    protected function _trash_or_restore_registrations($trash = true)
2728
-    {
2729
-        // if empty _REG_ID then get out because there's nothing to do
2730
-        if (empty($this->_req_data['_REG_ID'])) {
2731
-            EE_Error::add_error(
2732
-                sprintf(
2733
-                    esc_html__(
2734
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2735
-                        'event_espresso'
2736
-                    ),
2737
-                    $trash ? 'trash' : 'restore'
2738
-                ),
2739
-                __FILE__,
2740
-                __LINE__,
2741
-                __FUNCTION__
2742
-            );
2743
-            $this->_redirect_after_action(false, '', '', array(), true);
2744
-        }
2745
-        $success = 0;
2746
-        $overwrite_msgs = false;
2747
-        // Checkboxes
2748
-        if (! is_array($this->_req_data['_REG_ID'])) {
2749
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2750
-        }
2751
-        $reg_count = count($this->_req_data['_REG_ID']);
2752
-        // cycle thru checkboxes
2753
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2754
-            /** @var EE_Registration $REG */
2755
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2756
-            $payments = $REG->registration_payments();
2757
-            if (! empty($payments)) {
2758
-                $name = $REG->attendee() instanceof EE_Attendee
2759
-                    ? $REG->attendee()->full_name()
2760
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2761
-                $overwrite_msgs = true;
2762
-                EE_Error::add_error(
2763
-                    sprintf(
2764
-                        esc_html__(
2765
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2766
-                            'event_espresso'
2767
-                        ),
2768
-                        $name
2769
-                    ),
2770
-                    __FILE__,
2771
-                    __FUNCTION__,
2772
-                    __LINE__
2773
-                );
2774
-                // can't trash this registration because it has payments.
2775
-                continue;
2776
-            }
2777
-            $updated = $trash ? $REG->delete() : $REG->restore();
2778
-            if ($updated) {
2779
-                $success++;
2780
-            }
2781
-        }
2782
-        $this->_redirect_after_action(
2783
-            $success === $reg_count, // were ALL registrations affected?
2784
-            $success > 1
2785
-                ? esc_html__('Registrations', 'event_espresso')
2786
-                : esc_html__('Registration', 'event_espresso'),
2787
-            $trash
2788
-                ? esc_html__('moved to the trash', 'event_espresso')
2789
-                : esc_html__('restored', 'event_espresso'),
2790
-            $this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2791
-            $overwrite_msgs
2792
-        );
2793
-    }
2794
-
2795
-
2796
-    /**
2797
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2798
-     * registration but also.
2799
-     * 1. Removing relations to EE_Attendee
2800
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2801
-     * ALSO trashed.
2802
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2803
-     * 4. Removing relationships between all tickets and the related registrations
2804
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2805
-     * 6. Deleting permanently any related Checkins.
2806
-     *
2807
-     * @return void
2808
-     * @throws EE_Error
2809
-     * @throws InvalidArgumentException
2810
-     * @throws InvalidDataTypeException
2811
-     * @throws InvalidInterfaceException
2812
-     */
2813
-    protected function _delete_registrations()
2814
-    {
2815
-        $REG_MDL = EEM_Registration::instance();
2816
-        $success = 1;
2817
-        // Checkboxes
2818
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2819
-            // if array has more than one element than success message should be plural
2820
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2821
-            // cycle thru checkboxes
2822
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2823
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2824
-                if (! $REG instanceof EE_Registration) {
2825
-                    continue;
2826
-                }
2827
-                $deleted = $this->_delete_registration($REG);
2828
-                if (! $deleted) {
2829
-                    $success = 0;
2830
-                }
2831
-            }
2832
-        } else {
2833
-            // grab single id and delete
2834
-            $REG_ID = $this->_req_data['_REG_ID'];
2835
-            $REG = $REG_MDL->get_one_by_ID($REG_ID);
2836
-            $deleted = $this->_delete_registration($REG);
2837
-            if (! $deleted) {
2838
-                $success = 0;
2839
-            }
2840
-        }
2841
-        $what = $success > 1
2842
-            ? esc_html__('Registrations', 'event_espresso')
2843
-            : esc_html__('Registration', 'event_espresso');
2844
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2845
-        $this->_redirect_after_action(
2846
-            $success,
2847
-            $what,
2848
-            $action_desc,
2849
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2850
-            true
2851
-        );
2852
-    }
2853
-
2854
-
2855
-    /**
2856
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2857
-     * models get affected.
2858
-     *
2859
-     * @param  EE_Registration $REG registration to be deleted permenantly
2860
-     * @return bool true = successful deletion, false = fail.
2861
-     * @throws EE_Error
2862
-     */
2863
-    protected function _delete_registration(EE_Registration $REG)
2864
-    {
2865
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2866
-        // registrations on the transaction that are NOT trashed.
2867
-        $TXN = $REG->get_first_related('Transaction');
2868
-        $REGS = $TXN->get_many_related('Registration');
2869
-        $all_trashed = true;
2870
-        foreach ($REGS as $registration) {
2871
-            if (! $registration->get('REG_deleted')) {
2872
-                $all_trashed = false;
2873
-            }
2874
-        }
2875
-        if (! $all_trashed) {
2876
-            EE_Error::add_error(
2877
-                esc_html__(
2878
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2879
-                    'event_espresso'
2880
-                ),
2881
-                __FILE__,
2882
-                __FUNCTION__,
2883
-                __LINE__
2884
-            );
2885
-            return false;
2886
-        }
2887
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2888
-        // separately from THIS one).
2889
-        foreach ($REGS as $registration) {
2890
-            // delete related answers
2891
-            $registration->delete_related_permanently('Answer');
2892
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2893
-            $attendee = $registration->get_first_related('Attendee');
2894
-            if ($attendee instanceof EE_Attendee) {
2895
-                $registration->_remove_relation_to($attendee, 'Attendee');
2896
-            }
2897
-            // now remove relationships to tickets on this registration.
2898
-            $registration->_remove_relations('Ticket');
2899
-            // now delete permanently the checkins related to this registration.
2900
-            $registration->delete_related_permanently('Checkin');
2901
-            if ($registration->ID() === $REG->ID()) {
2902
-                continue;
2903
-            } //we don't want to delete permanently the existing registration just yet.
2904
-            // remove relation to transaction for these registrations if NOT the existing registrations
2905
-            $registration->_remove_relations('Transaction');
2906
-            // delete permanently any related messages.
2907
-            $registration->delete_related_permanently('Message');
2908
-            // now delete this registration permanently
2909
-            $registration->delete_permanently();
2910
-        }
2911
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2912
-        // (the transaction and line items should be all that's left).
2913
-        // delete the line items related to the transaction for this registration.
2914
-        $TXN->delete_related_permanently('Line_Item');
2915
-        // we need to remove all the relationships on the transaction
2916
-        $TXN->delete_related_permanently('Payment');
2917
-        $TXN->delete_related_permanently('Extra_Meta');
2918
-        $TXN->delete_related_permanently('Message');
2919
-        // now we can delete this REG permanently (and the transaction of course)
2920
-        $REG->delete_related_permanently('Transaction');
2921
-        return $REG->delete_permanently();
2922
-    }
2923
-
2924
-
2925
-    /**
2926
-     *    generates HTML for the Register New Attendee Admin page
2927
-     *
2928
-     * @access private
2929
-     * @throws DomainException
2930
-     * @throws EE_Error
2931
-     */
2932
-    public function new_registration()
2933
-    {
2934
-        if (! $this->_set_reg_event()) {
2935
-            throw new EE_Error(
2936
-                esc_html__(
2937
-                    'Unable to continue with registering because there is no Event ID in the request',
2938
-                    'event_espresso'
2939
-                )
2940
-            );
2941
-        }
2942
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2943
-        // gotta start with a clean slate if we're not coming here via ajax
2944
-        if (! defined('DOING_AJAX')
2945
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2946
-        ) {
2947
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2948
-        }
2949
-        $this->_template_args['event_name'] = '';
2950
-        // event name
2951
-        if ($this->_reg_event) {
2952
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2953
-            $edit_event_url = self::add_query_args_and_nonce(
2954
-                array(
2955
-                    'action' => 'edit',
2956
-                    'post'   => $this->_reg_event->ID(),
2957
-                ),
2958
-                EVENTS_ADMIN_URL
2959
-            );
2960
-            $edit_event_lnk = '<a href="'
2961
-                              . $edit_event_url
2962
-                              . '" title="'
2963
-                              . esc_attr__('Edit ', 'event_espresso')
2964
-                              . $this->_reg_event->name()
2965
-                              . '">'
2966
-                              . esc_html__('Edit Event', 'event_espresso')
2967
-                              . '</a>';
2968
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2969
-                                                   . $edit_event_lnk
2970
-                                                   . '</span>';
2971
-        }
2972
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2973
-        if (defined('DOING_AJAX')) {
2974
-            $this->_return_json();
2975
-        }
2976
-        // grab header
2977
-        $template_path =
2978
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2979
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2980
-            $template_path,
2981
-            $this->_template_args,
2982
-            true
2983
-        );
2984
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2985
-        // the details template wrapper
2986
-        $this->display_admin_page_with_sidebar();
2987
-    }
2988
-
2989
-
2990
-    /**
2991
-     * This returns the content for a registration step
2992
-     *
2993
-     * @access protected
2994
-     * @return string html
2995
-     * @throws DomainException
2996
-     * @throws EE_Error
2997
-     * @throws InvalidArgumentException
2998
-     * @throws InvalidDataTypeException
2999
-     * @throws InvalidInterfaceException
3000
-     */
3001
-    protected function _get_registration_step_content()
3002
-    {
3003
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3004
-            $warning_msg = sprintf(
3005
-                esc_html__(
3006
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3007
-                    'event_espresso'
3008
-                ),
3009
-                '<br />',
3010
-                '<h3 class="important-notice">',
3011
-                '</h3>',
3012
-                '<div class="float-right">',
3013
-                '<span id="redirect_timer" class="important-notice">30</span>',
3014
-                '</div>',
3015
-                '<b>',
3016
-                '</b>'
3017
-            );
3018
-            return '
2471
+	}
2472
+
2473
+
2474
+	/**
2475
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2476
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2477
+	 * to display the page
2478
+	 *
2479
+	 * @access protected
2480
+	 * @return void
2481
+	 * @throws EE_Error
2482
+	 */
2483
+	protected function _update_attendee_registration_form()
2484
+	{
2485
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2486
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2487
+			$REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2488
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2489
+			if ($success) {
2490
+				$what = esc_html__('Registration Form', 'event_espresso');
2491
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2492
+					: array('action' => 'default');
2493
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2494
+			}
2495
+		}
2496
+	}
2497
+
2498
+
2499
+	/**
2500
+	 * Gets the form for saving registrations custom questions (if done
2501
+	 * previously retrieves the cached form object, which may have validation errors in it)
2502
+	 *
2503
+	 * @param int $REG_ID
2504
+	 * @return EE_Registration_Custom_Questions_Form
2505
+	 * @throws EE_Error
2506
+	 * @throws InvalidArgumentException
2507
+	 * @throws InvalidDataTypeException
2508
+	 * @throws InvalidInterfaceException
2509
+	 */
2510
+	protected function _get_reg_custom_questions_form($REG_ID)
2511
+	{
2512
+		if (! $this->_reg_custom_questions_form) {
2513
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2514
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2515
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2516
+			);
2517
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2518
+		}
2519
+		return $this->_reg_custom_questions_form;
2520
+	}
2521
+
2522
+
2523
+	/**
2524
+	 * Saves
2525
+	 *
2526
+	 * @access private
2527
+	 * @param bool $REG_ID
2528
+	 * @return bool
2529
+	 * @throws EE_Error
2530
+	 * @throws InvalidArgumentException
2531
+	 * @throws InvalidDataTypeException
2532
+	 * @throws InvalidInterfaceException
2533
+	 */
2534
+	private function _save_reg_custom_questions_form($REG_ID = false)
2535
+	{
2536
+		if (! $REG_ID) {
2537
+			EE_Error::add_error(
2538
+				esc_html__(
2539
+					'An error occurred. No registration ID was received.',
2540
+					'event_espresso'
2541
+				),
2542
+				__FILE__,
2543
+				__FUNCTION__,
2544
+				__LINE__
2545
+			);
2546
+		}
2547
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2548
+		$form->receive_form_submission($this->_req_data);
2549
+		$success = false;
2550
+		if ($form->is_valid()) {
2551
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2552
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2553
+					$where_conditions = array(
2554
+						'QST_ID' => $question_id,
2555
+						'REG_ID' => $REG_ID,
2556
+					);
2557
+					$possibly_new_values = array(
2558
+						'ANS_value' => $input->normalized_value(),
2559
+					);
2560
+					$answer = EEM_Answer::instance()->get_one(array($where_conditions));
2561
+					if ($answer instanceof EE_Answer) {
2562
+						$success = $answer->save($possibly_new_values);
2563
+					} else {
2564
+						// insert it then
2565
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2566
+						$answer = EE_Answer::new_instance($cols_n_vals);
2567
+						$success = $answer->save();
2568
+					}
2569
+				}
2570
+			}
2571
+		} else {
2572
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2573
+		}
2574
+		return $success;
2575
+	}
2576
+
2577
+
2578
+	/**
2579
+	 *        generates HTML for the Registration main meta box
2580
+	 *
2581
+	 * @access public
2582
+	 * @return void
2583
+	 * @throws DomainException
2584
+	 * @throws EE_Error
2585
+	 * @throws InvalidArgumentException
2586
+	 * @throws InvalidDataTypeException
2587
+	 * @throws InvalidInterfaceException
2588
+	 */
2589
+	public function _reg_attendees_meta_box()
2590
+	{
2591
+		$REG = EEM_Registration::instance();
2592
+		// get all other registrations on this transaction, and cache
2593
+		// the attendees for them so we don't have to run another query using force_join
2594
+		$registrations = $REG->get_all(
2595
+			array(
2596
+				array(
2597
+					'TXN_ID' => $this->_registration->transaction_ID(),
2598
+					'REG_ID' => array('!=', $this->_registration->ID()),
2599
+				),
2600
+				'force_join' => array('Attendee'),
2601
+			)
2602
+		);
2603
+		$this->_template_args['attendees'] = array();
2604
+		$this->_template_args['attendee_notice'] = '';
2605
+		if (empty($registrations)
2606
+			|| (is_array($registrations)
2607
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2608
+		) {
2609
+			EE_Error::add_error(
2610
+				esc_html__(
2611
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2612
+					'event_espresso'
2613
+				),
2614
+				__FILE__,
2615
+				__FUNCTION__,
2616
+				__LINE__
2617
+			);
2618
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2619
+		} else {
2620
+			$att_nmbr = 1;
2621
+			foreach ($registrations as $registration) {
2622
+				/* @var $registration EE_Registration */
2623
+				$attendee = $registration->attendee()
2624
+					? $registration->attendee()
2625
+					: EEM_Attendee::instance()
2626
+								  ->create_default_object();
2627
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2628
+				$this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2629
+				$this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2630
+				$this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2631
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2632
+				$this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2633
+					', ',
2634
+					$attendee->full_address_as_array()
2635
+				);
2636
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2637
+					array(
2638
+						'action' => 'edit_attendee',
2639
+						'post'   => $attendee->ID(),
2640
+					),
2641
+					REG_ADMIN_URL
2642
+				);
2643
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2644
+				$att_nmbr++;
2645
+			}
2646
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2647
+		}
2648
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2649
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2650
+	}
2651
+
2652
+
2653
+	/**
2654
+	 *        generates HTML for the Edit Registration side meta box
2655
+	 *
2656
+	 * @access public
2657
+	 * @return void
2658
+	 * @throws DomainException
2659
+	 * @throws EE_Error
2660
+	 * @throws InvalidArgumentException
2661
+	 * @throws InvalidDataTypeException
2662
+	 * @throws InvalidInterfaceException
2663
+	 */
2664
+	public function _reg_registrant_side_meta_box()
2665
+	{
2666
+		/*@var $attendee EE_Attendee */
2667
+		$att_check = $this->_registration->attendee();
2668
+		$attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2669
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2670
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2671
+		// primary registration object (that way we know if we need to show create button or not)
2672
+		if (! $this->_registration->is_primary_registrant()) {
2673
+			$primary_registration = $this->_registration->get_primary_registration();
2674
+			$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2675
+				: null;
2676
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2677
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2678
+				// custom attendee object so let's not worry about the primary reg.
2679
+				$primary_registration = null;
2680
+			}
2681
+		} else {
2682
+			$primary_registration = null;
2683
+		}
2684
+		$this->_template_args['ATT_ID'] = $attendee->ID();
2685
+		$this->_template_args['fname'] = $attendee->fname();
2686
+		$this->_template_args['lname'] = $attendee->lname();
2687
+		$this->_template_args['email'] = $attendee->email();
2688
+		$this->_template_args['phone'] = $attendee->phone();
2689
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2690
+		// edit link
2691
+		$this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2692
+			array(
2693
+				'action' => 'edit_attendee',
2694
+				'post'   => $attendee->ID(),
2695
+			),
2696
+			REG_ADMIN_URL
2697
+		);
2698
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2699
+		// create link
2700
+		$this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2701
+			? EE_Admin_Page::add_query_args_and_nonce(
2702
+				array(
2703
+					'action'  => 'duplicate_attendee',
2704
+					'_REG_ID' => $this->_registration->ID(),
2705
+				),
2706
+				REG_ADMIN_URL
2707
+			) : '';
2708
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2709
+		$this->_template_args['att_check'] = $att_check;
2710
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2711
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2712
+	}
2713
+
2714
+
2715
+	/**
2716
+	 * trash or restore registrations
2717
+	 *
2718
+	 * @param  boolean $trash whether to archive or restore
2719
+	 * @return void
2720
+	 * @throws EE_Error
2721
+	 * @throws InvalidArgumentException
2722
+	 * @throws InvalidDataTypeException
2723
+	 * @throws InvalidInterfaceException
2724
+	 * @throws RuntimeException
2725
+	 * @access protected
2726
+	 */
2727
+	protected function _trash_or_restore_registrations($trash = true)
2728
+	{
2729
+		// if empty _REG_ID then get out because there's nothing to do
2730
+		if (empty($this->_req_data['_REG_ID'])) {
2731
+			EE_Error::add_error(
2732
+				sprintf(
2733
+					esc_html__(
2734
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2735
+						'event_espresso'
2736
+					),
2737
+					$trash ? 'trash' : 'restore'
2738
+				),
2739
+				__FILE__,
2740
+				__LINE__,
2741
+				__FUNCTION__
2742
+			);
2743
+			$this->_redirect_after_action(false, '', '', array(), true);
2744
+		}
2745
+		$success = 0;
2746
+		$overwrite_msgs = false;
2747
+		// Checkboxes
2748
+		if (! is_array($this->_req_data['_REG_ID'])) {
2749
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2750
+		}
2751
+		$reg_count = count($this->_req_data['_REG_ID']);
2752
+		// cycle thru checkboxes
2753
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2754
+			/** @var EE_Registration $REG */
2755
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2756
+			$payments = $REG->registration_payments();
2757
+			if (! empty($payments)) {
2758
+				$name = $REG->attendee() instanceof EE_Attendee
2759
+					? $REG->attendee()->full_name()
2760
+					: esc_html__('Unknown Attendee', 'event_espresso');
2761
+				$overwrite_msgs = true;
2762
+				EE_Error::add_error(
2763
+					sprintf(
2764
+						esc_html__(
2765
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2766
+							'event_espresso'
2767
+						),
2768
+						$name
2769
+					),
2770
+					__FILE__,
2771
+					__FUNCTION__,
2772
+					__LINE__
2773
+				);
2774
+				// can't trash this registration because it has payments.
2775
+				continue;
2776
+			}
2777
+			$updated = $trash ? $REG->delete() : $REG->restore();
2778
+			if ($updated) {
2779
+				$success++;
2780
+			}
2781
+		}
2782
+		$this->_redirect_after_action(
2783
+			$success === $reg_count, // were ALL registrations affected?
2784
+			$success > 1
2785
+				? esc_html__('Registrations', 'event_espresso')
2786
+				: esc_html__('Registration', 'event_espresso'),
2787
+			$trash
2788
+				? esc_html__('moved to the trash', 'event_espresso')
2789
+				: esc_html__('restored', 'event_espresso'),
2790
+			$this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2791
+			$overwrite_msgs
2792
+		);
2793
+	}
2794
+
2795
+
2796
+	/**
2797
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2798
+	 * registration but also.
2799
+	 * 1. Removing relations to EE_Attendee
2800
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2801
+	 * ALSO trashed.
2802
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2803
+	 * 4. Removing relationships between all tickets and the related registrations
2804
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2805
+	 * 6. Deleting permanently any related Checkins.
2806
+	 *
2807
+	 * @return void
2808
+	 * @throws EE_Error
2809
+	 * @throws InvalidArgumentException
2810
+	 * @throws InvalidDataTypeException
2811
+	 * @throws InvalidInterfaceException
2812
+	 */
2813
+	protected function _delete_registrations()
2814
+	{
2815
+		$REG_MDL = EEM_Registration::instance();
2816
+		$success = 1;
2817
+		// Checkboxes
2818
+		if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2819
+			// if array has more than one element than success message should be plural
2820
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2821
+			// cycle thru checkboxes
2822
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2823
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2824
+				if (! $REG instanceof EE_Registration) {
2825
+					continue;
2826
+				}
2827
+				$deleted = $this->_delete_registration($REG);
2828
+				if (! $deleted) {
2829
+					$success = 0;
2830
+				}
2831
+			}
2832
+		} else {
2833
+			// grab single id and delete
2834
+			$REG_ID = $this->_req_data['_REG_ID'];
2835
+			$REG = $REG_MDL->get_one_by_ID($REG_ID);
2836
+			$deleted = $this->_delete_registration($REG);
2837
+			if (! $deleted) {
2838
+				$success = 0;
2839
+			}
2840
+		}
2841
+		$what = $success > 1
2842
+			? esc_html__('Registrations', 'event_espresso')
2843
+			: esc_html__('Registration', 'event_espresso');
2844
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2845
+		$this->_redirect_after_action(
2846
+			$success,
2847
+			$what,
2848
+			$action_desc,
2849
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2850
+			true
2851
+		);
2852
+	}
2853
+
2854
+
2855
+	/**
2856
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2857
+	 * models get affected.
2858
+	 *
2859
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2860
+	 * @return bool true = successful deletion, false = fail.
2861
+	 * @throws EE_Error
2862
+	 */
2863
+	protected function _delete_registration(EE_Registration $REG)
2864
+	{
2865
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2866
+		// registrations on the transaction that are NOT trashed.
2867
+		$TXN = $REG->get_first_related('Transaction');
2868
+		$REGS = $TXN->get_many_related('Registration');
2869
+		$all_trashed = true;
2870
+		foreach ($REGS as $registration) {
2871
+			if (! $registration->get('REG_deleted')) {
2872
+				$all_trashed = false;
2873
+			}
2874
+		}
2875
+		if (! $all_trashed) {
2876
+			EE_Error::add_error(
2877
+				esc_html__(
2878
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2879
+					'event_espresso'
2880
+				),
2881
+				__FILE__,
2882
+				__FUNCTION__,
2883
+				__LINE__
2884
+			);
2885
+			return false;
2886
+		}
2887
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2888
+		// separately from THIS one).
2889
+		foreach ($REGS as $registration) {
2890
+			// delete related answers
2891
+			$registration->delete_related_permanently('Answer');
2892
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2893
+			$attendee = $registration->get_first_related('Attendee');
2894
+			if ($attendee instanceof EE_Attendee) {
2895
+				$registration->_remove_relation_to($attendee, 'Attendee');
2896
+			}
2897
+			// now remove relationships to tickets on this registration.
2898
+			$registration->_remove_relations('Ticket');
2899
+			// now delete permanently the checkins related to this registration.
2900
+			$registration->delete_related_permanently('Checkin');
2901
+			if ($registration->ID() === $REG->ID()) {
2902
+				continue;
2903
+			} //we don't want to delete permanently the existing registration just yet.
2904
+			// remove relation to transaction for these registrations if NOT the existing registrations
2905
+			$registration->_remove_relations('Transaction');
2906
+			// delete permanently any related messages.
2907
+			$registration->delete_related_permanently('Message');
2908
+			// now delete this registration permanently
2909
+			$registration->delete_permanently();
2910
+		}
2911
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2912
+		// (the transaction and line items should be all that's left).
2913
+		// delete the line items related to the transaction for this registration.
2914
+		$TXN->delete_related_permanently('Line_Item');
2915
+		// we need to remove all the relationships on the transaction
2916
+		$TXN->delete_related_permanently('Payment');
2917
+		$TXN->delete_related_permanently('Extra_Meta');
2918
+		$TXN->delete_related_permanently('Message');
2919
+		// now we can delete this REG permanently (and the transaction of course)
2920
+		$REG->delete_related_permanently('Transaction');
2921
+		return $REG->delete_permanently();
2922
+	}
2923
+
2924
+
2925
+	/**
2926
+	 *    generates HTML for the Register New Attendee Admin page
2927
+	 *
2928
+	 * @access private
2929
+	 * @throws DomainException
2930
+	 * @throws EE_Error
2931
+	 */
2932
+	public function new_registration()
2933
+	{
2934
+		if (! $this->_set_reg_event()) {
2935
+			throw new EE_Error(
2936
+				esc_html__(
2937
+					'Unable to continue with registering because there is no Event ID in the request',
2938
+					'event_espresso'
2939
+				)
2940
+			);
2941
+		}
2942
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2943
+		// gotta start with a clean slate if we're not coming here via ajax
2944
+		if (! defined('DOING_AJAX')
2945
+			&& (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2946
+		) {
2947
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2948
+		}
2949
+		$this->_template_args['event_name'] = '';
2950
+		// event name
2951
+		if ($this->_reg_event) {
2952
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2953
+			$edit_event_url = self::add_query_args_and_nonce(
2954
+				array(
2955
+					'action' => 'edit',
2956
+					'post'   => $this->_reg_event->ID(),
2957
+				),
2958
+				EVENTS_ADMIN_URL
2959
+			);
2960
+			$edit_event_lnk = '<a href="'
2961
+							  . $edit_event_url
2962
+							  . '" title="'
2963
+							  . esc_attr__('Edit ', 'event_espresso')
2964
+							  . $this->_reg_event->name()
2965
+							  . '">'
2966
+							  . esc_html__('Edit Event', 'event_espresso')
2967
+							  . '</a>';
2968
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2969
+												   . $edit_event_lnk
2970
+												   . '</span>';
2971
+		}
2972
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2973
+		if (defined('DOING_AJAX')) {
2974
+			$this->_return_json();
2975
+		}
2976
+		// grab header
2977
+		$template_path =
2978
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2979
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2980
+			$template_path,
2981
+			$this->_template_args,
2982
+			true
2983
+		);
2984
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2985
+		// the details template wrapper
2986
+		$this->display_admin_page_with_sidebar();
2987
+	}
2988
+
2989
+
2990
+	/**
2991
+	 * This returns the content for a registration step
2992
+	 *
2993
+	 * @access protected
2994
+	 * @return string html
2995
+	 * @throws DomainException
2996
+	 * @throws EE_Error
2997
+	 * @throws InvalidArgumentException
2998
+	 * @throws InvalidDataTypeException
2999
+	 * @throws InvalidInterfaceException
3000
+	 */
3001
+	protected function _get_registration_step_content()
3002
+	{
3003
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3004
+			$warning_msg = sprintf(
3005
+				esc_html__(
3006
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3007
+					'event_espresso'
3008
+				),
3009
+				'<br />',
3010
+				'<h3 class="important-notice">',
3011
+				'</h3>',
3012
+				'<div class="float-right">',
3013
+				'<span id="redirect_timer" class="important-notice">30</span>',
3014
+				'</div>',
3015
+				'<b>',
3016
+				'</b>'
3017
+			);
3018
+			return '
3019 3019
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3020 3020
 	<script >
3021 3021
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -3028,855 +3028,855 @@  discard block
 block discarded – undo
3028 3028
 	        }
3029 3029
 	    }, 800 );
3030 3030
 	</script >';
3031
-        }
3032
-        $template_args = array(
3033
-            'title'                    => '',
3034
-            'content'                  => '',
3035
-            'step_button_text'         => '',
3036
-            'show_notification_toggle' => false,
3037
-        );
3038
-        // to indicate we're processing a new registration
3039
-        $hidden_fields = array(
3040
-            'processing_registration' => array(
3041
-                'type'  => 'hidden',
3042
-                'value' => 0,
3043
-            ),
3044
-            'event_id'                => array(
3045
-                'type'  => 'hidden',
3046
-                'value' => $this->_reg_event->ID(),
3047
-            ),
3048
-        );
3049
-        // if the cart is empty then we know we're at step one so we'll display ticket selector
3050
-        $cart = EE_Registry::instance()->SSN->cart();
3051
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3052
-        switch ($step) {
3053
-            case 'ticket':
3054
-                $hidden_fields['processing_registration']['value'] = 1;
3055
-                $template_args['title'] = esc_html__(
3056
-                    'Step One: Select the Ticket for this registration',
3057
-                    'event_espresso'
3058
-                );
3059
-                $template_args['content'] =
3060
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3061
-                $template_args['step_button_text'] = esc_html__(
3062
-                    'Add Tickets and Continue to Registrant Details',
3063
-                    'event_espresso'
3064
-                );
3065
-                $template_args['show_notification_toggle'] = false;
3066
-                break;
3067
-            case 'questions':
3068
-                $hidden_fields['processing_registration']['value'] = 2;
3069
-                $template_args['title'] = esc_html__(
3070
-                    'Step Two: Add Registrant Details for this Registration',
3071
-                    'event_espresso'
3072
-                );
3073
-                // in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3074
-                // properly by the first process_reg_step run.
3075
-                $template_args['content'] =
3076
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
3077
-                $template_args['step_button_text'] = esc_html__(
3078
-                    'Save Registration and Continue to Details',
3079
-                    'event_espresso'
3080
-                );
3081
-                $template_args['show_notification_toggle'] = true;
3082
-                break;
3083
-        }
3084
-        // we come back to the process_registration_step route.
3085
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3086
-        return EEH_Template::display_template(
3087
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3088
-            $template_args,
3089
-            true
3090
-        );
3091
-    }
3092
-
3093
-
3094
-    /**
3095
-     *        set_reg_event
3096
-     *
3097
-     * @access private
3098
-     * @return bool
3099
-     * @throws EE_Error
3100
-     * @throws InvalidArgumentException
3101
-     * @throws InvalidDataTypeException
3102
-     * @throws InvalidInterfaceException
3103
-     */
3104
-    private function _set_reg_event()
3105
-    {
3106
-        if (is_object($this->_reg_event)) {
3107
-            return true;
3108
-        }
3109
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3110
-        if (! $EVT_ID) {
3111
-            return false;
3112
-        }
3113
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3114
-        return true;
3115
-    }
3116
-
3117
-
3118
-    /**
3119
-     * process_reg_step
3120
-     *
3121
-     * @access        public
3122
-     * @return string
3123
-     * @throws DomainException
3124
-     * @throws EE_Error
3125
-     * @throws InvalidArgumentException
3126
-     * @throws InvalidDataTypeException
3127
-     * @throws InvalidInterfaceException
3128
-     * @throws ReflectionException
3129
-     * @throws RuntimeException
3130
-     */
3131
-    public function process_reg_step()
3132
-    {
3133
-        EE_System::do_not_cache();
3134
-        $this->_set_reg_event();
3135
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3136
-        EE_Registry::instance()->REQ->set('uts', time());
3137
-        // what step are we on?
3138
-        $cart = EE_Registry::instance()->SSN->cart();
3139
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3140
-        // if doing ajax then we need to verify the nonce
3141
-        if (defined('DOING_AJAX')) {
3142
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3143
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3144
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3145
-        }
3146
-        switch ($step) {
3147
-            case 'ticket':
3148
-                // process ticket selection
3149
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3150
-                if ($success) {
3151
-                    EE_Error::add_success(
3152
-                        esc_html__(
3153
-                            'Tickets Selected. Now complete the registration.',
3154
-                            'event_espresso'
3155
-                        )
3156
-                    );
3157
-                } else {
3158
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3159
-                }
3160
-                if (defined('DOING_AJAX')) {
3161
-                    $this->new_registration(); // display next step
3162
-                } else {
3163
-                    $query_args = array(
3164
-                        'action'                  => 'new_registration',
3165
-                        'processing_registration' => 1,
3166
-                        'event_id'                => $this->_reg_event->ID(),
3167
-                        'uts'                     => time(),
3168
-                    );
3169
-                    $this->_redirect_after_action(
3170
-                        false,
3171
-                        '',
3172
-                        '',
3173
-                        $query_args,
3174
-                        true
3175
-                    );
3176
-                }
3177
-                break;
3178
-            case 'questions':
3179
-                if (! isset(
3180
-                    $this->_req_data['txn_reg_status_change'],
3181
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
3182
-                )
3183
-                ) {
3184
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3185
-                }
3186
-                // process registration
3187
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3188
-                if ($cart instanceof EE_Cart) {
3189
-                    $grand_total = $cart->get_cart_grand_total();
3190
-                    if ($grand_total instanceof EE_Line_Item) {
3191
-                        $grand_total->save_this_and_descendants_to_txn();
3192
-                    }
3193
-                }
3194
-                if (! $transaction instanceof EE_Transaction) {
3195
-                    $query_args = array(
3196
-                        'action'                  => 'new_registration',
3197
-                        'processing_registration' => 2,
3198
-                        'event_id'                => $this->_reg_event->ID(),
3199
-                        'uts'                     => time(),
3200
-                    );
3201
-                    if (defined('DOING_AJAX')) {
3202
-                        // display registration form again because there are errors (maybe validation?)
3203
-                        $this->new_registration();
3204
-                        return;
3205
-                    } else {
3206
-                        $this->_redirect_after_action(
3207
-                            false,
3208
-                            '',
3209
-                            '',
3210
-                            $query_args,
3211
-                            true
3212
-                        );
3213
-                        return;
3214
-                    }
3215
-                }
3216
-                // maybe update status, and make sure to save transaction if not done already
3217
-                if (! $transaction->update_status_based_on_total_paid()) {
3218
-                    $transaction->save();
3219
-                }
3220
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3221
-                $this->_req_data = array();
3222
-                $query_args = array(
3223
-                    'action'        => 'redirect_to_txn',
3224
-                    'TXN_ID'        => $transaction->ID(),
3225
-                    'EVT_ID'        => $this->_reg_event->ID(),
3226
-                    'event_name'    => urlencode($this->_reg_event->name()),
3227
-                    'redirect_from' => 'new_registration',
3228
-                );
3229
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3230
-                break;
3231
-        }
3232
-        // what are you looking here for?  Should be nothing to do at this point.
3233
-    }
3234
-
3235
-
3236
-    /**
3237
-     * redirect_to_txn
3238
-     *
3239
-     * @access public
3240
-     * @return void
3241
-     * @throws EE_Error
3242
-     * @throws InvalidArgumentException
3243
-     * @throws InvalidDataTypeException
3244
-     * @throws InvalidInterfaceException
3245
-     */
3246
-    public function redirect_to_txn()
3247
-    {
3248
-        EE_System::do_not_cache();
3249
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3250
-        $query_args = array(
3251
-            'action' => 'view_transaction',
3252
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3253
-            'page'   => 'espresso_transactions',
3254
-        );
3255
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3256
-            $query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3257
-            $query_args['event_name'] = urlencode($this->_req_data['event_name']);
3258
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3259
-        }
3260
-        EE_Error::add_success(
3261
-            esc_html__(
3262
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3263
-                'event_espresso'
3264
-            )
3265
-        );
3266
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3267
-    }
3268
-
3269
-
3270
-    /**
3271
-     *        generates HTML for the Attendee Contact List
3272
-     *
3273
-     * @access protected
3274
-     * @return void
3275
-     */
3276
-    protected function _attendee_contact_list_table()
3277
-    {
3278
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3279
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3280
-        $this->display_admin_list_table_page_with_no_sidebar();
3281
-    }
3282
-
3283
-
3284
-    /**
3285
-     *        get_attendees
3286
-     *
3287
-     * @param      $per_page
3288
-     * @param bool $count whether to return count or data.
3289
-     * @param bool $trash
3290
-     * @return array
3291
-     * @throws EE_Error
3292
-     * @throws InvalidArgumentException
3293
-     * @throws InvalidDataTypeException
3294
-     * @throws InvalidInterfaceException
3295
-     * @access public
3296
-     */
3297
-    public function get_attendees($per_page, $count = false, $trash = false)
3298
-    {
3299
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3300
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3301
-        $ATT_MDL = EEM_Attendee::instance();
3302
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3303
-        switch ($this->_req_data['orderby']) {
3304
-            case 'ATT_ID':
3305
-                $orderby = 'ATT_ID';
3306
-                break;
3307
-            case 'ATT_fname':
3308
-                $orderby = 'ATT_fname';
3309
-                break;
3310
-            case 'ATT_email':
3311
-                $orderby = 'ATT_email';
3312
-                break;
3313
-            case 'ATT_city':
3314
-                $orderby = 'ATT_city';
3315
-                break;
3316
-            case 'STA_ID':
3317
-                $orderby = 'STA_ID';
3318
-                break;
3319
-            case 'CNT_ID':
3320
-                $orderby = 'CNT_ID';
3321
-                break;
3322
-            case 'Registration_Count':
3323
-                $orderby = 'Registration_Count';
3324
-                break;
3325
-            default:
3326
-                $orderby = 'ATT_lname';
3327
-        }
3328
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3329
-            ? $this->_req_data['order']
3330
-            : 'ASC';
3331
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3332
-            ? $this->_req_data['paged']
3333
-            : 1;
3334
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3335
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3336
-            ? $this->_req_data['perpage']
3337
-            : $per_page;
3338
-        $_where = array();
3339
-        if (! empty($this->_req_data['s'])) {
3340
-            $sstr = '%' . $this->_req_data['s'] . '%';
3341
-            $_where['OR'] = array(
3342
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3343
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3344
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3345
-                'ATT_fname'                         => array('LIKE', $sstr),
3346
-                'ATT_lname'                         => array('LIKE', $sstr),
3347
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3348
-                'ATT_email'                         => array('LIKE', $sstr),
3349
-                'ATT_address'                       => array('LIKE', $sstr),
3350
-                'ATT_address2'                      => array('LIKE', $sstr),
3351
-                'ATT_city'                          => array('LIKE', $sstr),
3352
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3353
-                'State.STA_name'                    => array('LIKE', $sstr),
3354
-                'ATT_phone'                         => array('LIKE', $sstr),
3355
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3356
-                'Registration.REG_code'             => array('LIKE', $sstr),
3357
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3358
-            );
3359
-        }
3360
-        $offset = ($current_page - 1) * $per_page;
3361
-        $limit = $count ? null : array($offset, $per_page);
3362
-        $query_args = array(
3363
-            $_where,
3364
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3365
-            'limit'         => $limit,
3366
-        );
3367
-        if (! $count) {
3368
-            $query_args['order_by'] = array($orderby => $sort);
3369
-        }
3370
-        if ($trash) {
3371
-            $query_args[0]['status'] = array('!=', 'publish');
3372
-            $all_attendees = $count
3373
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3374
-                : $ATT_MDL->get_all($query_args);
3375
-        } else {
3376
-            $query_args[0]['status'] = array('IN', array('publish'));
3377
-            $all_attendees = $count
3378
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3379
-                : $ATT_MDL->get_all($query_args);
3380
-        }
3381
-        return $all_attendees;
3382
-    }
3383
-
3384
-
3385
-    /**
3386
-     * This is just taking care of resending the registration confirmation
3387
-     *
3388
-     * @access protected
3389
-     * @return void
3390
-     */
3391
-    protected function _resend_registration()
3392
-    {
3393
-        $this->_process_resend_registration();
3394
-        $query_args = isset($this->_req_data['redirect_to'])
3395
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3396
-            : array('action' => 'default');
3397
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3398
-    }
3399
-
3400
-    /**
3401
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3402
-     * to use when selecting registrations
3403
-     *
3404
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3405
-     *                                                     the query parameters from the request
3406
-     * @return void ends the request with a redirect or download
3407
-     */
3408
-    public function _registrations_report_base($method_name_for_getting_query_params)
3409
-    {
3410
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3411
-            wp_redirect(
3412
-                EE_Admin_Page::add_query_args_and_nonce(
3413
-                    array(
3414
-                        'page'        => 'espresso_batch',
3415
-                        'batch'       => 'file',
3416
-                        'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3417
-                        'filters'     => urlencode(
3418
-                            serialize(
3419
-                                call_user_func(
3420
-                                    array($this, $method_name_for_getting_query_params),
3421
-                                    EEH_Array::is_set(
3422
-                                        $this->_req_data,
3423
-                                        'filters',
3424
-                                        array()
3425
-                                    )
3426
-                                )
3427
-                            )
3428
-                        ),
3429
-                        'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3430
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3431
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3432
-                    )
3433
-                )
3434
-            );
3435
-        } else {
3436
-            $new_request_args = array(
3437
-                'export' => 'report',
3438
-                'action' => 'registrations_report_for_event',
3439
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3440
-            );
3441
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3442
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3443
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3444
-                $EE_Export = EE_Export::instance($this->_req_data);
3445
-                $EE_Export->export();
3446
-            }
3447
-        }
3448
-    }
3449
-
3450
-
3451
-    /**
3452
-     * Creates a registration report using only query parameters in the request
3453
-     *
3454
-     * @return void
3455
-     */
3456
-    public function _registrations_report()
3457
-    {
3458
-        $this->_registrations_report_base('_get_registration_query_parameters');
3459
-    }
3460
-
3461
-
3462
-    public function _contact_list_export()
3463
-    {
3464
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3465
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3466
-            $EE_Export = EE_Export::instance($this->_req_data);
3467
-            $EE_Export->export_attendees();
3468
-        }
3469
-    }
3470
-
3471
-
3472
-    public function _contact_list_report()
3473
-    {
3474
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3475
-            wp_redirect(
3476
-                EE_Admin_Page::add_query_args_and_nonce(
3477
-                    array(
3478
-                        'page'        => 'espresso_batch',
3479
-                        'batch'       => 'file',
3480
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3481
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3482
-                    )
3483
-                )
3484
-            );
3485
-        } else {
3486
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3487
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3488
-                $EE_Export = EE_Export::instance($this->_req_data);
3489
-                $EE_Export->report_attendees();
3490
-            }
3491
-        }
3492
-    }
3493
-
3494
-
3495
-
3496
-
3497
-
3498
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3499
-    /**
3500
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3501
-     *
3502
-     * @return void
3503
-     * @throws EE_Error
3504
-     * @throws InvalidArgumentException
3505
-     * @throws InvalidDataTypeException
3506
-     * @throws InvalidInterfaceException
3507
-     */
3508
-    protected function _duplicate_attendee()
3509
-    {
3510
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3511
-        // verify we have necessary info
3512
-        if (empty($this->_req_data['_REG_ID'])) {
3513
-            EE_Error::add_error(
3514
-                esc_html__(
3515
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3516
-                    'event_espresso'
3517
-                ),
3518
-                __FILE__,
3519
-                __LINE__,
3520
-                __FUNCTION__
3521
-            );
3522
-            $query_args = array('action' => $action);
3523
-            $this->_redirect_after_action('', '', '', $query_args, true);
3524
-        }
3525
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3526
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3527
-        $attendee = $registration->attendee();
3528
-        // remove relation of existing attendee on registration
3529
-        $registration->_remove_relation_to($attendee, 'Attendee');
3530
-        // new attendee
3531
-        $new_attendee = clone $attendee;
3532
-        $new_attendee->set('ATT_ID', 0);
3533
-        $new_attendee->save();
3534
-        // add new attendee to reg
3535
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3536
-        EE_Error::add_success(
3537
-            esc_html__(
3538
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3539
-                'event_espresso'
3540
-            )
3541
-        );
3542
-        // redirect to edit page for attendee
3543
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3544
-        $this->_redirect_after_action('', '', '', $query_args, true);
3545
-    }
3546
-
3547
-
3548
-    /**
3549
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3550
-     *
3551
-     * @param int     $post_id
3552
-     * @param WP_POST $post
3553
-     * @throws DomainException
3554
-     * @throws EE_Error
3555
-     * @throws InvalidArgumentException
3556
-     * @throws InvalidDataTypeException
3557
-     * @throws InvalidInterfaceException
3558
-     * @throws LogicException
3559
-     * @throws InvalidFormSubmissionException
3560
-     */
3561
-    protected function _insert_update_cpt_item($post_id, $post)
3562
-    {
3563
-        $success = true;
3564
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3565
-            ? EEM_Attendee::instance()->get_one_by_ID($post_id)
3566
-            : null;
3567
-        // for attendee updates
3568
-        if ($attendee instanceof EE_Attendee) {
3569
-            // note we should only be UPDATING attendees at this point.
3570
-            $updated_fields = array(
3571
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3572
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3573
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3574
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3575
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3576
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3577
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3578
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3579
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3580
-            );
3581
-            foreach ($updated_fields as $field => $value) {
3582
-                $attendee->set($field, $value);
3583
-            }
3584
-
3585
-            // process contact details metabox form handler (which will also save the attendee)
3586
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3587
-            $success = $contact_details_form->process($this->_req_data);
3588
-
3589
-            $attendee_update_callbacks = apply_filters(
3590
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3591
-                array()
3592
-            );
3593
-            foreach ($attendee_update_callbacks as $a_callback) {
3594
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3595
-                    throw new EE_Error(
3596
-                        sprintf(
3597
-                            esc_html__(
3598
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3599
-                                'event_espresso'
3600
-                            ),
3601
-                            $a_callback
3602
-                        )
3603
-                    );
3604
-                }
3605
-            }
3606
-        }
3607
-
3608
-        if ($success === false) {
3609
-            EE_Error::add_error(
3610
-                esc_html__(
3611
-                    'Something went wrong with updating the meta table data for the registration.',
3612
-                    'event_espresso'
3613
-                ),
3614
-                __FILE__,
3615
-                __FUNCTION__,
3616
-                __LINE__
3617
-            );
3618
-        }
3619
-    }
3620
-
3621
-
3622
-    public function trash_cpt_item($post_id)
3623
-    {
3624
-    }
3625
-
3626
-
3627
-    public function delete_cpt_item($post_id)
3628
-    {
3629
-    }
3630
-
3631
-
3632
-    public function restore_cpt_item($post_id)
3633
-    {
3634
-    }
3635
-
3636
-
3637
-    protected function _restore_cpt_item($post_id, $revision_id)
3638
-    {
3639
-    }
3640
-
3641
-
3642
-    public function attendee_editor_metaboxes()
3643
-    {
3644
-        $this->verify_cpt_object();
3645
-        remove_meta_box(
3646
-            'postexcerpt',
3647
-            esc_html__('Excerpt', 'event_espresso'),
3648
-            'post_excerpt_meta_box',
3649
-            $this->_cpt_routes[ $this->_req_action ],
3650
-            'normal',
3651
-            'core'
3652
-        );
3653
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3654
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3655
-            add_meta_box(
3656
-                'postexcerpt',
3657
-                esc_html__('Short Biography', 'event_espresso'),
3658
-                'post_excerpt_meta_box',
3659
-                $this->_cpt_routes[ $this->_req_action ],
3660
-                'normal'
3661
-            );
3662
-        }
3663
-        if (post_type_supports('espresso_attendees', 'comments')) {
3664
-            add_meta_box(
3665
-                'commentsdiv',
3666
-                esc_html__('Notes on the Contact', 'event_espresso'),
3667
-                'post_comment_meta_box',
3668
-                $this->_cpt_routes[ $this->_req_action ],
3669
-                'normal',
3670
-                'core'
3671
-            );
3672
-        }
3673
-        add_meta_box(
3674
-            'attendee_contact_info',
3675
-            esc_html__('Contact Info', 'event_espresso'),
3676
-            array($this, 'attendee_contact_info'),
3677
-            $this->_cpt_routes[ $this->_req_action ],
3678
-            'side',
3679
-            'core'
3680
-        );
3681
-        add_meta_box(
3682
-            'attendee_details_address',
3683
-            esc_html__('Address Details', 'event_espresso'),
3684
-            array($this, 'attendee_address_details'),
3685
-            $this->_cpt_routes[ $this->_req_action ],
3686
-            'normal',
3687
-            'core'
3688
-        );
3689
-        add_meta_box(
3690
-            'attendee_registrations',
3691
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3692
-            array($this, 'attendee_registrations_meta_box'),
3693
-            $this->_cpt_routes[ $this->_req_action ],
3694
-            'normal',
3695
-            'high'
3696
-        );
3697
-    }
3698
-
3699
-
3700
-    /**
3701
-     * Metabox for attendee contact info
3702
-     *
3703
-     * @param  WP_Post $post wp post object
3704
-     * @return string attendee contact info ( and form )
3705
-     * @throws EE_Error
3706
-     * @throws InvalidArgumentException
3707
-     * @throws InvalidDataTypeException
3708
-     * @throws InvalidInterfaceException
3709
-     * @throws LogicException
3710
-     * @throws DomainException
3711
-     */
3712
-    public function attendee_contact_info($post)
3713
-    {
3714
-        // get attendee object ( should already have it )
3715
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3716
-        $form->enqueueStylesAndScripts();
3717
-        echo $form->display();
3718
-    }
3719
-
3720
-
3721
-    /**
3722
-     * Return form handler for the contact details metabox
3723
-     *
3724
-     * @param EE_Attendee $attendee
3725
-     * @return AttendeeContactDetailsMetaboxFormHandler
3726
-     * @throws DomainException
3727
-     * @throws InvalidArgumentException
3728
-     * @throws InvalidDataTypeException
3729
-     * @throws InvalidInterfaceException
3730
-     */
3731
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3732
-    {
3733
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3734
-    }
3735
-
3736
-
3737
-    /**
3738
-     * Metabox for attendee details
3739
-     *
3740
-     * @param  WP_Post $post wp post object
3741
-     * @throws DomainException
3742
-     */
3743
-    public function attendee_address_details($post)
3744
-    {
3745
-        // get attendee object (should already have it)
3746
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3747
-        $this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3748
-            new EE_Question_Form_Input(
3749
-                EE_Question::new_instance(
3750
-                    array(
3751
-                        'QST_ID'           => 0,
3752
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3753
-                        'QST_system'       => 'admin-state',
3754
-                    )
3755
-                ),
3756
-                EE_Answer::new_instance(
3757
-                    array(
3758
-                        'ANS_ID'    => 0,
3759
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3760
-                    )
3761
-                ),
3762
-                array(
3763
-                    'input_id'       => 'STA_ID',
3764
-                    'input_name'     => 'STA_ID',
3765
-                    'input_prefix'   => '',
3766
-                    'append_qstn_id' => false,
3767
-                )
3768
-            )
3769
-        );
3770
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3771
-            new EE_Question_Form_Input(
3772
-                EE_Question::new_instance(
3773
-                    array(
3774
-                        'QST_ID'           => 0,
3775
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3776
-                        'QST_system'       => 'admin-country',
3777
-                    )
3778
-                ),
3779
-                EE_Answer::new_instance(
3780
-                    array(
3781
-                        'ANS_ID'    => 0,
3782
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3783
-                    )
3784
-                ),
3785
-                array(
3786
-                    'input_id'       => 'CNT_ISO',
3787
-                    'input_name'     => 'CNT_ISO',
3788
-                    'input_prefix'   => '',
3789
-                    'append_qstn_id' => false,
3790
-                )
3791
-            )
3792
-        );
3793
-        $template =
3794
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3795
-        EEH_Template::display_template($template, $this->_template_args);
3796
-    }
3797
-
3798
-
3799
-    /**
3800
-     *        _attendee_details
3801
-     *
3802
-     * @access protected
3803
-     * @param $post
3804
-     * @return void
3805
-     * @throws DomainException
3806
-     * @throws EE_Error
3807
-     */
3808
-    public function attendee_registrations_meta_box($post)
3809
-    {
3810
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3811
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3812
-        $template =
3813
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3814
-        EEH_Template::display_template($template, $this->_template_args);
3815
-    }
3816
-
3817
-
3818
-    /**
3819
-     * add in the form fields for the attendee edit
3820
-     *
3821
-     * @param  WP_Post $post wp post object
3822
-     * @return string html for new form.
3823
-     * @throws DomainException
3824
-     */
3825
-    public function after_title_form_fields($post)
3826
-    {
3827
-        if ($post->post_type == 'espresso_attendees') {
3828
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3829
-            $template_args['attendee'] = $this->_cpt_model_obj;
3830
-            EEH_Template::display_template($template, $template_args);
3831
-        }
3832
-    }
3833
-
3834
-
3835
-    /**
3836
-     *        _trash_or_restore_attendee
3837
-     *
3838
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3839
-     * @return void
3840
-     * @throws EE_Error
3841
-     * @throws InvalidArgumentException
3842
-     * @throws InvalidDataTypeException
3843
-     * @throws InvalidInterfaceException
3844
-     * @access protected
3845
-     */
3846
-    protected function _trash_or_restore_attendees($trash = true)
3847
-    {
3848
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3849
-        $ATT_MDL = EEM_Attendee::instance();
3850
-        $success = 1;
3851
-        // Checkboxes
3852
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3853
-            // if array has more than one element than success message should be plural
3854
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3855
-            // cycle thru checkboxes
3856
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3857
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3858
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3859
-                if (! $updated) {
3860
-                    $success = 0;
3861
-                }
3862
-            }
3863
-        } else {
3864
-            // grab single id and delete
3865
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3866
-            // get attendee
3867
-            $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3868
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3869
-            $updated = $att->save();
3870
-            if (! $updated) {
3871
-                $success = 0;
3872
-            }
3873
-        }
3874
-        $what = $success > 1
3875
-            ? esc_html__('Contacts', 'event_espresso')
3876
-            : esc_html__('Contact', 'event_espresso');
3877
-        $action_desc = $trash
3878
-            ? esc_html__('moved to the trash', 'event_espresso')
3879
-            : esc_html__('restored', 'event_espresso');
3880
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3881
-    }
3031
+		}
3032
+		$template_args = array(
3033
+			'title'                    => '',
3034
+			'content'                  => '',
3035
+			'step_button_text'         => '',
3036
+			'show_notification_toggle' => false,
3037
+		);
3038
+		// to indicate we're processing a new registration
3039
+		$hidden_fields = array(
3040
+			'processing_registration' => array(
3041
+				'type'  => 'hidden',
3042
+				'value' => 0,
3043
+			),
3044
+			'event_id'                => array(
3045
+				'type'  => 'hidden',
3046
+				'value' => $this->_reg_event->ID(),
3047
+			),
3048
+		);
3049
+		// if the cart is empty then we know we're at step one so we'll display ticket selector
3050
+		$cart = EE_Registry::instance()->SSN->cart();
3051
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3052
+		switch ($step) {
3053
+			case 'ticket':
3054
+				$hidden_fields['processing_registration']['value'] = 1;
3055
+				$template_args['title'] = esc_html__(
3056
+					'Step One: Select the Ticket for this registration',
3057
+					'event_espresso'
3058
+				);
3059
+				$template_args['content'] =
3060
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3061
+				$template_args['step_button_text'] = esc_html__(
3062
+					'Add Tickets and Continue to Registrant Details',
3063
+					'event_espresso'
3064
+				);
3065
+				$template_args['show_notification_toggle'] = false;
3066
+				break;
3067
+			case 'questions':
3068
+				$hidden_fields['processing_registration']['value'] = 2;
3069
+				$template_args['title'] = esc_html__(
3070
+					'Step Two: Add Registrant Details for this Registration',
3071
+					'event_espresso'
3072
+				);
3073
+				// in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3074
+				// properly by the first process_reg_step run.
3075
+				$template_args['content'] =
3076
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
3077
+				$template_args['step_button_text'] = esc_html__(
3078
+					'Save Registration and Continue to Details',
3079
+					'event_espresso'
3080
+				);
3081
+				$template_args['show_notification_toggle'] = true;
3082
+				break;
3083
+		}
3084
+		// we come back to the process_registration_step route.
3085
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3086
+		return EEH_Template::display_template(
3087
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3088
+			$template_args,
3089
+			true
3090
+		);
3091
+	}
3092
+
3093
+
3094
+	/**
3095
+	 *        set_reg_event
3096
+	 *
3097
+	 * @access private
3098
+	 * @return bool
3099
+	 * @throws EE_Error
3100
+	 * @throws InvalidArgumentException
3101
+	 * @throws InvalidDataTypeException
3102
+	 * @throws InvalidInterfaceException
3103
+	 */
3104
+	private function _set_reg_event()
3105
+	{
3106
+		if (is_object($this->_reg_event)) {
3107
+			return true;
3108
+		}
3109
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3110
+		if (! $EVT_ID) {
3111
+			return false;
3112
+		}
3113
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3114
+		return true;
3115
+	}
3116
+
3117
+
3118
+	/**
3119
+	 * process_reg_step
3120
+	 *
3121
+	 * @access        public
3122
+	 * @return string
3123
+	 * @throws DomainException
3124
+	 * @throws EE_Error
3125
+	 * @throws InvalidArgumentException
3126
+	 * @throws InvalidDataTypeException
3127
+	 * @throws InvalidInterfaceException
3128
+	 * @throws ReflectionException
3129
+	 * @throws RuntimeException
3130
+	 */
3131
+	public function process_reg_step()
3132
+	{
3133
+		EE_System::do_not_cache();
3134
+		$this->_set_reg_event();
3135
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3136
+		EE_Registry::instance()->REQ->set('uts', time());
3137
+		// what step are we on?
3138
+		$cart = EE_Registry::instance()->SSN->cart();
3139
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3140
+		// if doing ajax then we need to verify the nonce
3141
+		if (defined('DOING_AJAX')) {
3142
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
3143
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3144
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3145
+		}
3146
+		switch ($step) {
3147
+			case 'ticket':
3148
+				// process ticket selection
3149
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3150
+				if ($success) {
3151
+					EE_Error::add_success(
3152
+						esc_html__(
3153
+							'Tickets Selected. Now complete the registration.',
3154
+							'event_espresso'
3155
+						)
3156
+					);
3157
+				} else {
3158
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3159
+				}
3160
+				if (defined('DOING_AJAX')) {
3161
+					$this->new_registration(); // display next step
3162
+				} else {
3163
+					$query_args = array(
3164
+						'action'                  => 'new_registration',
3165
+						'processing_registration' => 1,
3166
+						'event_id'                => $this->_reg_event->ID(),
3167
+						'uts'                     => time(),
3168
+					);
3169
+					$this->_redirect_after_action(
3170
+						false,
3171
+						'',
3172
+						'',
3173
+						$query_args,
3174
+						true
3175
+					);
3176
+				}
3177
+				break;
3178
+			case 'questions':
3179
+				if (! isset(
3180
+					$this->_req_data['txn_reg_status_change'],
3181
+					$this->_req_data['txn_reg_status_change']['send_notifications']
3182
+				)
3183
+				) {
3184
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3185
+				}
3186
+				// process registration
3187
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3188
+				if ($cart instanceof EE_Cart) {
3189
+					$grand_total = $cart->get_cart_grand_total();
3190
+					if ($grand_total instanceof EE_Line_Item) {
3191
+						$grand_total->save_this_and_descendants_to_txn();
3192
+					}
3193
+				}
3194
+				if (! $transaction instanceof EE_Transaction) {
3195
+					$query_args = array(
3196
+						'action'                  => 'new_registration',
3197
+						'processing_registration' => 2,
3198
+						'event_id'                => $this->_reg_event->ID(),
3199
+						'uts'                     => time(),
3200
+					);
3201
+					if (defined('DOING_AJAX')) {
3202
+						// display registration form again because there are errors (maybe validation?)
3203
+						$this->new_registration();
3204
+						return;
3205
+					} else {
3206
+						$this->_redirect_after_action(
3207
+							false,
3208
+							'',
3209
+							'',
3210
+							$query_args,
3211
+							true
3212
+						);
3213
+						return;
3214
+					}
3215
+				}
3216
+				// maybe update status, and make sure to save transaction if not done already
3217
+				if (! $transaction->update_status_based_on_total_paid()) {
3218
+					$transaction->save();
3219
+				}
3220
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3221
+				$this->_req_data = array();
3222
+				$query_args = array(
3223
+					'action'        => 'redirect_to_txn',
3224
+					'TXN_ID'        => $transaction->ID(),
3225
+					'EVT_ID'        => $this->_reg_event->ID(),
3226
+					'event_name'    => urlencode($this->_reg_event->name()),
3227
+					'redirect_from' => 'new_registration',
3228
+				);
3229
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3230
+				break;
3231
+		}
3232
+		// what are you looking here for?  Should be nothing to do at this point.
3233
+	}
3234
+
3235
+
3236
+	/**
3237
+	 * redirect_to_txn
3238
+	 *
3239
+	 * @access public
3240
+	 * @return void
3241
+	 * @throws EE_Error
3242
+	 * @throws InvalidArgumentException
3243
+	 * @throws InvalidDataTypeException
3244
+	 * @throws InvalidInterfaceException
3245
+	 */
3246
+	public function redirect_to_txn()
3247
+	{
3248
+		EE_System::do_not_cache();
3249
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3250
+		$query_args = array(
3251
+			'action' => 'view_transaction',
3252
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3253
+			'page'   => 'espresso_transactions',
3254
+		);
3255
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3256
+			$query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3257
+			$query_args['event_name'] = urlencode($this->_req_data['event_name']);
3258
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3259
+		}
3260
+		EE_Error::add_success(
3261
+			esc_html__(
3262
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3263
+				'event_espresso'
3264
+			)
3265
+		);
3266
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3267
+	}
3268
+
3269
+
3270
+	/**
3271
+	 *        generates HTML for the Attendee Contact List
3272
+	 *
3273
+	 * @access protected
3274
+	 * @return void
3275
+	 */
3276
+	protected function _attendee_contact_list_table()
3277
+	{
3278
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3279
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3280
+		$this->display_admin_list_table_page_with_no_sidebar();
3281
+	}
3282
+
3283
+
3284
+	/**
3285
+	 *        get_attendees
3286
+	 *
3287
+	 * @param      $per_page
3288
+	 * @param bool $count whether to return count or data.
3289
+	 * @param bool $trash
3290
+	 * @return array
3291
+	 * @throws EE_Error
3292
+	 * @throws InvalidArgumentException
3293
+	 * @throws InvalidDataTypeException
3294
+	 * @throws InvalidInterfaceException
3295
+	 * @access public
3296
+	 */
3297
+	public function get_attendees($per_page, $count = false, $trash = false)
3298
+	{
3299
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3300
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3301
+		$ATT_MDL = EEM_Attendee::instance();
3302
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3303
+		switch ($this->_req_data['orderby']) {
3304
+			case 'ATT_ID':
3305
+				$orderby = 'ATT_ID';
3306
+				break;
3307
+			case 'ATT_fname':
3308
+				$orderby = 'ATT_fname';
3309
+				break;
3310
+			case 'ATT_email':
3311
+				$orderby = 'ATT_email';
3312
+				break;
3313
+			case 'ATT_city':
3314
+				$orderby = 'ATT_city';
3315
+				break;
3316
+			case 'STA_ID':
3317
+				$orderby = 'STA_ID';
3318
+				break;
3319
+			case 'CNT_ID':
3320
+				$orderby = 'CNT_ID';
3321
+				break;
3322
+			case 'Registration_Count':
3323
+				$orderby = 'Registration_Count';
3324
+				break;
3325
+			default:
3326
+				$orderby = 'ATT_lname';
3327
+		}
3328
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3329
+			? $this->_req_data['order']
3330
+			: 'ASC';
3331
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3332
+			? $this->_req_data['paged']
3333
+			: 1;
3334
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3335
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3336
+			? $this->_req_data['perpage']
3337
+			: $per_page;
3338
+		$_where = array();
3339
+		if (! empty($this->_req_data['s'])) {
3340
+			$sstr = '%' . $this->_req_data['s'] . '%';
3341
+			$_where['OR'] = array(
3342
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3343
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3344
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3345
+				'ATT_fname'                         => array('LIKE', $sstr),
3346
+				'ATT_lname'                         => array('LIKE', $sstr),
3347
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3348
+				'ATT_email'                         => array('LIKE', $sstr),
3349
+				'ATT_address'                       => array('LIKE', $sstr),
3350
+				'ATT_address2'                      => array('LIKE', $sstr),
3351
+				'ATT_city'                          => array('LIKE', $sstr),
3352
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3353
+				'State.STA_name'                    => array('LIKE', $sstr),
3354
+				'ATT_phone'                         => array('LIKE', $sstr),
3355
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3356
+				'Registration.REG_code'             => array('LIKE', $sstr),
3357
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3358
+			);
3359
+		}
3360
+		$offset = ($current_page - 1) * $per_page;
3361
+		$limit = $count ? null : array($offset, $per_page);
3362
+		$query_args = array(
3363
+			$_where,
3364
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3365
+			'limit'         => $limit,
3366
+		);
3367
+		if (! $count) {
3368
+			$query_args['order_by'] = array($orderby => $sort);
3369
+		}
3370
+		if ($trash) {
3371
+			$query_args[0]['status'] = array('!=', 'publish');
3372
+			$all_attendees = $count
3373
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3374
+				: $ATT_MDL->get_all($query_args);
3375
+		} else {
3376
+			$query_args[0]['status'] = array('IN', array('publish'));
3377
+			$all_attendees = $count
3378
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3379
+				: $ATT_MDL->get_all($query_args);
3380
+		}
3381
+		return $all_attendees;
3382
+	}
3383
+
3384
+
3385
+	/**
3386
+	 * This is just taking care of resending the registration confirmation
3387
+	 *
3388
+	 * @access protected
3389
+	 * @return void
3390
+	 */
3391
+	protected function _resend_registration()
3392
+	{
3393
+		$this->_process_resend_registration();
3394
+		$query_args = isset($this->_req_data['redirect_to'])
3395
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3396
+			: array('action' => 'default');
3397
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3398
+	}
3399
+
3400
+	/**
3401
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3402
+	 * to use when selecting registrations
3403
+	 *
3404
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3405
+	 *                                                     the query parameters from the request
3406
+	 * @return void ends the request with a redirect or download
3407
+	 */
3408
+	public function _registrations_report_base($method_name_for_getting_query_params)
3409
+	{
3410
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3411
+			wp_redirect(
3412
+				EE_Admin_Page::add_query_args_and_nonce(
3413
+					array(
3414
+						'page'        => 'espresso_batch',
3415
+						'batch'       => 'file',
3416
+						'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3417
+						'filters'     => urlencode(
3418
+							serialize(
3419
+								call_user_func(
3420
+									array($this, $method_name_for_getting_query_params),
3421
+									EEH_Array::is_set(
3422
+										$this->_req_data,
3423
+										'filters',
3424
+										array()
3425
+									)
3426
+								)
3427
+							)
3428
+						),
3429
+						'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3430
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3431
+						'return_url'  => urlencode($this->_req_data['return_url']),
3432
+					)
3433
+				)
3434
+			);
3435
+		} else {
3436
+			$new_request_args = array(
3437
+				'export' => 'report',
3438
+				'action' => 'registrations_report_for_event',
3439
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3440
+			);
3441
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3442
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3443
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3444
+				$EE_Export = EE_Export::instance($this->_req_data);
3445
+				$EE_Export->export();
3446
+			}
3447
+		}
3448
+	}
3449
+
3450
+
3451
+	/**
3452
+	 * Creates a registration report using only query parameters in the request
3453
+	 *
3454
+	 * @return void
3455
+	 */
3456
+	public function _registrations_report()
3457
+	{
3458
+		$this->_registrations_report_base('_get_registration_query_parameters');
3459
+	}
3460
+
3461
+
3462
+	public function _contact_list_export()
3463
+	{
3464
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3465
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3466
+			$EE_Export = EE_Export::instance($this->_req_data);
3467
+			$EE_Export->export_attendees();
3468
+		}
3469
+	}
3470
+
3471
+
3472
+	public function _contact_list_report()
3473
+	{
3474
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3475
+			wp_redirect(
3476
+				EE_Admin_Page::add_query_args_and_nonce(
3477
+					array(
3478
+						'page'        => 'espresso_batch',
3479
+						'batch'       => 'file',
3480
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3481
+						'return_url'  => urlencode($this->_req_data['return_url']),
3482
+					)
3483
+				)
3484
+			);
3485
+		} else {
3486
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3487
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3488
+				$EE_Export = EE_Export::instance($this->_req_data);
3489
+				$EE_Export->report_attendees();
3490
+			}
3491
+		}
3492
+	}
3493
+
3494
+
3495
+
3496
+
3497
+
3498
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3499
+	/**
3500
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3501
+	 *
3502
+	 * @return void
3503
+	 * @throws EE_Error
3504
+	 * @throws InvalidArgumentException
3505
+	 * @throws InvalidDataTypeException
3506
+	 * @throws InvalidInterfaceException
3507
+	 */
3508
+	protected function _duplicate_attendee()
3509
+	{
3510
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3511
+		// verify we have necessary info
3512
+		if (empty($this->_req_data['_REG_ID'])) {
3513
+			EE_Error::add_error(
3514
+				esc_html__(
3515
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3516
+					'event_espresso'
3517
+				),
3518
+				__FILE__,
3519
+				__LINE__,
3520
+				__FUNCTION__
3521
+			);
3522
+			$query_args = array('action' => $action);
3523
+			$this->_redirect_after_action('', '', '', $query_args, true);
3524
+		}
3525
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3526
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3527
+		$attendee = $registration->attendee();
3528
+		// remove relation of existing attendee on registration
3529
+		$registration->_remove_relation_to($attendee, 'Attendee');
3530
+		// new attendee
3531
+		$new_attendee = clone $attendee;
3532
+		$new_attendee->set('ATT_ID', 0);
3533
+		$new_attendee->save();
3534
+		// add new attendee to reg
3535
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3536
+		EE_Error::add_success(
3537
+			esc_html__(
3538
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3539
+				'event_espresso'
3540
+			)
3541
+		);
3542
+		// redirect to edit page for attendee
3543
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3544
+		$this->_redirect_after_action('', '', '', $query_args, true);
3545
+	}
3546
+
3547
+
3548
+	/**
3549
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3550
+	 *
3551
+	 * @param int     $post_id
3552
+	 * @param WP_POST $post
3553
+	 * @throws DomainException
3554
+	 * @throws EE_Error
3555
+	 * @throws InvalidArgumentException
3556
+	 * @throws InvalidDataTypeException
3557
+	 * @throws InvalidInterfaceException
3558
+	 * @throws LogicException
3559
+	 * @throws InvalidFormSubmissionException
3560
+	 */
3561
+	protected function _insert_update_cpt_item($post_id, $post)
3562
+	{
3563
+		$success = true;
3564
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3565
+			? EEM_Attendee::instance()->get_one_by_ID($post_id)
3566
+			: null;
3567
+		// for attendee updates
3568
+		if ($attendee instanceof EE_Attendee) {
3569
+			// note we should only be UPDATING attendees at this point.
3570
+			$updated_fields = array(
3571
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3572
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3573
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3574
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3575
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3576
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3577
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3578
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3579
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3580
+			);
3581
+			foreach ($updated_fields as $field => $value) {
3582
+				$attendee->set($field, $value);
3583
+			}
3584
+
3585
+			// process contact details metabox form handler (which will also save the attendee)
3586
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3587
+			$success = $contact_details_form->process($this->_req_data);
3588
+
3589
+			$attendee_update_callbacks = apply_filters(
3590
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3591
+				array()
3592
+			);
3593
+			foreach ($attendee_update_callbacks as $a_callback) {
3594
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3595
+					throw new EE_Error(
3596
+						sprintf(
3597
+							esc_html__(
3598
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3599
+								'event_espresso'
3600
+							),
3601
+							$a_callback
3602
+						)
3603
+					);
3604
+				}
3605
+			}
3606
+		}
3607
+
3608
+		if ($success === false) {
3609
+			EE_Error::add_error(
3610
+				esc_html__(
3611
+					'Something went wrong with updating the meta table data for the registration.',
3612
+					'event_espresso'
3613
+				),
3614
+				__FILE__,
3615
+				__FUNCTION__,
3616
+				__LINE__
3617
+			);
3618
+		}
3619
+	}
3620
+
3621
+
3622
+	public function trash_cpt_item($post_id)
3623
+	{
3624
+	}
3625
+
3626
+
3627
+	public function delete_cpt_item($post_id)
3628
+	{
3629
+	}
3630
+
3631
+
3632
+	public function restore_cpt_item($post_id)
3633
+	{
3634
+	}
3635
+
3636
+
3637
+	protected function _restore_cpt_item($post_id, $revision_id)
3638
+	{
3639
+	}
3640
+
3641
+
3642
+	public function attendee_editor_metaboxes()
3643
+	{
3644
+		$this->verify_cpt_object();
3645
+		remove_meta_box(
3646
+			'postexcerpt',
3647
+			esc_html__('Excerpt', 'event_espresso'),
3648
+			'post_excerpt_meta_box',
3649
+			$this->_cpt_routes[ $this->_req_action ],
3650
+			'normal',
3651
+			'core'
3652
+		);
3653
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3654
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3655
+			add_meta_box(
3656
+				'postexcerpt',
3657
+				esc_html__('Short Biography', 'event_espresso'),
3658
+				'post_excerpt_meta_box',
3659
+				$this->_cpt_routes[ $this->_req_action ],
3660
+				'normal'
3661
+			);
3662
+		}
3663
+		if (post_type_supports('espresso_attendees', 'comments')) {
3664
+			add_meta_box(
3665
+				'commentsdiv',
3666
+				esc_html__('Notes on the Contact', 'event_espresso'),
3667
+				'post_comment_meta_box',
3668
+				$this->_cpt_routes[ $this->_req_action ],
3669
+				'normal',
3670
+				'core'
3671
+			);
3672
+		}
3673
+		add_meta_box(
3674
+			'attendee_contact_info',
3675
+			esc_html__('Contact Info', 'event_espresso'),
3676
+			array($this, 'attendee_contact_info'),
3677
+			$this->_cpt_routes[ $this->_req_action ],
3678
+			'side',
3679
+			'core'
3680
+		);
3681
+		add_meta_box(
3682
+			'attendee_details_address',
3683
+			esc_html__('Address Details', 'event_espresso'),
3684
+			array($this, 'attendee_address_details'),
3685
+			$this->_cpt_routes[ $this->_req_action ],
3686
+			'normal',
3687
+			'core'
3688
+		);
3689
+		add_meta_box(
3690
+			'attendee_registrations',
3691
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3692
+			array($this, 'attendee_registrations_meta_box'),
3693
+			$this->_cpt_routes[ $this->_req_action ],
3694
+			'normal',
3695
+			'high'
3696
+		);
3697
+	}
3698
+
3699
+
3700
+	/**
3701
+	 * Metabox for attendee contact info
3702
+	 *
3703
+	 * @param  WP_Post $post wp post object
3704
+	 * @return string attendee contact info ( and form )
3705
+	 * @throws EE_Error
3706
+	 * @throws InvalidArgumentException
3707
+	 * @throws InvalidDataTypeException
3708
+	 * @throws InvalidInterfaceException
3709
+	 * @throws LogicException
3710
+	 * @throws DomainException
3711
+	 */
3712
+	public function attendee_contact_info($post)
3713
+	{
3714
+		// get attendee object ( should already have it )
3715
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3716
+		$form->enqueueStylesAndScripts();
3717
+		echo $form->display();
3718
+	}
3719
+
3720
+
3721
+	/**
3722
+	 * Return form handler for the contact details metabox
3723
+	 *
3724
+	 * @param EE_Attendee $attendee
3725
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3726
+	 * @throws DomainException
3727
+	 * @throws InvalidArgumentException
3728
+	 * @throws InvalidDataTypeException
3729
+	 * @throws InvalidInterfaceException
3730
+	 */
3731
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3732
+	{
3733
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3734
+	}
3735
+
3736
+
3737
+	/**
3738
+	 * Metabox for attendee details
3739
+	 *
3740
+	 * @param  WP_Post $post wp post object
3741
+	 * @throws DomainException
3742
+	 */
3743
+	public function attendee_address_details($post)
3744
+	{
3745
+		// get attendee object (should already have it)
3746
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3747
+		$this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3748
+			new EE_Question_Form_Input(
3749
+				EE_Question::new_instance(
3750
+					array(
3751
+						'QST_ID'           => 0,
3752
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3753
+						'QST_system'       => 'admin-state',
3754
+					)
3755
+				),
3756
+				EE_Answer::new_instance(
3757
+					array(
3758
+						'ANS_ID'    => 0,
3759
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3760
+					)
3761
+				),
3762
+				array(
3763
+					'input_id'       => 'STA_ID',
3764
+					'input_name'     => 'STA_ID',
3765
+					'input_prefix'   => '',
3766
+					'append_qstn_id' => false,
3767
+				)
3768
+			)
3769
+		);
3770
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3771
+			new EE_Question_Form_Input(
3772
+				EE_Question::new_instance(
3773
+					array(
3774
+						'QST_ID'           => 0,
3775
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3776
+						'QST_system'       => 'admin-country',
3777
+					)
3778
+				),
3779
+				EE_Answer::new_instance(
3780
+					array(
3781
+						'ANS_ID'    => 0,
3782
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3783
+					)
3784
+				),
3785
+				array(
3786
+					'input_id'       => 'CNT_ISO',
3787
+					'input_name'     => 'CNT_ISO',
3788
+					'input_prefix'   => '',
3789
+					'append_qstn_id' => false,
3790
+				)
3791
+			)
3792
+		);
3793
+		$template =
3794
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3795
+		EEH_Template::display_template($template, $this->_template_args);
3796
+	}
3797
+
3798
+
3799
+	/**
3800
+	 *        _attendee_details
3801
+	 *
3802
+	 * @access protected
3803
+	 * @param $post
3804
+	 * @return void
3805
+	 * @throws DomainException
3806
+	 * @throws EE_Error
3807
+	 */
3808
+	public function attendee_registrations_meta_box($post)
3809
+	{
3810
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3811
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3812
+		$template =
3813
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3814
+		EEH_Template::display_template($template, $this->_template_args);
3815
+	}
3816
+
3817
+
3818
+	/**
3819
+	 * add in the form fields for the attendee edit
3820
+	 *
3821
+	 * @param  WP_Post $post wp post object
3822
+	 * @return string html for new form.
3823
+	 * @throws DomainException
3824
+	 */
3825
+	public function after_title_form_fields($post)
3826
+	{
3827
+		if ($post->post_type == 'espresso_attendees') {
3828
+			$template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3829
+			$template_args['attendee'] = $this->_cpt_model_obj;
3830
+			EEH_Template::display_template($template, $template_args);
3831
+		}
3832
+	}
3833
+
3834
+
3835
+	/**
3836
+	 *        _trash_or_restore_attendee
3837
+	 *
3838
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3839
+	 * @return void
3840
+	 * @throws EE_Error
3841
+	 * @throws InvalidArgumentException
3842
+	 * @throws InvalidDataTypeException
3843
+	 * @throws InvalidInterfaceException
3844
+	 * @access protected
3845
+	 */
3846
+	protected function _trash_or_restore_attendees($trash = true)
3847
+	{
3848
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3849
+		$ATT_MDL = EEM_Attendee::instance();
3850
+		$success = 1;
3851
+		// Checkboxes
3852
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3853
+			// if array has more than one element than success message should be plural
3854
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3855
+			// cycle thru checkboxes
3856
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3857
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3858
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3859
+				if (! $updated) {
3860
+					$success = 0;
3861
+				}
3862
+			}
3863
+		} else {
3864
+			// grab single id and delete
3865
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3866
+			// get attendee
3867
+			$att = $ATT_MDL->get_one_by_ID($ATT_ID);
3868
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3869
+			$updated = $att->save();
3870
+			if (! $updated) {
3871
+				$success = 0;
3872
+			}
3873
+		}
3874
+		$what = $success > 1
3875
+			? esc_html__('Contacts', 'event_espresso')
3876
+			: esc_html__('Contact', 'event_espresso');
3877
+		$action_desc = $trash
3878
+			? esc_html__('moved to the trash', 'event_espresso')
3879
+			: esc_html__('restored', 'event_espresso');
3880
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3881
+	}
3882 3882
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4044 added lines, -4044 removed lines patch added patch discarded remove patch
@@ -17,4111 +17,4111 @@
 block discarded – undo
17 17
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var LoaderInterface $loader
22
-     */
23
-    protected $loader;
20
+	/**
21
+	 * @var LoaderInterface $loader
22
+	 */
23
+	protected $loader;
24 24
 
25
-    // set in _init_page_props()
26
-    public $page_slug;
25
+	// set in _init_page_props()
26
+	public $page_slug;
27 27
 
28
-    public $page_label;
28
+	public $page_label;
29 29
 
30
-    public $page_folder;
30
+	public $page_folder;
31 31
 
32
-    // set in define_page_props()
33
-    protected $_admin_base_url;
32
+	// set in define_page_props()
33
+	protected $_admin_base_url;
34 34
 
35
-    protected $_admin_base_path;
35
+	protected $_admin_base_path;
36 36
 
37
-    protected $_admin_page_title;
37
+	protected $_admin_page_title;
38 38
 
39
-    protected $_labels;
39
+	protected $_labels;
40 40
 
41 41
 
42
-    // set early within EE_Admin_Init
43
-    protected $_wp_page_slug;
42
+	// set early within EE_Admin_Init
43
+	protected $_wp_page_slug;
44 44
 
45
-    // navtabs
46
-    protected $_nav_tabs;
45
+	// navtabs
46
+	protected $_nav_tabs;
47 47
 
48
-    protected $_default_nav_tab_name;
48
+	protected $_default_nav_tab_name;
49 49
 
50
-    /**
51
-     * @var array $_help_tour
52
-     */
53
-    protected $_help_tour = array();
50
+	/**
51
+	 * @var array $_help_tour
52
+	 */
53
+	protected $_help_tour = array();
54 54
 
55 55
 
56
-    // template variables (used by templates)
57
-    protected $_template_path;
56
+	// template variables (used by templates)
57
+	protected $_template_path;
58 58
 
59
-    protected $_column_template_path;
59
+	protected $_column_template_path;
60 60
 
61
-    /**
62
-     * @var array $_template_args
63
-     */
64
-    protected $_template_args = array();
61
+	/**
62
+	 * @var array $_template_args
63
+	 */
64
+	protected $_template_args = array();
65 65
 
66
-    /**
67
-     * this will hold the list table object for a given view.
68
-     *
69
-     * @var EE_Admin_List_Table $_list_table_object
70
-     */
71
-    protected $_list_table_object;
66
+	/**
67
+	 * this will hold the list table object for a given view.
68
+	 *
69
+	 * @var EE_Admin_List_Table $_list_table_object
70
+	 */
71
+	protected $_list_table_object;
72 72
 
73
-    // bools
74
-    protected $_is_UI_request = null; // this starts at null so we can have no header routes progress through two states.
73
+	// bools
74
+	protected $_is_UI_request = null; // this starts at null so we can have no header routes progress through two states.
75 75
 
76
-    protected $_routing;
76
+	protected $_routing;
77 77
 
78
-    // list table args
79
-    protected $_view;
78
+	// list table args
79
+	protected $_view;
80 80
 
81
-    protected $_views;
81
+	protected $_views;
82 82
 
83 83
 
84
-    // action => method pairs used for routing incoming requests
85
-    protected $_page_routes;
84
+	// action => method pairs used for routing incoming requests
85
+	protected $_page_routes;
86 86
 
87
-    /**
88
-     * @var array $_page_config
89
-     */
90
-    protected $_page_config;
87
+	/**
88
+	 * @var array $_page_config
89
+	 */
90
+	protected $_page_config;
91 91
 
92
-    /**
93
-     * the current page route and route config
94
-     *
95
-     * @var string $_route
96
-     */
97
-    protected $_route;
92
+	/**
93
+	 * the current page route and route config
94
+	 *
95
+	 * @var string $_route
96
+	 */
97
+	protected $_route;
98 98
 
99
-    /**
100
-     * @var string $_cpt_route
101
-     */
102
-    protected $_cpt_route;
99
+	/**
100
+	 * @var string $_cpt_route
101
+	 */
102
+	protected $_cpt_route;
103 103
 
104
-    /**
105
-     * @var array $_route_config
106
-     */
107
-    protected $_route_config;
108
-
109
-    /**
110
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
111
-     * actions.
112
-     *
113
-     * @since 4.6.x
114
-     * @var array.
115
-     */
116
-    protected $_default_route_query_args;
117
-
118
-    // set via request page and action args.
119
-    protected $_current_page;
120
-
121
-    protected $_current_view;
122
-
123
-    protected $_current_page_view_url;
124
-
125
-    // sanitized request action (and nonce)
126
-
127
-    /**
128
-     * @var string $_req_action
129
-     */
130
-    protected $_req_action;
131
-
132
-    /**
133
-     * @var string $_req_nonce
134
-     */
135
-    protected $_req_nonce;
136
-
137
-    // search related
138
-    protected $_search_btn_label;
139
-
140
-    protected $_search_box_callback;
141
-
142
-    /**
143
-     * WP Current Screen object
144
-     *
145
-     * @var WP_Screen
146
-     */
147
-    protected $_current_screen;
148
-
149
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
150
-    protected $_hook_obj;
151
-
152
-    // for holding incoming request data
153
-    protected $_req_data;
154
-
155
-    // yes / no array for admin form fields
156
-    protected $_yes_no_values = array();
157
-
158
-    // some default things shared by all child classes
159
-    protected $_default_espresso_metaboxes;
160
-
161
-    /**
162
-     *    EE_Registry Object
163
-     *
164
-     * @var    EE_Registry
165
-     */
166
-    protected $EE = null;
167
-
168
-
169
-    /**
170
-     * This is just a property that flags whether the given route is a caffeinated route or not.
171
-     *
172
-     * @var boolean
173
-     */
174
-    protected $_is_caf = false;
175
-
176
-
177
-    /**
178
-     * @Constructor
179
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
180
-     * @throws EE_Error
181
-     * @throws InvalidArgumentException
182
-     * @throws ReflectionException
183
-     * @throws InvalidDataTypeException
184
-     * @throws InvalidInterfaceException
185
-     */
186
-    public function __construct($routing = true)
187
-    {
188
-        $this->loader = LoaderFactory::getLoader();
189
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
190
-            $this->_is_caf = true;
191
-        }
192
-        $this->_yes_no_values = array(
193
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
194
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
195
-        );
196
-        // set the _req_data property.
197
-        $this->_req_data = array_merge($_GET, $_POST);
198
-        // routing enabled?
199
-        $this->_routing = $routing;
200
-        // set initial page props (child method)
201
-        $this->_init_page_props();
202
-        // set global defaults
203
-        $this->_set_defaults();
204
-        // set early because incoming requests could be ajax related and we need to register those hooks.
205
-        $this->_global_ajax_hooks();
206
-        $this->_ajax_hooks();
207
-        // other_page_hooks have to be early too.
208
-        $this->_do_other_page_hooks();
209
-        // This just allows us to have extending classes do something specific
210
-        // before the parent constructor runs _page_setup().
211
-        if (method_exists($this, '_before_page_setup')) {
212
-            $this->_before_page_setup();
213
-        }
214
-        // set up page dependencies
215
-        $this->_page_setup();
216
-    }
217
-
218
-
219
-    /**
220
-     * _init_page_props
221
-     * Child classes use to set at least the following properties:
222
-     * $page_slug.
223
-     * $page_label.
224
-     *
225
-     * @abstract
226
-     * @return void
227
-     */
228
-    abstract protected function _init_page_props();
229
-
230
-
231
-    /**
232
-     * _ajax_hooks
233
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
234
-     * Note: within the ajax callback methods.
235
-     *
236
-     * @abstract
237
-     * @return void
238
-     */
239
-    abstract protected function _ajax_hooks();
240
-
241
-
242
-    /**
243
-     * _define_page_props
244
-     * child classes define page properties in here.  Must include at least:
245
-     * $_admin_base_url = base_url for all admin pages
246
-     * $_admin_page_title = default admin_page_title for admin pages
247
-     * $_labels = array of default labels for various automatically generated elements:
248
-     *    array(
249
-     *        'buttons' => array(
250
-     *            'add' => esc_html__('label for add new button'),
251
-     *            'edit' => esc_html__('label for edit button'),
252
-     *            'delete' => esc_html__('label for delete button')
253
-     *            )
254
-     *        )
255
-     *
256
-     * @abstract
257
-     * @return void
258
-     */
259
-    abstract protected function _define_page_props();
260
-
261
-
262
-    /**
263
-     * _set_page_routes
264
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
265
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
266
-     * have a 'default' route. Here's the format
267
-     * $this->_page_routes = array(
268
-     *        'default' => array(
269
-     *            'func' => '_default_method_handling_route',
270
-     *            'args' => array('array','of','args'),
271
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
272
-     *            ajax request, backend processing)
273
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
274
-     *            headers route after.  The string you enter here should match the defined route reference for a
275
-     *            headers sent route.
276
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
277
-     *            this route.
278
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
279
-     *            checks).
280
-     *        ),
281
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
282
-     *        handling method.
283
-     *        )
284
-     * )
285
-     *
286
-     * @abstract
287
-     * @return void
288
-     */
289
-    abstract protected function _set_page_routes();
290
-
291
-
292
-    /**
293
-     * _set_page_config
294
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
295
-     * array corresponds to the page_route for the loaded page. Format:
296
-     * $this->_page_config = array(
297
-     *        'default' => array(
298
-     *            'labels' => array(
299
-     *                'buttons' => array(
300
-     *                    'add' => esc_html__('label for adding item'),
301
-     *                    'edit' => esc_html__('label for editing item'),
302
-     *                    'delete' => esc_html__('label for deleting item')
303
-     *                ),
304
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
305
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
306
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
307
-     *            _define_page_props() method
308
-     *            'nav' => array(
309
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
310
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
311
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
312
-     *                'order' => 10, //required to indicate tab position.
313
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
314
-     *                displayed then add this parameter.
315
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
316
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
317
-     *            metaboxes set for eventespresso admin pages.
318
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
319
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
320
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
321
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
322
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
323
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
324
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
325
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
326
-     *            want to display.
327
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
328
-     *                'tab_id' => array(
329
-     *                    'title' => 'tab_title',
330
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
331
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
332
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
333
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
334
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
335
-     *                    attempt to use the callback which should match the name of a method in the class
336
-     *                    ),
337
-     *                'tab2_id' => array(
338
-     *                    'title' => 'tab2 title',
339
-     *                    'filename' => 'file_name_2'
340
-     *                    'callback' => 'callback_method_for_content',
341
-     *                 ),
342
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
343
-     *            help tab area on an admin page. @link
344
-     *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
345
-     *            'help_tour' => array(
346
-     *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
347
-     *                in a folder for this admin page named "help_tours", a file name matching the key given here
348
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
349
-     *            ),
350
-     *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
351
-     *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
352
-     *            just set
353
-     *            'require_nonce' to FALSE
354
-     *            )
355
-     * )
356
-     *
357
-     * @abstract
358
-     * @return void
359
-     */
360
-    abstract protected function _set_page_config();
361
-
362
-
363
-
364
-
365
-
366
-    /** end sample help_tour methods **/
367
-    /**
368
-     * _add_screen_options
369
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
370
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
371
-     * to a particular view.
372
-     *
373
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
374
-     *         see also WP_Screen object documents...
375
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
376
-     * @abstract
377
-     * @return void
378
-     */
379
-    abstract protected function _add_screen_options();
380
-
381
-
382
-    /**
383
-     * _add_feature_pointers
384
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
385
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
386
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
387
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
388
-     * extended) also see:
389
-     *
390
-     * @link   http://eamann.com/tech/wordpress-portland/
391
-     * @abstract
392
-     * @return void
393
-     */
394
-    abstract protected function _add_feature_pointers();
395
-
396
-
397
-    /**
398
-     * load_scripts_styles
399
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
400
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
401
-     * scripts/styles per view by putting them in a dynamic function in this format
402
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
403
-     *
404
-     * @abstract
405
-     * @return void
406
-     */
407
-    abstract public function load_scripts_styles();
408
-
409
-
410
-    /**
411
-     * admin_init
412
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
413
-     * all pages/views loaded by child class.
414
-     *
415
-     * @abstract
416
-     * @return void
417
-     */
418
-    abstract public function admin_init();
419
-
420
-
421
-    /**
422
-     * admin_notices
423
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
424
-     * all pages/views loaded by child class.
425
-     *
426
-     * @abstract
427
-     * @return void
428
-     */
429
-    abstract public function admin_notices();
430
-
431
-
432
-    /**
433
-     * admin_footer_scripts
434
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
435
-     * will apply to all pages/views loaded by child class.
436
-     *
437
-     * @return void
438
-     */
439
-    abstract public function admin_footer_scripts();
440
-
441
-
442
-    /**
443
-     * admin_footer
444
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
445
-     * apply to all pages/views loaded by child class.
446
-     *
447
-     * @return void
448
-     */
449
-    public function admin_footer()
450
-    {
451
-    }
452
-
453
-
454
-    /**
455
-     * _global_ajax_hooks
456
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
457
-     * Note: within the ajax callback methods.
458
-     *
459
-     * @abstract
460
-     * @return void
461
-     */
462
-    protected function _global_ajax_hooks()
463
-    {
464
-        // for lazy loading of metabox content
465
-        add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
466
-    }
467
-
468
-
469
-    public function ajax_metabox_content()
470
-    {
471
-        $contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
472
-        $url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
473
-        self::cached_rss_display($contentid, $url);
474
-        wp_die();
475
-    }
476
-
477
-
478
-    /**
479
-     * _page_setup
480
-     * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
481
-     * doesn't match the object.
482
-     *
483
-     * @final
484
-     * @return void
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws ReflectionException
488
-     * @throws InvalidDataTypeException
489
-     * @throws InvalidInterfaceException
490
-     */
491
-    final protected function _page_setup()
492
-    {
493
-        // requires?
494
-        // admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
495
-        add_action('admin_init', array($this, 'admin_init_global'), 5);
496
-        // next verify if we need to load anything...
497
-        $this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
498
-        $this->page_folder = strtolower(
499
-            str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
500
-        );
501
-        global $ee_menu_slugs;
502
-        $ee_menu_slugs = (array) $ee_menu_slugs;
503
-        if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))) {
504
-            return;
505
-        }
506
-        // becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
507
-        if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
508
-            $this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
509
-                ? $this->_req_data['action2']
510
-                : $this->_req_data['action'];
511
-        }
512
-        // then set blank or -1 action values to 'default'
513
-        $this->_req_action = isset($this->_req_data['action'])
514
-                             && ! empty($this->_req_data['action'])
515
-                             && $this->_req_data['action'] !== '-1'
516
-            ? sanitize_key($this->_req_data['action'])
517
-            : 'default';
518
-        // if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
519
-        //  This covers cases where we're coming in from a list table that isn't on the default route.
520
-        $this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
521
-            ? $this->_req_data['route'] : $this->_req_action;
522
-        // however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
523
-        $this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route'])
524
-            ? $this->_req_data['route']
525
-            : $this->_req_action;
526
-        $this->_current_view = $this->_req_action;
527
-        $this->_req_nonce = $this->_req_action . '_nonce';
528
-        $this->_define_page_props();
529
-        $this->_current_page_view_url = add_query_arg(
530
-            array('page' => $this->_current_page, 'action' => $this->_current_view),
531
-            $this->_admin_base_url
532
-        );
533
-        // default things
534
-        $this->_default_espresso_metaboxes = array(
535
-            '_espresso_news_post_box',
536
-            '_espresso_links_post_box',
537
-            '_espresso_ratings_request',
538
-            '_espresso_sponsors_post_box',
539
-        );
540
-        // set page configs
541
-        $this->_set_page_routes();
542
-        $this->_set_page_config();
543
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
544
-        if (isset($this->_req_data['wp_referer'])) {
545
-            $this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
546
-        }
547
-        // for caffeinated and other extended functionality.
548
-        //  If there is a _extend_page_config method
549
-        // then let's run that to modify the all the various page configuration arrays
550
-        if (method_exists($this, '_extend_page_config')) {
551
-            $this->_extend_page_config();
552
-        }
553
-        // for CPT and other extended functionality.
554
-        // If there is an _extend_page_config_for_cpt
555
-        // then let's run that to modify all the various page configuration arrays.
556
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
557
-            $this->_extend_page_config_for_cpt();
558
-        }
559
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
560
-        $this->_page_routes = apply_filters(
561
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
562
-            $this->_page_routes,
563
-            $this
564
-        );
565
-        $this->_page_config = apply_filters(
566
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
567
-            $this->_page_config,
568
-            $this
569
-        );
570
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
571
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
572
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
573
-            add_action(
574
-                'AHEE__EE_Admin_Page__route_admin_request',
575
-                array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
576
-                10,
577
-                2
578
-            );
579
-        }
580
-        // next route only if routing enabled
581
-        if ($this->_routing && ! defined('DOING_AJAX')) {
582
-            $this->_verify_routes();
583
-            // next let's just check user_access and kill if no access
584
-            $this->check_user_access();
585
-            if ($this->_is_UI_request) {
586
-                // admin_init stuff - global, all views for this page class, specific view
587
-                add_action('admin_init', array($this, 'admin_init'), 10);
588
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
589
-                    add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
590
-                }
591
-            } else {
592
-                // hijack regular WP loading and route admin request immediately
593
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
594
-                $this->route_admin_request();
595
-            }
596
-        }
597
-    }
598
-
599
-
600
-    /**
601
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
602
-     *
603
-     * @return void
604
-     * @throws ReflectionException
605
-     * @throws EE_Error
606
-     */
607
-    private function _do_other_page_hooks()
608
-    {
609
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
610
-        foreach ($registered_pages as $page) {
611
-            // now let's setup the file name and class that should be present
612
-            $classname = str_replace('.class.php', '', $page);
613
-            // autoloaders should take care of loading file
614
-            if (! class_exists($classname)) {
615
-                $error_msg[] = sprintf(
616
-                    esc_html__(
617
-                        'Something went wrong with loading the %s admin hooks page.',
618
-                        'event_espresso'
619
-                    ),
620
-                    $page
621
-                );
622
-                $error_msg[] = $error_msg[0]
623
-                               . "\r\n"
624
-                               . sprintf(
625
-                                   esc_html__(
626
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
627
-                                       'event_espresso'
628
-                                   ),
629
-                                   $page,
630
-                                   '<br />',
631
-                                   '<strong>' . $classname . '</strong>'
632
-                               );
633
-                throw new EE_Error(implode('||', $error_msg));
634
-            }
635
-            $a = new ReflectionClass($classname);
636
-            // notice we are passing the instance of this class to the hook object.
637
-            $hookobj[] = $a->newInstance($this);
638
-        }
639
-    }
640
-
641
-
642
-    public function load_page_dependencies()
643
-    {
644
-        try {
645
-            $this->_load_page_dependencies();
646
-        } catch (EE_Error $e) {
647
-            $e->get_error();
648
-        }
649
-    }
650
-
651
-
652
-    /**
653
-     * load_page_dependencies
654
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
655
-     *
656
-     * @return void
657
-     * @throws DomainException
658
-     * @throws EE_Error
659
-     * @throws InvalidArgumentException
660
-     * @throws InvalidDataTypeException
661
-     * @throws InvalidInterfaceException
662
-     * @throws ReflectionException
663
-     */
664
-    protected function _load_page_dependencies()
665
-    {
666
-        // let's set the current_screen and screen options to override what WP set
667
-        $this->_current_screen = get_current_screen();
668
-        // load admin_notices - global, page class, and view specific
669
-        add_action('admin_notices', array($this, 'admin_notices_global'), 5);
670
-        add_action('admin_notices', array($this, 'admin_notices'), 10);
671
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
672
-            add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
673
-        }
674
-        // load network admin_notices - global, page class, and view specific
675
-        add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
676
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
677
-            add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
678
-        }
679
-        // this will save any per_page screen options if they are present
680
-        $this->_set_per_page_screen_options();
681
-        // setup list table properties
682
-        $this->_set_list_table();
683
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
684
-        // However in some cases the metaboxes will need to be added within a route handling callback.
685
-        $this->_add_registered_meta_boxes();
686
-        $this->_add_screen_columns();
687
-        // add screen options - global, page child class, and view specific
688
-        $this->_add_global_screen_options();
689
-        $this->_add_screen_options();
690
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
691
-        if (method_exists($this, $add_screen_options)) {
692
-            $this->{$add_screen_options}();
693
-        }
694
-        // add help tab(s) and tours- set via page_config and qtips.
695
-        $this->_add_help_tour();
696
-        $this->_add_help_tabs();
697
-        $this->_add_qtips();
698
-        // add feature_pointers - global, page child class, and view specific
699
-        $this->_add_feature_pointers();
700
-        $this->_add_global_feature_pointers();
701
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
702
-        if (method_exists($this, $add_feature_pointer)) {
703
-            $this->{$add_feature_pointer}();
704
-        }
705
-        // enqueue scripts/styles - global, page class, and view specific
706
-        add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
707
-        add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
708
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
709
-            add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
710
-        }
711
-        add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
712
-        // admin_print_footer_scripts - global, page child class, and view specific.
713
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
714
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
715
-        // is a good use case. Notice the late priority we're giving these
716
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
717
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
718
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
719
-            add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
720
-        }
721
-        // admin footer scripts
722
-        add_action('admin_footer', array($this, 'admin_footer_global'), 99);
723
-        add_action('admin_footer', array($this, 'admin_footer'), 100);
724
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
725
-            add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
726
-        }
727
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
728
-        // targeted hook
729
-        do_action(
730
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
731
-        );
732
-    }
733
-
734
-
735
-    /**
736
-     * _set_defaults
737
-     * This sets some global defaults for class properties.
738
-     */
739
-    private function _set_defaults()
740
-    {
741
-        $this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
742
-        $this->_event = $this->_template_path = $this->_column_template_path = null;
743
-        $this->_nav_tabs = $this->_views = $this->_page_routes = array();
744
-        $this->_page_config = $this->_default_route_query_args = array();
745
-        $this->_default_nav_tab_name = 'overview';
746
-        // init template args
747
-        $this->_template_args = array(
748
-            'admin_page_header'  => '',
749
-            'admin_page_content' => '',
750
-            'post_body_content'  => '',
751
-            'before_list_table'  => '',
752
-            'after_list_table'   => '',
753
-        );
754
-    }
755
-
756
-
757
-    /**
758
-     * route_admin_request
759
-     *
760
-     * @see    _route_admin_request()
761
-     * @return exception|void error
762
-     * @throws InvalidArgumentException
763
-     * @throws InvalidInterfaceException
764
-     * @throws InvalidDataTypeException
765
-     * @throws EE_Error
766
-     * @throws ReflectionException
767
-     */
768
-    public function route_admin_request()
769
-    {
770
-        try {
771
-            $this->_route_admin_request();
772
-        } catch (EE_Error $e) {
773
-            $e->get_error();
774
-        }
775
-    }
776
-
777
-
778
-    public function set_wp_page_slug($wp_page_slug)
779
-    {
780
-        $this->_wp_page_slug = $wp_page_slug;
781
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
782
-        if (is_network_admin()) {
783
-            $this->_wp_page_slug .= '-network';
784
-        }
785
-    }
786
-
787
-
788
-    /**
789
-     * _verify_routes
790
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
791
-     * we know if we need to drop out.
792
-     *
793
-     * @return bool
794
-     * @throws EE_Error
795
-     */
796
-    protected function _verify_routes()
797
-    {
798
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
799
-        if (! $this->_current_page && ! defined('DOING_AJAX')) {
800
-            return false;
801
-        }
802
-        $this->_route = false;
803
-        // check that the page_routes array is not empty
804
-        if (empty($this->_page_routes)) {
805
-            // user error msg
806
-            $error_msg = sprintf(
807
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
808
-                $this->_admin_page_title
809
-            );
810
-            // developer error msg
811
-            $error_msg .= '||' . $error_msg
812
-                          . esc_html__(
813
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
814
-                              'event_espresso'
815
-                          );
816
-            throw new EE_Error($error_msg);
817
-        }
818
-        // and that the requested page route exists
819
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
820
-            $this->_route = $this->_page_routes[ $this->_req_action ];
821
-            $this->_route_config = isset($this->_page_config[ $this->_req_action ])
822
-                ? $this->_page_config[ $this->_req_action ] : array();
823
-        } else {
824
-            // user error msg
825
-            $error_msg = sprintf(
826
-                esc_html__(
827
-                    'The requested page route does not exist for the %s admin page.',
828
-                    'event_espresso'
829
-                ),
830
-                $this->_admin_page_title
831
-            );
832
-            // developer error msg
833
-            $error_msg .= '||' . $error_msg
834
-                          . sprintf(
835
-                              esc_html__(
836
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
837
-                                  'event_espresso'
838
-                              ),
839
-                              $this->_req_action
840
-                          );
841
-            throw new EE_Error($error_msg);
842
-        }
843
-        // and that a default route exists
844
-        if (! array_key_exists('default', $this->_page_routes)) {
845
-            // user error msg
846
-            $error_msg = sprintf(
847
-                esc_html__(
848
-                    'A default page route has not been set for the % admin page.',
849
-                    'event_espresso'
850
-                ),
851
-                $this->_admin_page_title
852
-            );
853
-            // developer error msg
854
-            $error_msg .= '||' . $error_msg
855
-                          . esc_html__(
856
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
857
-                              'event_espresso'
858
-                          );
859
-            throw new EE_Error($error_msg);
860
-        }
861
-        // first lets' catch if the UI request has EVER been set.
862
-        if ($this->_is_UI_request === null) {
863
-            // lets set if this is a UI request or not.
864
-            $this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
865
-            // wait a minute... we might have a noheader in the route array
866
-            $this->_is_UI_request = is_array($this->_route)
867
-                                    && isset($this->_route['noheader'])
868
-                                    && $this->_route['noheader'] ? false : $this->_is_UI_request;
869
-        }
870
-        $this->_set_current_labels();
871
-        return true;
872
-    }
873
-
874
-
875
-    /**
876
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
877
-     *
878
-     * @param  string $route the route name we're verifying
879
-     * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
880
-     * @throws EE_Error
881
-     */
882
-    protected function _verify_route($route)
883
-    {
884
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
885
-            return true;
886
-        }
887
-        // user error msg
888
-        $error_msg = sprintf(
889
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
890
-            $this->_admin_page_title
891
-        );
892
-        // developer error msg
893
-        $error_msg .= '||' . $error_msg
894
-                      . sprintf(
895
-                          esc_html__(
896
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
897
-                              'event_espresso'
898
-                          ),
899
-                          $route
900
-                      );
901
-        throw new EE_Error($error_msg);
902
-    }
903
-
904
-
905
-    /**
906
-     * perform nonce verification
907
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
908
-     * using this method (and save retyping!)
909
-     *
910
-     * @param  string $nonce     The nonce sent
911
-     * @param  string $nonce_ref The nonce reference string (name0)
912
-     * @return void
913
-     * @throws EE_Error
914
-     */
915
-    protected function _verify_nonce($nonce, $nonce_ref)
916
-    {
917
-        // verify nonce against expected value
918
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
919
-            // these are not the droids you are looking for !!!
920
-            $msg = sprintf(
921
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
922
-                '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
923
-                '</a>'
924
-            );
925
-            if (WP_DEBUG) {
926
-                $msg .= "\n  "
927
-                        . sprintf(
928
-                            esc_html__(
929
-                                'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
930
-                                'event_espresso'
931
-                            ),
932
-                            __CLASS__
933
-                        );
934
-            }
935
-            if (! defined('DOING_AJAX')) {
936
-                wp_die($msg);
937
-            } else {
938
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
939
-                $this->_return_json();
940
-            }
941
-        }
942
-    }
943
-
944
-
945
-    /**
946
-     * _route_admin_request()
947
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
948
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
949
-     * in the page routes and then will try to load the corresponding method.
950
-     *
951
-     * @return void
952
-     * @throws EE_Error
953
-     * @throws InvalidArgumentException
954
-     * @throws InvalidDataTypeException
955
-     * @throws InvalidInterfaceException
956
-     * @throws ReflectionException
957
-     */
958
-    protected function _route_admin_request()
959
-    {
960
-        if (! $this->_is_UI_request) {
961
-            $this->_verify_routes();
962
-        }
963
-        $nonce_check = isset($this->_route_config['require_nonce'])
964
-            ? $this->_route_config['require_nonce']
965
-            : true;
966
-        if ($this->_req_action !== 'default' && $nonce_check) {
967
-            // set nonce from post data
968
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
969
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ])
970
-                : '';
971
-            $this->_verify_nonce($nonce, $this->_req_nonce);
972
-        }
973
-        // set the nav_tabs array but ONLY if this is  UI_request
974
-        if ($this->_is_UI_request) {
975
-            $this->_set_nav_tabs();
976
-        }
977
-        // grab callback function
978
-        $func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
979
-        // check if callback has args
980
-        $args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
981
-        $error_msg = '';
982
-        // action right before calling route
983
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
984
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
985
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
986
-        }
987
-        // right before calling the route, let's remove _wp_http_referer from the
988
-        // $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
989
-        $_SERVER['REQUEST_URI'] = remove_query_arg(
990
-            '_wp_http_referer',
991
-            wp_unslash($_SERVER['REQUEST_URI'])
992
-        );
993
-        if (! empty($func)) {
994
-            if (is_array($func)) {
995
-                list($class, $method) = $func;
996
-            } elseif (strpos($func, '::') !== false) {
997
-                list($class, $method) = explode('::', $func);
998
-            } else {
999
-                $class = $this;
1000
-                $method = $func;
1001
-            }
1002
-            if (! (is_object($class) && $class === $this)) {
1003
-                // send along this admin page object for access by addons.
1004
-                $args['admin_page_object'] = $this;
1005
-            }
1006
-            if (// is it a method on a class that doesn't work?
1007
-                (
1008
-                    (
1009
-                        method_exists($class, $method)
1010
-                        && call_user_func_array(array($class, $method), $args) === false
1011
-                    )
1012
-                    && (
1013
-                        // is it a standalone function that doesn't work?
1014
-                        function_exists($method)
1015
-                        && call_user_func_array(
1016
-                            $func,
1017
-                            array_merge(array('admin_page_object' => $this), $args)
1018
-                        ) === false
1019
-                    )
1020
-                )
1021
-                || (
1022
-                    // is it neither a class method NOR a standalone function?
1023
-                    ! method_exists($class, $method)
1024
-                    && ! function_exists($method)
1025
-                )
1026
-            ) {
1027
-                // user error msg
1028
-                $error_msg = esc_html__(
1029
-                    'An error occurred. The  requested page route could not be found.',
1030
-                    'event_espresso'
1031
-                );
1032
-                // developer error msg
1033
-                $error_msg .= '||';
1034
-                $error_msg .= sprintf(
1035
-                    esc_html__(
1036
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1037
-                        'event_espresso'
1038
-                    ),
1039
-                    $method
1040
-                );
1041
-            }
1042
-            if (! empty($error_msg)) {
1043
-                throw new EE_Error($error_msg);
1044
-            }
1045
-        }
1046
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1047
-        // then we need to reset the routing properties to the new route.
1048
-        // now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1049
-        if ($this->_is_UI_request === false
1050
-            && is_array($this->_route)
1051
-            && ! empty($this->_route['headers_sent_route'])
1052
-        ) {
1053
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1054
-        }
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * This method just allows the resetting of page properties in the case where a no headers
1060
-     * route redirects to a headers route in its route config.
1061
-     *
1062
-     * @since   4.3.0
1063
-     * @param  string $new_route New (non header) route to redirect to.
1064
-     * @return   void
1065
-     * @throws ReflectionException
1066
-     * @throws InvalidArgumentException
1067
-     * @throws InvalidInterfaceException
1068
-     * @throws InvalidDataTypeException
1069
-     * @throws EE_Error
1070
-     */
1071
-    protected function _reset_routing_properties($new_route)
1072
-    {
1073
-        $this->_is_UI_request = true;
1074
-        // now we set the current route to whatever the headers_sent_route is set at
1075
-        $this->_req_data['action'] = $new_route;
1076
-        // rerun page setup
1077
-        $this->_page_setup();
1078
-    }
1079
-
1080
-
1081
-    /**
1082
-     * _add_query_arg
1083
-     * adds nonce to array of arguments then calls WP add_query_arg function
1084
-     *(internally just uses EEH_URL's function with the same name)
1085
-     *
1086
-     * @param array  $args
1087
-     * @param string $url
1088
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1089
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1090
-     *                                        Example usage: If the current page is:
1091
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1092
-     *                                        &action=default&event_id=20&month_range=March%202015
1093
-     *                                        &_wpnonce=5467821
1094
-     *                                        and you call:
1095
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1096
-     *                                        array(
1097
-     *                                        'action' => 'resend_something',
1098
-     *                                        'page=>espresso_registrations'
1099
-     *                                        ),
1100
-     *                                        $some_url,
1101
-     *                                        true
1102
-     *                                        );
1103
-     *                                        It will produce a url in this structure:
1104
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1105
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1106
-     *                                        month_range]=March%202015
1107
-     * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1108
-     * @return string
1109
-     */
1110
-    public static function add_query_args_and_nonce(
1111
-        $args = array(),
1112
-        $url = false,
1113
-        $sticky = false,
1114
-        $exclude_nonce = false
1115
-    ) {
1116
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1117
-        if ($sticky) {
1118
-            $request = $_REQUEST;
1119
-            unset($request['_wp_http_referer']);
1120
-            unset($request['wp_referer']);
1121
-            foreach ($request as $key => $value) {
1122
-                // do not add nonces
1123
-                if (strpos($key, 'nonce') !== false) {
1124
-                    continue;
1125
-                }
1126
-                $args[ 'wp_referer[' . $key . ']' ] = $value;
1127
-            }
1128
-        }
1129
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     * This returns a generated link that will load the related help tab.
1135
-     *
1136
-     * @param  string $help_tab_id the id for the connected help tab
1137
-     * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1138
-     * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1139
-     * @uses EEH_Template::get_help_tab_link()
1140
-     * @return string              generated link
1141
-     */
1142
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1143
-    {
1144
-        return EEH_Template::get_help_tab_link(
1145
-            $help_tab_id,
1146
-            $this->page_slug,
1147
-            $this->_req_action,
1148
-            $icon_style,
1149
-            $help_text
1150
-        );
1151
-    }
1152
-
1153
-
1154
-    /**
1155
-     * _add_help_tabs
1156
-     * Note child classes define their help tabs within the page_config array.
1157
-     *
1158
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1159
-     * @return void
1160
-     * @throws DomainException
1161
-     * @throws EE_Error
1162
-     */
1163
-    protected function _add_help_tabs()
1164
-    {
1165
-        $tour_buttons = '';
1166
-        if (isset($this->_page_config[ $this->_req_action ])) {
1167
-            $config = $this->_page_config[ $this->_req_action ];
1168
-            // is there a help tour for the current route?  if there is let's setup the tour buttons
1169
-            if (isset($this->_help_tour[ $this->_req_action ])) {
1170
-                $tb = array();
1171
-                $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1172
-                foreach ($this->_help_tour['tours'] as $tour) {
1173
-                    // if this is the end tour then we don't need to setup a button
1174
-                    if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1175
-                        continue;
1176
-                    }
1177
-                    $tb[] = '<button id="trigger-tour-'
1178
-                            . $tour->get_slug()
1179
-                            . '" class="button-primary trigger-ee-help-tour">'
1180
-                            . $tour->get_label()
1181
-                            . '</button>';
1182
-                }
1183
-                $tour_buttons .= implode('<br />', $tb);
1184
-                $tour_buttons .= '</div></div>';
1185
-            }
1186
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1187
-            if (is_array($config) && isset($config['help_sidebar'])) {
1188
-                // check that the callback given is valid
1189
-                if (! method_exists($this, $config['help_sidebar'])) {
1190
-                    throw new EE_Error(
1191
-                        sprintf(
1192
-                            esc_html__(
1193
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1194
-                                'event_espresso'
1195
-                            ),
1196
-                            $config['help_sidebar'],
1197
-                            get_class($this)
1198
-                        )
1199
-                    );
1200
-                }
1201
-                $content = apply_filters(
1202
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1203
-                    $this->{$config['help_sidebar']}()
1204
-                );
1205
-                $content .= $tour_buttons; // add help tour buttons.
1206
-                // do we have any help tours setup?  Cause if we do we want to add the buttons
1207
-                $this->_current_screen->set_help_sidebar($content);
1208
-            }
1209
-            // if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1210
-            if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1211
-                $this->_current_screen->set_help_sidebar($tour_buttons);
1212
-            }
1213
-            // handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1214
-            if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1215
-                $_ht['id'] = $this->page_slug;
1216
-                $_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1217
-                $_ht['content'] = '<p>'
1218
-                                  . esc_html__(
1219
-                                      'The buttons to the right allow you to start/restart any help tours available for this page',
1220
-                                      'event_espresso'
1221
-                                  ) . '</p>';
1222
-                $this->_current_screen->add_help_tab($_ht);
1223
-            }
1224
-            if (! isset($config['help_tabs'])) {
1225
-                return;
1226
-            } //no help tabs for this route
1227
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1228
-                // we're here so there ARE help tabs!
1229
-                // make sure we've got what we need
1230
-                if (! isset($cfg['title'])) {
1231
-                    throw new EE_Error(
1232
-                        esc_html__(
1233
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1234
-                            'event_espresso'
1235
-                        )
1236
-                    );
1237
-                }
1238
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1239
-                    throw new EE_Error(
1240
-                        esc_html__(
1241
-                            'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1242
-                            'event_espresso'
1243
-                        )
1244
-                    );
1245
-                }
1246
-                // first priority goes to content.
1247
-                if (! empty($cfg['content'])) {
1248
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1249
-                    // second priority goes to filename
1250
-                } elseif (! empty($cfg['filename'])) {
1251
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1252
-                    // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1253
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1254
-                                                             . basename($this->_get_dir())
1255
-                                                             . '/help_tabs/'
1256
-                                                             . $cfg['filename']
1257
-                                                             . '.help_tab.php' : $file_path;
1258
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1259
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1260
-                        EE_Error::add_error(
1261
-                            sprintf(
1262
-                                esc_html__(
1263
-                                    'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1264
-                                    'event_espresso'
1265
-                                ),
1266
-                                $tab_id,
1267
-                                key($config),
1268
-                                $file_path
1269
-                            ),
1270
-                            __FILE__,
1271
-                            __FUNCTION__,
1272
-                            __LINE__
1273
-                        );
1274
-                        return;
1275
-                    }
1276
-                    $template_args['admin_page_obj'] = $this;
1277
-                    $content = EEH_Template::display_template(
1278
-                        $file_path,
1279
-                        $template_args,
1280
-                        true
1281
-                    );
1282
-                } else {
1283
-                    $content = '';
1284
-                }
1285
-                // check if callback is valid
1286
-                if (empty($content) && (
1287
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1288
-                    )
1289
-                ) {
1290
-                    EE_Error::add_error(
1291
-                        sprintf(
1292
-                            esc_html__(
1293
-                                'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1294
-                                'event_espresso'
1295
-                            ),
1296
-                            $cfg['title']
1297
-                        ),
1298
-                        __FILE__,
1299
-                        __FUNCTION__,
1300
-                        __LINE__
1301
-                    );
1302
-                    return;
1303
-                }
1304
-                // setup config array for help tab method
1305
-                $id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1306
-                $_ht = array(
1307
-                    'id'       => $id,
1308
-                    'title'    => $cfg['title'],
1309
-                    'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1310
-                    'content'  => $content,
1311
-                );
1312
-                $this->_current_screen->add_help_tab($_ht);
1313
-            }
1314
-        }
1315
-    }
1316
-
1317
-
1318
-    /**
1319
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1320
-     * an array with properties for setting up usage of the joyride plugin
1321
-     *
1322
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1323
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1324
-     *         _set_page_config() comments
1325
-     * @return void
1326
-     * @throws EE_Error
1327
-     * @throws InvalidArgumentException
1328
-     * @throws InvalidDataTypeException
1329
-     * @throws InvalidInterfaceException
1330
-     */
1331
-    protected function _add_help_tour()
1332
-    {
1333
-        $tours = array();
1334
-        $this->_help_tour = array();
1335
-        // exit early if help tours are turned off globally
1336
-        if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1337
-            || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1338
-        ) {
1339
-            return;
1340
-        }
1341
-        // loop through _page_config to find any help_tour defined
1342
-        foreach ($this->_page_config as $route => $config) {
1343
-            // we're only going to set things up for this route
1344
-            if ($route !== $this->_req_action) {
1345
-                continue;
1346
-            }
1347
-            if (isset($config['help_tour'])) {
1348
-                foreach ($config['help_tour'] as $tour) {
1349
-                    $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1350
-                    // let's see if we can get that file...
1351
-                    // if not its possible this is a decaf route not set in caffeinated
1352
-                    // so lets try and get the caffeinated equivalent
1353
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1354
-                                                             . basename($this->_get_dir())
1355
-                                                             . '/help_tours/'
1356
-                                                             . $tour
1357
-                                                             . '.class.php' : $file_path;
1358
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1359
-                    if (! is_readable($file_path)) {
1360
-                        EE_Error::add_error(
1361
-                            sprintf(
1362
-                                esc_html__(
1363
-                                    'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1364
-                                    'event_espresso'
1365
-                                ),
1366
-                                $file_path,
1367
-                                $tour
1368
-                            ),
1369
-                            __FILE__,
1370
-                            __FUNCTION__,
1371
-                            __LINE__
1372
-                        );
1373
-                        return;
1374
-                    }
1375
-                    require_once $file_path;
1376
-                    if (! class_exists($tour)) {
1377
-                        $error_msg[] = sprintf(
1378
-                            esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1379
-                            $tour
1380
-                        );
1381
-                        $error_msg[] = $error_msg[0] . "\r\n"
1382
-                                       . sprintf(
1383
-                                           esc_html__(
1384
-                                               'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1385
-                                               'event_espresso'
1386
-                                           ),
1387
-                                           $tour,
1388
-                                           '<br />',
1389
-                                           $tour,
1390
-                                           $this->_req_action,
1391
-                                           get_class($this)
1392
-                                       );
1393
-                        throw new EE_Error(implode('||', $error_msg));
1394
-                    }
1395
-                    $tour_obj = new $tour($this->_is_caf);
1396
-                    $tours[] = $tour_obj;
1397
-                    $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1398
-                }
1399
-                // let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1400
-                $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1401
-                $tours[] = $end_stop_tour;
1402
-                $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1403
-            }
1404
-        }
1405
-        if (! empty($tours)) {
1406
-            $this->_help_tour['tours'] = $tours;
1407
-        }
1408
-        // that's it!  Now that the $_help_tours property is set (or not)
1409
-        // the scripts and html should be taken care of automatically.
1410
-    }
1411
-
1412
-
1413
-    /**
1414
-     * This simply sets up any qtips that have been defined in the page config
1415
-     *
1416
-     * @return void
1417
-     */
1418
-    protected function _add_qtips()
1419
-    {
1420
-        if (isset($this->_route_config['qtips'])) {
1421
-            $qtips = (array) $this->_route_config['qtips'];
1422
-            // load qtip loader
1423
-            $path = array(
1424
-                $this->_get_dir() . '/qtips/',
1425
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1426
-            );
1427
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1428
-        }
1429
-    }
1430
-
1431
-
1432
-    /**
1433
-     * _set_nav_tabs
1434
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1435
-     * wish to add additional tabs or modify accordingly.
1436
-     *
1437
-     * @return void
1438
-     * @throws InvalidArgumentException
1439
-     * @throws InvalidInterfaceException
1440
-     * @throws InvalidDataTypeException
1441
-     */
1442
-    protected function _set_nav_tabs()
1443
-    {
1444
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1445
-        $i = 0;
1446
-        foreach ($this->_page_config as $slug => $config) {
1447
-            if (! is_array($config)
1448
-                || (
1449
-                    is_array($config)
1450
-                    && (
1451
-                        (isset($config['nav']) && ! $config['nav'])
1452
-                        || ! isset($config['nav'])
1453
-                    )
1454
-                )
1455
-            ) {
1456
-                continue;
1457
-            }
1458
-            // no nav tab for this config
1459
-            // check for persistent flag
1460
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1461
-                // nav tab is only to appear when route requested.
1462
-                continue;
1463
-            }
1464
-            if (! $this->check_user_access($slug, true)) {
1465
-                // no nav tab because current user does not have access.
1466
-                continue;
1467
-            }
1468
-            $css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1469
-            $this->_nav_tabs[ $slug ] = array(
1470
-                'url'       => isset($config['nav']['url'])
1471
-                    ? $config['nav']['url']
1472
-                    : self::add_query_args_and_nonce(
1473
-                        array('action' => $slug),
1474
-                        $this->_admin_base_url
1475
-                    ),
1476
-                'link_text' => isset($config['nav']['label'])
1477
-                    ? $config['nav']['label']
1478
-                    : ucwords(
1479
-                        str_replace('_', ' ', $slug)
1480
-                    ),
1481
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1482
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1483
-            );
1484
-            $i++;
1485
-        }
1486
-        // if $this->_nav_tabs is empty then lets set the default
1487
-        if (empty($this->_nav_tabs)) {
1488
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = array(
1489
-                'url'       => $this->_admin_base_url,
1490
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1491
-                'css_class' => 'nav-tab-active',
1492
-                'order'     => 10,
1493
-            );
1494
-        }
1495
-        // now let's sort the tabs according to order
1496
-        usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1497
-    }
1498
-
1499
-
1500
-    /**
1501
-     * _set_current_labels
1502
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1503
-     * property array
1504
-     *
1505
-     * @return void
1506
-     */
1507
-    private function _set_current_labels()
1508
-    {
1509
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1510
-            foreach ($this->_route_config['labels'] as $label => $text) {
1511
-                if (is_array($text)) {
1512
-                    foreach ($text as $sublabel => $subtext) {
1513
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1514
-                    }
1515
-                } else {
1516
-                    $this->_labels[ $label ] = $text;
1517
-                }
1518
-            }
1519
-        }
1520
-    }
1521
-
1522
-
1523
-    /**
1524
-     *        verifies user access for this admin page
1525
-     *
1526
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1527
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1528
-     *                               return false if verify fail.
1529
-     * @return bool
1530
-     * @throws InvalidArgumentException
1531
-     * @throws InvalidDataTypeException
1532
-     * @throws InvalidInterfaceException
1533
-     */
1534
-    public function check_user_access($route_to_check = '', $verify_only = false)
1535
-    {
1536
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1537
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1538
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1539
-                      && is_array(
1540
-                          $this->_page_routes[ $route_to_check ]
1541
-                      )
1542
-                      && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1543
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1544
-        if (empty($capability) && empty($route_to_check)) {
1545
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1546
-                : $this->_route['capability'];
1547
-        } else {
1548
-            $capability = empty($capability) ? 'manage_options' : $capability;
1549
-        }
1550
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1551
-        if (! defined('DOING_AJAX')
1552
-            && (
1553
-                ! function_exists('is_admin')
1554
-                || ! EE_Registry::instance()->CAP->current_user_can(
1555
-                    $capability,
1556
-                    $this->page_slug
1557
-                    . '_'
1558
-                    . $route_to_check,
1559
-                    $id
1560
-                )
1561
-            )
1562
-        ) {
1563
-            if ($verify_only) {
1564
-                return false;
1565
-            }
1566
-            if (is_user_logged_in()) {
1567
-                wp_die(__('You do not have access to this route.', 'event_espresso'));
1568
-            } else {
1569
-                return false;
1570
-            }
1571
-        }
1572
-        return true;
1573
-    }
1574
-
1575
-
1576
-    /**
1577
-     * admin_init_global
1578
-     * This runs all the code that we want executed within the WP admin_init hook.
1579
-     * This method executes for ALL EE Admin pages.
1580
-     *
1581
-     * @return void
1582
-     */
1583
-    public function admin_init_global()
1584
-    {
1585
-    }
1586
-
1587
-
1588
-    /**
1589
-     * wp_loaded_global
1590
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1591
-     * EE_Admin page and will execute on every EE Admin Page load
1592
-     *
1593
-     * @return void
1594
-     */
1595
-    public function wp_loaded()
1596
-    {
1597
-    }
1598
-
1599
-
1600
-    /**
1601
-     * admin_notices
1602
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1603
-     * ALL EE_Admin pages.
1604
-     *
1605
-     * @return void
1606
-     */
1607
-    public function admin_notices_global()
1608
-    {
1609
-        $this->_display_no_javascript_warning();
1610
-        $this->_display_espresso_notices();
1611
-    }
1612
-
1613
-
1614
-    public function network_admin_notices_global()
1615
-    {
1616
-        $this->_display_no_javascript_warning();
1617
-        $this->_display_espresso_notices();
1618
-    }
1619
-
1620
-
1621
-    /**
1622
-     * admin_footer_scripts_global
1623
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1624
-     * will apply on ALL EE_Admin pages.
1625
-     *
1626
-     * @return void
1627
-     */
1628
-    public function admin_footer_scripts_global()
1629
-    {
1630
-        $this->_add_admin_page_ajax_loading_img();
1631
-        $this->_add_admin_page_overlay();
1632
-        // if metaboxes are present we need to add the nonce field
1633
-        if (isset($this->_route_config['metaboxes'])
1634
-            || isset($this->_route_config['list_table'])
1635
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1636
-        ) {
1637
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1638
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1639
-        }
1640
-    }
1641
-
1642
-
1643
-    /**
1644
-     * admin_footer_global
1645
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1646
-     * ALL EE_Admin Pages.
1647
-     *
1648
-     * @return void
1649
-     * @throws EE_Error
1650
-     */
1651
-    public function admin_footer_global()
1652
-    {
1653
-        // dialog container for dialog helper
1654
-        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1655
-        $d_cont .= '<div class="ee-notices"></div>';
1656
-        $d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1657
-        $d_cont .= '</div>';
1658
-        echo $d_cont;
1659
-        // help tour stuff?
1660
-        if (isset($this->_help_tour[ $this->_req_action ])) {
1661
-            echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1662
-        }
1663
-        // current set timezone for timezone js
1664
-        echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1665
-    }
1666
-
1667
-
1668
-    /**
1669
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1670
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1671
-     * help popups then in your templates or your content you set "triggers" for the content using the
1672
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1673
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1674
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1675
-     * for the
1676
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1677
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1678
-     *    'help_trigger_id' => array(
1679
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1680
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1681
-     *    )
1682
-     * );
1683
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1684
-     *
1685
-     * @param array $help_array
1686
-     * @param bool  $display
1687
-     * @return string content
1688
-     * @throws DomainException
1689
-     * @throws EE_Error
1690
-     */
1691
-    protected function _set_help_popup_content($help_array = array(), $display = false)
1692
-    {
1693
-        $content = '';
1694
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1695
-        // loop through the array and setup content
1696
-        foreach ($help_array as $trigger => $help) {
1697
-            // make sure the array is setup properly
1698
-            if (! isset($help['title']) || ! isset($help['content'])) {
1699
-                throw new EE_Error(
1700
-                    esc_html__(
1701
-                        'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1702
-                        'event_espresso'
1703
-                    )
1704
-                );
1705
-            }
1706
-            // we're good so let'd setup the template vars and then assign parsed template content to our content.
1707
-            $template_args = array(
1708
-                'help_popup_id'      => $trigger,
1709
-                'help_popup_title'   => $help['title'],
1710
-                'help_popup_content' => $help['content'],
1711
-            );
1712
-            $content .= EEH_Template::display_template(
1713
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1714
-                $template_args,
1715
-                true
1716
-            );
1717
-        }
1718
-        if ($display) {
1719
-            echo $content;
1720
-            return '';
1721
-        }
1722
-        return $content;
1723
-    }
1724
-
1725
-
1726
-    /**
1727
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1728
-     *
1729
-     * @return array properly formatted array for help popup content
1730
-     * @throws EE_Error
1731
-     */
1732
-    private function _get_help_content()
1733
-    {
1734
-        // what is the method we're looking for?
1735
-        $method_name = '_help_popup_content_' . $this->_req_action;
1736
-        // if method doesn't exist let's get out.
1737
-        if (! method_exists($this, $method_name)) {
1738
-            return array();
1739
-        }
1740
-        // k we're good to go let's retrieve the help array
1741
-        $help_array = call_user_func(array($this, $method_name));
1742
-        // make sure we've got an array!
1743
-        if (! is_array($help_array)) {
1744
-            throw new EE_Error(
1745
-                esc_html__(
1746
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1747
-                    'event_espresso'
1748
-                )
1749
-            );
1750
-        }
1751
-        return $help_array;
1752
-    }
1753
-
1754
-
1755
-    /**
1756
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1757
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1758
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1759
-     *
1760
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1761
-     * @param boolean $display    if false then we return the trigger string
1762
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1763
-     * @return string
1764
-     * @throws DomainException
1765
-     * @throws EE_Error
1766
-     */
1767
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1768
-    {
1769
-        if (defined('DOING_AJAX')) {
1770
-            return '';
1771
-        }
1772
-        // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1773
-        $help_array = $this->_get_help_content();
1774
-        $help_content = '';
1775
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1776
-            $help_array[ $trigger_id ] = array(
1777
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1778
-                'content' => esc_html__(
1779
-                    'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1780
-                    'event_espresso'
1781
-                ),
1782
-            );
1783
-            $help_content = $this->_set_help_popup_content($help_array, false);
1784
-        }
1785
-        // let's setup the trigger
1786
-        $content = '<a class="ee-dialog" href="?height='
1787
-                   . $dimensions[0]
1788
-                   . '&width='
1789
-                   . $dimensions[1]
1790
-                   . '&inlineId='
1791
-                   . $trigger_id
1792
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1793
-        $content .= $help_content;
1794
-        if ($display) {
1795
-            echo $content;
1796
-            return '';
1797
-        }
1798
-        return $content;
1799
-    }
1800
-
1801
-
1802
-    /**
1803
-     * _add_global_screen_options
1804
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1805
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1806
-     *
1807
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1808
-     *         see also WP_Screen object documents...
1809
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1810
-     * @abstract
1811
-     * @return void
1812
-     */
1813
-    private function _add_global_screen_options()
1814
-    {
1815
-    }
1816
-
1817
-
1818
-    /**
1819
-     * _add_global_feature_pointers
1820
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1821
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1822
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1823
-     *
1824
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1825
-     *         extended) also see:
1826
-     * @link   http://eamann.com/tech/wordpress-portland/
1827
-     * @abstract
1828
-     * @return void
1829
-     */
1830
-    private function _add_global_feature_pointers()
1831
-    {
1832
-    }
1833
-
1834
-
1835
-    /**
1836
-     * load_global_scripts_styles
1837
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1838
-     *
1839
-     * @return void
1840
-     * @throws EE_Error
1841
-     */
1842
-    public function load_global_scripts_styles()
1843
-    {
1844
-        /** STYLES **/
1845
-        // add debugging styles
1846
-        if (WP_DEBUG) {
1847
-            add_action('admin_head', array($this, 'add_xdebug_style'));
1848
-        }
1849
-        // register all styles
1850
-        wp_register_style(
1851
-            'espresso-ui-theme',
1852
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1853
-            array(),
1854
-            EVENT_ESPRESSO_VERSION
1855
-        );
1856
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1857
-        // helpers styles
1858
-        wp_register_style(
1859
-            'ee-text-links',
1860
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1861
-            array(),
1862
-            EVENT_ESPRESSO_VERSION
1863
-        );
1864
-        /** SCRIPTS **/
1865
-        // register all scripts
1866
-        wp_register_script(
1867
-            'ee-dialog',
1868
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1869
-            array('jquery', 'jquery-ui-draggable'),
1870
-            EVENT_ESPRESSO_VERSION,
1871
-            true
1872
-        );
1873
-        wp_register_script(
1874
-            'ee_admin_js',
1875
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1876
-            array('espresso_core', 'ee-parse-uri', 'ee-dialog'),
1877
-            EVENT_ESPRESSO_VERSION,
1878
-            true
1879
-        );
1880
-        wp_register_script(
1881
-            'jquery-ui-timepicker-addon',
1882
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1883
-            array('jquery-ui-datepicker', 'jquery-ui-slider'),
1884
-            EVENT_ESPRESSO_VERSION,
1885
-            true
1886
-        );
1887
-        add_filter('FHEE_load_joyride', '__return_true');
1888
-        // script for sorting tables
1889
-        wp_register_script(
1890
-            'espresso_ajax_table_sorting',
1891
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1892
-            array('ee_admin_js', 'jquery-ui-sortable'),
1893
-            EVENT_ESPRESSO_VERSION,
1894
-            true
1895
-        );
1896
-        // script for parsing uri's
1897
-        wp_register_script(
1898
-            'ee-parse-uri',
1899
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1900
-            array(),
1901
-            EVENT_ESPRESSO_VERSION,
1902
-            true
1903
-        );
1904
-        // and parsing associative serialized form elements
1905
-        wp_register_script(
1906
-            'ee-serialize-full-array',
1907
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1908
-            array('jquery'),
1909
-            EVENT_ESPRESSO_VERSION,
1910
-            true
1911
-        );
1912
-        // helpers scripts
1913
-        wp_register_script(
1914
-            'ee-text-links',
1915
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1916
-            array('jquery'),
1917
-            EVENT_ESPRESSO_VERSION,
1918
-            true
1919
-        );
1920
-        wp_register_script(
1921
-            'ee-moment-core',
1922
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1923
-            array(),
1924
-            EVENT_ESPRESSO_VERSION,
1925
-            true
1926
-        );
1927
-        wp_register_script(
1928
-            'ee-moment',
1929
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1930
-            array('ee-moment-core'),
1931
-            EVENT_ESPRESSO_VERSION,
1932
-            true
1933
-        );
1934
-        wp_register_script(
1935
-            'ee-datepicker',
1936
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1937
-            array('jquery-ui-timepicker-addon', 'ee-moment'),
1938
-            EVENT_ESPRESSO_VERSION,
1939
-            true
1940
-        );
1941
-        // google charts
1942
-        wp_register_script(
1943
-            'google-charts',
1944
-            'https://www.gstatic.com/charts/loader.js',
1945
-            array(),
1946
-            EVENT_ESPRESSO_VERSION,
1947
-            false
1948
-        );
1949
-        // ENQUEUE ALL BASICS BY DEFAULT
1950
-        wp_enqueue_style('ee-admin-css');
1951
-        wp_enqueue_script('ee_admin_js');
1952
-        wp_enqueue_script('ee-accounting');
1953
-        wp_enqueue_script('jquery-validate');
1954
-        // taking care of metaboxes
1955
-        if (empty($this->_cpt_route)
1956
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1957
-        ) {
1958
-            wp_enqueue_script('dashboard');
1959
-        }
1960
-        // LOCALIZED DATA
1961
-        // localize script for ajax lazy loading
1962
-        $lazy_loader_container_ids = apply_filters(
1963
-            'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1964
-            array('espresso_news_post_box_content')
1965
-        );
1966
-        wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1967
-        /**
1968
-         * help tour stuff
1969
-         */
1970
-        if (! empty($this->_help_tour)) {
1971
-            // register the js for kicking things off
1972
-            wp_enqueue_script(
1973
-                'ee-help-tour',
1974
-                EE_ADMIN_URL . 'assets/ee-help-tour.js',
1975
-                array('jquery-joyride'),
1976
-                EVENT_ESPRESSO_VERSION,
1977
-                true
1978
-            );
1979
-            $tours = array();
1980
-            // setup tours for the js tour object
1981
-            foreach ($this->_help_tour['tours'] as $tour) {
1982
-                if ($tour instanceof EE_Help_Tour) {
1983
-                    $tours[] = array(
1984
-                        'id'      => $tour->get_slug(),
1985
-                        'options' => $tour->get_options(),
1986
-                    );
1987
-                }
1988
-            }
1989
-            wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
1990
-            // admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1991
-        }
1992
-    }
1993
-
1994
-
1995
-    /**
1996
-     *        admin_footer_scripts_eei18n_js_strings
1997
-     *
1998
-     * @return        void
1999
-     */
2000
-    public function admin_footer_scripts_eei18n_js_strings()
2001
-    {
2002
-        EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
2003
-        EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
2004
-            'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2005
-            'event_espresso'
2006
-        );
2007
-        EE_Registry::$i18n_js_strings['January'] = esc_html__('January', 'event_espresso');
2008
-        EE_Registry::$i18n_js_strings['February'] = esc_html__('February', 'event_espresso');
2009
-        EE_Registry::$i18n_js_strings['March'] = esc_html__('March', 'event_espresso');
2010
-        EE_Registry::$i18n_js_strings['April'] = esc_html__('April', 'event_espresso');
2011
-        EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
2012
-        EE_Registry::$i18n_js_strings['June'] = esc_html__('June', 'event_espresso');
2013
-        EE_Registry::$i18n_js_strings['July'] = esc_html__('July', 'event_espresso');
2014
-        EE_Registry::$i18n_js_strings['August'] = esc_html__('August', 'event_espresso');
2015
-        EE_Registry::$i18n_js_strings['September'] = esc_html__('September', 'event_espresso');
2016
-        EE_Registry::$i18n_js_strings['October'] = esc_html__('October', 'event_espresso');
2017
-        EE_Registry::$i18n_js_strings['November'] = esc_html__('November', 'event_espresso');
2018
-        EE_Registry::$i18n_js_strings['December'] = esc_html__('December', 'event_espresso');
2019
-        EE_Registry::$i18n_js_strings['Jan'] = esc_html__('Jan', 'event_espresso');
2020
-        EE_Registry::$i18n_js_strings['Feb'] = esc_html__('Feb', 'event_espresso');
2021
-        EE_Registry::$i18n_js_strings['Mar'] = esc_html__('Mar', 'event_espresso');
2022
-        EE_Registry::$i18n_js_strings['Apr'] = esc_html__('Apr', 'event_espresso');
2023
-        EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
2024
-        EE_Registry::$i18n_js_strings['Jun'] = esc_html__('Jun', 'event_espresso');
2025
-        EE_Registry::$i18n_js_strings['Jul'] = esc_html__('Jul', 'event_espresso');
2026
-        EE_Registry::$i18n_js_strings['Aug'] = esc_html__('Aug', 'event_espresso');
2027
-        EE_Registry::$i18n_js_strings['Sep'] = esc_html__('Sep', 'event_espresso');
2028
-        EE_Registry::$i18n_js_strings['Oct'] = esc_html__('Oct', 'event_espresso');
2029
-        EE_Registry::$i18n_js_strings['Nov'] = esc_html__('Nov', 'event_espresso');
2030
-        EE_Registry::$i18n_js_strings['Dec'] = esc_html__('Dec', 'event_espresso');
2031
-        EE_Registry::$i18n_js_strings['Sunday'] = esc_html__('Sunday', 'event_espresso');
2032
-        EE_Registry::$i18n_js_strings['Monday'] = esc_html__('Monday', 'event_espresso');
2033
-        EE_Registry::$i18n_js_strings['Tuesday'] = esc_html__('Tuesday', 'event_espresso');
2034
-        EE_Registry::$i18n_js_strings['Wednesday'] = esc_html__('Wednesday', 'event_espresso');
2035
-        EE_Registry::$i18n_js_strings['Thursday'] = esc_html__('Thursday', 'event_espresso');
2036
-        EE_Registry::$i18n_js_strings['Friday'] = esc_html__('Friday', 'event_espresso');
2037
-        EE_Registry::$i18n_js_strings['Saturday'] = esc_html__('Saturday', 'event_espresso');
2038
-        EE_Registry::$i18n_js_strings['Sun'] = esc_html__('Sun', 'event_espresso');
2039
-        EE_Registry::$i18n_js_strings['Mon'] = esc_html__('Mon', 'event_espresso');
2040
-        EE_Registry::$i18n_js_strings['Tue'] = esc_html__('Tue', 'event_espresso');
2041
-        EE_Registry::$i18n_js_strings['Wed'] = esc_html__('Wed', 'event_espresso');
2042
-        EE_Registry::$i18n_js_strings['Thu'] = esc_html__('Thu', 'event_espresso');
2043
-        EE_Registry::$i18n_js_strings['Fri'] = esc_html__('Fri', 'event_espresso');
2044
-        EE_Registry::$i18n_js_strings['Sat'] = esc_html__('Sat', 'event_espresso');
2045
-    }
2046
-
2047
-
2048
-    /**
2049
-     *        load enhanced xdebug styles for ppl with failing eyesight
2050
-     *
2051
-     * @return        void
2052
-     */
2053
-    public function add_xdebug_style()
2054
-    {
2055
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2056
-    }
2057
-
2058
-
2059
-    /************************/
2060
-    /** LIST TABLE METHODS **/
2061
-    /************************/
2062
-    /**
2063
-     * this sets up the list table if the current view requires it.
2064
-     *
2065
-     * @return void
2066
-     * @throws EE_Error
2067
-     */
2068
-    protected function _set_list_table()
2069
-    {
2070
-        // first is this a list_table view?
2071
-        if (! isset($this->_route_config['list_table'])) {
2072
-            return;
2073
-        } //not a list_table view so get out.
2074
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2075
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2076
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2077
-            // user error msg
2078
-            $error_msg = esc_html__(
2079
-                'An error occurred. The requested list table views could not be found.',
2080
-                'event_espresso'
2081
-            );
2082
-            // developer error msg
2083
-            $error_msg .= '||'
2084
-                          . sprintf(
2085
-                              esc_html__(
2086
-                                  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2087
-                                  'event_espresso'
2088
-                              ),
2089
-                              $this->_req_action,
2090
-                              $list_table_view
2091
-                          );
2092
-            throw new EE_Error($error_msg);
2093
-        }
2094
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2095
-        $this->_views = apply_filters(
2096
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2097
-            $this->_views
2098
-        );
2099
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2100
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2101
-        $this->_set_list_table_view();
2102
-        $this->_set_list_table_object();
2103
-    }
2104
-
2105
-
2106
-    /**
2107
-     * set current view for List Table
2108
-     *
2109
-     * @return void
2110
-     */
2111
-    protected function _set_list_table_view()
2112
-    {
2113
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2114
-        // looking at active items or dumpster diving ?
2115
-        if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2116
-            $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2117
-        } else {
2118
-            $this->_view = sanitize_key($this->_req_data['status']);
2119
-        }
2120
-    }
2121
-
2122
-
2123
-    /**
2124
-     * _set_list_table_object
2125
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2126
-     *
2127
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2128
-     * @throws \InvalidArgumentException
2129
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2130
-     * @throws EE_Error
2131
-     * @throws InvalidInterfaceException
2132
-     */
2133
-    protected function _set_list_table_object()
2134
-    {
2135
-        if (isset($this->_route_config['list_table'])) {
2136
-            if (! class_exists($this->_route_config['list_table'])) {
2137
-                throw new EE_Error(
2138
-                    sprintf(
2139
-                        esc_html__(
2140
-                            'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2141
-                            'event_espresso'
2142
-                        ),
2143
-                        $this->_route_config['list_table'],
2144
-                        get_class($this)
2145
-                    )
2146
-                );
2147
-            }
2148
-            $this->_list_table_object = $this->loader->getShared(
2149
-                $this->_route_config['list_table'],
2150
-                array($this)
2151
-            );
2152
-        }
2153
-    }
2154
-
2155
-
2156
-    /**
2157
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2158
-     *
2159
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2160
-     *                                                    urls.  The array should be indexed by the view it is being
2161
-     *                                                    added to.
2162
-     * @return array
2163
-     */
2164
-    public function get_list_table_view_RLs($extra_query_args = array())
2165
-    {
2166
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2167
-        if (empty($this->_views)) {
2168
-            $this->_views = array();
2169
-        }
2170
-        // cycle thru views
2171
-        foreach ($this->_views as $key => $view) {
2172
-            $query_args = array();
2173
-            // check for current view
2174
-            $this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2175
-            $query_args['action'] = $this->_req_action;
2176
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2177
-            $query_args['status'] = $view['slug'];
2178
-            // merge any other arguments sent in.
2179
-            if (isset($extra_query_args[ $view['slug'] ])) {
2180
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2181
-            }
2182
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2183
-        }
2184
-        return $this->_views;
2185
-    }
2186
-
2187
-
2188
-    /**
2189
-     * _entries_per_page_dropdown
2190
-     * generates a drop down box for selecting the number of visible rows in an admin page list table
2191
-     *
2192
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2193
-     *         WP does it.
2194
-     * @param int $max_entries total number of rows in the table
2195
-     * @return string
2196
-     */
2197
-    protected function _entries_per_page_dropdown($max_entries = 0)
2198
-    {
2199
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2200
-        $values = array(10, 25, 50, 100);
2201
-        $per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2202
-        if ($max_entries) {
2203
-            $values[] = $max_entries;
2204
-            sort($values);
2205
-        }
2206
-        $entries_per_page_dropdown = '
104
+	/**
105
+	 * @var array $_route_config
106
+	 */
107
+	protected $_route_config;
108
+
109
+	/**
110
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
111
+	 * actions.
112
+	 *
113
+	 * @since 4.6.x
114
+	 * @var array.
115
+	 */
116
+	protected $_default_route_query_args;
117
+
118
+	// set via request page and action args.
119
+	protected $_current_page;
120
+
121
+	protected $_current_view;
122
+
123
+	protected $_current_page_view_url;
124
+
125
+	// sanitized request action (and nonce)
126
+
127
+	/**
128
+	 * @var string $_req_action
129
+	 */
130
+	protected $_req_action;
131
+
132
+	/**
133
+	 * @var string $_req_nonce
134
+	 */
135
+	protected $_req_nonce;
136
+
137
+	// search related
138
+	protected $_search_btn_label;
139
+
140
+	protected $_search_box_callback;
141
+
142
+	/**
143
+	 * WP Current Screen object
144
+	 *
145
+	 * @var WP_Screen
146
+	 */
147
+	protected $_current_screen;
148
+
149
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
150
+	protected $_hook_obj;
151
+
152
+	// for holding incoming request data
153
+	protected $_req_data;
154
+
155
+	// yes / no array for admin form fields
156
+	protected $_yes_no_values = array();
157
+
158
+	// some default things shared by all child classes
159
+	protected $_default_espresso_metaboxes;
160
+
161
+	/**
162
+	 *    EE_Registry Object
163
+	 *
164
+	 * @var    EE_Registry
165
+	 */
166
+	protected $EE = null;
167
+
168
+
169
+	/**
170
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
171
+	 *
172
+	 * @var boolean
173
+	 */
174
+	protected $_is_caf = false;
175
+
176
+
177
+	/**
178
+	 * @Constructor
179
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
180
+	 * @throws EE_Error
181
+	 * @throws InvalidArgumentException
182
+	 * @throws ReflectionException
183
+	 * @throws InvalidDataTypeException
184
+	 * @throws InvalidInterfaceException
185
+	 */
186
+	public function __construct($routing = true)
187
+	{
188
+		$this->loader = LoaderFactory::getLoader();
189
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
190
+			$this->_is_caf = true;
191
+		}
192
+		$this->_yes_no_values = array(
193
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
194
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
195
+		);
196
+		// set the _req_data property.
197
+		$this->_req_data = array_merge($_GET, $_POST);
198
+		// routing enabled?
199
+		$this->_routing = $routing;
200
+		// set initial page props (child method)
201
+		$this->_init_page_props();
202
+		// set global defaults
203
+		$this->_set_defaults();
204
+		// set early because incoming requests could be ajax related and we need to register those hooks.
205
+		$this->_global_ajax_hooks();
206
+		$this->_ajax_hooks();
207
+		// other_page_hooks have to be early too.
208
+		$this->_do_other_page_hooks();
209
+		// This just allows us to have extending classes do something specific
210
+		// before the parent constructor runs _page_setup().
211
+		if (method_exists($this, '_before_page_setup')) {
212
+			$this->_before_page_setup();
213
+		}
214
+		// set up page dependencies
215
+		$this->_page_setup();
216
+	}
217
+
218
+
219
+	/**
220
+	 * _init_page_props
221
+	 * Child classes use to set at least the following properties:
222
+	 * $page_slug.
223
+	 * $page_label.
224
+	 *
225
+	 * @abstract
226
+	 * @return void
227
+	 */
228
+	abstract protected function _init_page_props();
229
+
230
+
231
+	/**
232
+	 * _ajax_hooks
233
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
234
+	 * Note: within the ajax callback methods.
235
+	 *
236
+	 * @abstract
237
+	 * @return void
238
+	 */
239
+	abstract protected function _ajax_hooks();
240
+
241
+
242
+	/**
243
+	 * _define_page_props
244
+	 * child classes define page properties in here.  Must include at least:
245
+	 * $_admin_base_url = base_url for all admin pages
246
+	 * $_admin_page_title = default admin_page_title for admin pages
247
+	 * $_labels = array of default labels for various automatically generated elements:
248
+	 *    array(
249
+	 *        'buttons' => array(
250
+	 *            'add' => esc_html__('label for add new button'),
251
+	 *            'edit' => esc_html__('label for edit button'),
252
+	 *            'delete' => esc_html__('label for delete button')
253
+	 *            )
254
+	 *        )
255
+	 *
256
+	 * @abstract
257
+	 * @return void
258
+	 */
259
+	abstract protected function _define_page_props();
260
+
261
+
262
+	/**
263
+	 * _set_page_routes
264
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
265
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
266
+	 * have a 'default' route. Here's the format
267
+	 * $this->_page_routes = array(
268
+	 *        'default' => array(
269
+	 *            'func' => '_default_method_handling_route',
270
+	 *            'args' => array('array','of','args'),
271
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
272
+	 *            ajax request, backend processing)
273
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
274
+	 *            headers route after.  The string you enter here should match the defined route reference for a
275
+	 *            headers sent route.
276
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
277
+	 *            this route.
278
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
279
+	 *            checks).
280
+	 *        ),
281
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
282
+	 *        handling method.
283
+	 *        )
284
+	 * )
285
+	 *
286
+	 * @abstract
287
+	 * @return void
288
+	 */
289
+	abstract protected function _set_page_routes();
290
+
291
+
292
+	/**
293
+	 * _set_page_config
294
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
295
+	 * array corresponds to the page_route for the loaded page. Format:
296
+	 * $this->_page_config = array(
297
+	 *        'default' => array(
298
+	 *            'labels' => array(
299
+	 *                'buttons' => array(
300
+	 *                    'add' => esc_html__('label for adding item'),
301
+	 *                    'edit' => esc_html__('label for editing item'),
302
+	 *                    'delete' => esc_html__('label for deleting item')
303
+	 *                ),
304
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
305
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
306
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
307
+	 *            _define_page_props() method
308
+	 *            'nav' => array(
309
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
310
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
311
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
312
+	 *                'order' => 10, //required to indicate tab position.
313
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
314
+	 *                displayed then add this parameter.
315
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
316
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
317
+	 *            metaboxes set for eventespresso admin pages.
318
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
319
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
320
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
321
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
322
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
323
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
324
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
325
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
326
+	 *            want to display.
327
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
328
+	 *                'tab_id' => array(
329
+	 *                    'title' => 'tab_title',
330
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
331
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
332
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
333
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
334
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
335
+	 *                    attempt to use the callback which should match the name of a method in the class
336
+	 *                    ),
337
+	 *                'tab2_id' => array(
338
+	 *                    'title' => 'tab2 title',
339
+	 *                    'filename' => 'file_name_2'
340
+	 *                    'callback' => 'callback_method_for_content',
341
+	 *                 ),
342
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
343
+	 *            help tab area on an admin page. @link
344
+	 *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
345
+	 *            'help_tour' => array(
346
+	 *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
347
+	 *                in a folder for this admin page named "help_tours", a file name matching the key given here
348
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
349
+	 *            ),
350
+	 *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
351
+	 *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
352
+	 *            just set
353
+	 *            'require_nonce' to FALSE
354
+	 *            )
355
+	 * )
356
+	 *
357
+	 * @abstract
358
+	 * @return void
359
+	 */
360
+	abstract protected function _set_page_config();
361
+
362
+
363
+
364
+
365
+
366
+	/** end sample help_tour methods **/
367
+	/**
368
+	 * _add_screen_options
369
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
370
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
371
+	 * to a particular view.
372
+	 *
373
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
374
+	 *         see also WP_Screen object documents...
375
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
376
+	 * @abstract
377
+	 * @return void
378
+	 */
379
+	abstract protected function _add_screen_options();
380
+
381
+
382
+	/**
383
+	 * _add_feature_pointers
384
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
385
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
386
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
387
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
388
+	 * extended) also see:
389
+	 *
390
+	 * @link   http://eamann.com/tech/wordpress-portland/
391
+	 * @abstract
392
+	 * @return void
393
+	 */
394
+	abstract protected function _add_feature_pointers();
395
+
396
+
397
+	/**
398
+	 * load_scripts_styles
399
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
400
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
401
+	 * scripts/styles per view by putting them in a dynamic function in this format
402
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
403
+	 *
404
+	 * @abstract
405
+	 * @return void
406
+	 */
407
+	abstract public function load_scripts_styles();
408
+
409
+
410
+	/**
411
+	 * admin_init
412
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
413
+	 * all pages/views loaded by child class.
414
+	 *
415
+	 * @abstract
416
+	 * @return void
417
+	 */
418
+	abstract public function admin_init();
419
+
420
+
421
+	/**
422
+	 * admin_notices
423
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
424
+	 * all pages/views loaded by child class.
425
+	 *
426
+	 * @abstract
427
+	 * @return void
428
+	 */
429
+	abstract public function admin_notices();
430
+
431
+
432
+	/**
433
+	 * admin_footer_scripts
434
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
435
+	 * will apply to all pages/views loaded by child class.
436
+	 *
437
+	 * @return void
438
+	 */
439
+	abstract public function admin_footer_scripts();
440
+
441
+
442
+	/**
443
+	 * admin_footer
444
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
445
+	 * apply to all pages/views loaded by child class.
446
+	 *
447
+	 * @return void
448
+	 */
449
+	public function admin_footer()
450
+	{
451
+	}
452
+
453
+
454
+	/**
455
+	 * _global_ajax_hooks
456
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
457
+	 * Note: within the ajax callback methods.
458
+	 *
459
+	 * @abstract
460
+	 * @return void
461
+	 */
462
+	protected function _global_ajax_hooks()
463
+	{
464
+		// for lazy loading of metabox content
465
+		add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
466
+	}
467
+
468
+
469
+	public function ajax_metabox_content()
470
+	{
471
+		$contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
472
+		$url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
473
+		self::cached_rss_display($contentid, $url);
474
+		wp_die();
475
+	}
476
+
477
+
478
+	/**
479
+	 * _page_setup
480
+	 * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
481
+	 * doesn't match the object.
482
+	 *
483
+	 * @final
484
+	 * @return void
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws ReflectionException
488
+	 * @throws InvalidDataTypeException
489
+	 * @throws InvalidInterfaceException
490
+	 */
491
+	final protected function _page_setup()
492
+	{
493
+		// requires?
494
+		// admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
495
+		add_action('admin_init', array($this, 'admin_init_global'), 5);
496
+		// next verify if we need to load anything...
497
+		$this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
498
+		$this->page_folder = strtolower(
499
+			str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
500
+		);
501
+		global $ee_menu_slugs;
502
+		$ee_menu_slugs = (array) $ee_menu_slugs;
503
+		if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))) {
504
+			return;
505
+		}
506
+		// becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
507
+		if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
508
+			$this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
509
+				? $this->_req_data['action2']
510
+				: $this->_req_data['action'];
511
+		}
512
+		// then set blank or -1 action values to 'default'
513
+		$this->_req_action = isset($this->_req_data['action'])
514
+							 && ! empty($this->_req_data['action'])
515
+							 && $this->_req_data['action'] !== '-1'
516
+			? sanitize_key($this->_req_data['action'])
517
+			: 'default';
518
+		// if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
519
+		//  This covers cases where we're coming in from a list table that isn't on the default route.
520
+		$this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
521
+			? $this->_req_data['route'] : $this->_req_action;
522
+		// however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
523
+		$this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route'])
524
+			? $this->_req_data['route']
525
+			: $this->_req_action;
526
+		$this->_current_view = $this->_req_action;
527
+		$this->_req_nonce = $this->_req_action . '_nonce';
528
+		$this->_define_page_props();
529
+		$this->_current_page_view_url = add_query_arg(
530
+			array('page' => $this->_current_page, 'action' => $this->_current_view),
531
+			$this->_admin_base_url
532
+		);
533
+		// default things
534
+		$this->_default_espresso_metaboxes = array(
535
+			'_espresso_news_post_box',
536
+			'_espresso_links_post_box',
537
+			'_espresso_ratings_request',
538
+			'_espresso_sponsors_post_box',
539
+		);
540
+		// set page configs
541
+		$this->_set_page_routes();
542
+		$this->_set_page_config();
543
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
544
+		if (isset($this->_req_data['wp_referer'])) {
545
+			$this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
546
+		}
547
+		// for caffeinated and other extended functionality.
548
+		//  If there is a _extend_page_config method
549
+		// then let's run that to modify the all the various page configuration arrays
550
+		if (method_exists($this, '_extend_page_config')) {
551
+			$this->_extend_page_config();
552
+		}
553
+		// for CPT and other extended functionality.
554
+		// If there is an _extend_page_config_for_cpt
555
+		// then let's run that to modify all the various page configuration arrays.
556
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
557
+			$this->_extend_page_config_for_cpt();
558
+		}
559
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
560
+		$this->_page_routes = apply_filters(
561
+			'FHEE__' . get_class($this) . '__page_setup__page_routes',
562
+			$this->_page_routes,
563
+			$this
564
+		);
565
+		$this->_page_config = apply_filters(
566
+			'FHEE__' . get_class($this) . '__page_setup__page_config',
567
+			$this->_page_config,
568
+			$this
569
+		);
570
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
571
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
572
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
573
+			add_action(
574
+				'AHEE__EE_Admin_Page__route_admin_request',
575
+				array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
576
+				10,
577
+				2
578
+			);
579
+		}
580
+		// next route only if routing enabled
581
+		if ($this->_routing && ! defined('DOING_AJAX')) {
582
+			$this->_verify_routes();
583
+			// next let's just check user_access and kill if no access
584
+			$this->check_user_access();
585
+			if ($this->_is_UI_request) {
586
+				// admin_init stuff - global, all views for this page class, specific view
587
+				add_action('admin_init', array($this, 'admin_init'), 10);
588
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
589
+					add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
590
+				}
591
+			} else {
592
+				// hijack regular WP loading and route admin request immediately
593
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
594
+				$this->route_admin_request();
595
+			}
596
+		}
597
+	}
598
+
599
+
600
+	/**
601
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
602
+	 *
603
+	 * @return void
604
+	 * @throws ReflectionException
605
+	 * @throws EE_Error
606
+	 */
607
+	private function _do_other_page_hooks()
608
+	{
609
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
610
+		foreach ($registered_pages as $page) {
611
+			// now let's setup the file name and class that should be present
612
+			$classname = str_replace('.class.php', '', $page);
613
+			// autoloaders should take care of loading file
614
+			if (! class_exists($classname)) {
615
+				$error_msg[] = sprintf(
616
+					esc_html__(
617
+						'Something went wrong with loading the %s admin hooks page.',
618
+						'event_espresso'
619
+					),
620
+					$page
621
+				);
622
+				$error_msg[] = $error_msg[0]
623
+							   . "\r\n"
624
+							   . sprintf(
625
+								   esc_html__(
626
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
627
+									   'event_espresso'
628
+								   ),
629
+								   $page,
630
+								   '<br />',
631
+								   '<strong>' . $classname . '</strong>'
632
+							   );
633
+				throw new EE_Error(implode('||', $error_msg));
634
+			}
635
+			$a = new ReflectionClass($classname);
636
+			// notice we are passing the instance of this class to the hook object.
637
+			$hookobj[] = $a->newInstance($this);
638
+		}
639
+	}
640
+
641
+
642
+	public function load_page_dependencies()
643
+	{
644
+		try {
645
+			$this->_load_page_dependencies();
646
+		} catch (EE_Error $e) {
647
+			$e->get_error();
648
+		}
649
+	}
650
+
651
+
652
+	/**
653
+	 * load_page_dependencies
654
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
655
+	 *
656
+	 * @return void
657
+	 * @throws DomainException
658
+	 * @throws EE_Error
659
+	 * @throws InvalidArgumentException
660
+	 * @throws InvalidDataTypeException
661
+	 * @throws InvalidInterfaceException
662
+	 * @throws ReflectionException
663
+	 */
664
+	protected function _load_page_dependencies()
665
+	{
666
+		// let's set the current_screen and screen options to override what WP set
667
+		$this->_current_screen = get_current_screen();
668
+		// load admin_notices - global, page class, and view specific
669
+		add_action('admin_notices', array($this, 'admin_notices_global'), 5);
670
+		add_action('admin_notices', array($this, 'admin_notices'), 10);
671
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
672
+			add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
673
+		}
674
+		// load network admin_notices - global, page class, and view specific
675
+		add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
676
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
677
+			add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
678
+		}
679
+		// this will save any per_page screen options if they are present
680
+		$this->_set_per_page_screen_options();
681
+		// setup list table properties
682
+		$this->_set_list_table();
683
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
684
+		// However in some cases the metaboxes will need to be added within a route handling callback.
685
+		$this->_add_registered_meta_boxes();
686
+		$this->_add_screen_columns();
687
+		// add screen options - global, page child class, and view specific
688
+		$this->_add_global_screen_options();
689
+		$this->_add_screen_options();
690
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
691
+		if (method_exists($this, $add_screen_options)) {
692
+			$this->{$add_screen_options}();
693
+		}
694
+		// add help tab(s) and tours- set via page_config and qtips.
695
+		$this->_add_help_tour();
696
+		$this->_add_help_tabs();
697
+		$this->_add_qtips();
698
+		// add feature_pointers - global, page child class, and view specific
699
+		$this->_add_feature_pointers();
700
+		$this->_add_global_feature_pointers();
701
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
702
+		if (method_exists($this, $add_feature_pointer)) {
703
+			$this->{$add_feature_pointer}();
704
+		}
705
+		// enqueue scripts/styles - global, page class, and view specific
706
+		add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
707
+		add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
708
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
709
+			add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
710
+		}
711
+		add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
712
+		// admin_print_footer_scripts - global, page child class, and view specific.
713
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
714
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
715
+		// is a good use case. Notice the late priority we're giving these
716
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
717
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
718
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
719
+			add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
720
+		}
721
+		// admin footer scripts
722
+		add_action('admin_footer', array($this, 'admin_footer_global'), 99);
723
+		add_action('admin_footer', array($this, 'admin_footer'), 100);
724
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
725
+			add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
726
+		}
727
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
728
+		// targeted hook
729
+		do_action(
730
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
731
+		);
732
+	}
733
+
734
+
735
+	/**
736
+	 * _set_defaults
737
+	 * This sets some global defaults for class properties.
738
+	 */
739
+	private function _set_defaults()
740
+	{
741
+		$this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
742
+		$this->_event = $this->_template_path = $this->_column_template_path = null;
743
+		$this->_nav_tabs = $this->_views = $this->_page_routes = array();
744
+		$this->_page_config = $this->_default_route_query_args = array();
745
+		$this->_default_nav_tab_name = 'overview';
746
+		// init template args
747
+		$this->_template_args = array(
748
+			'admin_page_header'  => '',
749
+			'admin_page_content' => '',
750
+			'post_body_content'  => '',
751
+			'before_list_table'  => '',
752
+			'after_list_table'   => '',
753
+		);
754
+	}
755
+
756
+
757
+	/**
758
+	 * route_admin_request
759
+	 *
760
+	 * @see    _route_admin_request()
761
+	 * @return exception|void error
762
+	 * @throws InvalidArgumentException
763
+	 * @throws InvalidInterfaceException
764
+	 * @throws InvalidDataTypeException
765
+	 * @throws EE_Error
766
+	 * @throws ReflectionException
767
+	 */
768
+	public function route_admin_request()
769
+	{
770
+		try {
771
+			$this->_route_admin_request();
772
+		} catch (EE_Error $e) {
773
+			$e->get_error();
774
+		}
775
+	}
776
+
777
+
778
+	public function set_wp_page_slug($wp_page_slug)
779
+	{
780
+		$this->_wp_page_slug = $wp_page_slug;
781
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
782
+		if (is_network_admin()) {
783
+			$this->_wp_page_slug .= '-network';
784
+		}
785
+	}
786
+
787
+
788
+	/**
789
+	 * _verify_routes
790
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
791
+	 * we know if we need to drop out.
792
+	 *
793
+	 * @return bool
794
+	 * @throws EE_Error
795
+	 */
796
+	protected function _verify_routes()
797
+	{
798
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
799
+		if (! $this->_current_page && ! defined('DOING_AJAX')) {
800
+			return false;
801
+		}
802
+		$this->_route = false;
803
+		// check that the page_routes array is not empty
804
+		if (empty($this->_page_routes)) {
805
+			// user error msg
806
+			$error_msg = sprintf(
807
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
808
+				$this->_admin_page_title
809
+			);
810
+			// developer error msg
811
+			$error_msg .= '||' . $error_msg
812
+						  . esc_html__(
813
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
814
+							  'event_espresso'
815
+						  );
816
+			throw new EE_Error($error_msg);
817
+		}
818
+		// and that the requested page route exists
819
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
820
+			$this->_route = $this->_page_routes[ $this->_req_action ];
821
+			$this->_route_config = isset($this->_page_config[ $this->_req_action ])
822
+				? $this->_page_config[ $this->_req_action ] : array();
823
+		} else {
824
+			// user error msg
825
+			$error_msg = sprintf(
826
+				esc_html__(
827
+					'The requested page route does not exist for the %s admin page.',
828
+					'event_espresso'
829
+				),
830
+				$this->_admin_page_title
831
+			);
832
+			// developer error msg
833
+			$error_msg .= '||' . $error_msg
834
+						  . sprintf(
835
+							  esc_html__(
836
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
837
+								  'event_espresso'
838
+							  ),
839
+							  $this->_req_action
840
+						  );
841
+			throw new EE_Error($error_msg);
842
+		}
843
+		// and that a default route exists
844
+		if (! array_key_exists('default', $this->_page_routes)) {
845
+			// user error msg
846
+			$error_msg = sprintf(
847
+				esc_html__(
848
+					'A default page route has not been set for the % admin page.',
849
+					'event_espresso'
850
+				),
851
+				$this->_admin_page_title
852
+			);
853
+			// developer error msg
854
+			$error_msg .= '||' . $error_msg
855
+						  . esc_html__(
856
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
857
+							  'event_espresso'
858
+						  );
859
+			throw new EE_Error($error_msg);
860
+		}
861
+		// first lets' catch if the UI request has EVER been set.
862
+		if ($this->_is_UI_request === null) {
863
+			// lets set if this is a UI request or not.
864
+			$this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
865
+			// wait a minute... we might have a noheader in the route array
866
+			$this->_is_UI_request = is_array($this->_route)
867
+									&& isset($this->_route['noheader'])
868
+									&& $this->_route['noheader'] ? false : $this->_is_UI_request;
869
+		}
870
+		$this->_set_current_labels();
871
+		return true;
872
+	}
873
+
874
+
875
+	/**
876
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
877
+	 *
878
+	 * @param  string $route the route name we're verifying
879
+	 * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
880
+	 * @throws EE_Error
881
+	 */
882
+	protected function _verify_route($route)
883
+	{
884
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
885
+			return true;
886
+		}
887
+		// user error msg
888
+		$error_msg = sprintf(
889
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
890
+			$this->_admin_page_title
891
+		);
892
+		// developer error msg
893
+		$error_msg .= '||' . $error_msg
894
+					  . sprintf(
895
+						  esc_html__(
896
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
897
+							  'event_espresso'
898
+						  ),
899
+						  $route
900
+					  );
901
+		throw new EE_Error($error_msg);
902
+	}
903
+
904
+
905
+	/**
906
+	 * perform nonce verification
907
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
908
+	 * using this method (and save retyping!)
909
+	 *
910
+	 * @param  string $nonce     The nonce sent
911
+	 * @param  string $nonce_ref The nonce reference string (name0)
912
+	 * @return void
913
+	 * @throws EE_Error
914
+	 */
915
+	protected function _verify_nonce($nonce, $nonce_ref)
916
+	{
917
+		// verify nonce against expected value
918
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
919
+			// these are not the droids you are looking for !!!
920
+			$msg = sprintf(
921
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
922
+				'<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
923
+				'</a>'
924
+			);
925
+			if (WP_DEBUG) {
926
+				$msg .= "\n  "
927
+						. sprintf(
928
+							esc_html__(
929
+								'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
930
+								'event_espresso'
931
+							),
932
+							__CLASS__
933
+						);
934
+			}
935
+			if (! defined('DOING_AJAX')) {
936
+				wp_die($msg);
937
+			} else {
938
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
939
+				$this->_return_json();
940
+			}
941
+		}
942
+	}
943
+
944
+
945
+	/**
946
+	 * _route_admin_request()
947
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
948
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
949
+	 * in the page routes and then will try to load the corresponding method.
950
+	 *
951
+	 * @return void
952
+	 * @throws EE_Error
953
+	 * @throws InvalidArgumentException
954
+	 * @throws InvalidDataTypeException
955
+	 * @throws InvalidInterfaceException
956
+	 * @throws ReflectionException
957
+	 */
958
+	protected function _route_admin_request()
959
+	{
960
+		if (! $this->_is_UI_request) {
961
+			$this->_verify_routes();
962
+		}
963
+		$nonce_check = isset($this->_route_config['require_nonce'])
964
+			? $this->_route_config['require_nonce']
965
+			: true;
966
+		if ($this->_req_action !== 'default' && $nonce_check) {
967
+			// set nonce from post data
968
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
969
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ])
970
+				: '';
971
+			$this->_verify_nonce($nonce, $this->_req_nonce);
972
+		}
973
+		// set the nav_tabs array but ONLY if this is  UI_request
974
+		if ($this->_is_UI_request) {
975
+			$this->_set_nav_tabs();
976
+		}
977
+		// grab callback function
978
+		$func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
979
+		// check if callback has args
980
+		$args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
981
+		$error_msg = '';
982
+		// action right before calling route
983
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
984
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
985
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
986
+		}
987
+		// right before calling the route, let's remove _wp_http_referer from the
988
+		// $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
989
+		$_SERVER['REQUEST_URI'] = remove_query_arg(
990
+			'_wp_http_referer',
991
+			wp_unslash($_SERVER['REQUEST_URI'])
992
+		);
993
+		if (! empty($func)) {
994
+			if (is_array($func)) {
995
+				list($class, $method) = $func;
996
+			} elseif (strpos($func, '::') !== false) {
997
+				list($class, $method) = explode('::', $func);
998
+			} else {
999
+				$class = $this;
1000
+				$method = $func;
1001
+			}
1002
+			if (! (is_object($class) && $class === $this)) {
1003
+				// send along this admin page object for access by addons.
1004
+				$args['admin_page_object'] = $this;
1005
+			}
1006
+			if (// is it a method on a class that doesn't work?
1007
+				(
1008
+					(
1009
+						method_exists($class, $method)
1010
+						&& call_user_func_array(array($class, $method), $args) === false
1011
+					)
1012
+					&& (
1013
+						// is it a standalone function that doesn't work?
1014
+						function_exists($method)
1015
+						&& call_user_func_array(
1016
+							$func,
1017
+							array_merge(array('admin_page_object' => $this), $args)
1018
+						) === false
1019
+					)
1020
+				)
1021
+				|| (
1022
+					// is it neither a class method NOR a standalone function?
1023
+					! method_exists($class, $method)
1024
+					&& ! function_exists($method)
1025
+				)
1026
+			) {
1027
+				// user error msg
1028
+				$error_msg = esc_html__(
1029
+					'An error occurred. The  requested page route could not be found.',
1030
+					'event_espresso'
1031
+				);
1032
+				// developer error msg
1033
+				$error_msg .= '||';
1034
+				$error_msg .= sprintf(
1035
+					esc_html__(
1036
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1037
+						'event_espresso'
1038
+					),
1039
+					$method
1040
+				);
1041
+			}
1042
+			if (! empty($error_msg)) {
1043
+				throw new EE_Error($error_msg);
1044
+			}
1045
+		}
1046
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1047
+		// then we need to reset the routing properties to the new route.
1048
+		// now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1049
+		if ($this->_is_UI_request === false
1050
+			&& is_array($this->_route)
1051
+			&& ! empty($this->_route['headers_sent_route'])
1052
+		) {
1053
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1054
+		}
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * This method just allows the resetting of page properties in the case where a no headers
1060
+	 * route redirects to a headers route in its route config.
1061
+	 *
1062
+	 * @since   4.3.0
1063
+	 * @param  string $new_route New (non header) route to redirect to.
1064
+	 * @return   void
1065
+	 * @throws ReflectionException
1066
+	 * @throws InvalidArgumentException
1067
+	 * @throws InvalidInterfaceException
1068
+	 * @throws InvalidDataTypeException
1069
+	 * @throws EE_Error
1070
+	 */
1071
+	protected function _reset_routing_properties($new_route)
1072
+	{
1073
+		$this->_is_UI_request = true;
1074
+		// now we set the current route to whatever the headers_sent_route is set at
1075
+		$this->_req_data['action'] = $new_route;
1076
+		// rerun page setup
1077
+		$this->_page_setup();
1078
+	}
1079
+
1080
+
1081
+	/**
1082
+	 * _add_query_arg
1083
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1084
+	 *(internally just uses EEH_URL's function with the same name)
1085
+	 *
1086
+	 * @param array  $args
1087
+	 * @param string $url
1088
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1089
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1090
+	 *                                        Example usage: If the current page is:
1091
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1092
+	 *                                        &action=default&event_id=20&month_range=March%202015
1093
+	 *                                        &_wpnonce=5467821
1094
+	 *                                        and you call:
1095
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1096
+	 *                                        array(
1097
+	 *                                        'action' => 'resend_something',
1098
+	 *                                        'page=>espresso_registrations'
1099
+	 *                                        ),
1100
+	 *                                        $some_url,
1101
+	 *                                        true
1102
+	 *                                        );
1103
+	 *                                        It will produce a url in this structure:
1104
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1105
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1106
+	 *                                        month_range]=March%202015
1107
+	 * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1108
+	 * @return string
1109
+	 */
1110
+	public static function add_query_args_and_nonce(
1111
+		$args = array(),
1112
+		$url = false,
1113
+		$sticky = false,
1114
+		$exclude_nonce = false
1115
+	) {
1116
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1117
+		if ($sticky) {
1118
+			$request = $_REQUEST;
1119
+			unset($request['_wp_http_referer']);
1120
+			unset($request['wp_referer']);
1121
+			foreach ($request as $key => $value) {
1122
+				// do not add nonces
1123
+				if (strpos($key, 'nonce') !== false) {
1124
+					continue;
1125
+				}
1126
+				$args[ 'wp_referer[' . $key . ']' ] = $value;
1127
+			}
1128
+		}
1129
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 * This returns a generated link that will load the related help tab.
1135
+	 *
1136
+	 * @param  string $help_tab_id the id for the connected help tab
1137
+	 * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1138
+	 * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1139
+	 * @uses EEH_Template::get_help_tab_link()
1140
+	 * @return string              generated link
1141
+	 */
1142
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1143
+	{
1144
+		return EEH_Template::get_help_tab_link(
1145
+			$help_tab_id,
1146
+			$this->page_slug,
1147
+			$this->_req_action,
1148
+			$icon_style,
1149
+			$help_text
1150
+		);
1151
+	}
1152
+
1153
+
1154
+	/**
1155
+	 * _add_help_tabs
1156
+	 * Note child classes define their help tabs within the page_config array.
1157
+	 *
1158
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1159
+	 * @return void
1160
+	 * @throws DomainException
1161
+	 * @throws EE_Error
1162
+	 */
1163
+	protected function _add_help_tabs()
1164
+	{
1165
+		$tour_buttons = '';
1166
+		if (isset($this->_page_config[ $this->_req_action ])) {
1167
+			$config = $this->_page_config[ $this->_req_action ];
1168
+			// is there a help tour for the current route?  if there is let's setup the tour buttons
1169
+			if (isset($this->_help_tour[ $this->_req_action ])) {
1170
+				$tb = array();
1171
+				$tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1172
+				foreach ($this->_help_tour['tours'] as $tour) {
1173
+					// if this is the end tour then we don't need to setup a button
1174
+					if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1175
+						continue;
1176
+					}
1177
+					$tb[] = '<button id="trigger-tour-'
1178
+							. $tour->get_slug()
1179
+							. '" class="button-primary trigger-ee-help-tour">'
1180
+							. $tour->get_label()
1181
+							. '</button>';
1182
+				}
1183
+				$tour_buttons .= implode('<br />', $tb);
1184
+				$tour_buttons .= '</div></div>';
1185
+			}
1186
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1187
+			if (is_array($config) && isset($config['help_sidebar'])) {
1188
+				// check that the callback given is valid
1189
+				if (! method_exists($this, $config['help_sidebar'])) {
1190
+					throw new EE_Error(
1191
+						sprintf(
1192
+							esc_html__(
1193
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1194
+								'event_espresso'
1195
+							),
1196
+							$config['help_sidebar'],
1197
+							get_class($this)
1198
+						)
1199
+					);
1200
+				}
1201
+				$content = apply_filters(
1202
+					'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1203
+					$this->{$config['help_sidebar']}()
1204
+				);
1205
+				$content .= $tour_buttons; // add help tour buttons.
1206
+				// do we have any help tours setup?  Cause if we do we want to add the buttons
1207
+				$this->_current_screen->set_help_sidebar($content);
1208
+			}
1209
+			// if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1210
+			if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1211
+				$this->_current_screen->set_help_sidebar($tour_buttons);
1212
+			}
1213
+			// handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1214
+			if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1215
+				$_ht['id'] = $this->page_slug;
1216
+				$_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1217
+				$_ht['content'] = '<p>'
1218
+								  . esc_html__(
1219
+									  'The buttons to the right allow you to start/restart any help tours available for this page',
1220
+									  'event_espresso'
1221
+								  ) . '</p>';
1222
+				$this->_current_screen->add_help_tab($_ht);
1223
+			}
1224
+			if (! isset($config['help_tabs'])) {
1225
+				return;
1226
+			} //no help tabs for this route
1227
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1228
+				// we're here so there ARE help tabs!
1229
+				// make sure we've got what we need
1230
+				if (! isset($cfg['title'])) {
1231
+					throw new EE_Error(
1232
+						esc_html__(
1233
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1234
+							'event_espresso'
1235
+						)
1236
+					);
1237
+				}
1238
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1239
+					throw new EE_Error(
1240
+						esc_html__(
1241
+							'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1242
+							'event_espresso'
1243
+						)
1244
+					);
1245
+				}
1246
+				// first priority goes to content.
1247
+				if (! empty($cfg['content'])) {
1248
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1249
+					// second priority goes to filename
1250
+				} elseif (! empty($cfg['filename'])) {
1251
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1252
+					// it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1253
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1254
+															 . basename($this->_get_dir())
1255
+															 . '/help_tabs/'
1256
+															 . $cfg['filename']
1257
+															 . '.help_tab.php' : $file_path;
1258
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1259
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1260
+						EE_Error::add_error(
1261
+							sprintf(
1262
+								esc_html__(
1263
+									'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1264
+									'event_espresso'
1265
+								),
1266
+								$tab_id,
1267
+								key($config),
1268
+								$file_path
1269
+							),
1270
+							__FILE__,
1271
+							__FUNCTION__,
1272
+							__LINE__
1273
+						);
1274
+						return;
1275
+					}
1276
+					$template_args['admin_page_obj'] = $this;
1277
+					$content = EEH_Template::display_template(
1278
+						$file_path,
1279
+						$template_args,
1280
+						true
1281
+					);
1282
+				} else {
1283
+					$content = '';
1284
+				}
1285
+				// check if callback is valid
1286
+				if (empty($content) && (
1287
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1288
+					)
1289
+				) {
1290
+					EE_Error::add_error(
1291
+						sprintf(
1292
+							esc_html__(
1293
+								'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1294
+								'event_espresso'
1295
+							),
1296
+							$cfg['title']
1297
+						),
1298
+						__FILE__,
1299
+						__FUNCTION__,
1300
+						__LINE__
1301
+					);
1302
+					return;
1303
+				}
1304
+				// setup config array for help tab method
1305
+				$id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1306
+				$_ht = array(
1307
+					'id'       => $id,
1308
+					'title'    => $cfg['title'],
1309
+					'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1310
+					'content'  => $content,
1311
+				);
1312
+				$this->_current_screen->add_help_tab($_ht);
1313
+			}
1314
+		}
1315
+	}
1316
+
1317
+
1318
+	/**
1319
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1320
+	 * an array with properties for setting up usage of the joyride plugin
1321
+	 *
1322
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1323
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1324
+	 *         _set_page_config() comments
1325
+	 * @return void
1326
+	 * @throws EE_Error
1327
+	 * @throws InvalidArgumentException
1328
+	 * @throws InvalidDataTypeException
1329
+	 * @throws InvalidInterfaceException
1330
+	 */
1331
+	protected function _add_help_tour()
1332
+	{
1333
+		$tours = array();
1334
+		$this->_help_tour = array();
1335
+		// exit early if help tours are turned off globally
1336
+		if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1337
+			|| ! EE_Registry::instance()->CFG->admin->help_tour_activation
1338
+		) {
1339
+			return;
1340
+		}
1341
+		// loop through _page_config to find any help_tour defined
1342
+		foreach ($this->_page_config as $route => $config) {
1343
+			// we're only going to set things up for this route
1344
+			if ($route !== $this->_req_action) {
1345
+				continue;
1346
+			}
1347
+			if (isset($config['help_tour'])) {
1348
+				foreach ($config['help_tour'] as $tour) {
1349
+					$file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1350
+					// let's see if we can get that file...
1351
+					// if not its possible this is a decaf route not set in caffeinated
1352
+					// so lets try and get the caffeinated equivalent
1353
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1354
+															 . basename($this->_get_dir())
1355
+															 . '/help_tours/'
1356
+															 . $tour
1357
+															 . '.class.php' : $file_path;
1358
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1359
+					if (! is_readable($file_path)) {
1360
+						EE_Error::add_error(
1361
+							sprintf(
1362
+								esc_html__(
1363
+									'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1364
+									'event_espresso'
1365
+								),
1366
+								$file_path,
1367
+								$tour
1368
+							),
1369
+							__FILE__,
1370
+							__FUNCTION__,
1371
+							__LINE__
1372
+						);
1373
+						return;
1374
+					}
1375
+					require_once $file_path;
1376
+					if (! class_exists($tour)) {
1377
+						$error_msg[] = sprintf(
1378
+							esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1379
+							$tour
1380
+						);
1381
+						$error_msg[] = $error_msg[0] . "\r\n"
1382
+									   . sprintf(
1383
+										   esc_html__(
1384
+											   'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1385
+											   'event_espresso'
1386
+										   ),
1387
+										   $tour,
1388
+										   '<br />',
1389
+										   $tour,
1390
+										   $this->_req_action,
1391
+										   get_class($this)
1392
+									   );
1393
+						throw new EE_Error(implode('||', $error_msg));
1394
+					}
1395
+					$tour_obj = new $tour($this->_is_caf);
1396
+					$tours[] = $tour_obj;
1397
+					$this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1398
+				}
1399
+				// let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1400
+				$end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1401
+				$tours[] = $end_stop_tour;
1402
+				$this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1403
+			}
1404
+		}
1405
+		if (! empty($tours)) {
1406
+			$this->_help_tour['tours'] = $tours;
1407
+		}
1408
+		// that's it!  Now that the $_help_tours property is set (or not)
1409
+		// the scripts and html should be taken care of automatically.
1410
+	}
1411
+
1412
+
1413
+	/**
1414
+	 * This simply sets up any qtips that have been defined in the page config
1415
+	 *
1416
+	 * @return void
1417
+	 */
1418
+	protected function _add_qtips()
1419
+	{
1420
+		if (isset($this->_route_config['qtips'])) {
1421
+			$qtips = (array) $this->_route_config['qtips'];
1422
+			// load qtip loader
1423
+			$path = array(
1424
+				$this->_get_dir() . '/qtips/',
1425
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1426
+			);
1427
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1428
+		}
1429
+	}
1430
+
1431
+
1432
+	/**
1433
+	 * _set_nav_tabs
1434
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1435
+	 * wish to add additional tabs or modify accordingly.
1436
+	 *
1437
+	 * @return void
1438
+	 * @throws InvalidArgumentException
1439
+	 * @throws InvalidInterfaceException
1440
+	 * @throws InvalidDataTypeException
1441
+	 */
1442
+	protected function _set_nav_tabs()
1443
+	{
1444
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1445
+		$i = 0;
1446
+		foreach ($this->_page_config as $slug => $config) {
1447
+			if (! is_array($config)
1448
+				|| (
1449
+					is_array($config)
1450
+					&& (
1451
+						(isset($config['nav']) && ! $config['nav'])
1452
+						|| ! isset($config['nav'])
1453
+					)
1454
+				)
1455
+			) {
1456
+				continue;
1457
+			}
1458
+			// no nav tab for this config
1459
+			// check for persistent flag
1460
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1461
+				// nav tab is only to appear when route requested.
1462
+				continue;
1463
+			}
1464
+			if (! $this->check_user_access($slug, true)) {
1465
+				// no nav tab because current user does not have access.
1466
+				continue;
1467
+			}
1468
+			$css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1469
+			$this->_nav_tabs[ $slug ] = array(
1470
+				'url'       => isset($config['nav']['url'])
1471
+					? $config['nav']['url']
1472
+					: self::add_query_args_and_nonce(
1473
+						array('action' => $slug),
1474
+						$this->_admin_base_url
1475
+					),
1476
+				'link_text' => isset($config['nav']['label'])
1477
+					? $config['nav']['label']
1478
+					: ucwords(
1479
+						str_replace('_', ' ', $slug)
1480
+					),
1481
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1482
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1483
+			);
1484
+			$i++;
1485
+		}
1486
+		// if $this->_nav_tabs is empty then lets set the default
1487
+		if (empty($this->_nav_tabs)) {
1488
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = array(
1489
+				'url'       => $this->_admin_base_url,
1490
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1491
+				'css_class' => 'nav-tab-active',
1492
+				'order'     => 10,
1493
+			);
1494
+		}
1495
+		// now let's sort the tabs according to order
1496
+		usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1497
+	}
1498
+
1499
+
1500
+	/**
1501
+	 * _set_current_labels
1502
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1503
+	 * property array
1504
+	 *
1505
+	 * @return void
1506
+	 */
1507
+	private function _set_current_labels()
1508
+	{
1509
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1510
+			foreach ($this->_route_config['labels'] as $label => $text) {
1511
+				if (is_array($text)) {
1512
+					foreach ($text as $sublabel => $subtext) {
1513
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1514
+					}
1515
+				} else {
1516
+					$this->_labels[ $label ] = $text;
1517
+				}
1518
+			}
1519
+		}
1520
+	}
1521
+
1522
+
1523
+	/**
1524
+	 *        verifies user access for this admin page
1525
+	 *
1526
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1527
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1528
+	 *                               return false if verify fail.
1529
+	 * @return bool
1530
+	 * @throws InvalidArgumentException
1531
+	 * @throws InvalidDataTypeException
1532
+	 * @throws InvalidInterfaceException
1533
+	 */
1534
+	public function check_user_access($route_to_check = '', $verify_only = false)
1535
+	{
1536
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1537
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1538
+		$capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1539
+					  && is_array(
1540
+						  $this->_page_routes[ $route_to_check ]
1541
+					  )
1542
+					  && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1543
+			? $this->_page_routes[ $route_to_check ]['capability'] : null;
1544
+		if (empty($capability) && empty($route_to_check)) {
1545
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1546
+				: $this->_route['capability'];
1547
+		} else {
1548
+			$capability = empty($capability) ? 'manage_options' : $capability;
1549
+		}
1550
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1551
+		if (! defined('DOING_AJAX')
1552
+			&& (
1553
+				! function_exists('is_admin')
1554
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1555
+					$capability,
1556
+					$this->page_slug
1557
+					. '_'
1558
+					. $route_to_check,
1559
+					$id
1560
+				)
1561
+			)
1562
+		) {
1563
+			if ($verify_only) {
1564
+				return false;
1565
+			}
1566
+			if (is_user_logged_in()) {
1567
+				wp_die(__('You do not have access to this route.', 'event_espresso'));
1568
+			} else {
1569
+				return false;
1570
+			}
1571
+		}
1572
+		return true;
1573
+	}
1574
+
1575
+
1576
+	/**
1577
+	 * admin_init_global
1578
+	 * This runs all the code that we want executed within the WP admin_init hook.
1579
+	 * This method executes for ALL EE Admin pages.
1580
+	 *
1581
+	 * @return void
1582
+	 */
1583
+	public function admin_init_global()
1584
+	{
1585
+	}
1586
+
1587
+
1588
+	/**
1589
+	 * wp_loaded_global
1590
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1591
+	 * EE_Admin page and will execute on every EE Admin Page load
1592
+	 *
1593
+	 * @return void
1594
+	 */
1595
+	public function wp_loaded()
1596
+	{
1597
+	}
1598
+
1599
+
1600
+	/**
1601
+	 * admin_notices
1602
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1603
+	 * ALL EE_Admin pages.
1604
+	 *
1605
+	 * @return void
1606
+	 */
1607
+	public function admin_notices_global()
1608
+	{
1609
+		$this->_display_no_javascript_warning();
1610
+		$this->_display_espresso_notices();
1611
+	}
1612
+
1613
+
1614
+	public function network_admin_notices_global()
1615
+	{
1616
+		$this->_display_no_javascript_warning();
1617
+		$this->_display_espresso_notices();
1618
+	}
1619
+
1620
+
1621
+	/**
1622
+	 * admin_footer_scripts_global
1623
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1624
+	 * will apply on ALL EE_Admin pages.
1625
+	 *
1626
+	 * @return void
1627
+	 */
1628
+	public function admin_footer_scripts_global()
1629
+	{
1630
+		$this->_add_admin_page_ajax_loading_img();
1631
+		$this->_add_admin_page_overlay();
1632
+		// if metaboxes are present we need to add the nonce field
1633
+		if (isset($this->_route_config['metaboxes'])
1634
+			|| isset($this->_route_config['list_table'])
1635
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1636
+		) {
1637
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1638
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1639
+		}
1640
+	}
1641
+
1642
+
1643
+	/**
1644
+	 * admin_footer_global
1645
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1646
+	 * ALL EE_Admin Pages.
1647
+	 *
1648
+	 * @return void
1649
+	 * @throws EE_Error
1650
+	 */
1651
+	public function admin_footer_global()
1652
+	{
1653
+		// dialog container for dialog helper
1654
+		$d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1655
+		$d_cont .= '<div class="ee-notices"></div>';
1656
+		$d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1657
+		$d_cont .= '</div>';
1658
+		echo $d_cont;
1659
+		// help tour stuff?
1660
+		if (isset($this->_help_tour[ $this->_req_action ])) {
1661
+			echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1662
+		}
1663
+		// current set timezone for timezone js
1664
+		echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1665
+	}
1666
+
1667
+
1668
+	/**
1669
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1670
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1671
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1672
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1673
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1674
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1675
+	 * for the
1676
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1677
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1678
+	 *    'help_trigger_id' => array(
1679
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1680
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1681
+	 *    )
1682
+	 * );
1683
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1684
+	 *
1685
+	 * @param array $help_array
1686
+	 * @param bool  $display
1687
+	 * @return string content
1688
+	 * @throws DomainException
1689
+	 * @throws EE_Error
1690
+	 */
1691
+	protected function _set_help_popup_content($help_array = array(), $display = false)
1692
+	{
1693
+		$content = '';
1694
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1695
+		// loop through the array and setup content
1696
+		foreach ($help_array as $trigger => $help) {
1697
+			// make sure the array is setup properly
1698
+			if (! isset($help['title']) || ! isset($help['content'])) {
1699
+				throw new EE_Error(
1700
+					esc_html__(
1701
+						'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1702
+						'event_espresso'
1703
+					)
1704
+				);
1705
+			}
1706
+			// we're good so let'd setup the template vars and then assign parsed template content to our content.
1707
+			$template_args = array(
1708
+				'help_popup_id'      => $trigger,
1709
+				'help_popup_title'   => $help['title'],
1710
+				'help_popup_content' => $help['content'],
1711
+			);
1712
+			$content .= EEH_Template::display_template(
1713
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1714
+				$template_args,
1715
+				true
1716
+			);
1717
+		}
1718
+		if ($display) {
1719
+			echo $content;
1720
+			return '';
1721
+		}
1722
+		return $content;
1723
+	}
1724
+
1725
+
1726
+	/**
1727
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1728
+	 *
1729
+	 * @return array properly formatted array for help popup content
1730
+	 * @throws EE_Error
1731
+	 */
1732
+	private function _get_help_content()
1733
+	{
1734
+		// what is the method we're looking for?
1735
+		$method_name = '_help_popup_content_' . $this->_req_action;
1736
+		// if method doesn't exist let's get out.
1737
+		if (! method_exists($this, $method_name)) {
1738
+			return array();
1739
+		}
1740
+		// k we're good to go let's retrieve the help array
1741
+		$help_array = call_user_func(array($this, $method_name));
1742
+		// make sure we've got an array!
1743
+		if (! is_array($help_array)) {
1744
+			throw new EE_Error(
1745
+				esc_html__(
1746
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1747
+					'event_espresso'
1748
+				)
1749
+			);
1750
+		}
1751
+		return $help_array;
1752
+	}
1753
+
1754
+
1755
+	/**
1756
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1757
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1758
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1759
+	 *
1760
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1761
+	 * @param boolean $display    if false then we return the trigger string
1762
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1763
+	 * @return string
1764
+	 * @throws DomainException
1765
+	 * @throws EE_Error
1766
+	 */
1767
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1768
+	{
1769
+		if (defined('DOING_AJAX')) {
1770
+			return '';
1771
+		}
1772
+		// let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1773
+		$help_array = $this->_get_help_content();
1774
+		$help_content = '';
1775
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1776
+			$help_array[ $trigger_id ] = array(
1777
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1778
+				'content' => esc_html__(
1779
+					'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1780
+					'event_espresso'
1781
+				),
1782
+			);
1783
+			$help_content = $this->_set_help_popup_content($help_array, false);
1784
+		}
1785
+		// let's setup the trigger
1786
+		$content = '<a class="ee-dialog" href="?height='
1787
+				   . $dimensions[0]
1788
+				   . '&width='
1789
+				   . $dimensions[1]
1790
+				   . '&inlineId='
1791
+				   . $trigger_id
1792
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1793
+		$content .= $help_content;
1794
+		if ($display) {
1795
+			echo $content;
1796
+			return '';
1797
+		}
1798
+		return $content;
1799
+	}
1800
+
1801
+
1802
+	/**
1803
+	 * _add_global_screen_options
1804
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1805
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1806
+	 *
1807
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1808
+	 *         see also WP_Screen object documents...
1809
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1810
+	 * @abstract
1811
+	 * @return void
1812
+	 */
1813
+	private function _add_global_screen_options()
1814
+	{
1815
+	}
1816
+
1817
+
1818
+	/**
1819
+	 * _add_global_feature_pointers
1820
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1821
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1822
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1823
+	 *
1824
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1825
+	 *         extended) also see:
1826
+	 * @link   http://eamann.com/tech/wordpress-portland/
1827
+	 * @abstract
1828
+	 * @return void
1829
+	 */
1830
+	private function _add_global_feature_pointers()
1831
+	{
1832
+	}
1833
+
1834
+
1835
+	/**
1836
+	 * load_global_scripts_styles
1837
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1838
+	 *
1839
+	 * @return void
1840
+	 * @throws EE_Error
1841
+	 */
1842
+	public function load_global_scripts_styles()
1843
+	{
1844
+		/** STYLES **/
1845
+		// add debugging styles
1846
+		if (WP_DEBUG) {
1847
+			add_action('admin_head', array($this, 'add_xdebug_style'));
1848
+		}
1849
+		// register all styles
1850
+		wp_register_style(
1851
+			'espresso-ui-theme',
1852
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1853
+			array(),
1854
+			EVENT_ESPRESSO_VERSION
1855
+		);
1856
+		wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1857
+		// helpers styles
1858
+		wp_register_style(
1859
+			'ee-text-links',
1860
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1861
+			array(),
1862
+			EVENT_ESPRESSO_VERSION
1863
+		);
1864
+		/** SCRIPTS **/
1865
+		// register all scripts
1866
+		wp_register_script(
1867
+			'ee-dialog',
1868
+			EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1869
+			array('jquery', 'jquery-ui-draggable'),
1870
+			EVENT_ESPRESSO_VERSION,
1871
+			true
1872
+		);
1873
+		wp_register_script(
1874
+			'ee_admin_js',
1875
+			EE_ADMIN_URL . 'assets/ee-admin-page.js',
1876
+			array('espresso_core', 'ee-parse-uri', 'ee-dialog'),
1877
+			EVENT_ESPRESSO_VERSION,
1878
+			true
1879
+		);
1880
+		wp_register_script(
1881
+			'jquery-ui-timepicker-addon',
1882
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1883
+			array('jquery-ui-datepicker', 'jquery-ui-slider'),
1884
+			EVENT_ESPRESSO_VERSION,
1885
+			true
1886
+		);
1887
+		add_filter('FHEE_load_joyride', '__return_true');
1888
+		// script for sorting tables
1889
+		wp_register_script(
1890
+			'espresso_ajax_table_sorting',
1891
+			EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1892
+			array('ee_admin_js', 'jquery-ui-sortable'),
1893
+			EVENT_ESPRESSO_VERSION,
1894
+			true
1895
+		);
1896
+		// script for parsing uri's
1897
+		wp_register_script(
1898
+			'ee-parse-uri',
1899
+			EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1900
+			array(),
1901
+			EVENT_ESPRESSO_VERSION,
1902
+			true
1903
+		);
1904
+		// and parsing associative serialized form elements
1905
+		wp_register_script(
1906
+			'ee-serialize-full-array',
1907
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1908
+			array('jquery'),
1909
+			EVENT_ESPRESSO_VERSION,
1910
+			true
1911
+		);
1912
+		// helpers scripts
1913
+		wp_register_script(
1914
+			'ee-text-links',
1915
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1916
+			array('jquery'),
1917
+			EVENT_ESPRESSO_VERSION,
1918
+			true
1919
+		);
1920
+		wp_register_script(
1921
+			'ee-moment-core',
1922
+			EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1923
+			array(),
1924
+			EVENT_ESPRESSO_VERSION,
1925
+			true
1926
+		);
1927
+		wp_register_script(
1928
+			'ee-moment',
1929
+			EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1930
+			array('ee-moment-core'),
1931
+			EVENT_ESPRESSO_VERSION,
1932
+			true
1933
+		);
1934
+		wp_register_script(
1935
+			'ee-datepicker',
1936
+			EE_ADMIN_URL . 'assets/ee-datepicker.js',
1937
+			array('jquery-ui-timepicker-addon', 'ee-moment'),
1938
+			EVENT_ESPRESSO_VERSION,
1939
+			true
1940
+		);
1941
+		// google charts
1942
+		wp_register_script(
1943
+			'google-charts',
1944
+			'https://www.gstatic.com/charts/loader.js',
1945
+			array(),
1946
+			EVENT_ESPRESSO_VERSION,
1947
+			false
1948
+		);
1949
+		// ENQUEUE ALL BASICS BY DEFAULT
1950
+		wp_enqueue_style('ee-admin-css');
1951
+		wp_enqueue_script('ee_admin_js');
1952
+		wp_enqueue_script('ee-accounting');
1953
+		wp_enqueue_script('jquery-validate');
1954
+		// taking care of metaboxes
1955
+		if (empty($this->_cpt_route)
1956
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1957
+		) {
1958
+			wp_enqueue_script('dashboard');
1959
+		}
1960
+		// LOCALIZED DATA
1961
+		// localize script for ajax lazy loading
1962
+		$lazy_loader_container_ids = apply_filters(
1963
+			'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1964
+			array('espresso_news_post_box_content')
1965
+		);
1966
+		wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1967
+		/**
1968
+		 * help tour stuff
1969
+		 */
1970
+		if (! empty($this->_help_tour)) {
1971
+			// register the js for kicking things off
1972
+			wp_enqueue_script(
1973
+				'ee-help-tour',
1974
+				EE_ADMIN_URL . 'assets/ee-help-tour.js',
1975
+				array('jquery-joyride'),
1976
+				EVENT_ESPRESSO_VERSION,
1977
+				true
1978
+			);
1979
+			$tours = array();
1980
+			// setup tours for the js tour object
1981
+			foreach ($this->_help_tour['tours'] as $tour) {
1982
+				if ($tour instanceof EE_Help_Tour) {
1983
+					$tours[] = array(
1984
+						'id'      => $tour->get_slug(),
1985
+						'options' => $tour->get_options(),
1986
+					);
1987
+				}
1988
+			}
1989
+			wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
1990
+			// admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1991
+		}
1992
+	}
1993
+
1994
+
1995
+	/**
1996
+	 *        admin_footer_scripts_eei18n_js_strings
1997
+	 *
1998
+	 * @return        void
1999
+	 */
2000
+	public function admin_footer_scripts_eei18n_js_strings()
2001
+	{
2002
+		EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
2003
+		EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
2004
+			'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2005
+			'event_espresso'
2006
+		);
2007
+		EE_Registry::$i18n_js_strings['January'] = esc_html__('January', 'event_espresso');
2008
+		EE_Registry::$i18n_js_strings['February'] = esc_html__('February', 'event_espresso');
2009
+		EE_Registry::$i18n_js_strings['March'] = esc_html__('March', 'event_espresso');
2010
+		EE_Registry::$i18n_js_strings['April'] = esc_html__('April', 'event_espresso');
2011
+		EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
2012
+		EE_Registry::$i18n_js_strings['June'] = esc_html__('June', 'event_espresso');
2013
+		EE_Registry::$i18n_js_strings['July'] = esc_html__('July', 'event_espresso');
2014
+		EE_Registry::$i18n_js_strings['August'] = esc_html__('August', 'event_espresso');
2015
+		EE_Registry::$i18n_js_strings['September'] = esc_html__('September', 'event_espresso');
2016
+		EE_Registry::$i18n_js_strings['October'] = esc_html__('October', 'event_espresso');
2017
+		EE_Registry::$i18n_js_strings['November'] = esc_html__('November', 'event_espresso');
2018
+		EE_Registry::$i18n_js_strings['December'] = esc_html__('December', 'event_espresso');
2019
+		EE_Registry::$i18n_js_strings['Jan'] = esc_html__('Jan', 'event_espresso');
2020
+		EE_Registry::$i18n_js_strings['Feb'] = esc_html__('Feb', 'event_espresso');
2021
+		EE_Registry::$i18n_js_strings['Mar'] = esc_html__('Mar', 'event_espresso');
2022
+		EE_Registry::$i18n_js_strings['Apr'] = esc_html__('Apr', 'event_espresso');
2023
+		EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
2024
+		EE_Registry::$i18n_js_strings['Jun'] = esc_html__('Jun', 'event_espresso');
2025
+		EE_Registry::$i18n_js_strings['Jul'] = esc_html__('Jul', 'event_espresso');
2026
+		EE_Registry::$i18n_js_strings['Aug'] = esc_html__('Aug', 'event_espresso');
2027
+		EE_Registry::$i18n_js_strings['Sep'] = esc_html__('Sep', 'event_espresso');
2028
+		EE_Registry::$i18n_js_strings['Oct'] = esc_html__('Oct', 'event_espresso');
2029
+		EE_Registry::$i18n_js_strings['Nov'] = esc_html__('Nov', 'event_espresso');
2030
+		EE_Registry::$i18n_js_strings['Dec'] = esc_html__('Dec', 'event_espresso');
2031
+		EE_Registry::$i18n_js_strings['Sunday'] = esc_html__('Sunday', 'event_espresso');
2032
+		EE_Registry::$i18n_js_strings['Monday'] = esc_html__('Monday', 'event_espresso');
2033
+		EE_Registry::$i18n_js_strings['Tuesday'] = esc_html__('Tuesday', 'event_espresso');
2034
+		EE_Registry::$i18n_js_strings['Wednesday'] = esc_html__('Wednesday', 'event_espresso');
2035
+		EE_Registry::$i18n_js_strings['Thursday'] = esc_html__('Thursday', 'event_espresso');
2036
+		EE_Registry::$i18n_js_strings['Friday'] = esc_html__('Friday', 'event_espresso');
2037
+		EE_Registry::$i18n_js_strings['Saturday'] = esc_html__('Saturday', 'event_espresso');
2038
+		EE_Registry::$i18n_js_strings['Sun'] = esc_html__('Sun', 'event_espresso');
2039
+		EE_Registry::$i18n_js_strings['Mon'] = esc_html__('Mon', 'event_espresso');
2040
+		EE_Registry::$i18n_js_strings['Tue'] = esc_html__('Tue', 'event_espresso');
2041
+		EE_Registry::$i18n_js_strings['Wed'] = esc_html__('Wed', 'event_espresso');
2042
+		EE_Registry::$i18n_js_strings['Thu'] = esc_html__('Thu', 'event_espresso');
2043
+		EE_Registry::$i18n_js_strings['Fri'] = esc_html__('Fri', 'event_espresso');
2044
+		EE_Registry::$i18n_js_strings['Sat'] = esc_html__('Sat', 'event_espresso');
2045
+	}
2046
+
2047
+
2048
+	/**
2049
+	 *        load enhanced xdebug styles for ppl with failing eyesight
2050
+	 *
2051
+	 * @return        void
2052
+	 */
2053
+	public function add_xdebug_style()
2054
+	{
2055
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2056
+	}
2057
+
2058
+
2059
+	/************************/
2060
+	/** LIST TABLE METHODS **/
2061
+	/************************/
2062
+	/**
2063
+	 * this sets up the list table if the current view requires it.
2064
+	 *
2065
+	 * @return void
2066
+	 * @throws EE_Error
2067
+	 */
2068
+	protected function _set_list_table()
2069
+	{
2070
+		// first is this a list_table view?
2071
+		if (! isset($this->_route_config['list_table'])) {
2072
+			return;
2073
+		} //not a list_table view so get out.
2074
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2075
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2076
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2077
+			// user error msg
2078
+			$error_msg = esc_html__(
2079
+				'An error occurred. The requested list table views could not be found.',
2080
+				'event_espresso'
2081
+			);
2082
+			// developer error msg
2083
+			$error_msg .= '||'
2084
+						  . sprintf(
2085
+							  esc_html__(
2086
+								  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2087
+								  'event_espresso'
2088
+							  ),
2089
+							  $this->_req_action,
2090
+							  $list_table_view
2091
+						  );
2092
+			throw new EE_Error($error_msg);
2093
+		}
2094
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2095
+		$this->_views = apply_filters(
2096
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2097
+			$this->_views
2098
+		);
2099
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2100
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2101
+		$this->_set_list_table_view();
2102
+		$this->_set_list_table_object();
2103
+	}
2104
+
2105
+
2106
+	/**
2107
+	 * set current view for List Table
2108
+	 *
2109
+	 * @return void
2110
+	 */
2111
+	protected function _set_list_table_view()
2112
+	{
2113
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2114
+		// looking at active items or dumpster diving ?
2115
+		if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2116
+			$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2117
+		} else {
2118
+			$this->_view = sanitize_key($this->_req_data['status']);
2119
+		}
2120
+	}
2121
+
2122
+
2123
+	/**
2124
+	 * _set_list_table_object
2125
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2126
+	 *
2127
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2128
+	 * @throws \InvalidArgumentException
2129
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2130
+	 * @throws EE_Error
2131
+	 * @throws InvalidInterfaceException
2132
+	 */
2133
+	protected function _set_list_table_object()
2134
+	{
2135
+		if (isset($this->_route_config['list_table'])) {
2136
+			if (! class_exists($this->_route_config['list_table'])) {
2137
+				throw new EE_Error(
2138
+					sprintf(
2139
+						esc_html__(
2140
+							'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2141
+							'event_espresso'
2142
+						),
2143
+						$this->_route_config['list_table'],
2144
+						get_class($this)
2145
+					)
2146
+				);
2147
+			}
2148
+			$this->_list_table_object = $this->loader->getShared(
2149
+				$this->_route_config['list_table'],
2150
+				array($this)
2151
+			);
2152
+		}
2153
+	}
2154
+
2155
+
2156
+	/**
2157
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2158
+	 *
2159
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2160
+	 *                                                    urls.  The array should be indexed by the view it is being
2161
+	 *                                                    added to.
2162
+	 * @return array
2163
+	 */
2164
+	public function get_list_table_view_RLs($extra_query_args = array())
2165
+	{
2166
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2167
+		if (empty($this->_views)) {
2168
+			$this->_views = array();
2169
+		}
2170
+		// cycle thru views
2171
+		foreach ($this->_views as $key => $view) {
2172
+			$query_args = array();
2173
+			// check for current view
2174
+			$this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2175
+			$query_args['action'] = $this->_req_action;
2176
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2177
+			$query_args['status'] = $view['slug'];
2178
+			// merge any other arguments sent in.
2179
+			if (isset($extra_query_args[ $view['slug'] ])) {
2180
+				$query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2181
+			}
2182
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2183
+		}
2184
+		return $this->_views;
2185
+	}
2186
+
2187
+
2188
+	/**
2189
+	 * _entries_per_page_dropdown
2190
+	 * generates a drop down box for selecting the number of visible rows in an admin page list table
2191
+	 *
2192
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2193
+	 *         WP does it.
2194
+	 * @param int $max_entries total number of rows in the table
2195
+	 * @return string
2196
+	 */
2197
+	protected function _entries_per_page_dropdown($max_entries = 0)
2198
+	{
2199
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2200
+		$values = array(10, 25, 50, 100);
2201
+		$per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2202
+		if ($max_entries) {
2203
+			$values[] = $max_entries;
2204
+			sort($values);
2205
+		}
2206
+		$entries_per_page_dropdown = '
2207 2207
 			<div id="entries-per-page-dv" class="alignleft actions">
2208 2208
 				<label class="hide-if-no-js">
2209 2209
 					Show
2210 2210
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2211
-        foreach ($values as $value) {
2212
-            if ($value < $max_entries) {
2213
-                $selected = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2214
-                $entries_per_page_dropdown .= '
2211
+		foreach ($values as $value) {
2212
+			if ($value < $max_entries) {
2213
+				$selected = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2214
+				$entries_per_page_dropdown .= '
2215 2215
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2216
-            }
2217
-        }
2218
-        $selected = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2219
-        $entries_per_page_dropdown .= '
2216
+			}
2217
+		}
2218
+		$selected = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2219
+		$entries_per_page_dropdown .= '
2220 2220
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2221
-        $entries_per_page_dropdown .= '
2221
+		$entries_per_page_dropdown .= '
2222 2222
 					</select>
2223 2223
 					entries
2224 2224
 				</label>
2225 2225
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
2226 2226
 			</div>
2227 2227
 		';
2228
-        return $entries_per_page_dropdown;
2229
-    }
2230
-
2231
-
2232
-    /**
2233
-     *        _set_search_attributes
2234
-     *
2235
-     * @return        void
2236
-     */
2237
-    public function _set_search_attributes()
2238
-    {
2239
-        $this->_template_args['search']['btn_label'] = sprintf(
2240
-            esc_html__('Search %s', 'event_espresso'),
2241
-            empty($this->_search_btn_label) ? $this->page_label
2242
-                : $this->_search_btn_label
2243
-        );
2244
-        $this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
2245
-    }
2246
-
2247
-
2248
-
2249
-    /*** END LIST TABLE METHODS **/
2250
-
2251
-
2252
-    /**
2253
-     * _add_registered_metaboxes
2254
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2255
-     *
2256
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2257
-     * @return void
2258
-     * @throws EE_Error
2259
-     */
2260
-    private function _add_registered_meta_boxes()
2261
-    {
2262
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2263
-        // we only add meta boxes if the page_route calls for it
2264
-        if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2265
-            && is_array(
2266
-                $this->_route_config['metaboxes']
2267
-            )
2268
-        ) {
2269
-            // this simply loops through the callbacks provided
2270
-            // and checks if there is a corresponding callback registered by the child
2271
-            // if there is then we go ahead and process the metabox loader.
2272
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2273
-                // first check for Closures
2274
-                if ($metabox_callback instanceof Closure) {
2275
-                    $result = $metabox_callback();
2276
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2277
-                    $result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2278
-                } else {
2279
-                    $result = call_user_func(array($this, &$metabox_callback));
2280
-                }
2281
-                if ($result === false) {
2282
-                    // user error msg
2283
-                    $error_msg = esc_html__(
2284
-                        'An error occurred. The  requested metabox could not be found.',
2285
-                        'event_espresso'
2286
-                    );
2287
-                    // developer error msg
2288
-                    $error_msg .= '||'
2289
-                                  . sprintf(
2290
-                                      esc_html__(
2291
-                                          'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2292
-                                          'event_espresso'
2293
-                                      ),
2294
-                                      $metabox_callback
2295
-                                  );
2296
-                    throw new EE_Error($error_msg);
2297
-                }
2298
-            }
2299
-        }
2300
-    }
2301
-
2302
-
2303
-    /**
2304
-     * _add_screen_columns
2305
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2306
-     * the dynamic column template and we'll setup the column options for the page.
2307
-     *
2308
-     * @return void
2309
-     */
2310
-    private function _add_screen_columns()
2311
-    {
2312
-        if (is_array($this->_route_config)
2313
-            && isset($this->_route_config['columns'])
2314
-            && is_array($this->_route_config['columns'])
2315
-            && count($this->_route_config['columns']) === 2
2316
-        ) {
2317
-            add_screen_option(
2318
-                'layout_columns',
2319
-                array(
2320
-                    'max'     => (int) $this->_route_config['columns'][0],
2321
-                    'default' => (int) $this->_route_config['columns'][1],
2322
-                )
2323
-            );
2324
-            $this->_template_args['num_columns'] = $this->_route_config['columns'][0];
2325
-            $screen_id = $this->_current_screen->id;
2326
-            $screen_columns = (int) get_user_option("screen_layout_{$screen_id}");
2327
-            $total_columns = ! empty($screen_columns)
2328
-                ? $screen_columns
2329
-                : $this->_route_config['columns'][1];
2330
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2331
-            $this->_template_args['current_page'] = $this->_wp_page_slug;
2332
-            $this->_template_args['screen'] = $this->_current_screen;
2333
-            $this->_column_template_path = EE_ADMIN_TEMPLATE
2334
-                                           . 'admin_details_metabox_column_wrapper.template.php';
2335
-            // finally if we don't have has_metaboxes set in the route config
2336
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2337
-            $this->_route_config['has_metaboxes'] = true;
2338
-        }
2339
-    }
2340
-
2341
-
2342
-
2343
-    /** GLOBALLY AVAILABLE METABOXES **/
2344
-
2345
-
2346
-    /**
2347
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2348
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2349
-     * these get loaded on.
2350
-     */
2351
-    private function _espresso_news_post_box()
2352
-    {
2353
-        $news_box_title = apply_filters(
2354
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2355
-            esc_html__('New @ Event Espresso', 'event_espresso')
2356
-        );
2357
-        add_meta_box(
2358
-            'espresso_news_post_box',
2359
-            $news_box_title,
2360
-            array(
2361
-                $this,
2362
-                'espresso_news_post_box',
2363
-            ),
2364
-            $this->_wp_page_slug,
2365
-            'side'
2366
-        );
2367
-    }
2368
-
2369
-
2370
-    /**
2371
-     * Code for setting up espresso ratings request metabox.
2372
-     */
2373
-    protected function _espresso_ratings_request()
2374
-    {
2375
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2376
-            return;
2377
-        }
2378
-        $ratings_box_title = apply_filters(
2379
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2380
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2381
-        );
2382
-        add_meta_box(
2383
-            'espresso_ratings_request',
2384
-            $ratings_box_title,
2385
-            array(
2386
-                $this,
2387
-                'espresso_ratings_request',
2388
-            ),
2389
-            $this->_wp_page_slug,
2390
-            'side'
2391
-        );
2392
-    }
2393
-
2394
-
2395
-    /**
2396
-     * Code for setting up espresso ratings request metabox content.
2397
-     *
2398
-     * @throws DomainException
2399
-     */
2400
-    public function espresso_ratings_request()
2401
-    {
2402
-        EEH_Template::display_template(
2403
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2404
-            array()
2405
-        );
2406
-    }
2407
-
2408
-
2409
-    public static function cached_rss_display($rss_id, $url)
2410
-    {
2411
-        $loading = '<p class="widget-loading hide-if-no-js">'
2412
-                   . __('Loading&#8230;', 'event_espresso')
2413
-                   . '</p><p class="hide-if-js">'
2414
-                   . esc_html__('This widget requires JavaScript.', 'event_espresso')
2415
-                   . '</p>';
2416
-        $pre = '<div class="espresso-rss-display">' . "\n\t";
2417
-        $pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2418
-        $post = '</div>' . "\n";
2419
-        $cache_key = 'ee_rss_' . md5($rss_id);
2420
-        $output = get_transient($cache_key);
2421
-        if ($output !== false) {
2422
-            echo $pre . $output . $post;
2423
-            return true;
2424
-        }
2425
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2426
-            echo $pre . $loading . $post;
2427
-            return false;
2428
-        }
2429
-        ob_start();
2430
-        wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2431
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2432
-        return true;
2433
-    }
2434
-
2435
-
2436
-    public function espresso_news_post_box()
2437
-    {
2438
-        ?>
2228
+		return $entries_per_page_dropdown;
2229
+	}
2230
+
2231
+
2232
+	/**
2233
+	 *        _set_search_attributes
2234
+	 *
2235
+	 * @return        void
2236
+	 */
2237
+	public function _set_search_attributes()
2238
+	{
2239
+		$this->_template_args['search']['btn_label'] = sprintf(
2240
+			esc_html__('Search %s', 'event_espresso'),
2241
+			empty($this->_search_btn_label) ? $this->page_label
2242
+				: $this->_search_btn_label
2243
+		);
2244
+		$this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
2245
+	}
2246
+
2247
+
2248
+
2249
+	/*** END LIST TABLE METHODS **/
2250
+
2251
+
2252
+	/**
2253
+	 * _add_registered_metaboxes
2254
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2255
+	 *
2256
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2257
+	 * @return void
2258
+	 * @throws EE_Error
2259
+	 */
2260
+	private function _add_registered_meta_boxes()
2261
+	{
2262
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2263
+		// we only add meta boxes if the page_route calls for it
2264
+		if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2265
+			&& is_array(
2266
+				$this->_route_config['metaboxes']
2267
+			)
2268
+		) {
2269
+			// this simply loops through the callbacks provided
2270
+			// and checks if there is a corresponding callback registered by the child
2271
+			// if there is then we go ahead and process the metabox loader.
2272
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2273
+				// first check for Closures
2274
+				if ($metabox_callback instanceof Closure) {
2275
+					$result = $metabox_callback();
2276
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2277
+					$result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2278
+				} else {
2279
+					$result = call_user_func(array($this, &$metabox_callback));
2280
+				}
2281
+				if ($result === false) {
2282
+					// user error msg
2283
+					$error_msg = esc_html__(
2284
+						'An error occurred. The  requested metabox could not be found.',
2285
+						'event_espresso'
2286
+					);
2287
+					// developer error msg
2288
+					$error_msg .= '||'
2289
+								  . sprintf(
2290
+									  esc_html__(
2291
+										  'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2292
+										  'event_espresso'
2293
+									  ),
2294
+									  $metabox_callback
2295
+								  );
2296
+					throw new EE_Error($error_msg);
2297
+				}
2298
+			}
2299
+		}
2300
+	}
2301
+
2302
+
2303
+	/**
2304
+	 * _add_screen_columns
2305
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2306
+	 * the dynamic column template and we'll setup the column options for the page.
2307
+	 *
2308
+	 * @return void
2309
+	 */
2310
+	private function _add_screen_columns()
2311
+	{
2312
+		if (is_array($this->_route_config)
2313
+			&& isset($this->_route_config['columns'])
2314
+			&& is_array($this->_route_config['columns'])
2315
+			&& count($this->_route_config['columns']) === 2
2316
+		) {
2317
+			add_screen_option(
2318
+				'layout_columns',
2319
+				array(
2320
+					'max'     => (int) $this->_route_config['columns'][0],
2321
+					'default' => (int) $this->_route_config['columns'][1],
2322
+				)
2323
+			);
2324
+			$this->_template_args['num_columns'] = $this->_route_config['columns'][0];
2325
+			$screen_id = $this->_current_screen->id;
2326
+			$screen_columns = (int) get_user_option("screen_layout_{$screen_id}");
2327
+			$total_columns = ! empty($screen_columns)
2328
+				? $screen_columns
2329
+				: $this->_route_config['columns'][1];
2330
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2331
+			$this->_template_args['current_page'] = $this->_wp_page_slug;
2332
+			$this->_template_args['screen'] = $this->_current_screen;
2333
+			$this->_column_template_path = EE_ADMIN_TEMPLATE
2334
+										   . 'admin_details_metabox_column_wrapper.template.php';
2335
+			// finally if we don't have has_metaboxes set in the route config
2336
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2337
+			$this->_route_config['has_metaboxes'] = true;
2338
+		}
2339
+	}
2340
+
2341
+
2342
+
2343
+	/** GLOBALLY AVAILABLE METABOXES **/
2344
+
2345
+
2346
+	/**
2347
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2348
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2349
+	 * these get loaded on.
2350
+	 */
2351
+	private function _espresso_news_post_box()
2352
+	{
2353
+		$news_box_title = apply_filters(
2354
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2355
+			esc_html__('New @ Event Espresso', 'event_espresso')
2356
+		);
2357
+		add_meta_box(
2358
+			'espresso_news_post_box',
2359
+			$news_box_title,
2360
+			array(
2361
+				$this,
2362
+				'espresso_news_post_box',
2363
+			),
2364
+			$this->_wp_page_slug,
2365
+			'side'
2366
+		);
2367
+	}
2368
+
2369
+
2370
+	/**
2371
+	 * Code for setting up espresso ratings request metabox.
2372
+	 */
2373
+	protected function _espresso_ratings_request()
2374
+	{
2375
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2376
+			return;
2377
+		}
2378
+		$ratings_box_title = apply_filters(
2379
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2380
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2381
+		);
2382
+		add_meta_box(
2383
+			'espresso_ratings_request',
2384
+			$ratings_box_title,
2385
+			array(
2386
+				$this,
2387
+				'espresso_ratings_request',
2388
+			),
2389
+			$this->_wp_page_slug,
2390
+			'side'
2391
+		);
2392
+	}
2393
+
2394
+
2395
+	/**
2396
+	 * Code for setting up espresso ratings request metabox content.
2397
+	 *
2398
+	 * @throws DomainException
2399
+	 */
2400
+	public function espresso_ratings_request()
2401
+	{
2402
+		EEH_Template::display_template(
2403
+			EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2404
+			array()
2405
+		);
2406
+	}
2407
+
2408
+
2409
+	public static function cached_rss_display($rss_id, $url)
2410
+	{
2411
+		$loading = '<p class="widget-loading hide-if-no-js">'
2412
+				   . __('Loading&#8230;', 'event_espresso')
2413
+				   . '</p><p class="hide-if-js">'
2414
+				   . esc_html__('This widget requires JavaScript.', 'event_espresso')
2415
+				   . '</p>';
2416
+		$pre = '<div class="espresso-rss-display">' . "\n\t";
2417
+		$pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2418
+		$post = '</div>' . "\n";
2419
+		$cache_key = 'ee_rss_' . md5($rss_id);
2420
+		$output = get_transient($cache_key);
2421
+		if ($output !== false) {
2422
+			echo $pre . $output . $post;
2423
+			return true;
2424
+		}
2425
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2426
+			echo $pre . $loading . $post;
2427
+			return false;
2428
+		}
2429
+		ob_start();
2430
+		wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2431
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2432
+		return true;
2433
+	}
2434
+
2435
+
2436
+	public function espresso_news_post_box()
2437
+	{
2438
+		?>
2439 2439
         <div class="padding">
2440 2440
             <div id="espresso_news_post_box_content" class="infolinks">
2441 2441
                 <?php
2442
-                // Get RSS Feed(s)
2443
-                self::cached_rss_display(
2444
-                    'espresso_news_post_box_content',
2445
-                    urlencode(
2446
-                        apply_filters(
2447
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2448
-                            'http://eventespresso.com/feed/'
2449
-                        )
2450
-                    )
2451
-                );
2452
-                ?>
2442
+				// Get RSS Feed(s)
2443
+				self::cached_rss_display(
2444
+					'espresso_news_post_box_content',
2445
+					urlencode(
2446
+						apply_filters(
2447
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2448
+							'http://eventespresso.com/feed/'
2449
+						)
2450
+					)
2451
+				);
2452
+				?>
2453 2453
             </div>
2454 2454
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2455 2455
         </div>
2456 2456
         <?php
2457
-    }
2458
-
2459
-
2460
-    private function _espresso_links_post_box()
2461
-    {
2462
-        // Hiding until we actually have content to put in here...
2463
-        // add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2464
-    }
2465
-
2466
-
2467
-    public function espresso_links_post_box()
2468
-    {
2469
-        // Hiding until we actually have content to put in here...
2470
-        // EEH_Template::display_template(
2471
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2472
-        // );
2473
-    }
2474
-
2475
-
2476
-    protected function _espresso_sponsors_post_box()
2477
-    {
2478
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2479
-            add_meta_box(
2480
-                'espresso_sponsors_post_box',
2481
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2482
-                array($this, 'espresso_sponsors_post_box'),
2483
-                $this->_wp_page_slug,
2484
-                'side'
2485
-            );
2486
-        }
2487
-    }
2488
-
2489
-
2490
-    public function espresso_sponsors_post_box()
2491
-    {
2492
-        EEH_Template::display_template(
2493
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2494
-        );
2495
-    }
2496
-
2497
-
2498
-    private function _publish_post_box()
2499
-    {
2500
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2501
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2502
-        // then we'll use that for the metabox label.
2503
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2504
-        if (! empty($this->_labels['publishbox'])) {
2505
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2506
-                : $this->_labels['publishbox'];
2507
-        } else {
2508
-            $box_label = esc_html__('Publish', 'event_espresso');
2509
-        }
2510
-        $box_label = apply_filters(
2511
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2512
-            $box_label,
2513
-            $this->_req_action,
2514
-            $this
2515
-        );
2516
-        add_meta_box(
2517
-            $meta_box_ref,
2518
-            $box_label,
2519
-            array($this, 'editor_overview'),
2520
-            $this->_current_screen->id,
2521
-            'side',
2522
-            'high'
2523
-        );
2524
-    }
2525
-
2526
-
2527
-    public function editor_overview()
2528
-    {
2529
-        // if we have extra content set let's add it in if not make sure its empty
2530
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2531
-            ? $this->_template_args['publish_box_extra_content']
2532
-            : '';
2533
-        echo EEH_Template::display_template(
2534
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2535
-            $this->_template_args,
2536
-            true
2537
-        );
2538
-    }
2539
-
2540
-
2541
-    /** end of globally available metaboxes section **/
2542
-
2543
-
2544
-    /**
2545
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2546
-     * protected method.
2547
-     *
2548
-     * @see   $this->_set_publish_post_box_vars for param details
2549
-     * @since 4.6.0
2550
-     * @param string $name
2551
-     * @param int    $id
2552
-     * @param bool   $delete
2553
-     * @param string $save_close_redirect_URL
2554
-     * @param bool   $both_btns
2555
-     * @throws EE_Error
2556
-     * @throws InvalidArgumentException
2557
-     * @throws InvalidDataTypeException
2558
-     * @throws InvalidInterfaceException
2559
-     */
2560
-    public function set_publish_post_box_vars(
2561
-        $name = '',
2562
-        $id = 0,
2563
-        $delete = false,
2564
-        $save_close_redirect_URL = '',
2565
-        $both_btns = true
2566
-    ) {
2567
-        $this->_set_publish_post_box_vars(
2568
-            $name,
2569
-            $id,
2570
-            $delete,
2571
-            $save_close_redirect_URL,
2572
-            $both_btns
2573
-        );
2574
-    }
2575
-
2576
-
2577
-    /**
2578
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2579
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2580
-     * save, and save and close buttons to work properly, then you will want to include a
2581
-     * values for the name and id arguments.
2582
-     *
2583
-     * @todo  Add in validation for name/id arguments.
2584
-     * @param    string  $name                    key used for the action ID (i.e. event_id)
2585
-     * @param    int     $id                      id attached to the item published
2586
-     * @param    string  $delete                  page route callback for the delete action
2587
-     * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2588
-     * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2589
-     *                                            the Save button
2590
-     * @throws EE_Error
2591
-     * @throws InvalidArgumentException
2592
-     * @throws InvalidDataTypeException
2593
-     * @throws InvalidInterfaceException
2594
-     */
2595
-    protected function _set_publish_post_box_vars(
2596
-        $name = '',
2597
-        $id = 0,
2598
-        $delete = '',
2599
-        $save_close_redirect_URL = '',
2600
-        $both_btns = true
2601
-    ) {
2602
-        // if Save & Close, use a custom redirect URL or default to the main page?
2603
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2604
-            ? $save_close_redirect_URL
2605
-            : $this->_admin_base_url;
2606
-        // create the Save & Close and Save buttons
2607
-        $this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2608
-        // if we have extra content set let's add it in if not make sure its empty
2609
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2610
-            ? $this->_template_args['publish_box_extra_content']
2611
-            : '';
2612
-        if ($delete && ! empty($id)) {
2613
-            // make sure we have a default if just true is sent.
2614
-            $delete = ! empty($delete) ? $delete : 'delete';
2615
-            $delete_link_args = array($name => $id);
2616
-            $delete = $this->get_action_link_or_button(
2617
-                $delete,
2618
-                $delete,
2619
-                $delete_link_args,
2620
-                'submitdelete deletion',
2621
-                '',
2622
-                false
2623
-            );
2624
-        }
2625
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2626
-        if (! empty($name) && ! empty($id)) {
2627
-            $hidden_field_arr[ $name ] = array(
2628
-                'type'  => 'hidden',
2629
-                'value' => $id,
2630
-            );
2631
-            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2632
-        } else {
2633
-            $hf = '';
2634
-        }
2635
-        // add hidden field
2636
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2637
-            ? $hf[ $name ]['field']
2638
-            : $hf;
2639
-    }
2640
-
2641
-
2642
-    /**
2643
-     * displays an error message to ppl who have javascript disabled
2644
-     *
2645
-     * @return void
2646
-     */
2647
-    private function _display_no_javascript_warning()
2648
-    {
2649
-        ?>
2457
+	}
2458
+
2459
+
2460
+	private function _espresso_links_post_box()
2461
+	{
2462
+		// Hiding until we actually have content to put in here...
2463
+		// add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2464
+	}
2465
+
2466
+
2467
+	public function espresso_links_post_box()
2468
+	{
2469
+		// Hiding until we actually have content to put in here...
2470
+		// EEH_Template::display_template(
2471
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2472
+		// );
2473
+	}
2474
+
2475
+
2476
+	protected function _espresso_sponsors_post_box()
2477
+	{
2478
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2479
+			add_meta_box(
2480
+				'espresso_sponsors_post_box',
2481
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2482
+				array($this, 'espresso_sponsors_post_box'),
2483
+				$this->_wp_page_slug,
2484
+				'side'
2485
+			);
2486
+		}
2487
+	}
2488
+
2489
+
2490
+	public function espresso_sponsors_post_box()
2491
+	{
2492
+		EEH_Template::display_template(
2493
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2494
+		);
2495
+	}
2496
+
2497
+
2498
+	private function _publish_post_box()
2499
+	{
2500
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2501
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2502
+		// then we'll use that for the metabox label.
2503
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2504
+		if (! empty($this->_labels['publishbox'])) {
2505
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2506
+				: $this->_labels['publishbox'];
2507
+		} else {
2508
+			$box_label = esc_html__('Publish', 'event_espresso');
2509
+		}
2510
+		$box_label = apply_filters(
2511
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2512
+			$box_label,
2513
+			$this->_req_action,
2514
+			$this
2515
+		);
2516
+		add_meta_box(
2517
+			$meta_box_ref,
2518
+			$box_label,
2519
+			array($this, 'editor_overview'),
2520
+			$this->_current_screen->id,
2521
+			'side',
2522
+			'high'
2523
+		);
2524
+	}
2525
+
2526
+
2527
+	public function editor_overview()
2528
+	{
2529
+		// if we have extra content set let's add it in if not make sure its empty
2530
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2531
+			? $this->_template_args['publish_box_extra_content']
2532
+			: '';
2533
+		echo EEH_Template::display_template(
2534
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2535
+			$this->_template_args,
2536
+			true
2537
+		);
2538
+	}
2539
+
2540
+
2541
+	/** end of globally available metaboxes section **/
2542
+
2543
+
2544
+	/**
2545
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2546
+	 * protected method.
2547
+	 *
2548
+	 * @see   $this->_set_publish_post_box_vars for param details
2549
+	 * @since 4.6.0
2550
+	 * @param string $name
2551
+	 * @param int    $id
2552
+	 * @param bool   $delete
2553
+	 * @param string $save_close_redirect_URL
2554
+	 * @param bool   $both_btns
2555
+	 * @throws EE_Error
2556
+	 * @throws InvalidArgumentException
2557
+	 * @throws InvalidDataTypeException
2558
+	 * @throws InvalidInterfaceException
2559
+	 */
2560
+	public function set_publish_post_box_vars(
2561
+		$name = '',
2562
+		$id = 0,
2563
+		$delete = false,
2564
+		$save_close_redirect_URL = '',
2565
+		$both_btns = true
2566
+	) {
2567
+		$this->_set_publish_post_box_vars(
2568
+			$name,
2569
+			$id,
2570
+			$delete,
2571
+			$save_close_redirect_URL,
2572
+			$both_btns
2573
+		);
2574
+	}
2575
+
2576
+
2577
+	/**
2578
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2579
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2580
+	 * save, and save and close buttons to work properly, then you will want to include a
2581
+	 * values for the name and id arguments.
2582
+	 *
2583
+	 * @todo  Add in validation for name/id arguments.
2584
+	 * @param    string  $name                    key used for the action ID (i.e. event_id)
2585
+	 * @param    int     $id                      id attached to the item published
2586
+	 * @param    string  $delete                  page route callback for the delete action
2587
+	 * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2588
+	 * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2589
+	 *                                            the Save button
2590
+	 * @throws EE_Error
2591
+	 * @throws InvalidArgumentException
2592
+	 * @throws InvalidDataTypeException
2593
+	 * @throws InvalidInterfaceException
2594
+	 */
2595
+	protected function _set_publish_post_box_vars(
2596
+		$name = '',
2597
+		$id = 0,
2598
+		$delete = '',
2599
+		$save_close_redirect_URL = '',
2600
+		$both_btns = true
2601
+	) {
2602
+		// if Save & Close, use a custom redirect URL or default to the main page?
2603
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2604
+			? $save_close_redirect_URL
2605
+			: $this->_admin_base_url;
2606
+		// create the Save & Close and Save buttons
2607
+		$this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2608
+		// if we have extra content set let's add it in if not make sure its empty
2609
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2610
+			? $this->_template_args['publish_box_extra_content']
2611
+			: '';
2612
+		if ($delete && ! empty($id)) {
2613
+			// make sure we have a default if just true is sent.
2614
+			$delete = ! empty($delete) ? $delete : 'delete';
2615
+			$delete_link_args = array($name => $id);
2616
+			$delete = $this->get_action_link_or_button(
2617
+				$delete,
2618
+				$delete,
2619
+				$delete_link_args,
2620
+				'submitdelete deletion',
2621
+				'',
2622
+				false
2623
+			);
2624
+		}
2625
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2626
+		if (! empty($name) && ! empty($id)) {
2627
+			$hidden_field_arr[ $name ] = array(
2628
+				'type'  => 'hidden',
2629
+				'value' => $id,
2630
+			);
2631
+			$hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2632
+		} else {
2633
+			$hf = '';
2634
+		}
2635
+		// add hidden field
2636
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2637
+			? $hf[ $name ]['field']
2638
+			: $hf;
2639
+	}
2640
+
2641
+
2642
+	/**
2643
+	 * displays an error message to ppl who have javascript disabled
2644
+	 *
2645
+	 * @return void
2646
+	 */
2647
+	private function _display_no_javascript_warning()
2648
+	{
2649
+		?>
2650 2650
         <noscript>
2651 2651
             <div id="no-js-message" class="error">
2652 2652
                 <p style="font-size:1.3em;">
2653 2653
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2654 2654
                     <?php esc_html_e(
2655
-                        'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2656
-                        'event_espresso'
2657
-                    ); ?>
2655
+						'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2656
+						'event_espresso'
2657
+					); ?>
2658 2658
                 </p>
2659 2659
             </div>
2660 2660
         </noscript>
2661 2661
         <?php
2662
-    }
2663
-
2664
-
2665
-    /**
2666
-     * displays espresso success and/or error notices
2667
-     *
2668
-     * @return void
2669
-     */
2670
-    private function _display_espresso_notices()
2671
-    {
2672
-        $notices = $this->_get_transient(true);
2673
-        echo stripslashes($notices);
2674
-    }
2675
-
2676
-
2677
-    /**
2678
-     * spinny things pacify the masses
2679
-     *
2680
-     * @return void
2681
-     */
2682
-    protected function _add_admin_page_ajax_loading_img()
2683
-    {
2684
-        ?>
2662
+	}
2663
+
2664
+
2665
+	/**
2666
+	 * displays espresso success and/or error notices
2667
+	 *
2668
+	 * @return void
2669
+	 */
2670
+	private function _display_espresso_notices()
2671
+	{
2672
+		$notices = $this->_get_transient(true);
2673
+		echo stripslashes($notices);
2674
+	}
2675
+
2676
+
2677
+	/**
2678
+	 * spinny things pacify the masses
2679
+	 *
2680
+	 * @return void
2681
+	 */
2682
+	protected function _add_admin_page_ajax_loading_img()
2683
+	{
2684
+		?>
2685 2685
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2686 2686
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2687
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2687
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2688 2688
         </div>
2689 2689
         <?php
2690
-    }
2690
+	}
2691 2691
 
2692 2692
 
2693
-    /**
2694
-     * add admin page overlay for modal boxes
2695
-     *
2696
-     * @return void
2697
-     */
2698
-    protected function _add_admin_page_overlay()
2699
-    {
2700
-        ?>
2693
+	/**
2694
+	 * add admin page overlay for modal boxes
2695
+	 *
2696
+	 * @return void
2697
+	 */
2698
+	protected function _add_admin_page_overlay()
2699
+	{
2700
+		?>
2701 2701
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2702 2702
         <?php
2703
-    }
2704
-
2705
-
2706
-    /**
2707
-     * facade for add_meta_box
2708
-     *
2709
-     * @param string  $action        where the metabox get's displayed
2710
-     * @param string  $title         Title of Metabox (output in metabox header)
2711
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2712
-     *                               instead of the one created in here.
2713
-     * @param array   $callback_args an array of args supplied for the metabox
2714
-     * @param string  $column        what metabox column
2715
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2716
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2717
-     *                               created but just set our own callback for wp's add_meta_box.
2718
-     * @throws \DomainException
2719
-     */
2720
-    public function _add_admin_page_meta_box(
2721
-        $action,
2722
-        $title,
2723
-        $callback,
2724
-        $callback_args,
2725
-        $column = 'normal',
2726
-        $priority = 'high',
2727
-        $create_func = true
2728
-    ) {
2729
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2730
-        // if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2731
-        if (empty($callback_args) && $create_func) {
2732
-            $callback_args = array(
2733
-                'template_path' => $this->_template_path,
2734
-                'template_args' => $this->_template_args,
2735
-            );
2736
-        }
2737
-        // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2738
-        $call_back_func = $create_func
2739
-            ? function ($post, $metabox) {
2740
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2741
-                echo EEH_Template::display_template(
2742
-                    $metabox['args']['template_path'],
2743
-                    $metabox['args']['template_args'],
2744
-                    true
2745
-                );
2746
-            }
2747
-            : $callback;
2748
-        add_meta_box(
2749
-            str_replace('_', '-', $action) . '-mbox',
2750
-            $title,
2751
-            $call_back_func,
2752
-            $this->_wp_page_slug,
2753
-            $column,
2754
-            $priority,
2755
-            $callback_args
2756
-        );
2757
-    }
2758
-
2759
-
2760
-    /**
2761
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2762
-     *
2763
-     * @throws DomainException
2764
-     * @throws EE_Error
2765
-     */
2766
-    public function display_admin_page_with_metabox_columns()
2767
-    {
2768
-        $this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2769
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2770
-            $this->_column_template_path,
2771
-            $this->_template_args,
2772
-            true
2773
-        );
2774
-        // the final wrapper
2775
-        $this->admin_page_wrapper();
2776
-    }
2777
-
2778
-
2779
-    /**
2780
-     * generates  HTML wrapper for an admin details page
2781
-     *
2782
-     * @return void
2783
-     * @throws EE_Error
2784
-     * @throws DomainException
2785
-     */
2786
-    public function display_admin_page_with_sidebar()
2787
-    {
2788
-        $this->_display_admin_page(true);
2789
-    }
2790
-
2791
-
2792
-    /**
2793
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2794
-     *
2795
-     * @return void
2796
-     * @throws EE_Error
2797
-     * @throws DomainException
2798
-     */
2799
-    public function display_admin_page_with_no_sidebar()
2800
-    {
2801
-        $this->_display_admin_page();
2802
-    }
2803
-
2804
-
2805
-    /**
2806
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2807
-     *
2808
-     * @return void
2809
-     * @throws EE_Error
2810
-     * @throws DomainException
2811
-     */
2812
-    public function display_about_admin_page()
2813
-    {
2814
-        $this->_display_admin_page(false, true);
2815
-    }
2816
-
2817
-
2818
-    /**
2819
-     * display_admin_page
2820
-     * contains the code for actually displaying an admin page
2821
-     *
2822
-     * @param  boolean $sidebar true with sidebar, false without
2823
-     * @param  boolean $about   use the about admin wrapper instead of the default.
2824
-     * @return void
2825
-     * @throws DomainException
2826
-     * @throws EE_Error
2827
-     */
2828
-    private function _display_admin_page($sidebar = false, $about = false)
2829
-    {
2830
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2831
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2832
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2833
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2834
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2835
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2836
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2837
-            ? 'poststuff'
2838
-            : 'espresso-default-admin';
2839
-        $template_path = $sidebar
2840
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2841
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2842
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2843
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2844
-        }
2845
-        $template_path = ! empty($this->_column_template_path)
2846
-            ? $this->_column_template_path : $template_path;
2847
-        $this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content'])
2848
-            ? $this->_template_args['admin_page_content']
2849
-            : '';
2850
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2851
-            ? $this->_template_args['before_admin_page_content']
2852
-            : '';
2853
-        $this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content'])
2854
-            ? $this->_template_args['after_admin_page_content']
2855
-            : '';
2856
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2857
-            $template_path,
2858
-            $this->_template_args,
2859
-            true
2860
-        );
2861
-        // the final template wrapper
2862
-        $this->admin_page_wrapper($about);
2863
-    }
2864
-
2865
-
2866
-    /**
2867
-     * This is used to display caf preview pages.
2868
-     *
2869
-     * @since 4.3.2
2870
-     * @param string $utm_campaign_source what is the key used for google analytics link
2871
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2872
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2873
-     * @return void
2874
-     * @throws DomainException
2875
-     * @throws EE_Error
2876
-     * @throws InvalidArgumentException
2877
-     * @throws InvalidDataTypeException
2878
-     * @throws InvalidInterfaceException
2879
-     */
2880
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2881
-    {
2882
-        // let's generate a default preview action button if there isn't one already present.
2883
-        $this->_labels['buttons']['buy_now'] = esc_html__(
2884
-            'Upgrade to Event Espresso 4 Right Now',
2885
-            'event_espresso'
2886
-        );
2887
-        $buy_now_url = add_query_arg(
2888
-            array(
2889
-                'ee_ver'       => 'ee4',
2890
-                'utm_source'   => 'ee4_plugin_admin',
2891
-                'utm_medium'   => 'link',
2892
-                'utm_campaign' => $utm_campaign_source,
2893
-                'utm_content'  => 'buy_now_button',
2894
-            ),
2895
-            'http://eventespresso.com/pricing/'
2896
-        );
2897
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2898
-            ? $this->get_action_link_or_button(
2899
-                '',
2900
-                'buy_now',
2901
-                array(),
2902
-                'button-primary button-large',
2903
-                $buy_now_url,
2904
-                true
2905
-            )
2906
-            : $this->_template_args['preview_action_button'];
2907
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2908
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2909
-            $this->_template_args,
2910
-            true
2911
-        );
2912
-        $this->_display_admin_page($display_sidebar);
2913
-    }
2914
-
2915
-
2916
-    /**
2917
-     * display_admin_list_table_page_with_sidebar
2918
-     * generates HTML wrapper for an admin_page with list_table
2919
-     *
2920
-     * @return void
2921
-     * @throws EE_Error
2922
-     * @throws DomainException
2923
-     */
2924
-    public function display_admin_list_table_page_with_sidebar()
2925
-    {
2926
-        $this->_display_admin_list_table_page(true);
2927
-    }
2928
-
2929
-
2930
-    /**
2931
-     * display_admin_list_table_page_with_no_sidebar
2932
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2933
-     *
2934
-     * @return void
2935
-     * @throws EE_Error
2936
-     * @throws DomainException
2937
-     */
2938
-    public function display_admin_list_table_page_with_no_sidebar()
2939
-    {
2940
-        $this->_display_admin_list_table_page();
2941
-    }
2942
-
2943
-
2944
-    /**
2945
-     * generates html wrapper for an admin_list_table page
2946
-     *
2947
-     * @param boolean $sidebar whether to display with sidebar or not.
2948
-     * @return void
2949
-     * @throws DomainException
2950
-     * @throws EE_Error
2951
-     */
2952
-    private function _display_admin_list_table_page($sidebar = false)
2953
-    {
2954
-        // setup search attributes
2955
-        $this->_set_search_attributes();
2956
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2957
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2958
-        $this->_template_args['table_url'] = defined('DOING_AJAX')
2959
-            ? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2960
-            : add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2961
-        $this->_template_args['list_table'] = $this->_list_table_object;
2962
-        $this->_template_args['current_route'] = $this->_req_action;
2963
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2964
-        $ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2965
-        if (! empty($ajax_sorting_callback)) {
2966
-            $sortable_list_table_form_fields = wp_nonce_field(
2967
-                $ajax_sorting_callback . '_nonce',
2968
-                $ajax_sorting_callback . '_nonce',
2969
-                false,
2970
-                false
2971
-            );
2972
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2973
-                                                . $this->page_slug
2974
-                                                . '" />';
2975
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2976
-                                                . $ajax_sorting_callback
2977
-                                                . '" />';
2978
-        } else {
2979
-            $sortable_list_table_form_fields = '';
2980
-        }
2981
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2982
-        $hidden_form_fields = isset($this->_template_args['list_table_hidden_fields'])
2983
-            ? $this->_template_args['list_table_hidden_fields']
2984
-            : '';
2985
-        $nonce_ref = $this->_req_action . '_nonce';
2986
-        $hidden_form_fields .= '<input type="hidden" name="'
2987
-                               . $nonce_ref
2988
-                               . '" value="'
2989
-                               . wp_create_nonce($nonce_ref)
2990
-                               . '">';
2991
-        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2992
-        // display message about search results?
2993
-        $this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
2994
-            ? '<p class="ee-search-results">' . sprintf(
2995
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2996
-                trim($this->_req_data['s'], '%')
2997
-            ) . '</p>'
2998
-            : '';
2999
-        // filter before_list_table template arg
3000
-        $this->_template_args['before_list_table'] = apply_filters(
3001
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3002
-            $this->_template_args['before_list_table'],
3003
-            $this->page_slug,
3004
-            $this->_req_data,
3005
-            $this->_req_action
3006
-        );
3007
-        // convert to array and filter again
3008
-        // arrays are easier to inject new items in a specific location,
3009
-        // but would not be backwards compatible, so we have to add a new filter
3010
-        $this->_template_args['before_list_table'] = implode(
3011
-            " \n",
3012
-            (array) apply_filters(
3013
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3014
-                (array) $this->_template_args['before_list_table'],
3015
-                $this->page_slug,
3016
-                $this->_req_data,
3017
-                $this->_req_action
3018
-            )
3019
-        );
3020
-        // filter after_list_table template arg
3021
-        $this->_template_args['after_list_table'] = apply_filters(
3022
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3023
-            $this->_template_args['after_list_table'],
3024
-            $this->page_slug,
3025
-            $this->_req_data,
3026
-            $this->_req_action
3027
-        );
3028
-        // convert to array and filter again
3029
-        // arrays are easier to inject new items in a specific location,
3030
-        // but would not be backwards compatible, so we have to add a new filter
3031
-        $this->_template_args['after_list_table'] = implode(
3032
-            " \n",
3033
-            (array) apply_filters(
3034
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3035
-                (array) $this->_template_args['after_list_table'],
3036
-                $this->page_slug,
3037
-                $this->_req_data,
3038
-                $this->_req_action
3039
-            )
3040
-        );
3041
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3042
-            $template_path,
3043
-            $this->_template_args,
3044
-            true
3045
-        );
3046
-        // the final template wrapper
3047
-        if ($sidebar) {
3048
-            $this->display_admin_page_with_sidebar();
3049
-        } else {
3050
-            $this->display_admin_page_with_no_sidebar();
3051
-        }
3052
-    }
3053
-
3054
-
3055
-    /**
3056
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3057
-     * html string for the legend.
3058
-     * $items are expected in an array in the following format:
3059
-     * $legend_items = array(
3060
-     *        'item_id' => array(
3061
-     *            'icon' => 'http://url_to_icon_being_described.png',
3062
-     *            'desc' => esc_html__('localized description of item');
3063
-     *        )
3064
-     * );
3065
-     *
3066
-     * @param  array $items see above for format of array
3067
-     * @return string html string of legend
3068
-     * @throws DomainException
3069
-     */
3070
-    protected function _display_legend($items)
3071
-    {
3072
-        $this->_template_args['items'] = apply_filters(
3073
-            'FHEE__EE_Admin_Page___display_legend__items',
3074
-            (array) $items,
3075
-            $this
3076
-        );
3077
-        return EEH_Template::display_template(
3078
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3079
-            $this->_template_args,
3080
-            true
3081
-        );
3082
-    }
3083
-
3084
-
3085
-    /**
3086
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3087
-     * The returned json object is created from an array in the following format:
3088
-     * array(
3089
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3090
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3091
-     *  'notices' => '', // - contains any EE_Error formatted notices
3092
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3093
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3094
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3095
-     *  that might be included in here)
3096
-     * )
3097
-     * The json object is populated by whatever is set in the $_template_args property.
3098
-     *
3099
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3100
-     *                                 instead of displayed.
3101
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3102
-     * @return void
3103
-     * @throws EE_Error
3104
-     */
3105
-    protected function _return_json($sticky_notices = false, $notices_arguments = array())
3106
-    {
3107
-        // make sure any EE_Error notices have been handled.
3108
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3109
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3110
-        unset($this->_template_args['data']);
3111
-        $json = array(
3112
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3113
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3114
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3115
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3116
-            'notices'   => EE_Error::get_notices(),
3117
-            'content'   => isset($this->_template_args['admin_page_content'])
3118
-                ? $this->_template_args['admin_page_content'] : '',
3119
-            'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3120
-            'isEEajax'  => true
3121
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3122
-        );
3123
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3124
-        if (null === error_get_last() || ! headers_sent()) {
3125
-            header('Content-Type: application/json; charset=UTF-8');
3126
-        }
3127
-        echo wp_json_encode($json);
3128
-        exit();
3129
-    }
3130
-
3131
-
3132
-    /**
3133
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3134
-     *
3135
-     * @return void
3136
-     * @throws EE_Error
3137
-     */
3138
-    public function return_json()
3139
-    {
3140
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3141
-            $this->_return_json();
3142
-        } else {
3143
-            throw new EE_Error(
3144
-                sprintf(
3145
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3146
-                    __FUNCTION__
3147
-                )
3148
-            );
3149
-        }
3150
-    }
3151
-
3152
-
3153
-    /**
3154
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3155
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3156
-     *
3157
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3158
-     */
3159
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3160
-    {
3161
-        $this->_hook_obj = $hook_obj;
3162
-    }
3163
-
3164
-
3165
-    /**
3166
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3167
-     *
3168
-     * @param  boolean $about whether to use the special about page wrapper or default.
3169
-     * @return void
3170
-     * @throws DomainException
3171
-     * @throws EE_Error
3172
-     */
3173
-    public function admin_page_wrapper($about = false)
3174
-    {
3175
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3176
-        $this->_nav_tabs = $this->_get_main_nav_tabs();
3177
-        $this->_template_args['nav_tabs'] = $this->_nav_tabs;
3178
-        $this->_template_args['admin_page_title'] = $this->_admin_page_title;
3179
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3180
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3181
-            isset($this->_template_args['before_admin_page_content'])
3182
-                ? $this->_template_args['before_admin_page_content']
3183
-                : ''
3184
-        );
3185
-        $this->_template_args['after_admin_page_content'] = apply_filters(
3186
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3187
-            isset($this->_template_args['after_admin_page_content'])
3188
-                ? $this->_template_args['after_admin_page_content']
3189
-                : ''
3190
-        );
3191
-        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3192
-        // load settings page wrapper template
3193
-        $template_path = ! defined('DOING_AJAX')
3194
-            ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3195
-            : EE_ADMIN_TEMPLATE
3196
-              . 'admin_wrapper_ajax.template.php';
3197
-        // about page?
3198
-        $template_path = $about
3199
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3200
-            : $template_path;
3201
-        if (defined('DOING_AJAX')) {
3202
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3203
-                $template_path,
3204
-                $this->_template_args,
3205
-                true
3206
-            );
3207
-            $this->_return_json();
3208
-        } else {
3209
-            EEH_Template::display_template($template_path, $this->_template_args);
3210
-        }
3211
-    }
3212
-
3213
-
3214
-    /**
3215
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3216
-     *
3217
-     * @return string html
3218
-     * @throws EE_Error
3219
-     */
3220
-    protected function _get_main_nav_tabs()
3221
-    {
3222
-        // let's generate the html using the EEH_Tabbed_Content helper.
3223
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3224
-        // (rather than setting in the page_routes array)
3225
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3226
-    }
3227
-
3228
-
3229
-    /**
3230
-     *        sort nav tabs
3231
-     *
3232
-     * @param $a
3233
-     * @param $b
3234
-     * @return int
3235
-     */
3236
-    private function _sort_nav_tabs($a, $b)
3237
-    {
3238
-        if ($a['order'] === $b['order']) {
3239
-            return 0;
3240
-        }
3241
-        return ($a['order'] < $b['order']) ? -1 : 1;
3242
-    }
3243
-
3244
-
3245
-    /**
3246
-     *    generates HTML for the forms used on admin pages
3247
-     *
3248
-     * @param    array $input_vars - array of input field details
3249
-     * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3250
-     *                             use)
3251
-     * @param bool     $id
3252
-     * @return string
3253
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3254
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3255
-     */
3256
-    protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3257
-    {
3258
-        $content = $generator === 'string'
3259
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3260
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3261
-        return $content;
3262
-    }
3263
-
3264
-
3265
-    /**
3266
-     * generates the "Save" and "Save & Close" buttons for edit forms
3267
-     *
3268
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3269
-     *                                   Close" button.
3270
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3271
-     *                                   'Save', [1] => 'save & close')
3272
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3273
-     *                                   via the "name" value in the button).  We can also use this to just dump
3274
-     *                                   default actions by submitting some other value.
3275
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3276
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3277
-     *                                   close (normal form handling).
3278
-     */
3279
-    protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3280
-    {
3281
-        // make sure $text and $actions are in an array
3282
-        $text = (array) $text;
3283
-        $actions = (array) $actions;
3284
-        $referrer_url = empty($referrer)
3285
-            ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3286
-              . $_SERVER['REQUEST_URI']
3287
-              . '" />'
3288
-            : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3289
-              . $referrer
3290
-              . '" />';
3291
-        $button_text = ! empty($text)
3292
-            ? $text
3293
-            : array(
3294
-                esc_html__('Save', 'event_espresso'),
3295
-                esc_html__('Save and Close', 'event_espresso'),
3296
-            );
3297
-        $default_names = array('save', 'save_and_close');
3298
-        // add in a hidden index for the current page (so save and close redirects properly)
3299
-        $this->_template_args['save_buttons'] = $referrer_url;
3300
-        foreach ($button_text as $key => $button) {
3301
-            $ref = $default_names[ $key ];
3302
-            $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3303
-                                                     . $ref
3304
-                                                     . '" value="'
3305
-                                                     . $button
3306
-                                                     . '" name="'
3307
-                                                     . (! empty($actions) ? $actions[ $key ] : $ref)
3308
-                                                     . '" id="'
3309
-                                                     . $this->_current_view . '_' . $ref
3310
-                                                     . '" />';
3311
-            if (! $both) {
3312
-                break;
3313
-            }
3314
-        }
3315
-    }
3316
-
3317
-
3318
-    /**
3319
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3320
-     *
3321
-     * @see   $this->_set_add_edit_form_tags() for details on params
3322
-     * @since 4.6.0
3323
-     * @param string $route
3324
-     * @param array  $additional_hidden_fields
3325
-     */
3326
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3327
-    {
3328
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3329
-    }
3330
-
3331
-
3332
-    /**
3333
-     * set form open and close tags on add/edit pages.
3334
-     *
3335
-     * @param string $route                    the route you want the form to direct to
3336
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3337
-     * @return void
3338
-     */
3339
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3340
-    {
3341
-        if (empty($route)) {
3342
-            $user_msg = esc_html__(
3343
-                'An error occurred. No action was set for this page\'s form.',
3344
-                'event_espresso'
3345
-            );
3346
-            $dev_msg = $user_msg . "\n"
3347
-                       . sprintf(
3348
-                           esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3349
-                           __FUNCTION__,
3350
-                           __CLASS__
3351
-                       );
3352
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3353
-        }
3354
-        // open form
3355
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3356
-                                                             . $this->_admin_base_url
3357
-                                                             . '" id="'
3358
-                                                             . $route
3359
-                                                             . '_event_form" >';
3360
-        // add nonce
3361
-        $nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3362
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3363
-        // add REQUIRED form action
3364
-        $hidden_fields = array(
3365
-            'action' => array('type' => 'hidden', 'value' => $route),
3366
-        );
3367
-        // merge arrays
3368
-        $hidden_fields = is_array($additional_hidden_fields)
3369
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3370
-            : $hidden_fields;
3371
-        // generate form fields
3372
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3373
-        // add fields to form
3374
-        foreach ((array) $form_fields as $field_name => $form_field) {
3375
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3376
-        }
3377
-        // close form
3378
-        $this->_template_args['after_admin_page_content'] = '</form>';
3379
-    }
3380
-
3381
-
3382
-    /**
3383
-     * Public Wrapper for _redirect_after_action() method since its
3384
-     * discovered it would be useful for external code to have access.
3385
-     *
3386
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3387
-     * @since 4.5.0
3388
-     * @param bool   $success
3389
-     * @param string $what
3390
-     * @param string $action_desc
3391
-     * @param array  $query_args
3392
-     * @param bool   $override_overwrite
3393
-     * @throws EE_Error
3394
-     */
3395
-    public function redirect_after_action(
3396
-        $success = false,
3397
-        $what = 'item',
3398
-        $action_desc = 'processed',
3399
-        $query_args = array(),
3400
-        $override_overwrite = false
3401
-    ) {
3402
-        $this->_redirect_after_action(
3403
-            $success,
3404
-            $what,
3405
-            $action_desc,
3406
-            $query_args,
3407
-            $override_overwrite
3408
-        );
3409
-    }
3410
-
3411
-
3412
-    /**
3413
-     * Helper method for merging existing request data with the returned redirect url.
3414
-     *
3415
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3416
-     * filters are still applied.
3417
-     *
3418
-     * @param array $new_route_data
3419
-     * @return array
3420
-     */
3421
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3422
-    {
3423
-        foreach ($this->_req_data as $ref => $value) {
3424
-            // unset nonces
3425
-            if (strpos($ref, 'nonce') !== false) {
3426
-                unset($this->_req_data[ $ref ]);
3427
-                continue;
3428
-            }
3429
-            // urlencode values.
3430
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3431
-            $this->_req_data[ $ref ] = $value;
3432
-        }
3433
-        return array_merge($this->_req_data, $new_route_data);
3434
-    }
3435
-
3436
-
3437
-    /**
3438
-     *    _redirect_after_action
3439
-     *
3440
-     * @param int    $success            - whether success was for two or more records, or just one, or none
3441
-     * @param string $what               - what the action was performed on
3442
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
3443
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3444
-     *                                   action is completed
3445
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3446
-     *                                   override this so that they show.
3447
-     * @return void
3448
-     * @throws EE_Error
3449
-     */
3450
-    protected function _redirect_after_action(
3451
-        $success = 0,
3452
-        $what = 'item',
3453
-        $action_desc = 'processed',
3454
-        $query_args = array(),
3455
-        $override_overwrite = false
3456
-    ) {
3457
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3458
-        // class name for actions/filters.
3459
-        $classname = get_class($this);
3460
-        // set redirect url.
3461
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3462
-        // otherwise we go with whatever is set as the _admin_base_url
3463
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3464
-        $notices = EE_Error::get_notices(false);
3465
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3466
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3467
-            EE_Error::overwrite_success();
3468
-        }
3469
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3470
-            // how many records affected ? more than one record ? or just one ?
3471
-            if ($success > 1) {
3472
-                // set plural msg
3473
-                EE_Error::add_success(
3474
-                    sprintf(
3475
-                        esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3476
-                        $what,
3477
-                        $action_desc
3478
-                    ),
3479
-                    __FILE__,
3480
-                    __FUNCTION__,
3481
-                    __LINE__
3482
-                );
3483
-            } elseif ($success === 1) {
3484
-                // set singular msg
3485
-                EE_Error::add_success(
3486
-                    sprintf(
3487
-                        esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3488
-                        $what,
3489
-                        $action_desc
3490
-                    ),
3491
-                    __FILE__,
3492
-                    __FUNCTION__,
3493
-                    __LINE__
3494
-                );
3495
-            }
3496
-        }
3497
-        // check that $query_args isn't something crazy
3498
-        if (! is_array($query_args)) {
3499
-            $query_args = array();
3500
-        }
3501
-        /**
3502
-         * Allow injecting actions before the query_args are modified for possible different
3503
-         * redirections on save and close actions
3504
-         *
3505
-         * @since 4.2.0
3506
-         * @param array $query_args       The original query_args array coming into the
3507
-         *                                method.
3508
-         */
3509
-        do_action(
3510
-            "AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3511
-            $query_args
3512
-        );
3513
-        // calculate where we're going (if we have a "save and close" button pushed)
3514
-        if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3515
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3516
-            $parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3517
-            // regenerate query args array from referrer URL
3518
-            parse_str($parsed_url['query'], $query_args);
3519
-            // correct page and action will be in the query args now
3520
-            $redirect_url = admin_url('admin.php');
3521
-        }
3522
-        // merge any default query_args set in _default_route_query_args property
3523
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3524
-            $args_to_merge = array();
3525
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3526
-                // is there a wp_referer array in our _default_route_query_args property?
3527
-                if ($query_param === 'wp_referer') {
3528
-                    $query_value = (array) $query_value;
3529
-                    foreach ($query_value as $reference => $value) {
3530
-                        if (strpos($reference, 'nonce') !== false) {
3531
-                            continue;
3532
-                        }
3533
-                        // finally we will override any arguments in the referer with
3534
-                        // what might be set on the _default_route_query_args array.
3535
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3536
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3537
-                        } else {
3538
-                            $args_to_merge[ $reference ] = urlencode($value);
3539
-                        }
3540
-                    }
3541
-                    continue;
3542
-                }
3543
-                $args_to_merge[ $query_param ] = $query_value;
3544
-            }
3545
-            // now let's merge these arguments but override with what was specifically sent in to the
3546
-            // redirect.
3547
-            $query_args = array_merge($args_to_merge, $query_args);
3548
-        }
3549
-        $this->_process_notices($query_args);
3550
-        // generate redirect url
3551
-        // if redirecting to anything other than the main page, add a nonce
3552
-        if (isset($query_args['action'])) {
3553
-            // manually generate wp_nonce and merge that with the query vars
3554
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3555
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3556
-        }
3557
-        // we're adding some hooks and filters in here for processing any things just before redirects
3558
-        // (example: an admin page has done an insert or update and we want to run something after that).
3559
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3560
-        $redirect_url = apply_filters(
3561
-            'FHEE_redirect_' . $classname . $this->_req_action,
3562
-            self::add_query_args_and_nonce($query_args, $redirect_url),
3563
-            $query_args
3564
-        );
3565
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3566
-        if (defined('DOING_AJAX')) {
3567
-            $default_data = array(
3568
-                'close'        => true,
3569
-                'redirect_url' => $redirect_url,
3570
-                'where'        => 'main',
3571
-                'what'         => 'append',
3572
-            );
3573
-            $this->_template_args['success'] = $success;
3574
-            $this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge(
3575
-                $default_data,
3576
-                $this->_template_args['data']
3577
-            ) : $default_data;
3578
-            $this->_return_json();
3579
-        }
3580
-        wp_safe_redirect($redirect_url);
3581
-        exit();
3582
-    }
3583
-
3584
-
3585
-    /**
3586
-     * process any notices before redirecting (or returning ajax request)
3587
-     * This method sets the $this->_template_args['notices'] attribute;
3588
-     *
3589
-     * @param  array $query_args        any query args that need to be used for notice transient ('action')
3590
-     * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and
3591
-     *                                  page_routes haven't been defined yet.
3592
-     * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we
3593
-     *                                  still save a transient for the notice.
3594
-     * @return void
3595
-     * @throws EE_Error
3596
-     */
3597
-    protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3598
-    {
3599
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3600
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3601
-            $notices = EE_Error::get_notices(false);
3602
-            if (empty($this->_template_args['success'])) {
3603
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3604
-            }
3605
-            if (empty($this->_template_args['errors'])) {
3606
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3607
-            }
3608
-            if (empty($this->_template_args['attention'])) {
3609
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3610
-            }
3611
-        }
3612
-        $this->_template_args['notices'] = EE_Error::get_notices();
3613
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3614
-        if (! defined('DOING_AJAX') || $sticky_notices) {
3615
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3616
-            $this->_add_transient(
3617
-                $route,
3618
-                $this->_template_args['notices'],
3619
-                true,
3620
-                $skip_route_verify
3621
-            );
3622
-        }
3623
-    }
3624
-
3625
-
3626
-    /**
3627
-     * get_action_link_or_button
3628
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3629
-     *
3630
-     * @param string $action        use this to indicate which action the url is generated with.
3631
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3632
-     *                              property.
3633
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3634
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3635
-     * @param string $base_url      If this is not provided
3636
-     *                              the _admin_base_url will be used as the default for the button base_url.
3637
-     *                              Otherwise this value will be used.
3638
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3639
-     * @return string
3640
-     * @throws InvalidArgumentException
3641
-     * @throws InvalidInterfaceException
3642
-     * @throws InvalidDataTypeException
3643
-     * @throws EE_Error
3644
-     */
3645
-    public function get_action_link_or_button(
3646
-        $action,
3647
-        $type = 'add',
3648
-        $extra_request = array(),
3649
-        $class = 'button-primary',
3650
-        $base_url = '',
3651
-        $exclude_nonce = false
3652
-    ) {
3653
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3654
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3655
-            throw new EE_Error(
3656
-                sprintf(
3657
-                    esc_html__(
3658
-                        'There is no page route for given action for the button.  This action was given: %s',
3659
-                        'event_espresso'
3660
-                    ),
3661
-                    $action
3662
-                )
3663
-            );
3664
-        }
3665
-        if (! isset($this->_labels['buttons'][ $type ])) {
3666
-            throw new EE_Error(
3667
-                sprintf(
3668
-                    __(
3669
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3670
-                        'event_espresso'
3671
-                    ),
3672
-                    $type
3673
-                )
3674
-            );
3675
-        }
3676
-        // finally check user access for this button.
3677
-        $has_access = $this->check_user_access($action, true);
3678
-        if (! $has_access) {
3679
-            return '';
3680
-        }
3681
-        $_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
3682
-        $query_args = array(
3683
-            'action' => $action,
3684
-        );
3685
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3686
-        if (! empty($extra_request)) {
3687
-            $query_args = array_merge($extra_request, $query_args);
3688
-        }
3689
-        $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3690
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3691
-    }
3692
-
3693
-
3694
-    /**
3695
-     * _per_page_screen_option
3696
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3697
-     *
3698
-     * @return void
3699
-     * @throws InvalidArgumentException
3700
-     * @throws InvalidInterfaceException
3701
-     * @throws InvalidDataTypeException
3702
-     */
3703
-    protected function _per_page_screen_option()
3704
-    {
3705
-        $option = 'per_page';
3706
-        $args = array(
3707
-            'label'   => apply_filters(
3708
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3709
-                $this->_admin_page_title,
3710
-                $this
3711
-            ),
3712
-            'default' => (int) apply_filters(
3713
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3714
-                20
3715
-            ),
3716
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3717
-        );
3718
-        // ONLY add the screen option if the user has access to it.
3719
-        if ($this->check_user_access($this->_current_view, true)) {
3720
-            add_screen_option($option, $args);
3721
-        }
3722
-    }
3723
-
3724
-
3725
-    /**
3726
-     * set_per_page_screen_option
3727
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3728
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3729
-     * admin_menu.
3730
-     *
3731
-     * @return void
3732
-     */
3733
-    private function _set_per_page_screen_options()
3734
-    {
3735
-        if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3736
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3737
-            if (! $user = wp_get_current_user()) {
3738
-                return;
3739
-            }
3740
-            $option = $_POST['wp_screen_options']['option'];
3741
-            $value = $_POST['wp_screen_options']['value'];
3742
-            if ($option != sanitize_key($option)) {
3743
-                return;
3744
-            }
3745
-            $map_option = $option;
3746
-            $option = str_replace('-', '_', $option);
3747
-            switch ($map_option) {
3748
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3749
-                    $value = (int) $value;
3750
-                    $max_value = apply_filters(
3751
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3752
-                        999,
3753
-                        $this->_current_page,
3754
-                        $this->_current_view
3755
-                    );
3756
-                    if ($value < 1) {
3757
-                        return;
3758
-                    }
3759
-                    $value = min($value, $max_value);
3760
-                    break;
3761
-                default:
3762
-                    $value = apply_filters(
3763
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3764
-                        false,
3765
-                        $option,
3766
-                        $value
3767
-                    );
3768
-                    if (false === $value) {
3769
-                        return;
3770
-                    }
3771
-                    break;
3772
-            }
3773
-            update_user_meta($user->ID, $option, $value);
3774
-            wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3775
-            exit;
3776
-        }
3777
-    }
3778
-
3779
-
3780
-    /**
3781
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3782
-     *
3783
-     * @param array $data array that will be assigned to template args.
3784
-     */
3785
-    public function set_template_args($data)
3786
-    {
3787
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3788
-    }
3789
-
3790
-
3791
-    /**
3792
-     * This makes available the WP transient system for temporarily moving data between routes
3793
-     *
3794
-     * @param string $route             the route that should receive the transient
3795
-     * @param array  $data              the data that gets sent
3796
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3797
-     *                                  normal route transient.
3798
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3799
-     *                                  when we are adding a transient before page_routes have been defined.
3800
-     * @return void
3801
-     * @throws EE_Error
3802
-     */
3803
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3804
-    {
3805
-        $user_id = get_current_user_id();
3806
-        if (! $skip_route_verify) {
3807
-            $this->_verify_route($route);
3808
-        }
3809
-        // now let's set the string for what kind of transient we're setting
3810
-        $transient = $notices
3811
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3812
-            : 'rte_tx_' . $route . '_' . $user_id;
3813
-        $data = $notices ? array('notices' => $data) : $data;
3814
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3815
-        $existing = is_multisite() && is_network_admin()
3816
-            ? get_site_transient($transient)
3817
-            : get_transient($transient);
3818
-        if ($existing) {
3819
-            $data = array_merge((array) $data, (array) $existing);
3820
-        }
3821
-        if (is_multisite() && is_network_admin()) {
3822
-            set_site_transient($transient, $data, 8);
3823
-        } else {
3824
-            set_transient($transient, $data, 8);
3825
-        }
3826
-    }
3827
-
3828
-
3829
-    /**
3830
-     * this retrieves the temporary transient that has been set for moving data between routes.
3831
-     *
3832
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3833
-     * @param string $route
3834
-     * @return mixed data
3835
-     */
3836
-    protected function _get_transient($notices = false, $route = '')
3837
-    {
3838
-        $user_id = get_current_user_id();
3839
-        $route = ! $route ? $this->_req_action : $route;
3840
-        $transient = $notices
3841
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3842
-            : 'rte_tx_' . $route . '_' . $user_id;
3843
-        $data = is_multisite() && is_network_admin()
3844
-            ? get_site_transient($transient)
3845
-            : get_transient($transient);
3846
-        // delete transient after retrieval (just in case it hasn't expired);
3847
-        if (is_multisite() && is_network_admin()) {
3848
-            delete_site_transient($transient);
3849
-        } else {
3850
-            delete_transient($transient);
3851
-        }
3852
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3853
-    }
3854
-
3855
-
3856
-    /**
3857
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3858
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3859
-     * default route callback on the EE_Admin page you want it run.)
3860
-     *
3861
-     * @return void
3862
-     */
3863
-    protected function _transient_garbage_collection()
3864
-    {
3865
-        global $wpdb;
3866
-        // retrieve all existing transients
3867
-        $query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3868
-        if ($results = $wpdb->get_results($query)) {
3869
-            foreach ($results as $result) {
3870
-                $transient = str_replace('_transient_', '', $result->option_name);
3871
-                get_transient($transient);
3872
-                if (is_multisite() && is_network_admin()) {
3873
-                    get_site_transient($transient);
3874
-                }
3875
-            }
3876
-        }
3877
-    }
3878
-
3879
-
3880
-    /**
3881
-     * get_view
3882
-     *
3883
-     * @return string content of _view property
3884
-     */
3885
-    public function get_view()
3886
-    {
3887
-        return $this->_view;
3888
-    }
3889
-
3890
-
3891
-    /**
3892
-     * getter for the protected $_views property
3893
-     *
3894
-     * @return array
3895
-     */
3896
-    public function get_views()
3897
-    {
3898
-        return $this->_views;
3899
-    }
3900
-
3901
-
3902
-    /**
3903
-     * get_current_page
3904
-     *
3905
-     * @return string _current_page property value
3906
-     */
3907
-    public function get_current_page()
3908
-    {
3909
-        return $this->_current_page;
3910
-    }
3911
-
3912
-
3913
-    /**
3914
-     * get_current_view
3915
-     *
3916
-     * @return string _current_view property value
3917
-     */
3918
-    public function get_current_view()
3919
-    {
3920
-        return $this->_current_view;
3921
-    }
3922
-
3923
-
3924
-    /**
3925
-     * get_current_screen
3926
-     *
3927
-     * @return object The current WP_Screen object
3928
-     */
3929
-    public function get_current_screen()
3930
-    {
3931
-        return $this->_current_screen;
3932
-    }
3933
-
3934
-
3935
-    /**
3936
-     * get_current_page_view_url
3937
-     *
3938
-     * @return string This returns the url for the current_page_view.
3939
-     */
3940
-    public function get_current_page_view_url()
3941
-    {
3942
-        return $this->_current_page_view_url;
3943
-    }
3944
-
3945
-
3946
-    /**
3947
-     * just returns the _req_data property
3948
-     *
3949
-     * @return array
3950
-     */
3951
-    public function get_request_data()
3952
-    {
3953
-        return $this->_req_data;
3954
-    }
3955
-
3956
-
3957
-    /**
3958
-     * returns the _req_data protected property
3959
-     *
3960
-     * @return string
3961
-     */
3962
-    public function get_req_action()
3963
-    {
3964
-        return $this->_req_action;
3965
-    }
3966
-
3967
-
3968
-    /**
3969
-     * @return bool  value of $_is_caf property
3970
-     */
3971
-    public function is_caf()
3972
-    {
3973
-        return $this->_is_caf;
3974
-    }
3975
-
3976
-
3977
-    /**
3978
-     * @return mixed
3979
-     */
3980
-    public function default_espresso_metaboxes()
3981
-    {
3982
-        return $this->_default_espresso_metaboxes;
3983
-    }
3984
-
3985
-
3986
-    /**
3987
-     * @return mixed
3988
-     */
3989
-    public function admin_base_url()
3990
-    {
3991
-        return $this->_admin_base_url;
3992
-    }
3993
-
3994
-
3995
-    /**
3996
-     * @return mixed
3997
-     */
3998
-    public function wp_page_slug()
3999
-    {
4000
-        return $this->_wp_page_slug;
4001
-    }
4002
-
4003
-
4004
-    /**
4005
-     * updates  espresso configuration settings
4006
-     *
4007
-     * @param string                   $tab
4008
-     * @param EE_Config_Base|EE_Config $config
4009
-     * @param string                   $file file where error occurred
4010
-     * @param string                   $func function  where error occurred
4011
-     * @param string                   $line line no where error occurred
4012
-     * @return boolean
4013
-     */
4014
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4015
-    {
4016
-        // remove any options that are NOT going to be saved with the config settings.
4017
-        if (isset($config->core->ee_ueip_optin)) {
4018
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4019
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4020
-            update_option('ee_ueip_has_notified', true);
4021
-        }
4022
-        // and save it (note we're also doing the network save here)
4023
-        $net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4024
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4025
-        if ($config_saved && $net_saved) {
4026
-            EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4027
-            return true;
4028
-        }
4029
-        EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4030
-        return false;
4031
-    }
4032
-
4033
-
4034
-    /**
4035
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4036
-     *
4037
-     * @return array
4038
-     */
4039
-    public function get_yes_no_values()
4040
-    {
4041
-        return $this->_yes_no_values;
4042
-    }
4043
-
4044
-
4045
-    protected function _get_dir()
4046
-    {
4047
-        $reflector = new ReflectionClass(get_class($this));
4048
-        return dirname($reflector->getFileName());
4049
-    }
4050
-
4051
-
4052
-    /**
4053
-     * A helper for getting a "next link".
4054
-     *
4055
-     * @param string $url   The url to link to
4056
-     * @param string $class The class to use.
4057
-     * @return string
4058
-     */
4059
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4060
-    {
4061
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4062
-    }
4063
-
4064
-
4065
-    /**
4066
-     * A helper for getting a "previous link".
4067
-     *
4068
-     * @param string $url   The url to link to
4069
-     * @param string $class The class to use.
4070
-     * @return string
4071
-     */
4072
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4073
-    {
4074
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4075
-    }
4076
-
4077
-
4078
-
4079
-
4080
-
4081
-
4082
-
4083
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4084
-
4085
-
4086
-    /**
4087
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4088
-     * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4089
-     * _req_data array.
4090
-     *
4091
-     * @return bool success/fail
4092
-     * @throws EE_Error
4093
-     * @throws InvalidArgumentException
4094
-     * @throws ReflectionException
4095
-     * @throws InvalidDataTypeException
4096
-     * @throws InvalidInterfaceException
4097
-     */
4098
-    protected function _process_resend_registration()
4099
-    {
4100
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4101
-        do_action(
4102
-            'AHEE__EE_Admin_Page___process_resend_registration',
4103
-            $this->_template_args['success'],
4104
-            $this->_req_data
4105
-        );
4106
-        return $this->_template_args['success'];
4107
-    }
4108
-
4109
-
4110
-    /**
4111
-     * This automatically processes any payment message notifications when manual payment has been applied.
4112
-     *
4113
-     * @param \EE_Payment $payment
4114
-     * @return bool success/fail
4115
-     */
4116
-    protected function _process_payment_notification(EE_Payment $payment)
4117
-    {
4118
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4119
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4120
-        $this->_template_args['success'] = apply_filters(
4121
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4122
-            false,
4123
-            $payment
4124
-        );
4125
-        return $this->_template_args['success'];
4126
-    }
2703
+	}
2704
+
2705
+
2706
+	/**
2707
+	 * facade for add_meta_box
2708
+	 *
2709
+	 * @param string  $action        where the metabox get's displayed
2710
+	 * @param string  $title         Title of Metabox (output in metabox header)
2711
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2712
+	 *                               instead of the one created in here.
2713
+	 * @param array   $callback_args an array of args supplied for the metabox
2714
+	 * @param string  $column        what metabox column
2715
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2716
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2717
+	 *                               created but just set our own callback for wp's add_meta_box.
2718
+	 * @throws \DomainException
2719
+	 */
2720
+	public function _add_admin_page_meta_box(
2721
+		$action,
2722
+		$title,
2723
+		$callback,
2724
+		$callback_args,
2725
+		$column = 'normal',
2726
+		$priority = 'high',
2727
+		$create_func = true
2728
+	) {
2729
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2730
+		// if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2731
+		if (empty($callback_args) && $create_func) {
2732
+			$callback_args = array(
2733
+				'template_path' => $this->_template_path,
2734
+				'template_args' => $this->_template_args,
2735
+			);
2736
+		}
2737
+		// if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2738
+		$call_back_func = $create_func
2739
+			? function ($post, $metabox) {
2740
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2741
+				echo EEH_Template::display_template(
2742
+					$metabox['args']['template_path'],
2743
+					$metabox['args']['template_args'],
2744
+					true
2745
+				);
2746
+			}
2747
+			: $callback;
2748
+		add_meta_box(
2749
+			str_replace('_', '-', $action) . '-mbox',
2750
+			$title,
2751
+			$call_back_func,
2752
+			$this->_wp_page_slug,
2753
+			$column,
2754
+			$priority,
2755
+			$callback_args
2756
+		);
2757
+	}
2758
+
2759
+
2760
+	/**
2761
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2762
+	 *
2763
+	 * @throws DomainException
2764
+	 * @throws EE_Error
2765
+	 */
2766
+	public function display_admin_page_with_metabox_columns()
2767
+	{
2768
+		$this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2769
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2770
+			$this->_column_template_path,
2771
+			$this->_template_args,
2772
+			true
2773
+		);
2774
+		// the final wrapper
2775
+		$this->admin_page_wrapper();
2776
+	}
2777
+
2778
+
2779
+	/**
2780
+	 * generates  HTML wrapper for an admin details page
2781
+	 *
2782
+	 * @return void
2783
+	 * @throws EE_Error
2784
+	 * @throws DomainException
2785
+	 */
2786
+	public function display_admin_page_with_sidebar()
2787
+	{
2788
+		$this->_display_admin_page(true);
2789
+	}
2790
+
2791
+
2792
+	/**
2793
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2794
+	 *
2795
+	 * @return void
2796
+	 * @throws EE_Error
2797
+	 * @throws DomainException
2798
+	 */
2799
+	public function display_admin_page_with_no_sidebar()
2800
+	{
2801
+		$this->_display_admin_page();
2802
+	}
2803
+
2804
+
2805
+	/**
2806
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2807
+	 *
2808
+	 * @return void
2809
+	 * @throws EE_Error
2810
+	 * @throws DomainException
2811
+	 */
2812
+	public function display_about_admin_page()
2813
+	{
2814
+		$this->_display_admin_page(false, true);
2815
+	}
2816
+
2817
+
2818
+	/**
2819
+	 * display_admin_page
2820
+	 * contains the code for actually displaying an admin page
2821
+	 *
2822
+	 * @param  boolean $sidebar true with sidebar, false without
2823
+	 * @param  boolean $about   use the about admin wrapper instead of the default.
2824
+	 * @return void
2825
+	 * @throws DomainException
2826
+	 * @throws EE_Error
2827
+	 */
2828
+	private function _display_admin_page($sidebar = false, $about = false)
2829
+	{
2830
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2831
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2832
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2833
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2834
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2835
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2836
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2837
+			? 'poststuff'
2838
+			: 'espresso-default-admin';
2839
+		$template_path = $sidebar
2840
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2841
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2842
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2843
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2844
+		}
2845
+		$template_path = ! empty($this->_column_template_path)
2846
+			? $this->_column_template_path : $template_path;
2847
+		$this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content'])
2848
+			? $this->_template_args['admin_page_content']
2849
+			: '';
2850
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2851
+			? $this->_template_args['before_admin_page_content']
2852
+			: '';
2853
+		$this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content'])
2854
+			? $this->_template_args['after_admin_page_content']
2855
+			: '';
2856
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2857
+			$template_path,
2858
+			$this->_template_args,
2859
+			true
2860
+		);
2861
+		// the final template wrapper
2862
+		$this->admin_page_wrapper($about);
2863
+	}
2864
+
2865
+
2866
+	/**
2867
+	 * This is used to display caf preview pages.
2868
+	 *
2869
+	 * @since 4.3.2
2870
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2871
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2872
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2873
+	 * @return void
2874
+	 * @throws DomainException
2875
+	 * @throws EE_Error
2876
+	 * @throws InvalidArgumentException
2877
+	 * @throws InvalidDataTypeException
2878
+	 * @throws InvalidInterfaceException
2879
+	 */
2880
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2881
+	{
2882
+		// let's generate a default preview action button if there isn't one already present.
2883
+		$this->_labels['buttons']['buy_now'] = esc_html__(
2884
+			'Upgrade to Event Espresso 4 Right Now',
2885
+			'event_espresso'
2886
+		);
2887
+		$buy_now_url = add_query_arg(
2888
+			array(
2889
+				'ee_ver'       => 'ee4',
2890
+				'utm_source'   => 'ee4_plugin_admin',
2891
+				'utm_medium'   => 'link',
2892
+				'utm_campaign' => $utm_campaign_source,
2893
+				'utm_content'  => 'buy_now_button',
2894
+			),
2895
+			'http://eventespresso.com/pricing/'
2896
+		);
2897
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2898
+			? $this->get_action_link_or_button(
2899
+				'',
2900
+				'buy_now',
2901
+				array(),
2902
+				'button-primary button-large',
2903
+				$buy_now_url,
2904
+				true
2905
+			)
2906
+			: $this->_template_args['preview_action_button'];
2907
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2908
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2909
+			$this->_template_args,
2910
+			true
2911
+		);
2912
+		$this->_display_admin_page($display_sidebar);
2913
+	}
2914
+
2915
+
2916
+	/**
2917
+	 * display_admin_list_table_page_with_sidebar
2918
+	 * generates HTML wrapper for an admin_page with list_table
2919
+	 *
2920
+	 * @return void
2921
+	 * @throws EE_Error
2922
+	 * @throws DomainException
2923
+	 */
2924
+	public function display_admin_list_table_page_with_sidebar()
2925
+	{
2926
+		$this->_display_admin_list_table_page(true);
2927
+	}
2928
+
2929
+
2930
+	/**
2931
+	 * display_admin_list_table_page_with_no_sidebar
2932
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2933
+	 *
2934
+	 * @return void
2935
+	 * @throws EE_Error
2936
+	 * @throws DomainException
2937
+	 */
2938
+	public function display_admin_list_table_page_with_no_sidebar()
2939
+	{
2940
+		$this->_display_admin_list_table_page();
2941
+	}
2942
+
2943
+
2944
+	/**
2945
+	 * generates html wrapper for an admin_list_table page
2946
+	 *
2947
+	 * @param boolean $sidebar whether to display with sidebar or not.
2948
+	 * @return void
2949
+	 * @throws DomainException
2950
+	 * @throws EE_Error
2951
+	 */
2952
+	private function _display_admin_list_table_page($sidebar = false)
2953
+	{
2954
+		// setup search attributes
2955
+		$this->_set_search_attributes();
2956
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2957
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2958
+		$this->_template_args['table_url'] = defined('DOING_AJAX')
2959
+			? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2960
+			: add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2961
+		$this->_template_args['list_table'] = $this->_list_table_object;
2962
+		$this->_template_args['current_route'] = $this->_req_action;
2963
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2964
+		$ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2965
+		if (! empty($ajax_sorting_callback)) {
2966
+			$sortable_list_table_form_fields = wp_nonce_field(
2967
+				$ajax_sorting_callback . '_nonce',
2968
+				$ajax_sorting_callback . '_nonce',
2969
+				false,
2970
+				false
2971
+			);
2972
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2973
+												. $this->page_slug
2974
+												. '" />';
2975
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2976
+												. $ajax_sorting_callback
2977
+												. '" />';
2978
+		} else {
2979
+			$sortable_list_table_form_fields = '';
2980
+		}
2981
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2982
+		$hidden_form_fields = isset($this->_template_args['list_table_hidden_fields'])
2983
+			? $this->_template_args['list_table_hidden_fields']
2984
+			: '';
2985
+		$nonce_ref = $this->_req_action . '_nonce';
2986
+		$hidden_form_fields .= '<input type="hidden" name="'
2987
+							   . $nonce_ref
2988
+							   . '" value="'
2989
+							   . wp_create_nonce($nonce_ref)
2990
+							   . '">';
2991
+		$this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2992
+		// display message about search results?
2993
+		$this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
2994
+			? '<p class="ee-search-results">' . sprintf(
2995
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2996
+				trim($this->_req_data['s'], '%')
2997
+			) . '</p>'
2998
+			: '';
2999
+		// filter before_list_table template arg
3000
+		$this->_template_args['before_list_table'] = apply_filters(
3001
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3002
+			$this->_template_args['before_list_table'],
3003
+			$this->page_slug,
3004
+			$this->_req_data,
3005
+			$this->_req_action
3006
+		);
3007
+		// convert to array and filter again
3008
+		// arrays are easier to inject new items in a specific location,
3009
+		// but would not be backwards compatible, so we have to add a new filter
3010
+		$this->_template_args['before_list_table'] = implode(
3011
+			" \n",
3012
+			(array) apply_filters(
3013
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3014
+				(array) $this->_template_args['before_list_table'],
3015
+				$this->page_slug,
3016
+				$this->_req_data,
3017
+				$this->_req_action
3018
+			)
3019
+		);
3020
+		// filter after_list_table template arg
3021
+		$this->_template_args['after_list_table'] = apply_filters(
3022
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3023
+			$this->_template_args['after_list_table'],
3024
+			$this->page_slug,
3025
+			$this->_req_data,
3026
+			$this->_req_action
3027
+		);
3028
+		// convert to array and filter again
3029
+		// arrays are easier to inject new items in a specific location,
3030
+		// but would not be backwards compatible, so we have to add a new filter
3031
+		$this->_template_args['after_list_table'] = implode(
3032
+			" \n",
3033
+			(array) apply_filters(
3034
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3035
+				(array) $this->_template_args['after_list_table'],
3036
+				$this->page_slug,
3037
+				$this->_req_data,
3038
+				$this->_req_action
3039
+			)
3040
+		);
3041
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3042
+			$template_path,
3043
+			$this->_template_args,
3044
+			true
3045
+		);
3046
+		// the final template wrapper
3047
+		if ($sidebar) {
3048
+			$this->display_admin_page_with_sidebar();
3049
+		} else {
3050
+			$this->display_admin_page_with_no_sidebar();
3051
+		}
3052
+	}
3053
+
3054
+
3055
+	/**
3056
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3057
+	 * html string for the legend.
3058
+	 * $items are expected in an array in the following format:
3059
+	 * $legend_items = array(
3060
+	 *        'item_id' => array(
3061
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3062
+	 *            'desc' => esc_html__('localized description of item');
3063
+	 *        )
3064
+	 * );
3065
+	 *
3066
+	 * @param  array $items see above for format of array
3067
+	 * @return string html string of legend
3068
+	 * @throws DomainException
3069
+	 */
3070
+	protected function _display_legend($items)
3071
+	{
3072
+		$this->_template_args['items'] = apply_filters(
3073
+			'FHEE__EE_Admin_Page___display_legend__items',
3074
+			(array) $items,
3075
+			$this
3076
+		);
3077
+		return EEH_Template::display_template(
3078
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3079
+			$this->_template_args,
3080
+			true
3081
+		);
3082
+	}
3083
+
3084
+
3085
+	/**
3086
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3087
+	 * The returned json object is created from an array in the following format:
3088
+	 * array(
3089
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3090
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3091
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3092
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3093
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3094
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3095
+	 *  that might be included in here)
3096
+	 * )
3097
+	 * The json object is populated by whatever is set in the $_template_args property.
3098
+	 *
3099
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3100
+	 *                                 instead of displayed.
3101
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3102
+	 * @return void
3103
+	 * @throws EE_Error
3104
+	 */
3105
+	protected function _return_json($sticky_notices = false, $notices_arguments = array())
3106
+	{
3107
+		// make sure any EE_Error notices have been handled.
3108
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3109
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3110
+		unset($this->_template_args['data']);
3111
+		$json = array(
3112
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3113
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3114
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3115
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3116
+			'notices'   => EE_Error::get_notices(),
3117
+			'content'   => isset($this->_template_args['admin_page_content'])
3118
+				? $this->_template_args['admin_page_content'] : '',
3119
+			'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3120
+			'isEEajax'  => true
3121
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3122
+		);
3123
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3124
+		if (null === error_get_last() || ! headers_sent()) {
3125
+			header('Content-Type: application/json; charset=UTF-8');
3126
+		}
3127
+		echo wp_json_encode($json);
3128
+		exit();
3129
+	}
3130
+
3131
+
3132
+	/**
3133
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3134
+	 *
3135
+	 * @return void
3136
+	 * @throws EE_Error
3137
+	 */
3138
+	public function return_json()
3139
+	{
3140
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3141
+			$this->_return_json();
3142
+		} else {
3143
+			throw new EE_Error(
3144
+				sprintf(
3145
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3146
+					__FUNCTION__
3147
+				)
3148
+			);
3149
+		}
3150
+	}
3151
+
3152
+
3153
+	/**
3154
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3155
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3156
+	 *
3157
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3158
+	 */
3159
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3160
+	{
3161
+		$this->_hook_obj = $hook_obj;
3162
+	}
3163
+
3164
+
3165
+	/**
3166
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3167
+	 *
3168
+	 * @param  boolean $about whether to use the special about page wrapper or default.
3169
+	 * @return void
3170
+	 * @throws DomainException
3171
+	 * @throws EE_Error
3172
+	 */
3173
+	public function admin_page_wrapper($about = false)
3174
+	{
3175
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3176
+		$this->_nav_tabs = $this->_get_main_nav_tabs();
3177
+		$this->_template_args['nav_tabs'] = $this->_nav_tabs;
3178
+		$this->_template_args['admin_page_title'] = $this->_admin_page_title;
3179
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3180
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3181
+			isset($this->_template_args['before_admin_page_content'])
3182
+				? $this->_template_args['before_admin_page_content']
3183
+				: ''
3184
+		);
3185
+		$this->_template_args['after_admin_page_content'] = apply_filters(
3186
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3187
+			isset($this->_template_args['after_admin_page_content'])
3188
+				? $this->_template_args['after_admin_page_content']
3189
+				: ''
3190
+		);
3191
+		$this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3192
+		// load settings page wrapper template
3193
+		$template_path = ! defined('DOING_AJAX')
3194
+			? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3195
+			: EE_ADMIN_TEMPLATE
3196
+			  . 'admin_wrapper_ajax.template.php';
3197
+		// about page?
3198
+		$template_path = $about
3199
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3200
+			: $template_path;
3201
+		if (defined('DOING_AJAX')) {
3202
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3203
+				$template_path,
3204
+				$this->_template_args,
3205
+				true
3206
+			);
3207
+			$this->_return_json();
3208
+		} else {
3209
+			EEH_Template::display_template($template_path, $this->_template_args);
3210
+		}
3211
+	}
3212
+
3213
+
3214
+	/**
3215
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3216
+	 *
3217
+	 * @return string html
3218
+	 * @throws EE_Error
3219
+	 */
3220
+	protected function _get_main_nav_tabs()
3221
+	{
3222
+		// let's generate the html using the EEH_Tabbed_Content helper.
3223
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3224
+		// (rather than setting in the page_routes array)
3225
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3226
+	}
3227
+
3228
+
3229
+	/**
3230
+	 *        sort nav tabs
3231
+	 *
3232
+	 * @param $a
3233
+	 * @param $b
3234
+	 * @return int
3235
+	 */
3236
+	private function _sort_nav_tabs($a, $b)
3237
+	{
3238
+		if ($a['order'] === $b['order']) {
3239
+			return 0;
3240
+		}
3241
+		return ($a['order'] < $b['order']) ? -1 : 1;
3242
+	}
3243
+
3244
+
3245
+	/**
3246
+	 *    generates HTML for the forms used on admin pages
3247
+	 *
3248
+	 * @param    array $input_vars - array of input field details
3249
+	 * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3250
+	 *                             use)
3251
+	 * @param bool     $id
3252
+	 * @return string
3253
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3254
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3255
+	 */
3256
+	protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3257
+	{
3258
+		$content = $generator === 'string'
3259
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3260
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3261
+		return $content;
3262
+	}
3263
+
3264
+
3265
+	/**
3266
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3267
+	 *
3268
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3269
+	 *                                   Close" button.
3270
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3271
+	 *                                   'Save', [1] => 'save & close')
3272
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3273
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3274
+	 *                                   default actions by submitting some other value.
3275
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3276
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3277
+	 *                                   close (normal form handling).
3278
+	 */
3279
+	protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3280
+	{
3281
+		// make sure $text and $actions are in an array
3282
+		$text = (array) $text;
3283
+		$actions = (array) $actions;
3284
+		$referrer_url = empty($referrer)
3285
+			? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3286
+			  . $_SERVER['REQUEST_URI']
3287
+			  . '" />'
3288
+			: '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3289
+			  . $referrer
3290
+			  . '" />';
3291
+		$button_text = ! empty($text)
3292
+			? $text
3293
+			: array(
3294
+				esc_html__('Save', 'event_espresso'),
3295
+				esc_html__('Save and Close', 'event_espresso'),
3296
+			);
3297
+		$default_names = array('save', 'save_and_close');
3298
+		// add in a hidden index for the current page (so save and close redirects properly)
3299
+		$this->_template_args['save_buttons'] = $referrer_url;
3300
+		foreach ($button_text as $key => $button) {
3301
+			$ref = $default_names[ $key ];
3302
+			$this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3303
+													 . $ref
3304
+													 . '" value="'
3305
+													 . $button
3306
+													 . '" name="'
3307
+													 . (! empty($actions) ? $actions[ $key ] : $ref)
3308
+													 . '" id="'
3309
+													 . $this->_current_view . '_' . $ref
3310
+													 . '" />';
3311
+			if (! $both) {
3312
+				break;
3313
+			}
3314
+		}
3315
+	}
3316
+
3317
+
3318
+	/**
3319
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3320
+	 *
3321
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3322
+	 * @since 4.6.0
3323
+	 * @param string $route
3324
+	 * @param array  $additional_hidden_fields
3325
+	 */
3326
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3327
+	{
3328
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3329
+	}
3330
+
3331
+
3332
+	/**
3333
+	 * set form open and close tags on add/edit pages.
3334
+	 *
3335
+	 * @param string $route                    the route you want the form to direct to
3336
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3337
+	 * @return void
3338
+	 */
3339
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3340
+	{
3341
+		if (empty($route)) {
3342
+			$user_msg = esc_html__(
3343
+				'An error occurred. No action was set for this page\'s form.',
3344
+				'event_espresso'
3345
+			);
3346
+			$dev_msg = $user_msg . "\n"
3347
+					   . sprintf(
3348
+						   esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3349
+						   __FUNCTION__,
3350
+						   __CLASS__
3351
+					   );
3352
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3353
+		}
3354
+		// open form
3355
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3356
+															 . $this->_admin_base_url
3357
+															 . '" id="'
3358
+															 . $route
3359
+															 . '_event_form" >';
3360
+		// add nonce
3361
+		$nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3362
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3363
+		// add REQUIRED form action
3364
+		$hidden_fields = array(
3365
+			'action' => array('type' => 'hidden', 'value' => $route),
3366
+		);
3367
+		// merge arrays
3368
+		$hidden_fields = is_array($additional_hidden_fields)
3369
+			? array_merge($hidden_fields, $additional_hidden_fields)
3370
+			: $hidden_fields;
3371
+		// generate form fields
3372
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3373
+		// add fields to form
3374
+		foreach ((array) $form_fields as $field_name => $form_field) {
3375
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3376
+		}
3377
+		// close form
3378
+		$this->_template_args['after_admin_page_content'] = '</form>';
3379
+	}
3380
+
3381
+
3382
+	/**
3383
+	 * Public Wrapper for _redirect_after_action() method since its
3384
+	 * discovered it would be useful for external code to have access.
3385
+	 *
3386
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3387
+	 * @since 4.5.0
3388
+	 * @param bool   $success
3389
+	 * @param string $what
3390
+	 * @param string $action_desc
3391
+	 * @param array  $query_args
3392
+	 * @param bool   $override_overwrite
3393
+	 * @throws EE_Error
3394
+	 */
3395
+	public function redirect_after_action(
3396
+		$success = false,
3397
+		$what = 'item',
3398
+		$action_desc = 'processed',
3399
+		$query_args = array(),
3400
+		$override_overwrite = false
3401
+	) {
3402
+		$this->_redirect_after_action(
3403
+			$success,
3404
+			$what,
3405
+			$action_desc,
3406
+			$query_args,
3407
+			$override_overwrite
3408
+		);
3409
+	}
3410
+
3411
+
3412
+	/**
3413
+	 * Helper method for merging existing request data with the returned redirect url.
3414
+	 *
3415
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3416
+	 * filters are still applied.
3417
+	 *
3418
+	 * @param array $new_route_data
3419
+	 * @return array
3420
+	 */
3421
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3422
+	{
3423
+		foreach ($this->_req_data as $ref => $value) {
3424
+			// unset nonces
3425
+			if (strpos($ref, 'nonce') !== false) {
3426
+				unset($this->_req_data[ $ref ]);
3427
+				continue;
3428
+			}
3429
+			// urlencode values.
3430
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3431
+			$this->_req_data[ $ref ] = $value;
3432
+		}
3433
+		return array_merge($this->_req_data, $new_route_data);
3434
+	}
3435
+
3436
+
3437
+	/**
3438
+	 *    _redirect_after_action
3439
+	 *
3440
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
3441
+	 * @param string $what               - what the action was performed on
3442
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
3443
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3444
+	 *                                   action is completed
3445
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3446
+	 *                                   override this so that they show.
3447
+	 * @return void
3448
+	 * @throws EE_Error
3449
+	 */
3450
+	protected function _redirect_after_action(
3451
+		$success = 0,
3452
+		$what = 'item',
3453
+		$action_desc = 'processed',
3454
+		$query_args = array(),
3455
+		$override_overwrite = false
3456
+	) {
3457
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3458
+		// class name for actions/filters.
3459
+		$classname = get_class($this);
3460
+		// set redirect url.
3461
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3462
+		// otherwise we go with whatever is set as the _admin_base_url
3463
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3464
+		$notices = EE_Error::get_notices(false);
3465
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3466
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3467
+			EE_Error::overwrite_success();
3468
+		}
3469
+		if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3470
+			// how many records affected ? more than one record ? or just one ?
3471
+			if ($success > 1) {
3472
+				// set plural msg
3473
+				EE_Error::add_success(
3474
+					sprintf(
3475
+						esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3476
+						$what,
3477
+						$action_desc
3478
+					),
3479
+					__FILE__,
3480
+					__FUNCTION__,
3481
+					__LINE__
3482
+				);
3483
+			} elseif ($success === 1) {
3484
+				// set singular msg
3485
+				EE_Error::add_success(
3486
+					sprintf(
3487
+						esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3488
+						$what,
3489
+						$action_desc
3490
+					),
3491
+					__FILE__,
3492
+					__FUNCTION__,
3493
+					__LINE__
3494
+				);
3495
+			}
3496
+		}
3497
+		// check that $query_args isn't something crazy
3498
+		if (! is_array($query_args)) {
3499
+			$query_args = array();
3500
+		}
3501
+		/**
3502
+		 * Allow injecting actions before the query_args are modified for possible different
3503
+		 * redirections on save and close actions
3504
+		 *
3505
+		 * @since 4.2.0
3506
+		 * @param array $query_args       The original query_args array coming into the
3507
+		 *                                method.
3508
+		 */
3509
+		do_action(
3510
+			"AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3511
+			$query_args
3512
+		);
3513
+		// calculate where we're going (if we have a "save and close" button pushed)
3514
+		if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3515
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3516
+			$parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3517
+			// regenerate query args array from referrer URL
3518
+			parse_str($parsed_url['query'], $query_args);
3519
+			// correct page and action will be in the query args now
3520
+			$redirect_url = admin_url('admin.php');
3521
+		}
3522
+		// merge any default query_args set in _default_route_query_args property
3523
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3524
+			$args_to_merge = array();
3525
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3526
+				// is there a wp_referer array in our _default_route_query_args property?
3527
+				if ($query_param === 'wp_referer') {
3528
+					$query_value = (array) $query_value;
3529
+					foreach ($query_value as $reference => $value) {
3530
+						if (strpos($reference, 'nonce') !== false) {
3531
+							continue;
3532
+						}
3533
+						// finally we will override any arguments in the referer with
3534
+						// what might be set on the _default_route_query_args array.
3535
+						if (isset($this->_default_route_query_args[ $reference ])) {
3536
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3537
+						} else {
3538
+							$args_to_merge[ $reference ] = urlencode($value);
3539
+						}
3540
+					}
3541
+					continue;
3542
+				}
3543
+				$args_to_merge[ $query_param ] = $query_value;
3544
+			}
3545
+			// now let's merge these arguments but override with what was specifically sent in to the
3546
+			// redirect.
3547
+			$query_args = array_merge($args_to_merge, $query_args);
3548
+		}
3549
+		$this->_process_notices($query_args);
3550
+		// generate redirect url
3551
+		// if redirecting to anything other than the main page, add a nonce
3552
+		if (isset($query_args['action'])) {
3553
+			// manually generate wp_nonce and merge that with the query vars
3554
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3555
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3556
+		}
3557
+		// we're adding some hooks and filters in here for processing any things just before redirects
3558
+		// (example: an admin page has done an insert or update and we want to run something after that).
3559
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3560
+		$redirect_url = apply_filters(
3561
+			'FHEE_redirect_' . $classname . $this->_req_action,
3562
+			self::add_query_args_and_nonce($query_args, $redirect_url),
3563
+			$query_args
3564
+		);
3565
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3566
+		if (defined('DOING_AJAX')) {
3567
+			$default_data = array(
3568
+				'close'        => true,
3569
+				'redirect_url' => $redirect_url,
3570
+				'where'        => 'main',
3571
+				'what'         => 'append',
3572
+			);
3573
+			$this->_template_args['success'] = $success;
3574
+			$this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge(
3575
+				$default_data,
3576
+				$this->_template_args['data']
3577
+			) : $default_data;
3578
+			$this->_return_json();
3579
+		}
3580
+		wp_safe_redirect($redirect_url);
3581
+		exit();
3582
+	}
3583
+
3584
+
3585
+	/**
3586
+	 * process any notices before redirecting (or returning ajax request)
3587
+	 * This method sets the $this->_template_args['notices'] attribute;
3588
+	 *
3589
+	 * @param  array $query_args        any query args that need to be used for notice transient ('action')
3590
+	 * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and
3591
+	 *                                  page_routes haven't been defined yet.
3592
+	 * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we
3593
+	 *                                  still save a transient for the notice.
3594
+	 * @return void
3595
+	 * @throws EE_Error
3596
+	 */
3597
+	protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3598
+	{
3599
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3600
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3601
+			$notices = EE_Error::get_notices(false);
3602
+			if (empty($this->_template_args['success'])) {
3603
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3604
+			}
3605
+			if (empty($this->_template_args['errors'])) {
3606
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3607
+			}
3608
+			if (empty($this->_template_args['attention'])) {
3609
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3610
+			}
3611
+		}
3612
+		$this->_template_args['notices'] = EE_Error::get_notices();
3613
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3614
+		if (! defined('DOING_AJAX') || $sticky_notices) {
3615
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3616
+			$this->_add_transient(
3617
+				$route,
3618
+				$this->_template_args['notices'],
3619
+				true,
3620
+				$skip_route_verify
3621
+			);
3622
+		}
3623
+	}
3624
+
3625
+
3626
+	/**
3627
+	 * get_action_link_or_button
3628
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3629
+	 *
3630
+	 * @param string $action        use this to indicate which action the url is generated with.
3631
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3632
+	 *                              property.
3633
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3634
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3635
+	 * @param string $base_url      If this is not provided
3636
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3637
+	 *                              Otherwise this value will be used.
3638
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3639
+	 * @return string
3640
+	 * @throws InvalidArgumentException
3641
+	 * @throws InvalidInterfaceException
3642
+	 * @throws InvalidDataTypeException
3643
+	 * @throws EE_Error
3644
+	 */
3645
+	public function get_action_link_or_button(
3646
+		$action,
3647
+		$type = 'add',
3648
+		$extra_request = array(),
3649
+		$class = 'button-primary',
3650
+		$base_url = '',
3651
+		$exclude_nonce = false
3652
+	) {
3653
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3654
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3655
+			throw new EE_Error(
3656
+				sprintf(
3657
+					esc_html__(
3658
+						'There is no page route for given action for the button.  This action was given: %s',
3659
+						'event_espresso'
3660
+					),
3661
+					$action
3662
+				)
3663
+			);
3664
+		}
3665
+		if (! isset($this->_labels['buttons'][ $type ])) {
3666
+			throw new EE_Error(
3667
+				sprintf(
3668
+					__(
3669
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3670
+						'event_espresso'
3671
+					),
3672
+					$type
3673
+				)
3674
+			);
3675
+		}
3676
+		// finally check user access for this button.
3677
+		$has_access = $this->check_user_access($action, true);
3678
+		if (! $has_access) {
3679
+			return '';
3680
+		}
3681
+		$_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
3682
+		$query_args = array(
3683
+			'action' => $action,
3684
+		);
3685
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3686
+		if (! empty($extra_request)) {
3687
+			$query_args = array_merge($extra_request, $query_args);
3688
+		}
3689
+		$url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3690
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3691
+	}
3692
+
3693
+
3694
+	/**
3695
+	 * _per_page_screen_option
3696
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3697
+	 *
3698
+	 * @return void
3699
+	 * @throws InvalidArgumentException
3700
+	 * @throws InvalidInterfaceException
3701
+	 * @throws InvalidDataTypeException
3702
+	 */
3703
+	protected function _per_page_screen_option()
3704
+	{
3705
+		$option = 'per_page';
3706
+		$args = array(
3707
+			'label'   => apply_filters(
3708
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3709
+				$this->_admin_page_title,
3710
+				$this
3711
+			),
3712
+			'default' => (int) apply_filters(
3713
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3714
+				20
3715
+			),
3716
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3717
+		);
3718
+		// ONLY add the screen option if the user has access to it.
3719
+		if ($this->check_user_access($this->_current_view, true)) {
3720
+			add_screen_option($option, $args);
3721
+		}
3722
+	}
3723
+
3724
+
3725
+	/**
3726
+	 * set_per_page_screen_option
3727
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3728
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3729
+	 * admin_menu.
3730
+	 *
3731
+	 * @return void
3732
+	 */
3733
+	private function _set_per_page_screen_options()
3734
+	{
3735
+		if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3736
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3737
+			if (! $user = wp_get_current_user()) {
3738
+				return;
3739
+			}
3740
+			$option = $_POST['wp_screen_options']['option'];
3741
+			$value = $_POST['wp_screen_options']['value'];
3742
+			if ($option != sanitize_key($option)) {
3743
+				return;
3744
+			}
3745
+			$map_option = $option;
3746
+			$option = str_replace('-', '_', $option);
3747
+			switch ($map_option) {
3748
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3749
+					$value = (int) $value;
3750
+					$max_value = apply_filters(
3751
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3752
+						999,
3753
+						$this->_current_page,
3754
+						$this->_current_view
3755
+					);
3756
+					if ($value < 1) {
3757
+						return;
3758
+					}
3759
+					$value = min($value, $max_value);
3760
+					break;
3761
+				default:
3762
+					$value = apply_filters(
3763
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3764
+						false,
3765
+						$option,
3766
+						$value
3767
+					);
3768
+					if (false === $value) {
3769
+						return;
3770
+					}
3771
+					break;
3772
+			}
3773
+			update_user_meta($user->ID, $option, $value);
3774
+			wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3775
+			exit;
3776
+		}
3777
+	}
3778
+
3779
+
3780
+	/**
3781
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3782
+	 *
3783
+	 * @param array $data array that will be assigned to template args.
3784
+	 */
3785
+	public function set_template_args($data)
3786
+	{
3787
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3788
+	}
3789
+
3790
+
3791
+	/**
3792
+	 * This makes available the WP transient system for temporarily moving data between routes
3793
+	 *
3794
+	 * @param string $route             the route that should receive the transient
3795
+	 * @param array  $data              the data that gets sent
3796
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3797
+	 *                                  normal route transient.
3798
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3799
+	 *                                  when we are adding a transient before page_routes have been defined.
3800
+	 * @return void
3801
+	 * @throws EE_Error
3802
+	 */
3803
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3804
+	{
3805
+		$user_id = get_current_user_id();
3806
+		if (! $skip_route_verify) {
3807
+			$this->_verify_route($route);
3808
+		}
3809
+		// now let's set the string for what kind of transient we're setting
3810
+		$transient = $notices
3811
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3812
+			: 'rte_tx_' . $route . '_' . $user_id;
3813
+		$data = $notices ? array('notices' => $data) : $data;
3814
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3815
+		$existing = is_multisite() && is_network_admin()
3816
+			? get_site_transient($transient)
3817
+			: get_transient($transient);
3818
+		if ($existing) {
3819
+			$data = array_merge((array) $data, (array) $existing);
3820
+		}
3821
+		if (is_multisite() && is_network_admin()) {
3822
+			set_site_transient($transient, $data, 8);
3823
+		} else {
3824
+			set_transient($transient, $data, 8);
3825
+		}
3826
+	}
3827
+
3828
+
3829
+	/**
3830
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3831
+	 *
3832
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3833
+	 * @param string $route
3834
+	 * @return mixed data
3835
+	 */
3836
+	protected function _get_transient($notices = false, $route = '')
3837
+	{
3838
+		$user_id = get_current_user_id();
3839
+		$route = ! $route ? $this->_req_action : $route;
3840
+		$transient = $notices
3841
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3842
+			: 'rte_tx_' . $route . '_' . $user_id;
3843
+		$data = is_multisite() && is_network_admin()
3844
+			? get_site_transient($transient)
3845
+			: get_transient($transient);
3846
+		// delete transient after retrieval (just in case it hasn't expired);
3847
+		if (is_multisite() && is_network_admin()) {
3848
+			delete_site_transient($transient);
3849
+		} else {
3850
+			delete_transient($transient);
3851
+		}
3852
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3853
+	}
3854
+
3855
+
3856
+	/**
3857
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3858
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3859
+	 * default route callback on the EE_Admin page you want it run.)
3860
+	 *
3861
+	 * @return void
3862
+	 */
3863
+	protected function _transient_garbage_collection()
3864
+	{
3865
+		global $wpdb;
3866
+		// retrieve all existing transients
3867
+		$query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3868
+		if ($results = $wpdb->get_results($query)) {
3869
+			foreach ($results as $result) {
3870
+				$transient = str_replace('_transient_', '', $result->option_name);
3871
+				get_transient($transient);
3872
+				if (is_multisite() && is_network_admin()) {
3873
+					get_site_transient($transient);
3874
+				}
3875
+			}
3876
+		}
3877
+	}
3878
+
3879
+
3880
+	/**
3881
+	 * get_view
3882
+	 *
3883
+	 * @return string content of _view property
3884
+	 */
3885
+	public function get_view()
3886
+	{
3887
+		return $this->_view;
3888
+	}
3889
+
3890
+
3891
+	/**
3892
+	 * getter for the protected $_views property
3893
+	 *
3894
+	 * @return array
3895
+	 */
3896
+	public function get_views()
3897
+	{
3898
+		return $this->_views;
3899
+	}
3900
+
3901
+
3902
+	/**
3903
+	 * get_current_page
3904
+	 *
3905
+	 * @return string _current_page property value
3906
+	 */
3907
+	public function get_current_page()
3908
+	{
3909
+		return $this->_current_page;
3910
+	}
3911
+
3912
+
3913
+	/**
3914
+	 * get_current_view
3915
+	 *
3916
+	 * @return string _current_view property value
3917
+	 */
3918
+	public function get_current_view()
3919
+	{
3920
+		return $this->_current_view;
3921
+	}
3922
+
3923
+
3924
+	/**
3925
+	 * get_current_screen
3926
+	 *
3927
+	 * @return object The current WP_Screen object
3928
+	 */
3929
+	public function get_current_screen()
3930
+	{
3931
+		return $this->_current_screen;
3932
+	}
3933
+
3934
+
3935
+	/**
3936
+	 * get_current_page_view_url
3937
+	 *
3938
+	 * @return string This returns the url for the current_page_view.
3939
+	 */
3940
+	public function get_current_page_view_url()
3941
+	{
3942
+		return $this->_current_page_view_url;
3943
+	}
3944
+
3945
+
3946
+	/**
3947
+	 * just returns the _req_data property
3948
+	 *
3949
+	 * @return array
3950
+	 */
3951
+	public function get_request_data()
3952
+	{
3953
+		return $this->_req_data;
3954
+	}
3955
+
3956
+
3957
+	/**
3958
+	 * returns the _req_data protected property
3959
+	 *
3960
+	 * @return string
3961
+	 */
3962
+	public function get_req_action()
3963
+	{
3964
+		return $this->_req_action;
3965
+	}
3966
+
3967
+
3968
+	/**
3969
+	 * @return bool  value of $_is_caf property
3970
+	 */
3971
+	public function is_caf()
3972
+	{
3973
+		return $this->_is_caf;
3974
+	}
3975
+
3976
+
3977
+	/**
3978
+	 * @return mixed
3979
+	 */
3980
+	public function default_espresso_metaboxes()
3981
+	{
3982
+		return $this->_default_espresso_metaboxes;
3983
+	}
3984
+
3985
+
3986
+	/**
3987
+	 * @return mixed
3988
+	 */
3989
+	public function admin_base_url()
3990
+	{
3991
+		return $this->_admin_base_url;
3992
+	}
3993
+
3994
+
3995
+	/**
3996
+	 * @return mixed
3997
+	 */
3998
+	public function wp_page_slug()
3999
+	{
4000
+		return $this->_wp_page_slug;
4001
+	}
4002
+
4003
+
4004
+	/**
4005
+	 * updates  espresso configuration settings
4006
+	 *
4007
+	 * @param string                   $tab
4008
+	 * @param EE_Config_Base|EE_Config $config
4009
+	 * @param string                   $file file where error occurred
4010
+	 * @param string                   $func function  where error occurred
4011
+	 * @param string                   $line line no where error occurred
4012
+	 * @return boolean
4013
+	 */
4014
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4015
+	{
4016
+		// remove any options that are NOT going to be saved with the config settings.
4017
+		if (isset($config->core->ee_ueip_optin)) {
4018
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4019
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4020
+			update_option('ee_ueip_has_notified', true);
4021
+		}
4022
+		// and save it (note we're also doing the network save here)
4023
+		$net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4024
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4025
+		if ($config_saved && $net_saved) {
4026
+			EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4027
+			return true;
4028
+		}
4029
+		EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4030
+		return false;
4031
+	}
4032
+
4033
+
4034
+	/**
4035
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4036
+	 *
4037
+	 * @return array
4038
+	 */
4039
+	public function get_yes_no_values()
4040
+	{
4041
+		return $this->_yes_no_values;
4042
+	}
4043
+
4044
+
4045
+	protected function _get_dir()
4046
+	{
4047
+		$reflector = new ReflectionClass(get_class($this));
4048
+		return dirname($reflector->getFileName());
4049
+	}
4050
+
4051
+
4052
+	/**
4053
+	 * A helper for getting a "next link".
4054
+	 *
4055
+	 * @param string $url   The url to link to
4056
+	 * @param string $class The class to use.
4057
+	 * @return string
4058
+	 */
4059
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4060
+	{
4061
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4062
+	}
4063
+
4064
+
4065
+	/**
4066
+	 * A helper for getting a "previous link".
4067
+	 *
4068
+	 * @param string $url   The url to link to
4069
+	 * @param string $class The class to use.
4070
+	 * @return string
4071
+	 */
4072
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4073
+	{
4074
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4075
+	}
4076
+
4077
+
4078
+
4079
+
4080
+
4081
+
4082
+
4083
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4084
+
4085
+
4086
+	/**
4087
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4088
+	 * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4089
+	 * _req_data array.
4090
+	 *
4091
+	 * @return bool success/fail
4092
+	 * @throws EE_Error
4093
+	 * @throws InvalidArgumentException
4094
+	 * @throws ReflectionException
4095
+	 * @throws InvalidDataTypeException
4096
+	 * @throws InvalidInterfaceException
4097
+	 */
4098
+	protected function _process_resend_registration()
4099
+	{
4100
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4101
+		do_action(
4102
+			'AHEE__EE_Admin_Page___process_resend_registration',
4103
+			$this->_template_args['success'],
4104
+			$this->_req_data
4105
+		);
4106
+		return $this->_template_args['success'];
4107
+	}
4108
+
4109
+
4110
+	/**
4111
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4112
+	 *
4113
+	 * @param \EE_Payment $payment
4114
+	 * @return bool success/fail
4115
+	 */
4116
+	protected function _process_payment_notification(EE_Payment $payment)
4117
+	{
4118
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4119
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4120
+		$this->_template_args['success'] = apply_filters(
4121
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4122
+			false,
4123
+			$payment
4124
+		);
4125
+		return $this->_template_args['success'];
4126
+	}
4127 4127
 }
Please login to merge, or discard this patch.
Spacing   +185 added lines, -185 removed lines patch added patch discarded remove patch
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
         );
501 501
         global $ee_menu_slugs;
502 502
         $ee_menu_slugs = (array) $ee_menu_slugs;
503
-        if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))) {
503
+        if ( ! defined('DOING_AJAX') && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))) {
504 504
             return;
505 505
         }
506 506
         // becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
@@ -524,7 +524,7 @@  discard block
 block discarded – undo
524 524
             ? $this->_req_data['route']
525 525
             : $this->_req_action;
526 526
         $this->_current_view = $this->_req_action;
527
-        $this->_req_nonce = $this->_req_action . '_nonce';
527
+        $this->_req_nonce = $this->_req_action.'_nonce';
528 528
         $this->_define_page_props();
529 529
         $this->_current_page_view_url = add_query_arg(
530 530
             array('page' => $this->_current_page, 'action' => $this->_current_view),
@@ -558,21 +558,21 @@  discard block
 block discarded – undo
558 558
         }
559 559
         // filter routes and page_config so addons can add their stuff. Filtering done per class
560 560
         $this->_page_routes = apply_filters(
561
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
561
+            'FHEE__'.get_class($this).'__page_setup__page_routes',
562 562
             $this->_page_routes,
563 563
             $this
564 564
         );
565 565
         $this->_page_config = apply_filters(
566
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
566
+            'FHEE__'.get_class($this).'__page_setup__page_config',
567 567
             $this->_page_config,
568 568
             $this
569 569
         );
570 570
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
571 571
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
572
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
572
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
573 573
             add_action(
574 574
                 'AHEE__EE_Admin_Page__route_admin_request',
575
-                array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
575
+                array($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view),
576 576
                 10,
577 577
                 2
578 578
             );
@@ -585,8 +585,8 @@  discard block
 block discarded – undo
585 585
             if ($this->_is_UI_request) {
586 586
                 // admin_init stuff - global, all views for this page class, specific view
587 587
                 add_action('admin_init', array($this, 'admin_init'), 10);
588
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
589
-                    add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
588
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
589
+                    add_action('admin_init', array($this, 'admin_init_'.$this->_current_view), 15);
590 590
                 }
591 591
             } else {
592 592
                 // hijack regular WP loading and route admin request immediately
@@ -606,12 +606,12 @@  discard block
 block discarded – undo
606 606
      */
607 607
     private function _do_other_page_hooks()
608 608
     {
609
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
609
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, array());
610 610
         foreach ($registered_pages as $page) {
611 611
             // now let's setup the file name and class that should be present
612 612
             $classname = str_replace('.class.php', '', $page);
613 613
             // autoloaders should take care of loading file
614
-            if (! class_exists($classname)) {
614
+            if ( ! class_exists($classname)) {
615 615
                 $error_msg[] = sprintf(
616 616
                     esc_html__(
617 617
                         'Something went wrong with loading the %s admin hooks page.',
@@ -628,7 +628,7 @@  discard block
 block discarded – undo
628 628
                                    ),
629 629
                                    $page,
630 630
                                    '<br />',
631
-                                   '<strong>' . $classname . '</strong>'
631
+                                   '<strong>'.$classname.'</strong>'
632 632
                                );
633 633
                 throw new EE_Error(implode('||', $error_msg));
634 634
             }
@@ -668,13 +668,13 @@  discard block
 block discarded – undo
668 668
         // load admin_notices - global, page class, and view specific
669 669
         add_action('admin_notices', array($this, 'admin_notices_global'), 5);
670 670
         add_action('admin_notices', array($this, 'admin_notices'), 10);
671
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
672
-            add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
671
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
672
+            add_action('admin_notices', array($this, 'admin_notices_'.$this->_current_view), 15);
673 673
         }
674 674
         // load network admin_notices - global, page class, and view specific
675 675
         add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
676
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
677
-            add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
676
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
677
+            add_action('network_admin_notices', array($this, 'network_admin_notices_'.$this->_current_view));
678 678
         }
679 679
         // this will save any per_page screen options if they are present
680 680
         $this->_set_per_page_screen_options();
@@ -796,7 +796,7 @@  discard block
 block discarded – undo
796 796
     protected function _verify_routes()
797 797
     {
798 798
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
799
-        if (! $this->_current_page && ! defined('DOING_AJAX')) {
799
+        if ( ! $this->_current_page && ! defined('DOING_AJAX')) {
800 800
             return false;
801 801
         }
802 802
         $this->_route = false;
@@ -808,7 +808,7 @@  discard block
 block discarded – undo
808 808
                 $this->_admin_page_title
809 809
             );
810 810
             // developer error msg
811
-            $error_msg .= '||' . $error_msg
811
+            $error_msg .= '||'.$error_msg
812 812
                           . esc_html__(
813 813
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
814 814
                               'event_espresso'
@@ -817,9 +817,9 @@  discard block
 block discarded – undo
817 817
         }
818 818
         // and that the requested page route exists
819 819
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
820
-            $this->_route = $this->_page_routes[ $this->_req_action ];
821
-            $this->_route_config = isset($this->_page_config[ $this->_req_action ])
822
-                ? $this->_page_config[ $this->_req_action ] : array();
820
+            $this->_route = $this->_page_routes[$this->_req_action];
821
+            $this->_route_config = isset($this->_page_config[$this->_req_action])
822
+                ? $this->_page_config[$this->_req_action] : array();
823 823
         } else {
824 824
             // user error msg
825 825
             $error_msg = sprintf(
@@ -830,7 +830,7 @@  discard block
 block discarded – undo
830 830
                 $this->_admin_page_title
831 831
             );
832 832
             // developer error msg
833
-            $error_msg .= '||' . $error_msg
833
+            $error_msg .= '||'.$error_msg
834 834
                           . sprintf(
835 835
                               esc_html__(
836 836
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -841,7 +841,7 @@  discard block
 block discarded – undo
841 841
             throw new EE_Error($error_msg);
842 842
         }
843 843
         // and that a default route exists
844
-        if (! array_key_exists('default', $this->_page_routes)) {
844
+        if ( ! array_key_exists('default', $this->_page_routes)) {
845 845
             // user error msg
846 846
             $error_msg = sprintf(
847 847
                 esc_html__(
@@ -851,7 +851,7 @@  discard block
 block discarded – undo
851 851
                 $this->_admin_page_title
852 852
             );
853 853
             // developer error msg
854
-            $error_msg .= '||' . $error_msg
854
+            $error_msg .= '||'.$error_msg
855 855
                           . esc_html__(
856 856
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
857 857
                               'event_espresso'
@@ -890,7 +890,7 @@  discard block
 block discarded – undo
890 890
             $this->_admin_page_title
891 891
         );
892 892
         // developer error msg
893
-        $error_msg .= '||' . $error_msg
893
+        $error_msg .= '||'.$error_msg
894 894
                       . sprintf(
895 895
                           esc_html__(
896 896
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -915,7 +915,7 @@  discard block
 block discarded – undo
915 915
     protected function _verify_nonce($nonce, $nonce_ref)
916 916
     {
917 917
         // verify nonce against expected value
918
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
918
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
919 919
             // these are not the droids you are looking for !!!
920 920
             $msg = sprintf(
921 921
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -932,7 +932,7 @@  discard block
 block discarded – undo
932 932
                             __CLASS__
933 933
                         );
934 934
             }
935
-            if (! defined('DOING_AJAX')) {
935
+            if ( ! defined('DOING_AJAX')) {
936 936
                 wp_die($msg);
937 937
             } else {
938 938
                 EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -957,7 +957,7 @@  discard block
 block discarded – undo
957 957
      */
958 958
     protected function _route_admin_request()
959 959
     {
960
-        if (! $this->_is_UI_request) {
960
+        if ( ! $this->_is_UI_request) {
961 961
             $this->_verify_routes();
962 962
         }
963 963
         $nonce_check = isset($this->_route_config['require_nonce'])
@@ -965,8 +965,8 @@  discard block
 block discarded – undo
965 965
             : true;
966 966
         if ($this->_req_action !== 'default' && $nonce_check) {
967 967
             // set nonce from post data
968
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
969
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ])
968
+            $nonce = isset($this->_req_data[$this->_req_nonce])
969
+                ? sanitize_text_field($this->_req_data[$this->_req_nonce])
970 970
                 : '';
971 971
             $this->_verify_nonce($nonce, $this->_req_nonce);
972 972
         }
@@ -981,7 +981,7 @@  discard block
 block discarded – undo
981 981
         $error_msg = '';
982 982
         // action right before calling route
983 983
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
984
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
984
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
985 985
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
986 986
         }
987 987
         // right before calling the route, let's remove _wp_http_referer from the
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
             '_wp_http_referer',
991 991
             wp_unslash($_SERVER['REQUEST_URI'])
992 992
         );
993
-        if (! empty($func)) {
993
+        if ( ! empty($func)) {
994 994
             if (is_array($func)) {
995 995
                 list($class, $method) = $func;
996 996
             } elseif (strpos($func, '::') !== false) {
@@ -999,7 +999,7 @@  discard block
 block discarded – undo
999 999
                 $class = $this;
1000 1000
                 $method = $func;
1001 1001
             }
1002
-            if (! (is_object($class) && $class === $this)) {
1002
+            if ( ! (is_object($class) && $class === $this)) {
1003 1003
                 // send along this admin page object for access by addons.
1004 1004
                 $args['admin_page_object'] = $this;
1005 1005
             }
@@ -1039,7 +1039,7 @@  discard block
 block discarded – undo
1039 1039
                     $method
1040 1040
                 );
1041 1041
             }
1042
-            if (! empty($error_msg)) {
1042
+            if ( ! empty($error_msg)) {
1043 1043
                 throw new EE_Error($error_msg);
1044 1044
             }
1045 1045
         }
@@ -1123,7 +1123,7 @@  discard block
 block discarded – undo
1123 1123
                 if (strpos($key, 'nonce') !== false) {
1124 1124
                     continue;
1125 1125
                 }
1126
-                $args[ 'wp_referer[' . $key . ']' ] = $value;
1126
+                $args['wp_referer['.$key.']'] = $value;
1127 1127
             }
1128 1128
         }
1129 1129
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
@@ -1163,10 +1163,10 @@  discard block
 block discarded – undo
1163 1163
     protected function _add_help_tabs()
1164 1164
     {
1165 1165
         $tour_buttons = '';
1166
-        if (isset($this->_page_config[ $this->_req_action ])) {
1167
-            $config = $this->_page_config[ $this->_req_action ];
1166
+        if (isset($this->_page_config[$this->_req_action])) {
1167
+            $config = $this->_page_config[$this->_req_action];
1168 1168
             // is there a help tour for the current route?  if there is let's setup the tour buttons
1169
-            if (isset($this->_help_tour[ $this->_req_action ])) {
1169
+            if (isset($this->_help_tour[$this->_req_action])) {
1170 1170
                 $tb = array();
1171 1171
                 $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1172 1172
                 foreach ($this->_help_tour['tours'] as $tour) {
@@ -1186,7 +1186,7 @@  discard block
 block discarded – undo
1186 1186
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1187 1187
             if (is_array($config) && isset($config['help_sidebar'])) {
1188 1188
                 // check that the callback given is valid
1189
-                if (! method_exists($this, $config['help_sidebar'])) {
1189
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1190 1190
                     throw new EE_Error(
1191 1191
                         sprintf(
1192 1192
                             esc_html__(
@@ -1199,7 +1199,7 @@  discard block
 block discarded – undo
1199 1199
                     );
1200 1200
                 }
1201 1201
                 $content = apply_filters(
1202
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1202
+                    'FHEE__'.get_class($this).'__add_help_tabs__help_sidebar',
1203 1203
                     $this->{$config['help_sidebar']}()
1204 1204
                 );
1205 1205
                 $content .= $tour_buttons; // add help tour buttons.
@@ -1207,27 +1207,27 @@  discard block
 block discarded – undo
1207 1207
                 $this->_current_screen->set_help_sidebar($content);
1208 1208
             }
1209 1209
             // if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1210
-            if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1210
+            if ( ! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1211 1211
                 $this->_current_screen->set_help_sidebar($tour_buttons);
1212 1212
             }
1213 1213
             // handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1214
-            if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1214
+            if ( ! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1215 1215
                 $_ht['id'] = $this->page_slug;
1216 1216
                 $_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1217 1217
                 $_ht['content'] = '<p>'
1218 1218
                                   . esc_html__(
1219 1219
                                       'The buttons to the right allow you to start/restart any help tours available for this page',
1220 1220
                                       'event_espresso'
1221
-                                  ) . '</p>';
1221
+                                  ).'</p>';
1222 1222
                 $this->_current_screen->add_help_tab($_ht);
1223 1223
             }
1224
-            if (! isset($config['help_tabs'])) {
1224
+            if ( ! isset($config['help_tabs'])) {
1225 1225
                 return;
1226 1226
             } //no help tabs for this route
1227 1227
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1228 1228
                 // we're here so there ARE help tabs!
1229 1229
                 // make sure we've got what we need
1230
-                if (! isset($cfg['title'])) {
1230
+                if ( ! isset($cfg['title'])) {
1231 1231
                     throw new EE_Error(
1232 1232
                         esc_html__(
1233 1233
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1235,7 +1235,7 @@  discard block
 block discarded – undo
1235 1235
                         )
1236 1236
                     );
1237 1237
                 }
1238
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1238
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1239 1239
                     throw new EE_Error(
1240 1240
                         esc_html__(
1241 1241
                             'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
@@ -1244,11 +1244,11 @@  discard block
 block discarded – undo
1244 1244
                     );
1245 1245
                 }
1246 1246
                 // first priority goes to content.
1247
-                if (! empty($cfg['content'])) {
1247
+                if ( ! empty($cfg['content'])) {
1248 1248
                     $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1249 1249
                     // second priority goes to filename
1250
-                } elseif (! empty($cfg['filename'])) {
1251
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1250
+                } elseif ( ! empty($cfg['filename'])) {
1251
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1252 1252
                     // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1253 1253
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1254 1254
                                                              . basename($this->_get_dir())
@@ -1256,7 +1256,7 @@  discard block
 block discarded – undo
1256 1256
                                                              . $cfg['filename']
1257 1257
                                                              . '.help_tab.php' : $file_path;
1258 1258
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1259
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1259
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1260 1260
                         EE_Error::add_error(
1261 1261
                             sprintf(
1262 1262
                                 esc_html__(
@@ -1302,7 +1302,7 @@  discard block
 block discarded – undo
1302 1302
                     return;
1303 1303
                 }
1304 1304
                 // setup config array for help tab method
1305
-                $id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1305
+                $id = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1306 1306
                 $_ht = array(
1307 1307
                     'id'       => $id,
1308 1308
                     'title'    => $cfg['title'],
@@ -1346,7 +1346,7 @@  discard block
 block discarded – undo
1346 1346
             }
1347 1347
             if (isset($config['help_tour'])) {
1348 1348
                 foreach ($config['help_tour'] as $tour) {
1349
-                    $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1349
+                    $file_path = $this->_get_dir().'/help_tours/'.$tour.'.class.php';
1350 1350
                     // let's see if we can get that file...
1351 1351
                     // if not its possible this is a decaf route not set in caffeinated
1352 1352
                     // so lets try and get the caffeinated equivalent
@@ -1356,7 +1356,7 @@  discard block
 block discarded – undo
1356 1356
                                                              . $tour
1357 1357
                                                              . '.class.php' : $file_path;
1358 1358
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1359
-                    if (! is_readable($file_path)) {
1359
+                    if ( ! is_readable($file_path)) {
1360 1360
                         EE_Error::add_error(
1361 1361
                             sprintf(
1362 1362
                                 esc_html__(
@@ -1373,12 +1373,12 @@  discard block
 block discarded – undo
1373 1373
                         return;
1374 1374
                     }
1375 1375
                     require_once $file_path;
1376
-                    if (! class_exists($tour)) {
1376
+                    if ( ! class_exists($tour)) {
1377 1377
                         $error_msg[] = sprintf(
1378 1378
                             esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1379 1379
                             $tour
1380 1380
                         );
1381
-                        $error_msg[] = $error_msg[0] . "\r\n"
1381
+                        $error_msg[] = $error_msg[0]."\r\n"
1382 1382
                                        . sprintf(
1383 1383
                                            esc_html__(
1384 1384
                                                'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
@@ -1394,15 +1394,15 @@  discard block
 block discarded – undo
1394 1394
                     }
1395 1395
                     $tour_obj = new $tour($this->_is_caf);
1396 1396
                     $tours[] = $tour_obj;
1397
-                    $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1397
+                    $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1398 1398
                 }
1399 1399
                 // let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1400 1400
                 $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1401 1401
                 $tours[] = $end_stop_tour;
1402
-                $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1402
+                $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1403 1403
             }
1404 1404
         }
1405
-        if (! empty($tours)) {
1405
+        if ( ! empty($tours)) {
1406 1406
             $this->_help_tour['tours'] = $tours;
1407 1407
         }
1408 1408
         // that's it!  Now that the $_help_tours property is set (or not)
@@ -1421,8 +1421,8 @@  discard block
 block discarded – undo
1421 1421
             $qtips = (array) $this->_route_config['qtips'];
1422 1422
             // load qtip loader
1423 1423
             $path = array(
1424
-                $this->_get_dir() . '/qtips/',
1425
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1424
+                $this->_get_dir().'/qtips/',
1425
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1426 1426
             );
1427 1427
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1428 1428
         }
@@ -1444,7 +1444,7 @@  discard block
 block discarded – undo
1444 1444
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1445 1445
         $i = 0;
1446 1446
         foreach ($this->_page_config as $slug => $config) {
1447
-            if (! is_array($config)
1447
+            if ( ! is_array($config)
1448 1448
                 || (
1449 1449
                     is_array($config)
1450 1450
                     && (
@@ -1461,12 +1461,12 @@  discard block
 block discarded – undo
1461 1461
                 // nav tab is only to appear when route requested.
1462 1462
                 continue;
1463 1463
             }
1464
-            if (! $this->check_user_access($slug, true)) {
1464
+            if ( ! $this->check_user_access($slug, true)) {
1465 1465
                 // no nav tab because current user does not have access.
1466 1466
                 continue;
1467 1467
             }
1468
-            $css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1469
-            $this->_nav_tabs[ $slug ] = array(
1468
+            $css_class = isset($config['css_class']) ? $config['css_class'].' ' : '';
1469
+            $this->_nav_tabs[$slug] = array(
1470 1470
                 'url'       => isset($config['nav']['url'])
1471 1471
                     ? $config['nav']['url']
1472 1472
                     : self::add_query_args_and_nonce(
@@ -1478,14 +1478,14 @@  discard block
 block discarded – undo
1478 1478
                     : ucwords(
1479 1479
                         str_replace('_', ' ', $slug)
1480 1480
                     ),
1481
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1481
+                'css_class' => $this->_req_action === $slug ? $css_class.'nav-tab-active' : $css_class,
1482 1482
                 'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1483 1483
             );
1484 1484
             $i++;
1485 1485
         }
1486 1486
         // if $this->_nav_tabs is empty then lets set the default
1487 1487
         if (empty($this->_nav_tabs)) {
1488
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = array(
1488
+            $this->_nav_tabs[$this->_default_nav_tab_name] = array(
1489 1489
                 'url'       => $this->_admin_base_url,
1490 1490
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1491 1491
                 'css_class' => 'nav-tab-active',
@@ -1510,10 +1510,10 @@  discard block
 block discarded – undo
1510 1510
             foreach ($this->_route_config['labels'] as $label => $text) {
1511 1511
                 if (is_array($text)) {
1512 1512
                     foreach ($text as $sublabel => $subtext) {
1513
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1513
+                        $this->_labels[$label][$sublabel] = $subtext;
1514 1514
                     }
1515 1515
                 } else {
1516
-                    $this->_labels[ $label ] = $text;
1516
+                    $this->_labels[$label] = $text;
1517 1517
                 }
1518 1518
             }
1519 1519
         }
@@ -1535,12 +1535,12 @@  discard block
 block discarded – undo
1535 1535
     {
1536 1536
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1537 1537
         $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1538
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1538
+        $capability = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1539 1539
                       && is_array(
1540
-                          $this->_page_routes[ $route_to_check ]
1540
+                          $this->_page_routes[$route_to_check]
1541 1541
                       )
1542
-                      && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1543
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1542
+                      && ! empty($this->_page_routes[$route_to_check]['capability'])
1543
+            ? $this->_page_routes[$route_to_check]['capability'] : null;
1544 1544
         if (empty($capability) && empty($route_to_check)) {
1545 1545
             $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1546 1546
                 : $this->_route['capability'];
@@ -1548,7 +1548,7 @@  discard block
 block discarded – undo
1548 1548
             $capability = empty($capability) ? 'manage_options' : $capability;
1549 1549
         }
1550 1550
         $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1551
-        if (! defined('DOING_AJAX')
1551
+        if ( ! defined('DOING_AJAX')
1552 1552
             && (
1553 1553
                 ! function_exists('is_admin')
1554 1554
                 || ! EE_Registry::instance()->CAP->current_user_can(
@@ -1651,17 +1651,17 @@  discard block
 block discarded – undo
1651 1651
     public function admin_footer_global()
1652 1652
     {
1653 1653
         // dialog container for dialog helper
1654
-        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1654
+        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">'."\n";
1655 1655
         $d_cont .= '<div class="ee-notices"></div>';
1656 1656
         $d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1657 1657
         $d_cont .= '</div>';
1658 1658
         echo $d_cont;
1659 1659
         // help tour stuff?
1660
-        if (isset($this->_help_tour[ $this->_req_action ])) {
1661
-            echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1660
+        if (isset($this->_help_tour[$this->_req_action])) {
1661
+            echo implode('<br />', $this->_help_tour[$this->_req_action]);
1662 1662
         }
1663 1663
         // current set timezone for timezone js
1664
-        echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1664
+        echo '<span id="current_timezone" class="hidden">'.EEH_DTT_Helper::get_timezone().'</span>';
1665 1665
     }
1666 1666
 
1667 1667
 
@@ -1695,7 +1695,7 @@  discard block
 block discarded – undo
1695 1695
         // loop through the array and setup content
1696 1696
         foreach ($help_array as $trigger => $help) {
1697 1697
             // make sure the array is setup properly
1698
-            if (! isset($help['title']) || ! isset($help['content'])) {
1698
+            if ( ! isset($help['title']) || ! isset($help['content'])) {
1699 1699
                 throw new EE_Error(
1700 1700
                     esc_html__(
1701 1701
                         'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
@@ -1710,7 +1710,7 @@  discard block
 block discarded – undo
1710 1710
                 'help_popup_content' => $help['content'],
1711 1711
             );
1712 1712
             $content .= EEH_Template::display_template(
1713
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1713
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1714 1714
                 $template_args,
1715 1715
                 true
1716 1716
             );
@@ -1732,15 +1732,15 @@  discard block
 block discarded – undo
1732 1732
     private function _get_help_content()
1733 1733
     {
1734 1734
         // what is the method we're looking for?
1735
-        $method_name = '_help_popup_content_' . $this->_req_action;
1735
+        $method_name = '_help_popup_content_'.$this->_req_action;
1736 1736
         // if method doesn't exist let's get out.
1737
-        if (! method_exists($this, $method_name)) {
1737
+        if ( ! method_exists($this, $method_name)) {
1738 1738
             return array();
1739 1739
         }
1740 1740
         // k we're good to go let's retrieve the help array
1741 1741
         $help_array = call_user_func(array($this, $method_name));
1742 1742
         // make sure we've got an array!
1743
-        if (! is_array($help_array)) {
1743
+        if ( ! is_array($help_array)) {
1744 1744
             throw new EE_Error(
1745 1745
                 esc_html__(
1746 1746
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1772,8 +1772,8 @@  discard block
 block discarded – undo
1772 1772
         // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1773 1773
         $help_array = $this->_get_help_content();
1774 1774
         $help_content = '';
1775
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1776
-            $help_array[ $trigger_id ] = array(
1775
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1776
+            $help_array[$trigger_id] = array(
1777 1777
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1778 1778
                 'content' => esc_html__(
1779 1779
                     'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
@@ -1849,15 +1849,15 @@  discard block
 block discarded – undo
1849 1849
         // register all styles
1850 1850
         wp_register_style(
1851 1851
             'espresso-ui-theme',
1852
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1852
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1853 1853
             array(),
1854 1854
             EVENT_ESPRESSO_VERSION
1855 1855
         );
1856
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1856
+        wp_register_style('ee-admin-css', EE_ADMIN_URL.'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1857 1857
         // helpers styles
1858 1858
         wp_register_style(
1859 1859
             'ee-text-links',
1860
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1860
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.css',
1861 1861
             array(),
1862 1862
             EVENT_ESPRESSO_VERSION
1863 1863
         );
@@ -1865,21 +1865,21 @@  discard block
 block discarded – undo
1865 1865
         // register all scripts
1866 1866
         wp_register_script(
1867 1867
             'ee-dialog',
1868
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1868
+            EE_ADMIN_URL.'assets/ee-dialog-helper.js',
1869 1869
             array('jquery', 'jquery-ui-draggable'),
1870 1870
             EVENT_ESPRESSO_VERSION,
1871 1871
             true
1872 1872
         );
1873 1873
         wp_register_script(
1874 1874
             'ee_admin_js',
1875
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1875
+            EE_ADMIN_URL.'assets/ee-admin-page.js',
1876 1876
             array('espresso_core', 'ee-parse-uri', 'ee-dialog'),
1877 1877
             EVENT_ESPRESSO_VERSION,
1878 1878
             true
1879 1879
         );
1880 1880
         wp_register_script(
1881 1881
             'jquery-ui-timepicker-addon',
1882
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1882
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery-ui-timepicker-addon.js',
1883 1883
             array('jquery-ui-datepicker', 'jquery-ui-slider'),
1884 1884
             EVENT_ESPRESSO_VERSION,
1885 1885
             true
@@ -1888,7 +1888,7 @@  discard block
 block discarded – undo
1888 1888
         // script for sorting tables
1889 1889
         wp_register_script(
1890 1890
             'espresso_ajax_table_sorting',
1891
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1891
+            EE_ADMIN_URL.'assets/espresso_ajax_table_sorting.js',
1892 1892
             array('ee_admin_js', 'jquery-ui-sortable'),
1893 1893
             EVENT_ESPRESSO_VERSION,
1894 1894
             true
@@ -1896,7 +1896,7 @@  discard block
 block discarded – undo
1896 1896
         // script for parsing uri's
1897 1897
         wp_register_script(
1898 1898
             'ee-parse-uri',
1899
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1899
+            EE_GLOBAL_ASSETS_URL.'scripts/parseuri.js',
1900 1900
             array(),
1901 1901
             EVENT_ESPRESSO_VERSION,
1902 1902
             true
@@ -1904,7 +1904,7 @@  discard block
 block discarded – undo
1904 1904
         // and parsing associative serialized form elements
1905 1905
         wp_register_script(
1906 1906
             'ee-serialize-full-array',
1907
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1907
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery.serializefullarray.js',
1908 1908
             array('jquery'),
1909 1909
             EVENT_ESPRESSO_VERSION,
1910 1910
             true
@@ -1912,28 +1912,28 @@  discard block
 block discarded – undo
1912 1912
         // helpers scripts
1913 1913
         wp_register_script(
1914 1914
             'ee-text-links',
1915
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1915
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.js',
1916 1916
             array('jquery'),
1917 1917
             EVENT_ESPRESSO_VERSION,
1918 1918
             true
1919 1919
         );
1920 1920
         wp_register_script(
1921 1921
             'ee-moment-core',
1922
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1922
+            EE_THIRD_PARTY_URL.'moment/moment-with-locales.min.js',
1923 1923
             array(),
1924 1924
             EVENT_ESPRESSO_VERSION,
1925 1925
             true
1926 1926
         );
1927 1927
         wp_register_script(
1928 1928
             'ee-moment',
1929
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1929
+            EE_THIRD_PARTY_URL.'moment/moment-timezone-with-data.min.js',
1930 1930
             array('ee-moment-core'),
1931 1931
             EVENT_ESPRESSO_VERSION,
1932 1932
             true
1933 1933
         );
1934 1934
         wp_register_script(
1935 1935
             'ee-datepicker',
1936
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1936
+            EE_ADMIN_URL.'assets/ee-datepicker.js',
1937 1937
             array('jquery-ui-timepicker-addon', 'ee-moment'),
1938 1938
             EVENT_ESPRESSO_VERSION,
1939 1939
             true
@@ -1967,11 +1967,11 @@  discard block
 block discarded – undo
1967 1967
         /**
1968 1968
          * help tour stuff
1969 1969
          */
1970
-        if (! empty($this->_help_tour)) {
1970
+        if ( ! empty($this->_help_tour)) {
1971 1971
             // register the js for kicking things off
1972 1972
             wp_enqueue_script(
1973 1973
                 'ee-help-tour',
1974
-                EE_ADMIN_URL . 'assets/ee-help-tour.js',
1974
+                EE_ADMIN_URL.'assets/ee-help-tour.js',
1975 1975
                 array('jquery-joyride'),
1976 1976
                 EVENT_ESPRESSO_VERSION,
1977 1977
                 true
@@ -2068,12 +2068,12 @@  discard block
 block discarded – undo
2068 2068
     protected function _set_list_table()
2069 2069
     {
2070 2070
         // first is this a list_table view?
2071
-        if (! isset($this->_route_config['list_table'])) {
2071
+        if ( ! isset($this->_route_config['list_table'])) {
2072 2072
             return;
2073 2073
         } //not a list_table view so get out.
2074 2074
         // list table functions are per view specific (because some admin pages might have more than one list table!)
2075
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2076
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2075
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
2076
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2077 2077
             // user error msg
2078 2078
             $error_msg = esc_html__(
2079 2079
                 'An error occurred. The requested list table views could not be found.',
@@ -2093,10 +2093,10 @@  discard block
 block discarded – undo
2093 2093
         }
2094 2094
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2095 2095
         $this->_views = apply_filters(
2096
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2096
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2097 2097
             $this->_views
2098 2098
         );
2099
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2099
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2100 2100
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2101 2101
         $this->_set_list_table_view();
2102 2102
         $this->_set_list_table_object();
@@ -2112,7 +2112,7 @@  discard block
 block discarded – undo
2112 2112
     {
2113 2113
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2114 2114
         // looking at active items or dumpster diving ?
2115
-        if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2115
+        if ( ! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2116 2116
             $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2117 2117
         } else {
2118 2118
             $this->_view = sanitize_key($this->_req_data['status']);
@@ -2133,7 +2133,7 @@  discard block
 block discarded – undo
2133 2133
     protected function _set_list_table_object()
2134 2134
     {
2135 2135
         if (isset($this->_route_config['list_table'])) {
2136
-            if (! class_exists($this->_route_config['list_table'])) {
2136
+            if ( ! class_exists($this->_route_config['list_table'])) {
2137 2137
                 throw new EE_Error(
2138 2138
                     sprintf(
2139 2139
                         esc_html__(
@@ -2171,15 +2171,15 @@  discard block
 block discarded – undo
2171 2171
         foreach ($this->_views as $key => $view) {
2172 2172
             $query_args = array();
2173 2173
             // check for current view
2174
-            $this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2174
+            $this->_views[$key]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2175 2175
             $query_args['action'] = $this->_req_action;
2176
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2176
+            $query_args[$this->_req_action.'_nonce'] = wp_create_nonce($query_args['action'].'_nonce');
2177 2177
             $query_args['status'] = $view['slug'];
2178 2178
             // merge any other arguments sent in.
2179
-            if (isset($extra_query_args[ $view['slug'] ])) {
2180
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2179
+            if (isset($extra_query_args[$view['slug']])) {
2180
+                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2181 2181
             }
2182
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2182
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2183 2183
         }
2184 2184
         return $this->_views;
2185 2185
     }
@@ -2198,7 +2198,7 @@  discard block
 block discarded – undo
2198 2198
     {
2199 2199
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2200 2200
         $values = array(10, 25, 50, 100);
2201
-        $per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2201
+        $per_page = ( ! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2202 2202
         if ($max_entries) {
2203 2203
             $values[] = $max_entries;
2204 2204
             sort($values);
@@ -2210,14 +2210,14 @@  discard block
 block discarded – undo
2210 2210
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2211 2211
         foreach ($values as $value) {
2212 2212
             if ($value < $max_entries) {
2213
-                $selected = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2213
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2214 2214
                 $entries_per_page_dropdown .= '
2215
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2215
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2216 2216
             }
2217 2217
         }
2218
-        $selected = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2218
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2219 2219
         $entries_per_page_dropdown .= '
2220
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2220
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2221 2221
         $entries_per_page_dropdown .= '
2222 2222
 					</select>
2223 2223
 					entries
@@ -2241,7 +2241,7 @@  discard block
 block discarded – undo
2241 2241
             empty($this->_search_btn_label) ? $this->page_label
2242 2242
                 : $this->_search_btn_label
2243 2243
         );
2244
-        $this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
2244
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2245 2245
     }
2246 2246
 
2247 2247
 
@@ -2327,7 +2327,7 @@  discard block
 block discarded – undo
2327 2327
             $total_columns = ! empty($screen_columns)
2328 2328
                 ? $screen_columns
2329 2329
                 : $this->_route_config['columns'][1];
2330
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2330
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2331 2331
             $this->_template_args['current_page'] = $this->_wp_page_slug;
2332 2332
             $this->_template_args['screen'] = $this->_current_screen;
2333 2333
             $this->_column_template_path = EE_ADMIN_TEMPLATE
@@ -2372,7 +2372,7 @@  discard block
 block discarded – undo
2372 2372
      */
2373 2373
     protected function _espresso_ratings_request()
2374 2374
     {
2375
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2375
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2376 2376
             return;
2377 2377
         }
2378 2378
         $ratings_box_title = apply_filters(
@@ -2400,7 +2400,7 @@  discard block
 block discarded – undo
2400 2400
     public function espresso_ratings_request()
2401 2401
     {
2402 2402
         EEH_Template::display_template(
2403
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2403
+            EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php',
2404 2404
             array()
2405 2405
         );
2406 2406
     }
@@ -2413,17 +2413,17 @@  discard block
 block discarded – undo
2413 2413
                    . '</p><p class="hide-if-js">'
2414 2414
                    . esc_html__('This widget requires JavaScript.', 'event_espresso')
2415 2415
                    . '</p>';
2416
-        $pre = '<div class="espresso-rss-display">' . "\n\t";
2417
-        $pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2418
-        $post = '</div>' . "\n";
2419
-        $cache_key = 'ee_rss_' . md5($rss_id);
2416
+        $pre = '<div class="espresso-rss-display">'."\n\t";
2417
+        $pre .= '<span id="'.$rss_id.'_url" class="hidden">'.$url.'</span>';
2418
+        $post = '</div>'."\n";
2419
+        $cache_key = 'ee_rss_'.md5($rss_id);
2420 2420
         $output = get_transient($cache_key);
2421 2421
         if ($output !== false) {
2422
-            echo $pre . $output . $post;
2422
+            echo $pre.$output.$post;
2423 2423
             return true;
2424 2424
         }
2425
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2426
-            echo $pre . $loading . $post;
2425
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2426
+            echo $pre.$loading.$post;
2427 2427
             return false;
2428 2428
         }
2429 2429
         ob_start();
@@ -2490,19 +2490,19 @@  discard block
 block discarded – undo
2490 2490
     public function espresso_sponsors_post_box()
2491 2491
     {
2492 2492
         EEH_Template::display_template(
2493
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2493
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2494 2494
         );
2495 2495
     }
2496 2496
 
2497 2497
 
2498 2498
     private function _publish_post_box()
2499 2499
     {
2500
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2500
+        $meta_box_ref = 'espresso_'.$this->page_slug.'_editor_overview';
2501 2501
         // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2502 2502
         // then we'll use that for the metabox label.
2503 2503
         // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2504
-        if (! empty($this->_labels['publishbox'])) {
2505
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2504
+        if ( ! empty($this->_labels['publishbox'])) {
2505
+            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2506 2506
                 : $this->_labels['publishbox'];
2507 2507
         } else {
2508 2508
             $box_label = esc_html__('Publish', 'event_espresso');
@@ -2531,7 +2531,7 @@  discard block
 block discarded – undo
2531 2531
             ? $this->_template_args['publish_box_extra_content']
2532 2532
             : '';
2533 2533
         echo EEH_Template::display_template(
2534
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2534
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2535 2535
             $this->_template_args,
2536 2536
             true
2537 2537
         );
@@ -2623,8 +2623,8 @@  discard block
 block discarded – undo
2623 2623
             );
2624 2624
         }
2625 2625
         $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2626
-        if (! empty($name) && ! empty($id)) {
2627
-            $hidden_field_arr[ $name ] = array(
2626
+        if ( ! empty($name) && ! empty($id)) {
2627
+            $hidden_field_arr[$name] = array(
2628 2628
                 'type'  => 'hidden',
2629 2629
                 'value' => $id,
2630 2630
             );
@@ -2634,7 +2634,7 @@  discard block
 block discarded – undo
2634 2634
         }
2635 2635
         // add hidden field
2636 2636
         $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2637
-            ? $hf[ $name ]['field']
2637
+            ? $hf[$name]['field']
2638 2638
             : $hf;
2639 2639
     }
2640 2640
 
@@ -2736,7 +2736,7 @@  discard block
 block discarded – undo
2736 2736
         }
2737 2737
         // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2738 2738
         $call_back_func = $create_func
2739
-            ? function ($post, $metabox) {
2739
+            ? function($post, $metabox) {
2740 2740
                 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2741 2741
                 echo EEH_Template::display_template(
2742 2742
                     $metabox['args']['template_path'],
@@ -2746,7 +2746,7 @@  discard block
 block discarded – undo
2746 2746
             }
2747 2747
             : $callback;
2748 2748
         add_meta_box(
2749
-            str_replace('_', '-', $action) . '-mbox',
2749
+            str_replace('_', '-', $action).'-mbox',
2750 2750
             $title,
2751 2751
             $call_back_func,
2752 2752
             $this->_wp_page_slug,
@@ -2838,9 +2838,9 @@  discard block
 block discarded – undo
2838 2838
             : 'espresso-default-admin';
2839 2839
         $template_path = $sidebar
2840 2840
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2841
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2841
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2842 2842
         if (defined('DOING_AJAX') && DOING_AJAX) {
2843
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2843
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2844 2844
         }
2845 2845
         $template_path = ! empty($this->_column_template_path)
2846 2846
             ? $this->_column_template_path : $template_path;
@@ -2905,7 +2905,7 @@  discard block
 block discarded – undo
2905 2905
             )
2906 2906
             : $this->_template_args['preview_action_button'];
2907 2907
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2908
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2908
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2909 2909
             $this->_template_args,
2910 2910
             true
2911 2911
         );
@@ -2954,7 +2954,7 @@  discard block
 block discarded – undo
2954 2954
         // setup search attributes
2955 2955
         $this->_set_search_attributes();
2956 2956
         $this->_template_args['current_page'] = $this->_wp_page_slug;
2957
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2957
+        $template_path = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
2958 2958
         $this->_template_args['table_url'] = defined('DOING_AJAX')
2959 2959
             ? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2960 2960
             : add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
@@ -2962,10 +2962,10 @@  discard block
 block discarded – undo
2962 2962
         $this->_template_args['current_route'] = $this->_req_action;
2963 2963
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2964 2964
         $ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2965
-        if (! empty($ajax_sorting_callback)) {
2965
+        if ( ! empty($ajax_sorting_callback)) {
2966 2966
             $sortable_list_table_form_fields = wp_nonce_field(
2967
-                $ajax_sorting_callback . '_nonce',
2968
-                $ajax_sorting_callback . '_nonce',
2967
+                $ajax_sorting_callback.'_nonce',
2968
+                $ajax_sorting_callback.'_nonce',
2969 2969
                 false,
2970 2970
                 false
2971 2971
             );
@@ -2982,7 +2982,7 @@  discard block
 block discarded – undo
2982 2982
         $hidden_form_fields = isset($this->_template_args['list_table_hidden_fields'])
2983 2983
             ? $this->_template_args['list_table_hidden_fields']
2984 2984
             : '';
2985
-        $nonce_ref = $this->_req_action . '_nonce';
2985
+        $nonce_ref = $this->_req_action.'_nonce';
2986 2986
         $hidden_form_fields .= '<input type="hidden" name="'
2987 2987
                                . $nonce_ref
2988 2988
                                . '" value="'
@@ -2991,10 +2991,10 @@  discard block
 block discarded – undo
2991 2991
         $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2992 2992
         // display message about search results?
2993 2993
         $this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
2994
-            ? '<p class="ee-search-results">' . sprintf(
2994
+            ? '<p class="ee-search-results">'.sprintf(
2995 2995
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2996 2996
                 trim($this->_req_data['s'], '%')
2997
-            ) . '</p>'
2997
+            ).'</p>'
2998 2998
             : '';
2999 2999
         // filter before_list_table template arg
3000 3000
         $this->_template_args['before_list_table'] = apply_filters(
@@ -3075,7 +3075,7 @@  discard block
 block discarded – undo
3075 3075
             $this
3076 3076
         );
3077 3077
         return EEH_Template::display_template(
3078
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3078
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3079 3079
             $this->_template_args,
3080 3080
             true
3081 3081
         );
@@ -3298,17 +3298,17 @@  discard block
 block discarded – undo
3298 3298
         // add in a hidden index for the current page (so save and close redirects properly)
3299 3299
         $this->_template_args['save_buttons'] = $referrer_url;
3300 3300
         foreach ($button_text as $key => $button) {
3301
-            $ref = $default_names[ $key ];
3301
+            $ref = $default_names[$key];
3302 3302
             $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3303 3303
                                                      . $ref
3304 3304
                                                      . '" value="'
3305 3305
                                                      . $button
3306 3306
                                                      . '" name="'
3307
-                                                     . (! empty($actions) ? $actions[ $key ] : $ref)
3307
+                                                     . ( ! empty($actions) ? $actions[$key] : $ref)
3308 3308
                                                      . '" id="'
3309
-                                                     . $this->_current_view . '_' . $ref
3309
+                                                     . $this->_current_view.'_'.$ref
3310 3310
                                                      . '" />';
3311
-            if (! $both) {
3311
+            if ( ! $both) {
3312 3312
                 break;
3313 3313
             }
3314 3314
         }
@@ -3343,13 +3343,13 @@  discard block
 block discarded – undo
3343 3343
                 'An error occurred. No action was set for this page\'s form.',
3344 3344
                 'event_espresso'
3345 3345
             );
3346
-            $dev_msg = $user_msg . "\n"
3346
+            $dev_msg = $user_msg."\n"
3347 3347
                        . sprintf(
3348 3348
                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3349 3349
                            __FUNCTION__,
3350 3350
                            __CLASS__
3351 3351
                        );
3352
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3352
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3353 3353
         }
3354 3354
         // open form
3355 3355
         $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
@@ -3358,8 +3358,8 @@  discard block
 block discarded – undo
3358 3358
                                                              . $route
3359 3359
                                                              . '_event_form" >';
3360 3360
         // add nonce
3361
-        $nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3362
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3361
+        $nonce = wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3362
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3363 3363
         // add REQUIRED form action
3364 3364
         $hidden_fields = array(
3365 3365
             'action' => array('type' => 'hidden', 'value' => $route),
@@ -3372,7 +3372,7 @@  discard block
 block discarded – undo
3372 3372
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3373 3373
         // add fields to form
3374 3374
         foreach ((array) $form_fields as $field_name => $form_field) {
3375
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3375
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3376 3376
         }
3377 3377
         // close form
3378 3378
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3423,12 +3423,12 @@  discard block
 block discarded – undo
3423 3423
         foreach ($this->_req_data as $ref => $value) {
3424 3424
             // unset nonces
3425 3425
             if (strpos($ref, 'nonce') !== false) {
3426
-                unset($this->_req_data[ $ref ]);
3426
+                unset($this->_req_data[$ref]);
3427 3427
                 continue;
3428 3428
             }
3429 3429
             // urlencode values.
3430 3430
             $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3431
-            $this->_req_data[ $ref ] = $value;
3431
+            $this->_req_data[$ref] = $value;
3432 3432
         }
3433 3433
         return array_merge($this->_req_data, $new_route_data);
3434 3434
     }
@@ -3463,10 +3463,10 @@  discard block
 block discarded – undo
3463 3463
         $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3464 3464
         $notices = EE_Error::get_notices(false);
3465 3465
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3466
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3466
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3467 3467
             EE_Error::overwrite_success();
3468 3468
         }
3469
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3469
+        if ( ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3470 3470
             // how many records affected ? more than one record ? or just one ?
3471 3471
             if ($success > 1) {
3472 3472
                 // set plural msg
@@ -3495,7 +3495,7 @@  discard block
 block discarded – undo
3495 3495
             }
3496 3496
         }
3497 3497
         // check that $query_args isn't something crazy
3498
-        if (! is_array($query_args)) {
3498
+        if ( ! is_array($query_args)) {
3499 3499
             $query_args = array();
3500 3500
         }
3501 3501
         /**
@@ -3520,7 +3520,7 @@  discard block
 block discarded – undo
3520 3520
             $redirect_url = admin_url('admin.php');
3521 3521
         }
3522 3522
         // merge any default query_args set in _default_route_query_args property
3523
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3523
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3524 3524
             $args_to_merge = array();
3525 3525
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3526 3526
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3532,15 +3532,15 @@  discard block
 block discarded – undo
3532 3532
                         }
3533 3533
                         // finally we will override any arguments in the referer with
3534 3534
                         // what might be set on the _default_route_query_args array.
3535
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3536
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3535
+                        if (isset($this->_default_route_query_args[$reference])) {
3536
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3537 3537
                         } else {
3538
-                            $args_to_merge[ $reference ] = urlencode($value);
3538
+                            $args_to_merge[$reference] = urlencode($value);
3539 3539
                         }
3540 3540
                     }
3541 3541
                     continue;
3542 3542
                 }
3543
-                $args_to_merge[ $query_param ] = $query_value;
3543
+                $args_to_merge[$query_param] = $query_value;
3544 3544
             }
3545 3545
             // now let's merge these arguments but override with what was specifically sent in to the
3546 3546
             // redirect.
@@ -3552,13 +3552,13 @@  discard block
 block discarded – undo
3552 3552
         if (isset($query_args['action'])) {
3553 3553
             // manually generate wp_nonce and merge that with the query vars
3554 3554
             // becuz the wp_nonce_url function wrecks havoc on some vars
3555
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3555
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3556 3556
         }
3557 3557
         // we're adding some hooks and filters in here for processing any things just before redirects
3558 3558
         // (example: an admin page has done an insert or update and we want to run something after that).
3559
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3559
+        do_action('AHEE_redirect_'.$classname.$this->_req_action, $query_args);
3560 3560
         $redirect_url = apply_filters(
3561
-            'FHEE_redirect_' . $classname . $this->_req_action,
3561
+            'FHEE_redirect_'.$classname.$this->_req_action,
3562 3562
             self::add_query_args_and_nonce($query_args, $redirect_url),
3563 3563
             $query_args
3564 3564
         );
@@ -3611,7 +3611,7 @@  discard block
 block discarded – undo
3611 3611
         }
3612 3612
         $this->_template_args['notices'] = EE_Error::get_notices();
3613 3613
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3614
-        if (! defined('DOING_AJAX') || $sticky_notices) {
3614
+        if ( ! defined('DOING_AJAX') || $sticky_notices) {
3615 3615
             $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3616 3616
             $this->_add_transient(
3617 3617
                 $route,
@@ -3651,7 +3651,7 @@  discard block
 block discarded – undo
3651 3651
         $exclude_nonce = false
3652 3652
     ) {
3653 3653
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3654
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3654
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3655 3655
             throw new EE_Error(
3656 3656
                 sprintf(
3657 3657
                     esc_html__(
@@ -3662,7 +3662,7 @@  discard block
 block discarded – undo
3662 3662
                 )
3663 3663
             );
3664 3664
         }
3665
-        if (! isset($this->_labels['buttons'][ $type ])) {
3665
+        if ( ! isset($this->_labels['buttons'][$type])) {
3666 3666
             throw new EE_Error(
3667 3667
                 sprintf(
3668 3668
                     __(
@@ -3675,7 +3675,7 @@  discard block
 block discarded – undo
3675 3675
         }
3676 3676
         // finally check user access for this button.
3677 3677
         $has_access = $this->check_user_access($action, true);
3678
-        if (! $has_access) {
3678
+        if ( ! $has_access) {
3679 3679
             return '';
3680 3680
         }
3681 3681
         $_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3683,11 +3683,11 @@  discard block
 block discarded – undo
3683 3683
             'action' => $action,
3684 3684
         );
3685 3685
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3686
-        if (! empty($extra_request)) {
3686
+        if ( ! empty($extra_request)) {
3687 3687
             $query_args = array_merge($extra_request, $query_args);
3688 3688
         }
3689 3689
         $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3690
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3690
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3691 3691
     }
3692 3692
 
3693 3693
 
@@ -3713,7 +3713,7 @@  discard block
 block discarded – undo
3713 3713
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3714 3714
                 20
3715 3715
             ),
3716
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3716
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3717 3717
         );
3718 3718
         // ONLY add the screen option if the user has access to it.
3719 3719
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3734,7 +3734,7 @@  discard block
 block discarded – undo
3734 3734
     {
3735 3735
         if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3736 3736
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3737
-            if (! $user = wp_get_current_user()) {
3737
+            if ( ! $user = wp_get_current_user()) {
3738 3738
                 return;
3739 3739
             }
3740 3740
             $option = $_POST['wp_screen_options']['option'];
@@ -3745,7 +3745,7 @@  discard block
 block discarded – undo
3745 3745
             $map_option = $option;
3746 3746
             $option = str_replace('-', '_', $option);
3747 3747
             switch ($map_option) {
3748
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3748
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3749 3749
                     $value = (int) $value;
3750 3750
                     $max_value = apply_filters(
3751 3751
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
@@ -3803,13 +3803,13 @@  discard block
 block discarded – undo
3803 3803
     protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3804 3804
     {
3805 3805
         $user_id = get_current_user_id();
3806
-        if (! $skip_route_verify) {
3806
+        if ( ! $skip_route_verify) {
3807 3807
             $this->_verify_route($route);
3808 3808
         }
3809 3809
         // now let's set the string for what kind of transient we're setting
3810 3810
         $transient = $notices
3811
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3812
-            : 'rte_tx_' . $route . '_' . $user_id;
3811
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3812
+            : 'rte_tx_'.$route.'_'.$user_id;
3813 3813
         $data = $notices ? array('notices' => $data) : $data;
3814 3814
         // is there already a transient for this route?  If there is then let's ADD to that transient
3815 3815
         $existing = is_multisite() && is_network_admin()
@@ -3838,8 +3838,8 @@  discard block
 block discarded – undo
3838 3838
         $user_id = get_current_user_id();
3839 3839
         $route = ! $route ? $this->_req_action : $route;
3840 3840
         $transient = $notices
3841
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3842
-            : 'rte_tx_' . $route . '_' . $user_id;
3841
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3842
+            : 'rte_tx_'.$route.'_'.$user_id;
3843 3843
         $data = is_multisite() && is_network_admin()
3844 3844
             ? get_site_transient($transient)
3845 3845
             : get_transient($transient);
@@ -4058,7 +4058,7 @@  discard block
 block discarded – undo
4058 4058
      */
4059 4059
     protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4060 4060
     {
4061
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4061
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4062 4062
     }
4063 4063
 
4064 4064
 
@@ -4071,7 +4071,7 @@  discard block
 block discarded – undo
4071 4071
      */
4072 4072
     protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4073 4073
     {
4074
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4074
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4075 4075
     }
4076 4076
 
4077 4077
 
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Generator.lib.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
      * there's a single shared message template group among all the events.  Otherwise it returns null.
469 469
      *
470 470
      * @param array $event_ids
471
-     * @return EE_Message_Template_Group|null
471
+     * @return null|EE_Base_Class
472 472
      * @throws EE_Error
473 473
      * @throws InvalidArgumentException
474 474
      * @throws InvalidDataTypeException
@@ -504,7 +504,7 @@  discard block
 block discarded – undo
504 504
     /**
505 505
      * Retrieves the global message template group for the current messenger and message type.
506 506
      *
507
-     * @return EE_Message_Template_Group|null
507
+     * @return null|EE_Base_Class
508 508
      * @throws EE_Error
509 509
      * @throws InvalidArgumentException
510 510
      * @throws InvalidDataTypeException
@@ -659,7 +659,7 @@  discard block
 block discarded – undo
659 659
      * @param EE_Messages_Addressee     $recipient
660 660
      * @param array                     $templates formatted array of templates used for parsing data.
661 661
      * @param EE_Message_Template_Group $message_template_group
662
-     * @return bool|EE_Message
662
+     * @return EE_Message
663 663
      * @throws EE_Error
664 664
      * @throws InvalidArgumentException
665 665
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +992 added lines, -992 removed lines patch added patch discarded remove patch
@@ -17,997 +17,997 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * @type EE_Messages_Data_Handler_Collection
22
-     */
23
-    protected $_data_handler_collection;
24
-
25
-    /**
26
-     * @type  EE_Message_Template_Group_Collection
27
-     */
28
-    protected $_template_collection;
29
-
30
-    /**
31
-     * This will hold the data handler for the current EE_Message being generated.
32
-     *
33
-     * @type EE_Messages_incoming_data
34
-     */
35
-    protected $_current_data_handler;
36
-
37
-    /**
38
-     * This holds the EE_Messages_Queue that contains the messages to generate.
39
-     *
40
-     * @type EE_Messages_Queue
41
-     */
42
-    protected $_generation_queue;
43
-
44
-    /**
45
-     * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
46
-     *
47
-     * @type EE_Messages_Queue
48
-     */
49
-    protected $_ready_queue;
50
-
51
-    /**
52
-     * This is a container for any error messages that get created through the generation
53
-     * process.
54
-     *
55
-     * @type array
56
-     */
57
-    protected $_error_msg = array();
58
-
59
-    /**
60
-     * Flag used to set when the current EE_Message in the generation queue has been verified.
61
-     *
62
-     * @type bool
63
-     */
64
-    protected $_verified = false;
65
-
66
-    /**
67
-     * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
68
-     *
69
-     * @type EE_messenger
70
-     */
71
-    protected $_current_messenger;
72
-
73
-    /**
74
-     * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
75
-     *
76
-     * @type EE_message_type
77
-     */
78
-    protected $_current_message_type;
79
-
80
-    /**
81
-     * @type EEH_Parse_Shortcodes
82
-     */
83
-    protected $_shortcode_parser;
84
-
85
-
86
-    /**
87
-     * @param EE_Messages_Queue                     $generation_queue
88
-     * @param \EE_Messages_Queue                    $ready_queue
89
-     * @param \EE_Messages_Data_Handler_Collection  $data_handler_collection
90
-     * @param \EE_Message_Template_Group_Collection $template_collection
91
-     * @param \EEH_Parse_Shortcodes                 $shortcode_parser
92
-     */
93
-    public function __construct(
94
-        EE_Messages_Queue $generation_queue,
95
-        EE_Messages_Queue $ready_queue,
96
-        EE_Messages_Data_Handler_Collection $data_handler_collection,
97
-        EE_Message_Template_Group_Collection $template_collection,
98
-        EEH_Parse_Shortcodes $shortcode_parser
99
-    ) {
100
-        $this->_generation_queue        = $generation_queue;
101
-        $this->_ready_queue             = $ready_queue;
102
-        $this->_data_handler_collection = $data_handler_collection;
103
-        $this->_template_collection     = $template_collection;
104
-        $this->_shortcode_parser        = $shortcode_parser;
105
-    }
106
-
107
-
108
-    /**
109
-     * @return EE_Messages_Queue
110
-     */
111
-    public function generation_queue()
112
-    {
113
-        return $this->_generation_queue;
114
-    }
115
-
116
-
117
-    /**
118
-     *  This iterates through the provided queue and generates the EE_Message objects.
119
-     *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
120
-     *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
121
-     *  for the caller to decide what to do with it.
122
-     *
123
-     * @param   bool $save Whether to save the EE_Message objects in the new queue or just return.
124
-     * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
125
-     * @throws EE_Error
126
-     * @throws InvalidArgumentException
127
-     * @throws InvalidDataTypeException
128
-     * @throws InvalidInterfaceException
129
-     * @throws ReflectionException
130
-     */
131
-    public function generate($save = true)
132
-    {
133
-        // iterate through the messages in the queue, generate, and add to new queue.
134
-        $this->_generation_queue->get_message_repository()->rewind();
135
-        while ($this->_generation_queue->get_message_repository()->valid()) {
136
-            // reset "current" properties
137
-            $this->_reset_current_properties();
138
-
139
-            /** @type EE_Message $msg */
140
-            $msg = $this->_generation_queue->get_message_repository()->current();
141
-
142
-            /**
143
-             * need to get the next object and capture it for setting manually after deletes.  The reason is that when
144
-             * an object is removed from the repo then valid for the next object will fail.
145
-             */
146
-            $this->_generation_queue->get_message_repository()->next();
147
-            $next_msg = $this->_generation_queue->get_message_repository()->current();
148
-            // restore pointer to current item
149
-            $this->_generation_queue->get_message_repository()->set_current($msg);
150
-
151
-            // skip and delete if the current $msg is NOT incomplete (queued for generation)
152
-            if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
153
-                // we keep this item in the db just remove from the repo.
154
-                $this->_generation_queue->get_message_repository()->remove($msg);
155
-                // next item
156
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
157
-                continue;
158
-            }
159
-
160
-            if ($this->_verify()) {
161
-                // let's get generating!
162
-                $this->_generate();
163
-            }
164
-
165
-            // don't persist debug_only messages if the messages system is not in debug mode.
166
-            if ($msg->STS_ID() === EEM_Message::status_debug_only
167
-                && ! EEM_Message::debug()
168
-            ) {
169
-                do_action(
170
-                    'AHEE__EE_Messages_Generator__generate__before_debug_delete',
171
-                    $msg,
172
-                    $this->_error_msg,
173
-                    $this->_current_messenger,
174
-                    $this->_current_message_type,
175
-                    $this->_current_data_handler
176
-                );
177
-                $this->_generation_queue->get_message_repository()->delete();
178
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
179
-                continue;
180
-            }
181
-
182
-            // if there are error messages then let's set the status and the error message.
183
-            if ($this->_error_msg) {
184
-                // if the status is already debug only, then let's leave it at that.
185
-                if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
186
-                    $msg->set_STS_ID(EEM_Message::status_failed);
187
-                }
188
-                do_action(
189
-                    'AHEE__EE_Messages_Generator__generate__processing_failed_message',
190
-                    $msg,
191
-                    $this->_error_msg,
192
-                    $this->_current_messenger,
193
-                    $this->_current_message_type,
194
-                    $this->_current_data_handler
195
-                );
196
-                $msg->set_error_message(
197
-                    esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
198
-                    . "\n"
199
-                    . implode("\n", $this->_error_msg)
200
-                );
201
-                $msg->set_modified(time());
202
-            } else {
203
-                do_action(
204
-                    'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
205
-                    $msg,
206
-                    $this->_error_msg,
207
-                    $this->_current_messenger,
208
-                    $this->_current_message_type,
209
-                    $this->_current_data_handler
210
-                );
211
-                // remove from db
212
-                $this->_generation_queue->get_message_repository()->delete();
213
-            }
214
-            // next item
215
-            $this->_generation_queue->get_message_repository()->set_current($next_msg);
216
-        }
217
-
218
-        // generation queue is ALWAYS saved to record any errors in the generation process.
219
-        $this->_generation_queue->save();
220
-
221
-        /**
222
-         * save _ready_queue if flag set.
223
-         * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
224
-         * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
225
-         * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
226
-         * irrelevant.
227
-         */
228
-        if ($save) {
229
-            $this->_ready_queue->save();
230
-        }
231
-
232
-        // final reset of properties
233
-        $this->_reset_current_properties();
234
-
235
-        return $this->_ready_queue;
236
-    }
237
-
238
-
239
-    /**
240
-     * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
241
-     * in the generation queue.
242
-     */
243
-    protected function _reset_current_properties()
244
-    {
245
-        $this->_verified = false;
246
-        // make sure any _data value in the current message type is reset
247
-        if ($this->_current_message_type instanceof EE_message_type) {
248
-            $this->_current_message_type->reset_data();
249
-        }
250
-        $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
251
-    }
252
-
253
-
254
-    /**
255
-     * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
256
-     * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
257
-     * _generating_queue.
258
-     *
259
-     * @return bool Whether the message was successfully generated or not.
260
-     * @throws EE_Error
261
-     * @throws InvalidArgumentException
262
-     * @throws InvalidDataTypeException
263
-     * @throws InvalidInterfaceException
264
-     * @throws ReflectionException
265
-     */
266
-    protected function _generate()
267
-    {
268
-        // double check verification has run and that everything is ready to work with (saves us having to validate
269
-        // everything again).
270
-        if (! $this->_verified) {
271
-            return false; // get out because we don't have a valid setup to work with.
272
-        }
273
-
274
-
275
-        try {
276
-            $addressees = $this->_current_message_type->get_addressees(
277
-                $this->_current_data_handler,
278
-                $this->_generation_queue->get_message_repository()->current()->context()
279
-            );
280
-        } catch (EE_Error $e) {
281
-            $this->_error_msg[] = $e->getMessage();
282
-            return false;
283
-        }
284
-
285
-
286
-        // if no addressees then get out because there is nothing to generation (possible bad data).
287
-        if (! $this->_valid_addressees($addressees)) {
288
-            do_action(
289
-                'AHEE__EE_Messages_Generator___generate__invalid_addressees',
290
-                $this->_generation_queue->get_message_repository()->current(),
291
-                $addressees,
292
-                $this->_current_messenger,
293
-                $this->_current_message_type,
294
-                $this->_current_data_handler
295
-            );
296
-            $this->_generation_queue->get_message_repository()->current()->set_STS_ID(
297
-                EEM_Message::status_debug_only
298
-            );
299
-            $this->_error_msg[] = esc_html__(
300
-                'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
301
-                'event_espresso'
302
-            );
303
-            return false;
304
-        }
305
-
306
-        $message_template_group = $this->_get_message_template_group();
307
-
308
-        // in the unlikely event there is no EE_Message_Template_Group available, get out!
309
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
310
-            $this->_error_msg[] = esc_html__(
311
-                'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
312
-                'event_espresso'
313
-            );
314
-            return false;
315
-        }
316
-
317
-        // get formatted templates for using to parse and setup EE_Message objects.
318
-        $templates = $this->_get_templates($message_template_group);
319
-
320
-
321
-        // setup new EE_Message objects (and add to _ready_queue)
322
-        return $this->_assemble_messages($addressees, $templates, $message_template_group);
323
-    }
324
-
325
-
326
-    /**
327
-     * Retrieves the message template group being used for generating messages.
328
-     * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
329
-     *
330
-     * @return EE_Message_Template_Group|null
331
-     * @throws EE_Error
332
-     * @throws InvalidArgumentException
333
-     * @throws InvalidDataTypeException
334
-     * @throws InvalidInterfaceException
335
-     * @throws ReflectionException
336
-     */
337
-    protected function _get_message_template_group()
338
-    {
339
-        // first see if there is a specific message template group requested (current message in the queue has a
340
-        // specific GRP_ID
341
-        $message_template_group = $this->_specific_message_template_group_from_queue();
342
-        if ($message_template_group instanceof EE_Message_Template_Group) {
343
-            return $message_template_group;
344
-        }
345
-
346
-        // get event_ids from the datahandler so we can check to see if there's already a message template group for
347
-        // them in the collection.
348
-        $event_ids              = $this->_get_event_ids_from_current_data_handler();
349
-        $message_template_group = $this->_template_collection->get_by_key(
350
-            $this->_template_collection->getKey(
351
-                $this->_current_messenger->name,
352
-                $this->_current_message_type->name,
353
-                $event_ids
354
-            )
355
-        );
356
-
357
-        // if we have a message template group then no need to hit the database, just return it.
358
-        if ($message_template_group instanceof EE_Message_Template_Group) {
359
-            return $message_template_group;
360
-        }
361
-
362
-        // okay made it here, so let's get the global group first for this messenger and message type to ensure
363
-        // there is no override set.
364
-        $global_message_template_group =
365
-            $this->_get_global_message_template_group_for_current_messenger_and_message_type();
366
-
367
-        if ($global_message_template_group instanceof EE_Message_Template_Group
368
-            && $global_message_template_group->get('MTP_is_override')
369
-        ) {
370
-            return $global_message_template_group;
371
-        }
372
-
373
-        // if we're still here, that means there was no message template group for the events in the collection and
374
-        // the global message template group for the messenger and message type is not set for override.  So next step
375
-        // is to see if there is a common shared custom message template group for this set of events.
376
-        $message_template_group = $this->_get_shared_message_template_for_events($event_ids);
377
-        if ($message_template_group instanceof EE_Message_Template_Group) {
378
-            return $message_template_group;
379
-        }
380
-
381
-        // STILL here?  Okay that means the fallback is to just use the global message template group for this event
382
-        // set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this
383
-        // request) and return it.
384
-        if ($global_message_template_group instanceof EE_Message_Template_Group) {
385
-            $this->_template_collection->add(
386
-                $global_message_template_group,
387
-                $event_ids
388
-            );
389
-            return $global_message_template_group;
390
-        }
391
-
392
-        // if we land here that means there's NO active message template group for this set.
393
-        // TODO this will be a good target for some optimization down the road.  Whenever there is no active message
394
-        // template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
395
-        // this should likely bit hit rarely enough that it's not a significant issue.
396
-        return null;
397
-    }
398
-
399
-
400
-    /**
401
-     * This checks the current message in the queue and determines if there is a specific Message Template Group
402
-     * requested for that message.
403
-     *
404
-     * @return EE_Message_Template_Group|null
405
-     * @throws EE_Error
406
-     * @throws InvalidArgumentException
407
-     * @throws InvalidDataTypeException
408
-     * @throws InvalidInterfaceException
409
-     */
410
-    protected function _specific_message_template_group_from_queue()
411
-    {
412
-        // is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
413
-        // so let's use that.
414
-        $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
415
-
416
-        if ($GRP_ID) {
417
-            // attempt to retrieve from repo first
418
-            $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419
-            if ($message_template_group instanceof EE_Message_Template_Group) {
420
-                return $message_template_group;  // got it!
421
-            }
422
-
423
-            // nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
424
-            // is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
425
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
426
-            if ($message_template_group instanceof EE_Message_Template_Group) {
427
-                $this->_template_collection->add($message_template_group);
428
-                return $message_template_group;
429
-            }
430
-        }
431
-        return null;
432
-    }
433
-
434
-
435
-    /**
436
-     * Returns whether the event ids passed in all share the same message template group for the current message type
437
-     * and messenger.
438
-     *
439
-     * @param array $event_ids
440
-     * @return bool true means they DO share the same message template group, false means they don't.
441
-     * @throws EE_Error
442
-     * @throws InvalidArgumentException
443
-     * @throws InvalidDataTypeException
444
-     * @throws InvalidInterfaceException
445
-     */
446
-    protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447
-    {
448
-        foreach ($this->_current_data_handler->events as $event) {
449
-            $event_ids[ $event['ID'] ] = $event['ID'];
450
-        }
451
-        $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452
-            array(
453
-                array(
454
-                    'Event.EVT_ID'           => array('IN', $event_ids),
455
-                    'MTP_messenger'    => $this->_current_messenger->name,
456
-                    'MTP_message_type' => $this->_current_message_type->name,
457
-                ),
458
-            ),
459
-            'GRP_ID',
460
-            true
461
-        );
462
-        return $count_of_message_template_groups === 1;
463
-    }
464
-
465
-
466
-    /**
467
-     * This will get the shared message template group for events that are in the current data handler but ONLY if
468
-     * there's a single shared message template group among all the events.  Otherwise it returns null.
469
-     *
470
-     * @param array $event_ids
471
-     * @return EE_Message_Template_Group|null
472
-     * @throws EE_Error
473
-     * @throws InvalidArgumentException
474
-     * @throws InvalidDataTypeException
475
-     * @throws InvalidInterfaceException
476
-     */
477
-    protected function _get_shared_message_template_for_events(array $event_ids)
478
-    {
479
-        $message_template_group = null;
480
-        if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
481
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one(
482
-                array(
483
-                    array(
484
-                        'Event.EVT_ID'           => array('IN', $event_ids),
485
-                        'MTP_messenger'    => $this->_current_messenger->name,
486
-                        'MTP_message_type' => $this->_current_message_type->name,
487
-                        'MTP_is_active'    => true,
488
-                    ),
489
-                    'group_by' => 'GRP_ID',
490
-                )
491
-            );
492
-            // store this in the collection if its valid
493
-            if ($message_template_group instanceof EE_Message_Template_Group) {
494
-                $this->_template_collection->add(
495
-                    $message_template_group,
496
-                    $event_ids
497
-                );
498
-            }
499
-        }
500
-        return $message_template_group;
501
-    }
502
-
503
-
504
-    /**
505
-     * Retrieves the global message template group for the current messenger and message type.
506
-     *
507
-     * @return EE_Message_Template_Group|null
508
-     * @throws EE_Error
509
-     * @throws InvalidArgumentException
510
-     * @throws InvalidDataTypeException
511
-     * @throws InvalidInterfaceException
512
-     */
513
-    protected function _get_global_message_template_group_for_current_messenger_and_message_type()
514
-    {
515
-        // first check the collection (we use an array with 0 in it to represent global groups).
516
-        $global_message_template_group = $this->_template_collection->get_by_key(
517
-            $this->_template_collection->getKey(
518
-                $this->_current_messenger->name,
519
-                $this->_current_message_type->name,
520
-                array(0)
521
-            )
522
-        );
523
-
524
-        // if we don't have a group lets hit the db.
525
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
526
-            $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527
-                array(
528
-                    array(
529
-                        'MTP_messenger'    => $this->_current_messenger->name,
530
-                        'MTP_message_type' => $this->_current_message_type->name,
531
-                        'MTP_is_active'    => true,
532
-                        'MTP_is_global'    => true,
533
-                    ),
534
-                )
535
-            );
536
-            // if we have a group, add it to the collection.
537
-            if ($global_message_template_group instanceof EE_Message_Template_Group) {
538
-                $this->_template_collection->add(
539
-                    $global_message_template_group,
540
-                    array(0)
541
-                );
542
-            }
543
-        }
544
-        return $global_message_template_group;
545
-    }
546
-
547
-
548
-    /**
549
-     * Returns an array of event ids for all the events within the current data handler.
550
-     *
551
-     * @return array
552
-     */
553
-    protected function _get_event_ids_from_current_data_handler()
554
-    {
555
-        $event_ids = array();
556
-        foreach ($this->_current_data_handler->events as $event) {
557
-            $event_ids[ $event['ID'] ] = $event['ID'];
558
-        }
559
-        return $event_ids;
560
-    }
561
-
562
-
563
-    /**
564
-     *  Retrieves formatted array of template information for each context specific to the given
565
-     *  EE_Message_Template_Group
566
-     *
567
-     * @param EE_Message_Template_Group $message_template_group
568
-     * @return array The returned array is in this structure:
569
-     *                          array(
570
-     *                          'field_name' => array(
571
-     *                          'context' => 'content'
572
-     *                          )
573
-     *                          )
574
-     * @throws EE_Error
575
-     * @throws InvalidArgumentException
576
-     * @throws InvalidDataTypeException
577
-     * @throws InvalidInterfaceException
578
-     * @throws ReflectionException
579
-     */
580
-    protected function _get_templates(EE_Message_Template_Group $message_template_group)
581
-    {
582
-        $templates         = array();
583
-        $context_templates = $message_template_group->context_templates();
584
-        foreach ($context_templates as $context => $template_fields) {
585
-            foreach ($template_fields as $template_field => $template_obj) {
586
-                if (! $template_obj instanceof EE_Message_Template) {
587
-                    continue;
588
-                }
589
-                $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
590
-            }
591
-        }
592
-        return $templates;
593
-    }
594
-
595
-
596
-    /**
597
-     * Assembles new fully generated EE_Message objects and adds to _ready_queue
598
-     *
599
-     * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
600
-     *                                               context.
601
-     * @param array                     $templates   formatted array of templates used for parsing data.
602
-     * @param EE_Message_Template_Group $message_template_group
603
-     * @return bool true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
604
-     *                                               method will attempt to generate ALL EE_Message objects and add to
605
-     *                                               the _ready_queue.  Successfully generated messages get added to the
606
-     *                                               queue with EEM_Message::status_idle, unsuccessfully generated
607
-     *                                               messages will get added to the queue as EEM_Message::status_failed.
608
-     *                                               Very rarely should "false" be returned from this method.
609
-     * @throws EE_Error
610
-     * @throws InvalidArgumentException
611
-     * @throws InvalidDataTypeException
612
-     * @throws InvalidIdentifierException
613
-     * @throws InvalidInterfaceException
614
-     * @throws ReflectionException
615
-     */
616
-    protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
617
-    {
618
-
619
-        // if templates are empty then get out because we can't generate anything.
620
-        if (! $templates) {
621
-            $this->_error_msg[] = esc_html__(
622
-                'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623
-                'event_espresso'
624
-            );
625
-            return false;
626
-        }
627
-
628
-        // We use this as the counter for generated messages because don't forget we may be executing this inside of a
629
-        // generation_queue.  So _ready_queue may have generated EE_Message objects already.
630
-        $generated_count = 0;
631
-        foreach ($addressees as $context => $recipients) {
632
-            foreach ($recipients as $recipient) {
633
-                $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
634
-                if ($message instanceof EE_Message) {
635
-                    $this->_ready_queue->add(
636
-                        $message,
637
-                        array(),
638
-                        $this->_generation_queue->get_message_repository()->is_preview(),
639
-                        $this->_generation_queue->get_message_repository()->is_test_send()
640
-                    );
641
-                    $generated_count++;
642
-                }
643
-
644
-                // if the current MSG being generated is for a test send then we'll only use ONE message in the
645
-                // generation.
646
-                if ($this->_generation_queue->get_message_repository()->is_test_send()) {
647
-                    break 2;
648
-                }
649
-            }
650
-        }
651
-
652
-        // if there are no generated messages then something else fatal went wrong.
653
-        return $generated_count > 0;
654
-    }
655
-
656
-
657
-    /**
658
-     * @param string                    $context   The context for the generated message.
659
-     * @param EE_Messages_Addressee     $recipient
660
-     * @param array                     $templates formatted array of templates used for parsing data.
661
-     * @param EE_Message_Template_Group $message_template_group
662
-     * @return bool|EE_Message
663
-     * @throws EE_Error
664
-     * @throws InvalidArgumentException
665
-     * @throws InvalidDataTypeException
666
-     * @throws InvalidInterfaceException
667
-     * @throws ReflectionException
668
-     * @throws InvalidIdentifierException
669
-     */
670
-    protected function _setup_message_object(
671
-        $context,
672
-        EE_Messages_Addressee $recipient,
673
-        $templates,
674
-        EE_Message_Template_Group $message_template_group
675
-    ) {
676
-        // stuff we already know
677
-        $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
678
-        $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
679
-            ? $this->_current_data_handler->txn->ID()
680
-            : $transaction_id;
681
-        $message_fields = array(
682
-            'GRP_ID'           => $message_template_group->ID(),
683
-            'TXN_ID'           => $transaction_id,
684
-            'MSG_messenger'    => $this->_current_messenger->name,
685
-            'MSG_message_type' => $this->_current_message_type->name,
686
-            'MSG_context'      => $context,
687
-        );
688
-
689
-        // recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
690
-        // the info from the att_obj found in the EE_Messages_Addressee object.
691
-        if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
692
-            $message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
693
-                ? $recipient->att_obj->ID()
694
-                : 0;
695
-            $message_fields['MSG_recipient_type'] = 'Attendee';
696
-        } else {
697
-            $message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
698
-            $message_fields['MSG_recipient_type'] = $recipient->recipient_type;
699
-        }
700
-        $message = EE_Message_Factory::create($message_fields);
701
-
702
-        // grab valid shortcodes for shortcode parser
703
-        $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
704
-        $m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705
-
706
-        // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
-        if (! $this->_generation_queue->get_message_repository()->is_preview()
708
-            && (
709
-                            (
710
-                                empty($templates['to'][ $context ])
711
-                                && ! $this->_current_messenger->allow_empty_to_field()
712
-                            )
713
-                            || ! $message_template_group->is_context_active($context)
714
-                        )
715
-        ) {
716
-            // we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
717
-            // field.
718
-            return false;
719
-        }
720
-        $error_msg = array();
721
-        foreach ($templates as $field => $field_context) {
722
-            $error_msg = array();
723
-            // let's setup the valid shortcodes for the incoming context.
724
-            $valid_shortcodes = $mt_shortcodes[ $context ];
725
-            // merge in valid shortcodes for the field.
726
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
727
-            if (isset($templates[ $field ][ $context ])) {
728
-                // prefix field.
729
-                $column_name = 'MSG_' . $field;
730
-                try {
731
-                    $content = $this->_shortcode_parser->parse_message_template(
732
-                        $templates[ $field ][ $context ],
733
-                        $recipient,
734
-                        $shortcodes,
735
-                        $this->_current_message_type,
736
-                        $this->_current_messenger,
737
-                        $message
738
-                    );
739
-                    // the model field removes slashes when setting (usually necessary when the input is from the
740
-                    // request) but this value is from another model and has no slashes. So add them so it matchces
741
-                    // what the field expected (otherwise slashes will have been stripped from this an extra time)
742
-                    $message->set_field_or_extra_meta($column_name, addslashes($content));
743
-                } catch (EE_Error $e) {
744
-                    $error_msg[] = sprintf(
745
-                        /* Translators: First place holder is message model field name.
20
+	/**
21
+	 * @type EE_Messages_Data_Handler_Collection
22
+	 */
23
+	protected $_data_handler_collection;
24
+
25
+	/**
26
+	 * @type  EE_Message_Template_Group_Collection
27
+	 */
28
+	protected $_template_collection;
29
+
30
+	/**
31
+	 * This will hold the data handler for the current EE_Message being generated.
32
+	 *
33
+	 * @type EE_Messages_incoming_data
34
+	 */
35
+	protected $_current_data_handler;
36
+
37
+	/**
38
+	 * This holds the EE_Messages_Queue that contains the messages to generate.
39
+	 *
40
+	 * @type EE_Messages_Queue
41
+	 */
42
+	protected $_generation_queue;
43
+
44
+	/**
45
+	 * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
46
+	 *
47
+	 * @type EE_Messages_Queue
48
+	 */
49
+	protected $_ready_queue;
50
+
51
+	/**
52
+	 * This is a container for any error messages that get created through the generation
53
+	 * process.
54
+	 *
55
+	 * @type array
56
+	 */
57
+	protected $_error_msg = array();
58
+
59
+	/**
60
+	 * Flag used to set when the current EE_Message in the generation queue has been verified.
61
+	 *
62
+	 * @type bool
63
+	 */
64
+	protected $_verified = false;
65
+
66
+	/**
67
+	 * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
68
+	 *
69
+	 * @type EE_messenger
70
+	 */
71
+	protected $_current_messenger;
72
+
73
+	/**
74
+	 * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
75
+	 *
76
+	 * @type EE_message_type
77
+	 */
78
+	protected $_current_message_type;
79
+
80
+	/**
81
+	 * @type EEH_Parse_Shortcodes
82
+	 */
83
+	protected $_shortcode_parser;
84
+
85
+
86
+	/**
87
+	 * @param EE_Messages_Queue                     $generation_queue
88
+	 * @param \EE_Messages_Queue                    $ready_queue
89
+	 * @param \EE_Messages_Data_Handler_Collection  $data_handler_collection
90
+	 * @param \EE_Message_Template_Group_Collection $template_collection
91
+	 * @param \EEH_Parse_Shortcodes                 $shortcode_parser
92
+	 */
93
+	public function __construct(
94
+		EE_Messages_Queue $generation_queue,
95
+		EE_Messages_Queue $ready_queue,
96
+		EE_Messages_Data_Handler_Collection $data_handler_collection,
97
+		EE_Message_Template_Group_Collection $template_collection,
98
+		EEH_Parse_Shortcodes $shortcode_parser
99
+	) {
100
+		$this->_generation_queue        = $generation_queue;
101
+		$this->_ready_queue             = $ready_queue;
102
+		$this->_data_handler_collection = $data_handler_collection;
103
+		$this->_template_collection     = $template_collection;
104
+		$this->_shortcode_parser        = $shortcode_parser;
105
+	}
106
+
107
+
108
+	/**
109
+	 * @return EE_Messages_Queue
110
+	 */
111
+	public function generation_queue()
112
+	{
113
+		return $this->_generation_queue;
114
+	}
115
+
116
+
117
+	/**
118
+	 *  This iterates through the provided queue and generates the EE_Message objects.
119
+	 *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
120
+	 *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
121
+	 *  for the caller to decide what to do with it.
122
+	 *
123
+	 * @param   bool $save Whether to save the EE_Message objects in the new queue or just return.
124
+	 * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
125
+	 * @throws EE_Error
126
+	 * @throws InvalidArgumentException
127
+	 * @throws InvalidDataTypeException
128
+	 * @throws InvalidInterfaceException
129
+	 * @throws ReflectionException
130
+	 */
131
+	public function generate($save = true)
132
+	{
133
+		// iterate through the messages in the queue, generate, and add to new queue.
134
+		$this->_generation_queue->get_message_repository()->rewind();
135
+		while ($this->_generation_queue->get_message_repository()->valid()) {
136
+			// reset "current" properties
137
+			$this->_reset_current_properties();
138
+
139
+			/** @type EE_Message $msg */
140
+			$msg = $this->_generation_queue->get_message_repository()->current();
141
+
142
+			/**
143
+			 * need to get the next object and capture it for setting manually after deletes.  The reason is that when
144
+			 * an object is removed from the repo then valid for the next object will fail.
145
+			 */
146
+			$this->_generation_queue->get_message_repository()->next();
147
+			$next_msg = $this->_generation_queue->get_message_repository()->current();
148
+			// restore pointer to current item
149
+			$this->_generation_queue->get_message_repository()->set_current($msg);
150
+
151
+			// skip and delete if the current $msg is NOT incomplete (queued for generation)
152
+			if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
153
+				// we keep this item in the db just remove from the repo.
154
+				$this->_generation_queue->get_message_repository()->remove($msg);
155
+				// next item
156
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
157
+				continue;
158
+			}
159
+
160
+			if ($this->_verify()) {
161
+				// let's get generating!
162
+				$this->_generate();
163
+			}
164
+
165
+			// don't persist debug_only messages if the messages system is not in debug mode.
166
+			if ($msg->STS_ID() === EEM_Message::status_debug_only
167
+				&& ! EEM_Message::debug()
168
+			) {
169
+				do_action(
170
+					'AHEE__EE_Messages_Generator__generate__before_debug_delete',
171
+					$msg,
172
+					$this->_error_msg,
173
+					$this->_current_messenger,
174
+					$this->_current_message_type,
175
+					$this->_current_data_handler
176
+				);
177
+				$this->_generation_queue->get_message_repository()->delete();
178
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
179
+				continue;
180
+			}
181
+
182
+			// if there are error messages then let's set the status and the error message.
183
+			if ($this->_error_msg) {
184
+				// if the status is already debug only, then let's leave it at that.
185
+				if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
186
+					$msg->set_STS_ID(EEM_Message::status_failed);
187
+				}
188
+				do_action(
189
+					'AHEE__EE_Messages_Generator__generate__processing_failed_message',
190
+					$msg,
191
+					$this->_error_msg,
192
+					$this->_current_messenger,
193
+					$this->_current_message_type,
194
+					$this->_current_data_handler
195
+				);
196
+				$msg->set_error_message(
197
+					esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
198
+					. "\n"
199
+					. implode("\n", $this->_error_msg)
200
+				);
201
+				$msg->set_modified(time());
202
+			} else {
203
+				do_action(
204
+					'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
205
+					$msg,
206
+					$this->_error_msg,
207
+					$this->_current_messenger,
208
+					$this->_current_message_type,
209
+					$this->_current_data_handler
210
+				);
211
+				// remove from db
212
+				$this->_generation_queue->get_message_repository()->delete();
213
+			}
214
+			// next item
215
+			$this->_generation_queue->get_message_repository()->set_current($next_msg);
216
+		}
217
+
218
+		// generation queue is ALWAYS saved to record any errors in the generation process.
219
+		$this->_generation_queue->save();
220
+
221
+		/**
222
+		 * save _ready_queue if flag set.
223
+		 * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
224
+		 * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
225
+		 * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
226
+		 * irrelevant.
227
+		 */
228
+		if ($save) {
229
+			$this->_ready_queue->save();
230
+		}
231
+
232
+		// final reset of properties
233
+		$this->_reset_current_properties();
234
+
235
+		return $this->_ready_queue;
236
+	}
237
+
238
+
239
+	/**
240
+	 * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
241
+	 * in the generation queue.
242
+	 */
243
+	protected function _reset_current_properties()
244
+	{
245
+		$this->_verified = false;
246
+		// make sure any _data value in the current message type is reset
247
+		if ($this->_current_message_type instanceof EE_message_type) {
248
+			$this->_current_message_type->reset_data();
249
+		}
250
+		$this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
251
+	}
252
+
253
+
254
+	/**
255
+	 * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
256
+	 * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
257
+	 * _generating_queue.
258
+	 *
259
+	 * @return bool Whether the message was successfully generated or not.
260
+	 * @throws EE_Error
261
+	 * @throws InvalidArgumentException
262
+	 * @throws InvalidDataTypeException
263
+	 * @throws InvalidInterfaceException
264
+	 * @throws ReflectionException
265
+	 */
266
+	protected function _generate()
267
+	{
268
+		// double check verification has run and that everything is ready to work with (saves us having to validate
269
+		// everything again).
270
+		if (! $this->_verified) {
271
+			return false; // get out because we don't have a valid setup to work with.
272
+		}
273
+
274
+
275
+		try {
276
+			$addressees = $this->_current_message_type->get_addressees(
277
+				$this->_current_data_handler,
278
+				$this->_generation_queue->get_message_repository()->current()->context()
279
+			);
280
+		} catch (EE_Error $e) {
281
+			$this->_error_msg[] = $e->getMessage();
282
+			return false;
283
+		}
284
+
285
+
286
+		// if no addressees then get out because there is nothing to generation (possible bad data).
287
+		if (! $this->_valid_addressees($addressees)) {
288
+			do_action(
289
+				'AHEE__EE_Messages_Generator___generate__invalid_addressees',
290
+				$this->_generation_queue->get_message_repository()->current(),
291
+				$addressees,
292
+				$this->_current_messenger,
293
+				$this->_current_message_type,
294
+				$this->_current_data_handler
295
+			);
296
+			$this->_generation_queue->get_message_repository()->current()->set_STS_ID(
297
+				EEM_Message::status_debug_only
298
+			);
299
+			$this->_error_msg[] = esc_html__(
300
+				'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
301
+				'event_espresso'
302
+			);
303
+			return false;
304
+		}
305
+
306
+		$message_template_group = $this->_get_message_template_group();
307
+
308
+		// in the unlikely event there is no EE_Message_Template_Group available, get out!
309
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
310
+			$this->_error_msg[] = esc_html__(
311
+				'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
312
+				'event_espresso'
313
+			);
314
+			return false;
315
+		}
316
+
317
+		// get formatted templates for using to parse and setup EE_Message objects.
318
+		$templates = $this->_get_templates($message_template_group);
319
+
320
+
321
+		// setup new EE_Message objects (and add to _ready_queue)
322
+		return $this->_assemble_messages($addressees, $templates, $message_template_group);
323
+	}
324
+
325
+
326
+	/**
327
+	 * Retrieves the message template group being used for generating messages.
328
+	 * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
329
+	 *
330
+	 * @return EE_Message_Template_Group|null
331
+	 * @throws EE_Error
332
+	 * @throws InvalidArgumentException
333
+	 * @throws InvalidDataTypeException
334
+	 * @throws InvalidInterfaceException
335
+	 * @throws ReflectionException
336
+	 */
337
+	protected function _get_message_template_group()
338
+	{
339
+		// first see if there is a specific message template group requested (current message in the queue has a
340
+		// specific GRP_ID
341
+		$message_template_group = $this->_specific_message_template_group_from_queue();
342
+		if ($message_template_group instanceof EE_Message_Template_Group) {
343
+			return $message_template_group;
344
+		}
345
+
346
+		// get event_ids from the datahandler so we can check to see if there's already a message template group for
347
+		// them in the collection.
348
+		$event_ids              = $this->_get_event_ids_from_current_data_handler();
349
+		$message_template_group = $this->_template_collection->get_by_key(
350
+			$this->_template_collection->getKey(
351
+				$this->_current_messenger->name,
352
+				$this->_current_message_type->name,
353
+				$event_ids
354
+			)
355
+		);
356
+
357
+		// if we have a message template group then no need to hit the database, just return it.
358
+		if ($message_template_group instanceof EE_Message_Template_Group) {
359
+			return $message_template_group;
360
+		}
361
+
362
+		// okay made it here, so let's get the global group first for this messenger and message type to ensure
363
+		// there is no override set.
364
+		$global_message_template_group =
365
+			$this->_get_global_message_template_group_for_current_messenger_and_message_type();
366
+
367
+		if ($global_message_template_group instanceof EE_Message_Template_Group
368
+			&& $global_message_template_group->get('MTP_is_override')
369
+		) {
370
+			return $global_message_template_group;
371
+		}
372
+
373
+		// if we're still here, that means there was no message template group for the events in the collection and
374
+		// the global message template group for the messenger and message type is not set for override.  So next step
375
+		// is to see if there is a common shared custom message template group for this set of events.
376
+		$message_template_group = $this->_get_shared_message_template_for_events($event_ids);
377
+		if ($message_template_group instanceof EE_Message_Template_Group) {
378
+			return $message_template_group;
379
+		}
380
+
381
+		// STILL here?  Okay that means the fallback is to just use the global message template group for this event
382
+		// set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this
383
+		// request) and return it.
384
+		if ($global_message_template_group instanceof EE_Message_Template_Group) {
385
+			$this->_template_collection->add(
386
+				$global_message_template_group,
387
+				$event_ids
388
+			);
389
+			return $global_message_template_group;
390
+		}
391
+
392
+		// if we land here that means there's NO active message template group for this set.
393
+		// TODO this will be a good target for some optimization down the road.  Whenever there is no active message
394
+		// template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
395
+		// this should likely bit hit rarely enough that it's not a significant issue.
396
+		return null;
397
+	}
398
+
399
+
400
+	/**
401
+	 * This checks the current message in the queue and determines if there is a specific Message Template Group
402
+	 * requested for that message.
403
+	 *
404
+	 * @return EE_Message_Template_Group|null
405
+	 * @throws EE_Error
406
+	 * @throws InvalidArgumentException
407
+	 * @throws InvalidDataTypeException
408
+	 * @throws InvalidInterfaceException
409
+	 */
410
+	protected function _specific_message_template_group_from_queue()
411
+	{
412
+		// is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
413
+		// so let's use that.
414
+		$GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
415
+
416
+		if ($GRP_ID) {
417
+			// attempt to retrieve from repo first
418
+			$message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419
+			if ($message_template_group instanceof EE_Message_Template_Group) {
420
+				return $message_template_group;  // got it!
421
+			}
422
+
423
+			// nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
424
+			// is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
425
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
426
+			if ($message_template_group instanceof EE_Message_Template_Group) {
427
+				$this->_template_collection->add($message_template_group);
428
+				return $message_template_group;
429
+			}
430
+		}
431
+		return null;
432
+	}
433
+
434
+
435
+	/**
436
+	 * Returns whether the event ids passed in all share the same message template group for the current message type
437
+	 * and messenger.
438
+	 *
439
+	 * @param array $event_ids
440
+	 * @return bool true means they DO share the same message template group, false means they don't.
441
+	 * @throws EE_Error
442
+	 * @throws InvalidArgumentException
443
+	 * @throws InvalidDataTypeException
444
+	 * @throws InvalidInterfaceException
445
+	 */
446
+	protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447
+	{
448
+		foreach ($this->_current_data_handler->events as $event) {
449
+			$event_ids[ $event['ID'] ] = $event['ID'];
450
+		}
451
+		$count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452
+			array(
453
+				array(
454
+					'Event.EVT_ID'           => array('IN', $event_ids),
455
+					'MTP_messenger'    => $this->_current_messenger->name,
456
+					'MTP_message_type' => $this->_current_message_type->name,
457
+				),
458
+			),
459
+			'GRP_ID',
460
+			true
461
+		);
462
+		return $count_of_message_template_groups === 1;
463
+	}
464
+
465
+
466
+	/**
467
+	 * This will get the shared message template group for events that are in the current data handler but ONLY if
468
+	 * there's a single shared message template group among all the events.  Otherwise it returns null.
469
+	 *
470
+	 * @param array $event_ids
471
+	 * @return EE_Message_Template_Group|null
472
+	 * @throws EE_Error
473
+	 * @throws InvalidArgumentException
474
+	 * @throws InvalidDataTypeException
475
+	 * @throws InvalidInterfaceException
476
+	 */
477
+	protected function _get_shared_message_template_for_events(array $event_ids)
478
+	{
479
+		$message_template_group = null;
480
+		if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
481
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one(
482
+				array(
483
+					array(
484
+						'Event.EVT_ID'           => array('IN', $event_ids),
485
+						'MTP_messenger'    => $this->_current_messenger->name,
486
+						'MTP_message_type' => $this->_current_message_type->name,
487
+						'MTP_is_active'    => true,
488
+					),
489
+					'group_by' => 'GRP_ID',
490
+				)
491
+			);
492
+			// store this in the collection if its valid
493
+			if ($message_template_group instanceof EE_Message_Template_Group) {
494
+				$this->_template_collection->add(
495
+					$message_template_group,
496
+					$event_ids
497
+				);
498
+			}
499
+		}
500
+		return $message_template_group;
501
+	}
502
+
503
+
504
+	/**
505
+	 * Retrieves the global message template group for the current messenger and message type.
506
+	 *
507
+	 * @return EE_Message_Template_Group|null
508
+	 * @throws EE_Error
509
+	 * @throws InvalidArgumentException
510
+	 * @throws InvalidDataTypeException
511
+	 * @throws InvalidInterfaceException
512
+	 */
513
+	protected function _get_global_message_template_group_for_current_messenger_and_message_type()
514
+	{
515
+		// first check the collection (we use an array with 0 in it to represent global groups).
516
+		$global_message_template_group = $this->_template_collection->get_by_key(
517
+			$this->_template_collection->getKey(
518
+				$this->_current_messenger->name,
519
+				$this->_current_message_type->name,
520
+				array(0)
521
+			)
522
+		);
523
+
524
+		// if we don't have a group lets hit the db.
525
+		if (! $global_message_template_group instanceof EE_Message_Template_Group) {
526
+			$global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527
+				array(
528
+					array(
529
+						'MTP_messenger'    => $this->_current_messenger->name,
530
+						'MTP_message_type' => $this->_current_message_type->name,
531
+						'MTP_is_active'    => true,
532
+						'MTP_is_global'    => true,
533
+					),
534
+				)
535
+			);
536
+			// if we have a group, add it to the collection.
537
+			if ($global_message_template_group instanceof EE_Message_Template_Group) {
538
+				$this->_template_collection->add(
539
+					$global_message_template_group,
540
+					array(0)
541
+				);
542
+			}
543
+		}
544
+		return $global_message_template_group;
545
+	}
546
+
547
+
548
+	/**
549
+	 * Returns an array of event ids for all the events within the current data handler.
550
+	 *
551
+	 * @return array
552
+	 */
553
+	protected function _get_event_ids_from_current_data_handler()
554
+	{
555
+		$event_ids = array();
556
+		foreach ($this->_current_data_handler->events as $event) {
557
+			$event_ids[ $event['ID'] ] = $event['ID'];
558
+		}
559
+		return $event_ids;
560
+	}
561
+
562
+
563
+	/**
564
+	 *  Retrieves formatted array of template information for each context specific to the given
565
+	 *  EE_Message_Template_Group
566
+	 *
567
+	 * @param EE_Message_Template_Group $message_template_group
568
+	 * @return array The returned array is in this structure:
569
+	 *                          array(
570
+	 *                          'field_name' => array(
571
+	 *                          'context' => 'content'
572
+	 *                          )
573
+	 *                          )
574
+	 * @throws EE_Error
575
+	 * @throws InvalidArgumentException
576
+	 * @throws InvalidDataTypeException
577
+	 * @throws InvalidInterfaceException
578
+	 * @throws ReflectionException
579
+	 */
580
+	protected function _get_templates(EE_Message_Template_Group $message_template_group)
581
+	{
582
+		$templates         = array();
583
+		$context_templates = $message_template_group->context_templates();
584
+		foreach ($context_templates as $context => $template_fields) {
585
+			foreach ($template_fields as $template_field => $template_obj) {
586
+				if (! $template_obj instanceof EE_Message_Template) {
587
+					continue;
588
+				}
589
+				$templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
590
+			}
591
+		}
592
+		return $templates;
593
+	}
594
+
595
+
596
+	/**
597
+	 * Assembles new fully generated EE_Message objects and adds to _ready_queue
598
+	 *
599
+	 * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
600
+	 *                                               context.
601
+	 * @param array                     $templates   formatted array of templates used for parsing data.
602
+	 * @param EE_Message_Template_Group $message_template_group
603
+	 * @return bool true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
604
+	 *                                               method will attempt to generate ALL EE_Message objects and add to
605
+	 *                                               the _ready_queue.  Successfully generated messages get added to the
606
+	 *                                               queue with EEM_Message::status_idle, unsuccessfully generated
607
+	 *                                               messages will get added to the queue as EEM_Message::status_failed.
608
+	 *                                               Very rarely should "false" be returned from this method.
609
+	 * @throws EE_Error
610
+	 * @throws InvalidArgumentException
611
+	 * @throws InvalidDataTypeException
612
+	 * @throws InvalidIdentifierException
613
+	 * @throws InvalidInterfaceException
614
+	 * @throws ReflectionException
615
+	 */
616
+	protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
617
+	{
618
+
619
+		// if templates are empty then get out because we can't generate anything.
620
+		if (! $templates) {
621
+			$this->_error_msg[] = esc_html__(
622
+				'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623
+				'event_espresso'
624
+			);
625
+			return false;
626
+		}
627
+
628
+		// We use this as the counter for generated messages because don't forget we may be executing this inside of a
629
+		// generation_queue.  So _ready_queue may have generated EE_Message objects already.
630
+		$generated_count = 0;
631
+		foreach ($addressees as $context => $recipients) {
632
+			foreach ($recipients as $recipient) {
633
+				$message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
634
+				if ($message instanceof EE_Message) {
635
+					$this->_ready_queue->add(
636
+						$message,
637
+						array(),
638
+						$this->_generation_queue->get_message_repository()->is_preview(),
639
+						$this->_generation_queue->get_message_repository()->is_test_send()
640
+					);
641
+					$generated_count++;
642
+				}
643
+
644
+				// if the current MSG being generated is for a test send then we'll only use ONE message in the
645
+				// generation.
646
+				if ($this->_generation_queue->get_message_repository()->is_test_send()) {
647
+					break 2;
648
+				}
649
+			}
650
+		}
651
+
652
+		// if there are no generated messages then something else fatal went wrong.
653
+		return $generated_count > 0;
654
+	}
655
+
656
+
657
+	/**
658
+	 * @param string                    $context   The context for the generated message.
659
+	 * @param EE_Messages_Addressee     $recipient
660
+	 * @param array                     $templates formatted array of templates used for parsing data.
661
+	 * @param EE_Message_Template_Group $message_template_group
662
+	 * @return bool|EE_Message
663
+	 * @throws EE_Error
664
+	 * @throws InvalidArgumentException
665
+	 * @throws InvalidDataTypeException
666
+	 * @throws InvalidInterfaceException
667
+	 * @throws ReflectionException
668
+	 * @throws InvalidIdentifierException
669
+	 */
670
+	protected function _setup_message_object(
671
+		$context,
672
+		EE_Messages_Addressee $recipient,
673
+		$templates,
674
+		EE_Message_Template_Group $message_template_group
675
+	) {
676
+		// stuff we already know
677
+		$transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
678
+		$transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
679
+			? $this->_current_data_handler->txn->ID()
680
+			: $transaction_id;
681
+		$message_fields = array(
682
+			'GRP_ID'           => $message_template_group->ID(),
683
+			'TXN_ID'           => $transaction_id,
684
+			'MSG_messenger'    => $this->_current_messenger->name,
685
+			'MSG_message_type' => $this->_current_message_type->name,
686
+			'MSG_context'      => $context,
687
+		);
688
+
689
+		// recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
690
+		// the info from the att_obj found in the EE_Messages_Addressee object.
691
+		if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
692
+			$message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
693
+				? $recipient->att_obj->ID()
694
+				: 0;
695
+			$message_fields['MSG_recipient_type'] = 'Attendee';
696
+		} else {
697
+			$message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
698
+			$message_fields['MSG_recipient_type'] = $recipient->recipient_type;
699
+		}
700
+		$message = EE_Message_Factory::create($message_fields);
701
+
702
+		// grab valid shortcodes for shortcode parser
703
+		$mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
704
+		$m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705
+
706
+		// if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
+		if (! $this->_generation_queue->get_message_repository()->is_preview()
708
+			&& (
709
+							(
710
+								empty($templates['to'][ $context ])
711
+								&& ! $this->_current_messenger->allow_empty_to_field()
712
+							)
713
+							|| ! $message_template_group->is_context_active($context)
714
+						)
715
+		) {
716
+			// we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
717
+			// field.
718
+			return false;
719
+		}
720
+		$error_msg = array();
721
+		foreach ($templates as $field => $field_context) {
722
+			$error_msg = array();
723
+			// let's setup the valid shortcodes for the incoming context.
724
+			$valid_shortcodes = $mt_shortcodes[ $context ];
725
+			// merge in valid shortcodes for the field.
726
+			$shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
727
+			if (isset($templates[ $field ][ $context ])) {
728
+				// prefix field.
729
+				$column_name = 'MSG_' . $field;
730
+				try {
731
+					$content = $this->_shortcode_parser->parse_message_template(
732
+						$templates[ $field ][ $context ],
733
+						$recipient,
734
+						$shortcodes,
735
+						$this->_current_message_type,
736
+						$this->_current_messenger,
737
+						$message
738
+					);
739
+					// the model field removes slashes when setting (usually necessary when the input is from the
740
+					// request) but this value is from another model and has no slashes. So add them so it matchces
741
+					// what the field expected (otherwise slashes will have been stripped from this an extra time)
742
+					$message->set_field_or_extra_meta($column_name, addslashes($content));
743
+				} catch (EE_Error $e) {
744
+					$error_msg[] = sprintf(
745
+						/* Translators: First place holder is message model field name.
746 746
                          * Second placeholder is exception error message */
747
-                        esc_html__(
748
-                            'There was a problem generating the content for the field %s: %s',
749
-                            'event_espresso'
750
-                        ),
751
-                        $field,
752
-                        $e->getMessage()
753
-                    );
754
-                    $message->set_STS_ID(EEM_Message::status_failed);
755
-                }
756
-            }
757
-        }
758
-
759
-        if ($message->STS_ID() === EEM_Message::status_failed) {
760
-            $error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
761
-                         . "\n"
762
-                         . implode("\n", $error_msg);
763
-            $message->set_error_message($error_msg);
764
-        } else {
765
-            $message->set_STS_ID(EEM_Message::status_idle);
766
-        }
767
-        return $message;
768
-    }
769
-
770
-
771
-    /**
772
-     * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
773
-     * error message if either is missing.
774
-     *
775
-     * @return bool true means there were no errors, false means there were errors.
776
-     */
777
-    protected function _verify()
778
-    {
779
-        // reset error message to an empty array.
780
-        $this->_error_msg = array();
781
-        $valid            = true;
782
-        $valid            = $valid ? $this->_validate_messenger_and_message_type() : $valid;
783
-        $valid            = $valid ? $this->_validate_and_setup_data() : $valid;
784
-
785
-        // set the verified flag so we know everything has been validated.
786
-        $this->_verified = $valid;
787
-
788
-        return $valid;
789
-    }
790
-
791
-
792
-    /**
793
-     * This accepts an array and validates that it is an array indexed by context with each value being an array of
794
-     * EE_Messages_Addressee objects.
795
-     *
796
-     * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
797
-     * @return bool
798
-     */
799
-    protected function _valid_addressees($addressees)
800
-    {
801
-        if (! $addressees || ! is_array($addressees)) {
802
-            return false;
803
-        }
804
-
805
-        foreach ($addressees as $addressee_array) {
806
-            foreach ($addressee_array as $addressee) {
807
-                if (! $addressee instanceof EE_Messages_Addressee) {
808
-                    return false;
809
-                }
810
-            }
811
-        }
812
-        return true;
813
-    }
814
-
815
-
816
-    /**
817
-     * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
818
-     * queue. This process sets error messages if something is wrong.
819
-     *
820
-     * @return bool   true is if there are no errors.  false is if there is.
821
-     */
822
-    protected function _validate_messenger_and_message_type()
823
-    {
824
-
825
-        // first are there any existing error messages?  If so then return.
826
-        if ($this->_error_msg) {
827
-            return false;
828
-        }
829
-        /** @type EE_Message $message */
830
-        $message = $this->_generation_queue->get_message_repository()->current();
831
-        try {
832
-            $this->_current_messenger = $message->valid_messenger(true)
833
-                ? $message->messenger_object()
834
-                : null;
835
-        } catch (Exception $e) {
836
-            $this->_error_msg[] = $e->getMessage();
837
-        }
838
-        try {
839
-            $this->_current_message_type = $message->valid_message_type(true)
840
-                ? $message->message_type_object()
841
-                : null;
842
-        } catch (Exception $e) {
843
-            $this->_error_msg[] = $e->getMessage();
844
-        }
845
-
846
-        /**
847
-         * Check if there is any generation data, but only if this is not for a preview.
848
-         */
849
-        if (! $this->_generation_queue->get_message_repository()->get_generation_data()
850
-            && (
851
-                ! $this->_generation_queue->get_message_repository()->is_preview()
852
-                && $this->_generation_queue->get_message_repository()->get_data_handler()
853
-                   !== 'EE_Messages_Preview_incoming_data'
854
-            )
855
-        ) {
856
-            $this->_error_msg[] = esc_html__(
857
-                'There is no generation data for this message. Unable to generate.',
858
-                'event_espresso'
859
-            );
860
-        }
861
-
862
-        return empty($this->_error_msg);
863
-    }
864
-
865
-
866
-    /**
867
-     * This method retrieves the expected data handler for the message type and validates the generation data for that
868
-     * data handler.
869
-     *
870
-     * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
871
-     */
872
-    protected function _validate_and_setup_data()
873
-    {
874
-
875
-        // First, are there any existing error messages?  If so, return because if there were errors elsewhere this
876
-        // can't be used anyways.
877
-        if ($this->_error_msg) {
878
-            return false;
879
-        }
880
-
881
-        $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
882
-
883
-        /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/
884
-        $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
885
-            ? $this->_generation_queue->get_message_repository()->get_data_handler()
886
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
887
-
888
-        // If this EE_Message is for a preview, then let's switch out to the preview data handler.
889
-        if ($this->_generation_queue->get_message_repository()->is_preview()) {
890
-            $data_handler_class_name = 'EE_Messages_Preview_incoming_data';
891
-        }
892
-
893
-        // First get the class name for the data handler (and also verifies it exists.
894
-        if (! class_exists($data_handler_class_name)) {
895
-            $this->_error_msg[] = sprintf(
896
-                /* Translators: Both placeholders are the names of php classes. */
897
-                esc_html__(
898
-                    'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
899
-                    'event_espresso'
900
-                ),
901
-                'EE_Messages_incoming_data',
902
-                $data_handler_class_name
903
-            );
904
-            return false;
905
-        }
906
-
907
-        // convert generation_data for data_handler_instantiation.
908
-        $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
909
-
910
-        // note, this may set error messages as well.
911
-        $this->_set_data_handler($generation_data, $data_handler_class_name);
912
-
913
-        return empty($this->_error_msg);
914
-    }
915
-
916
-
917
-    /**
918
-     * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
919
-     * adds it to the _data repository.
920
-     *
921
-     * @param mixed  $generating_data           This is data expected by the instantiated data handler.
922
-     * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
923
-     *                                          instantiated.
924
-     */
925
-    protected function _set_data_handler($generating_data, $data_handler_class_name)
926
-    {
927
-        // valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
928
-        // there is already a ready data handler in the repository.
929
-        $this->_current_data_handler = $this->_data_handler_collection->get_by_key(
930
-            $this->_data_handler_collection->get_key(
931
-                $data_handler_class_name,
932
-                $generating_data
933
-            )
934
-        );
935
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
936
-            // no saved data_handler in the repo so let's set one up and add it to the repo.
937
-            try {
938
-                $this->_current_data_handler = new $data_handler_class_name($generating_data);
939
-                $this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
940
-            } catch (Exception $e) {
941
-                $this->_error_msg[] = $e->getMessage();
942
-            }
943
-        }
944
-    }
945
-
946
-
947
-    /**
948
-     * The queued EE_Message for generation does not save the data used for generation as objects
949
-     * because serialization of those objects could be problematic if the data is saved to the db.
950
-     * So this method calls the static method on the associated data_handler for the given message_type
951
-     * and that preps the data for later instantiation when generating.
952
-     *
953
-     * @param EE_Message_To_Generate $message_to_generate
954
-     * @param bool                   $preview Indicate whether this is being used for a preview or not.
955
-     * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
956
-     */
957
-    protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
958
-    {
959
-        /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
960
-        $data_handler = $message_to_generate->get_data_handler_class_name($preview);
961
-        if (! $message_to_generate->valid()) {
962
-            return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
963
-        }
964
-        return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
965
-    }
966
-
967
-
968
-    /**
969
-     * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
970
-     *
971
-     * @param EE_Message_To_Generate $message_to_generate
972
-     * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
973
-     * @throws InvalidArgumentException
974
-     * @throws InvalidDataTypeException
975
-     * @throws InvalidInterfaceException
976
-     */
977
-    public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
978
-    {
979
-        // prep data
980
-        $data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
981
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
982
-
983
-        $message = $message_to_generate->get_EE_Message();
984
-        $GRP_ID = $request->getRequestParam('GRP_ID', 0);
985
-
986
-        $GRP_ID = apply_filters(
987
-            'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
988
-            $GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
989
-            $message,
990
-            $message_to_generate,
991
-            $test_send
992
-        );
993
-
994
-        if ($GRP_ID > 0) {
995
-            $message->set_GRP_ID($GRP_ID);
996
-        }
997
-
998
-        if ($data === false) {
999
-            $message->set_STS_ID(EEM_Message::status_failed);
1000
-            $message->set_error_message(
1001
-                esc_html__(
1002
-                    'Unable to prepare data for persistence to the database.',
1003
-                    'event_espresso'
1004
-                )
1005
-            );
1006
-        } else {
1007
-            // make sure that the data handler is cached on the message as well
1008
-            $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1009
-        }
1010
-
1011
-        $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1012
-    }
747
+						esc_html__(
748
+							'There was a problem generating the content for the field %s: %s',
749
+							'event_espresso'
750
+						),
751
+						$field,
752
+						$e->getMessage()
753
+					);
754
+					$message->set_STS_ID(EEM_Message::status_failed);
755
+				}
756
+			}
757
+		}
758
+
759
+		if ($message->STS_ID() === EEM_Message::status_failed) {
760
+			$error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
761
+						 . "\n"
762
+						 . implode("\n", $error_msg);
763
+			$message->set_error_message($error_msg);
764
+		} else {
765
+			$message->set_STS_ID(EEM_Message::status_idle);
766
+		}
767
+		return $message;
768
+	}
769
+
770
+
771
+	/**
772
+	 * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
773
+	 * error message if either is missing.
774
+	 *
775
+	 * @return bool true means there were no errors, false means there were errors.
776
+	 */
777
+	protected function _verify()
778
+	{
779
+		// reset error message to an empty array.
780
+		$this->_error_msg = array();
781
+		$valid            = true;
782
+		$valid            = $valid ? $this->_validate_messenger_and_message_type() : $valid;
783
+		$valid            = $valid ? $this->_validate_and_setup_data() : $valid;
784
+
785
+		// set the verified flag so we know everything has been validated.
786
+		$this->_verified = $valid;
787
+
788
+		return $valid;
789
+	}
790
+
791
+
792
+	/**
793
+	 * This accepts an array and validates that it is an array indexed by context with each value being an array of
794
+	 * EE_Messages_Addressee objects.
795
+	 *
796
+	 * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
797
+	 * @return bool
798
+	 */
799
+	protected function _valid_addressees($addressees)
800
+	{
801
+		if (! $addressees || ! is_array($addressees)) {
802
+			return false;
803
+		}
804
+
805
+		foreach ($addressees as $addressee_array) {
806
+			foreach ($addressee_array as $addressee) {
807
+				if (! $addressee instanceof EE_Messages_Addressee) {
808
+					return false;
809
+				}
810
+			}
811
+		}
812
+		return true;
813
+	}
814
+
815
+
816
+	/**
817
+	 * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
818
+	 * queue. This process sets error messages if something is wrong.
819
+	 *
820
+	 * @return bool   true is if there are no errors.  false is if there is.
821
+	 */
822
+	protected function _validate_messenger_and_message_type()
823
+	{
824
+
825
+		// first are there any existing error messages?  If so then return.
826
+		if ($this->_error_msg) {
827
+			return false;
828
+		}
829
+		/** @type EE_Message $message */
830
+		$message = $this->_generation_queue->get_message_repository()->current();
831
+		try {
832
+			$this->_current_messenger = $message->valid_messenger(true)
833
+				? $message->messenger_object()
834
+				: null;
835
+		} catch (Exception $e) {
836
+			$this->_error_msg[] = $e->getMessage();
837
+		}
838
+		try {
839
+			$this->_current_message_type = $message->valid_message_type(true)
840
+				? $message->message_type_object()
841
+				: null;
842
+		} catch (Exception $e) {
843
+			$this->_error_msg[] = $e->getMessage();
844
+		}
845
+
846
+		/**
847
+		 * Check if there is any generation data, but only if this is not for a preview.
848
+		 */
849
+		if (! $this->_generation_queue->get_message_repository()->get_generation_data()
850
+			&& (
851
+				! $this->_generation_queue->get_message_repository()->is_preview()
852
+				&& $this->_generation_queue->get_message_repository()->get_data_handler()
853
+				   !== 'EE_Messages_Preview_incoming_data'
854
+			)
855
+		) {
856
+			$this->_error_msg[] = esc_html__(
857
+				'There is no generation data for this message. Unable to generate.',
858
+				'event_espresso'
859
+			);
860
+		}
861
+
862
+		return empty($this->_error_msg);
863
+	}
864
+
865
+
866
+	/**
867
+	 * This method retrieves the expected data handler for the message type and validates the generation data for that
868
+	 * data handler.
869
+	 *
870
+	 * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
871
+	 */
872
+	protected function _validate_and_setup_data()
873
+	{
874
+
875
+		// First, are there any existing error messages?  If so, return because if there were errors elsewhere this
876
+		// can't be used anyways.
877
+		if ($this->_error_msg) {
878
+			return false;
879
+		}
880
+
881
+		$generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
882
+
883
+		/** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/
884
+		$data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
885
+			? $this->_generation_queue->get_message_repository()->get_data_handler()
886
+			: 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
887
+
888
+		// If this EE_Message is for a preview, then let's switch out to the preview data handler.
889
+		if ($this->_generation_queue->get_message_repository()->is_preview()) {
890
+			$data_handler_class_name = 'EE_Messages_Preview_incoming_data';
891
+		}
892
+
893
+		// First get the class name for the data handler (and also verifies it exists.
894
+		if (! class_exists($data_handler_class_name)) {
895
+			$this->_error_msg[] = sprintf(
896
+				/* Translators: Both placeholders are the names of php classes. */
897
+				esc_html__(
898
+					'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
899
+					'event_espresso'
900
+				),
901
+				'EE_Messages_incoming_data',
902
+				$data_handler_class_name
903
+			);
904
+			return false;
905
+		}
906
+
907
+		// convert generation_data for data_handler_instantiation.
908
+		$generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
909
+
910
+		// note, this may set error messages as well.
911
+		$this->_set_data_handler($generation_data, $data_handler_class_name);
912
+
913
+		return empty($this->_error_msg);
914
+	}
915
+
916
+
917
+	/**
918
+	 * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
919
+	 * adds it to the _data repository.
920
+	 *
921
+	 * @param mixed  $generating_data           This is data expected by the instantiated data handler.
922
+	 * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
923
+	 *                                          instantiated.
924
+	 */
925
+	protected function _set_data_handler($generating_data, $data_handler_class_name)
926
+	{
927
+		// valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
928
+		// there is already a ready data handler in the repository.
929
+		$this->_current_data_handler = $this->_data_handler_collection->get_by_key(
930
+			$this->_data_handler_collection->get_key(
931
+				$data_handler_class_name,
932
+				$generating_data
933
+			)
934
+		);
935
+		if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
936
+			// no saved data_handler in the repo so let's set one up and add it to the repo.
937
+			try {
938
+				$this->_current_data_handler = new $data_handler_class_name($generating_data);
939
+				$this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
940
+			} catch (Exception $e) {
941
+				$this->_error_msg[] = $e->getMessage();
942
+			}
943
+		}
944
+	}
945
+
946
+
947
+	/**
948
+	 * The queued EE_Message for generation does not save the data used for generation as objects
949
+	 * because serialization of those objects could be problematic if the data is saved to the db.
950
+	 * So this method calls the static method on the associated data_handler for the given message_type
951
+	 * and that preps the data for later instantiation when generating.
952
+	 *
953
+	 * @param EE_Message_To_Generate $message_to_generate
954
+	 * @param bool                   $preview Indicate whether this is being used for a preview or not.
955
+	 * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
956
+	 */
957
+	protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
958
+	{
959
+		/** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
960
+		$data_handler = $message_to_generate->get_data_handler_class_name($preview);
961
+		if (! $message_to_generate->valid()) {
962
+			return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
963
+		}
964
+		return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
965
+	}
966
+
967
+
968
+	/**
969
+	 * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
970
+	 *
971
+	 * @param EE_Message_To_Generate $message_to_generate
972
+	 * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
973
+	 * @throws InvalidArgumentException
974
+	 * @throws InvalidDataTypeException
975
+	 * @throws InvalidInterfaceException
976
+	 */
977
+	public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
978
+	{
979
+		// prep data
980
+		$data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
981
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
982
+
983
+		$message = $message_to_generate->get_EE_Message();
984
+		$GRP_ID = $request->getRequestParam('GRP_ID', 0);
985
+
986
+		$GRP_ID = apply_filters(
987
+			'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
988
+			$GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
989
+			$message,
990
+			$message_to_generate,
991
+			$test_send
992
+		);
993
+
994
+		if ($GRP_ID > 0) {
995
+			$message->set_GRP_ID($GRP_ID);
996
+		}
997
+
998
+		if ($data === false) {
999
+			$message->set_STS_ID(EEM_Message::status_failed);
1000
+			$message->set_error_message(
1001
+				esc_html__(
1002
+					'Unable to prepare data for persistence to the database.',
1003
+					'event_espresso'
1004
+				)
1005
+			);
1006
+		} else {
1007
+			// make sure that the data handler is cached on the message as well
1008
+			$data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1009
+		}
1010
+
1011
+		$this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1012
+	}
1013 1013
 }
Please login to merge, or discard this patch.
Spacing   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
     {
268 268
         // double check verification has run and that everything is ready to work with (saves us having to validate
269 269
         // everything again).
270
-        if (! $this->_verified) {
270
+        if ( ! $this->_verified) {
271 271
             return false; // get out because we don't have a valid setup to work with.
272 272
         }
273 273
 
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
 
285 285
 
286 286
         // if no addressees then get out because there is nothing to generation (possible bad data).
287
-        if (! $this->_valid_addressees($addressees)) {
287
+        if ( ! $this->_valid_addressees($addressees)) {
288 288
             do_action(
289 289
                 'AHEE__EE_Messages_Generator___generate__invalid_addressees',
290 290
                 $this->_generation_queue->get_message_repository()->current(),
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
         $message_template_group = $this->_get_message_template_group();
307 307
 
308 308
         // in the unlikely event there is no EE_Message_Template_Group available, get out!
309
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
309
+        if ( ! $message_template_group instanceof EE_Message_Template_Group) {
310 310
             $this->_error_msg[] = esc_html__(
311 311
                 'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
312 312
                 'event_espresso'
@@ -417,7 +417,7 @@  discard block
 block discarded – undo
417 417
             // attempt to retrieve from repo first
418 418
             $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419 419
             if ($message_template_group instanceof EE_Message_Template_Group) {
420
-                return $message_template_group;  // got it!
420
+                return $message_template_group; // got it!
421 421
             }
422 422
 
423 423
             // nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
     protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447 447
     {
448 448
         foreach ($this->_current_data_handler->events as $event) {
449
-            $event_ids[ $event['ID'] ] = $event['ID'];
449
+            $event_ids[$event['ID']] = $event['ID'];
450 450
         }
451 451
         $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452 452
             array(
@@ -522,7 +522,7 @@  discard block
 block discarded – undo
522 522
         );
523 523
 
524 524
         // if we don't have a group lets hit the db.
525
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
525
+        if ( ! $global_message_template_group instanceof EE_Message_Template_Group) {
526 526
             $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527 527
                 array(
528 528
                     array(
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
     {
555 555
         $event_ids = array();
556 556
         foreach ($this->_current_data_handler->events as $event) {
557
-            $event_ids[ $event['ID'] ] = $event['ID'];
557
+            $event_ids[$event['ID']] = $event['ID'];
558 558
         }
559 559
         return $event_ids;
560 560
     }
@@ -583,10 +583,10 @@  discard block
 block discarded – undo
583 583
         $context_templates = $message_template_group->context_templates();
584 584
         foreach ($context_templates as $context => $template_fields) {
585 585
             foreach ($template_fields as $template_field => $template_obj) {
586
-                if (! $template_obj instanceof EE_Message_Template) {
586
+                if ( ! $template_obj instanceof EE_Message_Template) {
587 587
                     continue;
588 588
                 }
589
-                $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
589
+                $templates[$template_field][$context] = $template_obj->get('MTP_content');
590 590
             }
591 591
         }
592 592
         return $templates;
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
     {
618 618
 
619 619
         // if templates are empty then get out because we can't generate anything.
620
-        if (! $templates) {
620
+        if ( ! $templates) {
621 621
             $this->_error_msg[] = esc_html__(
622 622
                 'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623 623
                 'event_espresso'
@@ -704,10 +704,10 @@  discard block
 block discarded – undo
704 704
         $m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705 705
 
706 706
         // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
-        if (! $this->_generation_queue->get_message_repository()->is_preview()
707
+        if ( ! $this->_generation_queue->get_message_repository()->is_preview()
708 708
             && (
709 709
                             (
710
-                                empty($templates['to'][ $context ])
710
+                                empty($templates['to'][$context])
711 711
                                 && ! $this->_current_messenger->allow_empty_to_field()
712 712
                             )
713 713
                             || ! $message_template_group->is_context_active($context)
@@ -721,15 +721,15 @@  discard block
 block discarded – undo
721 721
         foreach ($templates as $field => $field_context) {
722 722
             $error_msg = array();
723 723
             // let's setup the valid shortcodes for the incoming context.
724
-            $valid_shortcodes = $mt_shortcodes[ $context ];
724
+            $valid_shortcodes = $mt_shortcodes[$context];
725 725
             // merge in valid shortcodes for the field.
726
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
727
-            if (isset($templates[ $field ][ $context ])) {
726
+            $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes;
727
+            if (isset($templates[$field][$context])) {
728 728
                 // prefix field.
729
-                $column_name = 'MSG_' . $field;
729
+                $column_name = 'MSG_'.$field;
730 730
                 try {
731 731
                     $content = $this->_shortcode_parser->parse_message_template(
732
-                        $templates[ $field ][ $context ],
732
+                        $templates[$field][$context],
733 733
                         $recipient,
734 734
                         $shortcodes,
735 735
                         $this->_current_message_type,
@@ -798,13 +798,13 @@  discard block
 block discarded – undo
798 798
      */
799 799
     protected function _valid_addressees($addressees)
800 800
     {
801
-        if (! $addressees || ! is_array($addressees)) {
801
+        if ( ! $addressees || ! is_array($addressees)) {
802 802
             return false;
803 803
         }
804 804
 
805 805
         foreach ($addressees as $addressee_array) {
806 806
             foreach ($addressee_array as $addressee) {
807
-                if (! $addressee instanceof EE_Messages_Addressee) {
807
+                if ( ! $addressee instanceof EE_Messages_Addressee) {
808 808
                     return false;
809 809
                 }
810 810
             }
@@ -846,7 +846,7 @@  discard block
 block discarded – undo
846 846
         /**
847 847
          * Check if there is any generation data, but only if this is not for a preview.
848 848
          */
849
-        if (! $this->_generation_queue->get_message_repository()->get_generation_data()
849
+        if ( ! $this->_generation_queue->get_message_repository()->get_generation_data()
850 850
             && (
851 851
                 ! $this->_generation_queue->get_message_repository()->is_preview()
852 852
                 && $this->_generation_queue->get_message_repository()->get_data_handler()
@@ -883,7 +883,7 @@  discard block
 block discarded – undo
883 883
         /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/
884 884
         $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
885 885
             ? $this->_generation_queue->get_message_repository()->get_data_handler()
886
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
886
+            : 'EE_Messages_'.$this->_current_message_type->get_data_handler($generation_data).'_incoming_data';
887 887
 
888 888
         // If this EE_Message is for a preview, then let's switch out to the preview data handler.
889 889
         if ($this->_generation_queue->get_message_repository()->is_preview()) {
@@ -891,7 +891,7 @@  discard block
 block discarded – undo
891 891
         }
892 892
 
893 893
         // First get the class name for the data handler (and also verifies it exists.
894
-        if (! class_exists($data_handler_class_name)) {
894
+        if ( ! class_exists($data_handler_class_name)) {
895 895
             $this->_error_msg[] = sprintf(
896 896
                 /* Translators: Both placeholders are the names of php classes. */
897 897
                 esc_html__(
@@ -932,7 +932,7 @@  discard block
 block discarded – undo
932 932
                 $generating_data
933 933
             )
934 934
         );
935
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
935
+        if ( ! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
936 936
             // no saved data_handler in the repo so let's set one up and add it to the repo.
937 937
             try {
938 938
                 $this->_current_data_handler = new $data_handler_class_name($generating_data);
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
     {
959 959
         /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
960 960
         $data_handler = $message_to_generate->get_data_handler_class_name($preview);
961
-        if (! $message_to_generate->valid()) {
961
+        if ( ! $message_to_generate->valid()) {
962 962
             return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
963 963
         }
964 964
         return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
38 38
  * @since           4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.4.0');
65
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.4.0');
65
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.78.rc.022');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.78.rc.022');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
Please login to merge, or discard this patch.